From fb99711259ef8fad42557cf38418d04e85ebd5d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diogo=20Ferr=C3=A3o?= Date: Fri, 8 Mar 2024 10:09:37 +0000 Subject: [PATCH 1/4] Onboard Argus: config and client impl --- docs/stackit_config_set.md | 1 + docs/stackit_config_unset.md | 1 + go.mod | 1 + go.sum | 2 ++ internal/cmd/config/set/set.go | 6 +++- internal/cmd/config/unset/unset.go | 7 ++++ internal/cmd/config/unset/unset_test.go | 3 ++ internal/pkg/config/config.go | 3 ++ internal/pkg/services/argus/client/client.go | 37 ++++++++++++++++++++ 9 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 internal/pkg/services/argus/client/client.go diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index 096dd2aa2..3b92975dc 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -29,6 +29,7 @@ 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" diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 35f65a296..b69ab2449 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -26,6 +26,7 @@ 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 diff --git a/go.mod b/go.mod index 8a3d5ff20..5280d1343 100644 --- a/go.mod +++ b/go.mod @@ -48,6 +48,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/argus v0.9.5 github.com/stackitcloud/stackit-sdk-go/services/logme v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.10.1 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v0.8.6 diff --git a/go.sum b/go.sum index 47eac769f..33d8f6ab4 100644 --- a/go.sum +++ b/go.sum @@ -75,6 +75,8 @@ github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stackitcloud/stackit-sdk-go/core v0.10.0 h1:IcY8xa/6wo8EhRE9mpCvz4EtTkkoiIa2ZwPHuc5zGyw= github.com/stackitcloud/stackit-sdk-go/core v0.10.0/go.mod h1:B5dkVm2HlBRG7liBVIFNqncDb6TUHnJ7t0GsKhAFuRk= +github.com/stackitcloud/stackit-sdk-go/services/argus v0.9.5 h1:RLsA2jO9sMNpn7NYdtFyumY5Vj4n4WtBm2J2NBKlsnw= +github.com/stackitcloud/stackit-sdk-go/services/argus v0.9.5/go.mod h1:lzGbqwV0hqeX/kUvaaFTgjOJRxUlsZ911TX1YAcKwqc= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.1.1 h1:h7dCaBlbU34WSGuEXREmCdCzQafZgdXDZuairAzeuo8= github.com/stackitcloud/stackit-sdk-go/services/authorization v0.1.1/go.mod h1:V+wTIfuJRV8PiSOfMX6GCTaHWltGaLCz8ImOKeHIaIA= github.com/stackitcloud/stackit-sdk-go/services/dns v0.8.4 h1:n/X2pVdETDXGHk+vCsg0p3b2zGxSRMJ065to/aAoncg= diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index a24be106c..485a1ef9b 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -18,6 +18,7 @@ import ( const ( sessionTimeLimitFlag = "session-time-limit" + argusCustomEndpointFlag = "argus-custom-endpoint" authorizationCustomEndpointFlag = "authorization-custom-endpoint" dnsCustomEndpointFlag = "dns-custom-endpoint" logMeCustomEndpointFlag = "logme-custom-endpoint" @@ -92,6 +93,7 @@ func NewCmd() *cobra.Command { 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(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") cmd.Flags().String(logMeCustomEndpointFlag, "", "LogMe API base URL, used in calls to this API") @@ -107,7 +109,9 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(serviceAccountCustomEndpointFlag, "", "Service Account API base URL, used in calls to this API") cmd.Flags().String(skeCustomEndpointFlag, "", "SKE API base URL, used in calls to this API") - err := viper.BindPFlag(config.AuthorizationCustomEndpointKey, cmd.Flags().Lookup(authorizationCustomEndpointFlag)) + err := viper.BindPFlag(config.ArgusCustomEndpointKey, cmd.Flags().Lookup(argusCustomEndpointFlag)) + cobra.CheckErr(err) + err = viper.BindPFlag(config.AuthorizationCustomEndpointKey, cmd.Flags().Lookup(authorizationCustomEndpointFlag)) cobra.CheckErr(err) err = viper.BindPFlag(config.DNSCustomEndpointKey, cmd.Flags().Lookup(dnsCustomEndpointFlag)) cobra.CheckErr(err) diff --git a/internal/cmd/config/unset/unset.go b/internal/cmd/config/unset/unset.go index f0c7fe3be..ac9e63a64 100644 --- a/internal/cmd/config/unset/unset.go +++ b/internal/cmd/config/unset/unset.go @@ -20,6 +20,7 @@ const ( sessionTimeLimitFlag = "session-time-limit" + argusCustomEndpointFlag = "argus-custom-endpoint" authorizationCustomEndpointFlag = "authorization-custom-endpoint" dnsCustomEndpointFlag = "dns-custom-endpoint" logMeCustomEndpointFlag = "logme-custom-endpoint" @@ -43,6 +44,7 @@ type inputModel struct { SessionTimeLimit bool + ArgusCustomEndpoint bool AuthorizationCustomEndpoint bool DNSCustomEndpoint bool LogMeCustomEndpoint bool @@ -93,6 +95,9 @@ func NewCmd() *cobra.Command { viper.Set(config.SessionTimeLimitKey, config.SessionTimeLimitDefault) } + if model.ArgusCustomEndpoint { + viper.Set(config.ArgusCustomEndpointKey, "") + } if model.AuthorizationCustomEndpoint { viper.Set(config.AuthorizationCustomEndpointKey, "") } @@ -154,6 +159,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(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") cmd.Flags().Bool(logMeCustomEndpointFlag, false, "LogMe API base URL. If unset, uses the default base URL") @@ -177,6 +183,7 @@ func parseInput(cmd *cobra.Command) *inputModel { ProjectId: flags.FlagToBoolValue(cmd, projectIdFlag), SessionTimeLimit: flags.FlagToBoolValue(cmd, sessionTimeLimitFlag), + ArgusCustomEndpoint: flags.FlagToBoolValue(cmd, argusCustomEndpointFlag), AuthorizationCustomEndpoint: flags.FlagToBoolValue(cmd, authorizationCustomEndpointFlag), DNSCustomEndpoint: flags.FlagToBoolValue(cmd, dnsCustomEndpointFlag), LogMeCustomEndpoint: flags.FlagToBoolValue(cmd, logMeCustomEndpointFlag), diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index a6b92e526..6154a6ce4 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -12,6 +12,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]bool)) map[string]bool projectIdFlag: true, outputFormatFlag: true, + argusCustomEndpointFlag: true, authorizationCustomEndpointFlag: true, dnsCustomEndpointFlag: true, logMeCustomEndpointFlag: true, @@ -36,6 +37,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { ProjectId: true, OutputFormat: true, + ArgusCustomEndpoint: true, AuthorizationCustomEndpoint: true, DNSCustomEndpoint: true, LogMeCustomEndpoint: true, @@ -76,6 +78,7 @@ func TestParseInput(t *testing.T) { model.ProjectId = false model.OutputFormat = false + model.ArgusCustomEndpoint = false model.AuthorizationCustomEndpoint = false model.DNSCustomEndpoint = false model.LogMeCustomEndpoint = false diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 82baa091a..b94b82127 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -16,6 +16,7 @@ const ( ProjectIdKey = "project_id" SessionTimeLimitKey = "session_time_limit" + ArgusCustomEndpointKey = "argus_custom_endpoint" AuthorizationCustomEndpointKey = "authorization_custom_endpoint" DNSCustomEndpointKey = "dns_custom_endpoint" LogMeCustomEndpointKey = "logme_custom_endpoint" @@ -56,6 +57,7 @@ var ConfigKeys = []string{ OpenSearchCustomEndpointKey, PostgresFlexCustomEndpointKey, ResourceManagerEndpointKey, + ArgusCustomEndpointKey, AuthorizationCustomEndpointKey, MongoDBFlexCustomEndpointKey, RabbitMQCustomEndpointKey, @@ -128,6 +130,7 @@ func setConfigDefaults() { viper.SetDefault(ProjectIdKey, "") viper.SetDefault(SessionTimeLimitKey, SessionTimeLimitDefault) viper.SetDefault(DNSCustomEndpointKey, "") + viper.SetDefault(ArgusCustomEndpointKey, "") viper.SetDefault(AuthorizationCustomEndpointKey, "") viper.SetDefault(MongoDBFlexCustomEndpointKey, "") viper.SetDefault(ObjectStorageCustomEndpointKey, "") diff --git a/internal/pkg/services/argus/client/client.go b/internal/pkg/services/argus/client/client.go new file mode 100644 index 000000000..3563978be --- /dev/null +++ b/internal/pkg/services/argus/client/client.go @@ -0,0 +1,37 @@ +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/spf13/cobra" + "github.com/spf13/viper" + sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/stackit-sdk-go/services/argus" +) + +func ConfigureClient(cmd *cobra.Command) (*argus.APIClient, error) { + var err error + var apiClient *argus.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")) + + customEndpoint := viper.GetString(config.MariaDBCustomEndpointKey) + + if customEndpoint != "" { + cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint)) + } + + apiClient, err = argus.NewAPIClient(cfgOptions...) + if err != nil { + return nil, &errors.AuthError{} + } + + return apiClient, nil +} From 64610e9b705da7b877e56d1614f8dd96f8555adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diogo=20Ferr=C3=A3o?= Date: Fri, 8 Mar 2024 10:26:43 +0000 Subject: [PATCH 2/4] Onboard Argus: plans command --- docs/stackit.md | 1 + docs/stackit_argus.md | 32 +++++ docs/stackit_argus_plans.md | 45 ++++++ internal/cmd/argus/argus.go | 25 ++++ internal/cmd/argus/plans/plans.go | 144 +++++++++++++++++++ internal/cmd/argus/plans/plans_test.go | 185 +++++++++++++++++++++++++ internal/cmd/root.go | 2 + 7 files changed, 434 insertions(+) create mode 100644 docs/stackit_argus.md create mode 100644 docs/stackit_argus_plans.md create mode 100644 internal/cmd/argus/argus.go create mode 100644 internal/cmd/argus/plans/plans.go create mode 100644 internal/cmd/argus/plans/plans_test.go diff --git a/docs/stackit.md b/docs/stackit.md index 5f5f6f242..7c7484487 100644 --- a/docs/stackit.md +++ b/docs/stackit.md @@ -25,6 +25,7 @@ stackit [flags] ### SEE ALSO +* [stackit argus](./stackit_argus.md) - Provides functionality for Argus * [stackit auth](./stackit_auth.md) - Provides authentication functionality * [stackit config](./stackit_config.md) - Provides functionality for CLI configuration options * [stackit curl](./stackit_curl.md) - Executes an authenticated HTTP request to an endpoint diff --git a/docs/stackit_argus.md b/docs/stackit_argus.md new file mode 100644 index 000000000..c4c7415bb --- /dev/null +++ b/docs/stackit_argus.md @@ -0,0 +1,32 @@ +## 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"] + -p, --project-id string Project ID +``` + +### SEE ALSO + +* [stackit](./stackit.md) - Manage STACKIT resources using the command line +* [stackit argus plans](./stackit_argus_plans.md) - Lists all Argus service plans + diff --git a/docs/stackit_argus_plans.md b/docs/stackit_argus_plans.md new file mode 100644 index 000000000..ef4f1f1ad --- /dev/null +++ b/docs/stackit_argus_plans.md @@ -0,0 +1,45 @@ +## 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"] + -p, --project-id string Project ID +``` + +### SEE ALSO + +* [stackit argus](./stackit_argus.md) - Provides functionality for Argus + diff --git a/internal/cmd/argus/argus.go b/internal/cmd/argus/argus.go new file mode 100644 index 000000000..67ec57e7e --- /dev/null +++ b/internal/cmd/argus/argus.go @@ -0,0 +1,25 @@ +package argus + +import ( + "github.com/stackitcloud/stackit-cli/internal/cmd/argus/plans" + "github.com/stackitcloud/stackit-cli/internal/pkg/args" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" +) + +func NewCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "argus", + Short: "Provides functionality for Argus", + Long: "Provides functionality for Argus.", + Args: args.NoArgs, + Run: utils.CmdHelp, + } + addSubcommands(cmd) + return cmd +} + +func addSubcommands(cmd *cobra.Command) { + cmd.AddCommand(plans.NewCmd()) +} diff --git a/internal/cmd/argus/plans/plans.go b/internal/cmd/argus/plans/plans.go new file mode 100644 index 000000000..7dc0c7a82 --- /dev/null +++ b/internal/cmd/argus/plans/plans.go @@ -0,0 +1,144 @@ +package plans + +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/projectname" + "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/client" + "github.com/stackitcloud/stackit-cli/internal/pkg/tables" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/argus" +) + +const ( + limitFlag = "limit" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + Limit *int64 +} + +func NewCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "plans", + Short: "Lists all Argus service plans", + Long: "Lists all Argus service plans.", + Args: args.NoArgs, + Example: examples.Build( + examples.NewExample( + `List all Argus service plans`, + "$ stackit argus plans"), + examples.NewExample( + `List all Argus service plans in JSON format`, + "$ stackit argus plans --output-format json"), + examples.NewExample( + `List up to 10 Argus service plans`, + "$ stackit argus plans --limit 10"), + ), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + model, err := parseInput(cmd) + if err != nil { + return err + } + + // Configure API client + apiClient, err := client.ConfigureClient(cmd) + if err != nil { + return err + } + + // Call API + req := buildRequest(ctx, model, apiClient) + resp, err := req.Execute() + if err != nil { + return fmt.Errorf("get Argus service plans: %w", err) + } + plans := *resp.Plans + if len(plans) == 0 { + projectLabel, err := projectname.GetProjectName(ctx, cmd) + if err != nil { + projectLabel = model.ProjectId + } + cmd.Printf("No plans found for project %q\n", projectLabel) + return nil + } + + // Truncate output + if model.Limit != nil && len(plans) > int(*model.Limit) { + plans = plans[:*model.Limit] + } + + return outputResult(cmd, model.OutputFormat, plans) + }, + } + + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list") +} + +func parseInput(cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + limit := flags.FlagToInt64Pointer(cmd, limitFlag) + if limit != nil && *limit < 1 { + return nil, &errors.FlagValidationError{ + Flag: limitFlag, + Details: "must be greater than 0", + } + } + + return &inputModel{ + GlobalFlagModel: globalFlags, + Limit: limit, + }, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient *argus.APIClient) argus.ApiListPlansRequest { + req := apiClient.ListPlans(ctx, model.ProjectId) + return req +} + +func outputResult(cmd *cobra.Command, outputFormat string, plans []argus.Plan) error { + switch outputFormat { + case globalflags.JSONOutputFormat: + details, err := json.MarshalIndent(plans, "", " ") + if err != nil { + return fmt.Errorf("marshal Argus plans: %w", err) + } + cmd.Println(string(details)) + + return nil + default: + table := tables.NewTable() + table.SetHeader("PLAN NAME", "ID", "DESCRIPTION") + for i := range plans { + o := plans[i] + table.AddRow(*o.Name, *o.Id, *o.Description) + table.AddSeparator() + } + table.EnableAutoMergeOnColumns(1) + err := table.Display(cmd) + if err != nil { + return fmt.Errorf("render table: %w", err) + } + + return nil + } +} diff --git a/internal/cmd/argus/plans/plans_test.go b/internal/cmd/argus/plans/plans_test.go new file mode 100644 index 000000000..d7072ab48 --- /dev/null +++ b/internal/cmd/argus/plans/plans_test.go @@ -0,0 +1,185 @@ +package plans + +import ( + "context" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "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/argus" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &argus.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, + }, + Limit: utils.Ptr(int64(10)), + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureRequest(mods ...func(request *argus.ApiListPlansRequest)) argus.ApiListPlansRequest { + request := testClient.ListPlans(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, + }, + { + 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) + } + + model, err := parseInput(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 argus.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), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} diff --git a/internal/cmd/root.go b/internal/cmd/root.go index bfb9a1f12..726bbd180 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -6,6 +6,7 @@ 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/config" "github.com/stackitcloud/stackit-cli/internal/cmd/curl" @@ -84,6 +85,7 @@ func configureFlags(cmd *cobra.Command) error { } func addSubcommands(cmd *cobra.Command) { + cmd.AddCommand(argus.NewCmd()) cmd.AddCommand(auth.NewCmd()) cmd.AddCommand(config.NewCmd()) cmd.AddCommand(curl.NewCmd()) From 07dfbdb2616ab8bd7869583056933027fd954476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diogo=20Ferr=C3=A3o?= Date: Fri, 8 Mar 2024 10:51:39 +0000 Subject: [PATCH 3/4] integrate argus in unset tests --- internal/cmd/config/unset/unset_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/internal/cmd/config/unset/unset_test.go b/internal/cmd/config/unset/unset_test.go index 6154a6ce4..f68717953 100644 --- a/internal/cmd/config/unset/unset_test.go +++ b/internal/cmd/config/unset/unset_test.go @@ -113,6 +113,16 @@ func TestParseInput(t *testing.T) { model.OutputFormat = false }), }, + { + description: "argus custom endpoint empty", + flagValues: fixtureFlagValues(func(flagValues map[string]bool) { + flagValues[argusCustomEndpointFlag] = false + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.ArgusCustomEndpoint = false + }), + }, { description: "dns custom endpoint empty", flagValues: fixtureFlagValues(func(flagValues map[string]bool) { From af8c265820164de04983f048173c6b702dd1f946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diogo=20Ferr=C3=A3o?= Date: Fri, 8 Mar 2024 11:14:40 +0000 Subject: [PATCH 4/4] Addressed comments --- internal/cmd/argus/plans/plans.go | 4 ++-- internal/pkg/services/argus/client/client.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/cmd/argus/plans/plans.go b/internal/cmd/argus/plans/plans.go index 7dc0c7a82..a74e5c534 100644 --- a/internal/cmd/argus/plans/plans.go +++ b/internal/cmd/argus/plans/plans.go @@ -127,10 +127,10 @@ func outputResult(cmd *cobra.Command, outputFormat string, plans []argus.Plan) e return nil default: table := tables.NewTable() - table.SetHeader("PLAN NAME", "ID", "DESCRIPTION") + table.SetHeader("ID", "PLAN NAME", "DESCRIPTION") for i := range plans { o := plans[i] - table.AddRow(*o.Name, *o.Id, *o.Description) + table.AddRow(*o.Id, *o.Name, *o.Description) table.AddSeparator() } table.EnableAutoMergeOnColumns(1) diff --git a/internal/pkg/services/argus/client/client.go b/internal/pkg/services/argus/client/client.go index 3563978be..ebf90f114 100644 --- a/internal/pkg/services/argus/client/client.go +++ b/internal/pkg/services/argus/client/client.go @@ -22,7 +22,7 @@ func ConfigureClient(cmd *cobra.Command) (*argus.APIClient, error) { } cfgOptions = append(cfgOptions, authCfgOption, sdkConfig.WithRegion("eu01")) - customEndpoint := viper.GetString(config.MariaDBCustomEndpointKey) + customEndpoint := viper.GetString(config.ArgusCustomEndpointKey) if customEndpoint != "" { cfgOptions = append(cfgOptions, sdkConfig.WithEndpoint(customEndpoint))