From 80bb330f9ab28f86d1175eaaa3cbf1f2bea087b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Wed, 17 Apr 2024 14:14:10 +0100 Subject: [PATCH 1/6] Copy files from single sign-on --- .../public-read-access/disable/disable.go | 115 ++++++++ .../disable/disable_test.go | 269 ++++++++++++++++++ .../public-read-access/enable/enable.go | 115 ++++++++ .../public-read-access/enable/enable_test.go | 269 ++++++++++++++++++ .../public-read-access/public_read_access.go | 33 +++ 5 files changed, 801 insertions(+) create mode 100644 internal/cmd/argus/grafana/public-read-access/disable/disable.go create mode 100644 internal/cmd/argus/grafana/public-read-access/disable/disable_test.go create mode 100644 internal/cmd/argus/grafana/public-read-access/enable/enable.go create mode 100644 internal/cmd/argus/grafana/public-read-access/enable/enable_test.go create mode 100644 internal/cmd/argus/grafana/public-read-access/public_read_access.go diff --git a/internal/cmd/argus/grafana/public-read-access/disable/disable.go b/internal/cmd/argus/grafana/public-read-access/disable/disable.go new file mode 100644 index 000000000..090320e4c --- /dev/null +++ b/internal/cmd/argus/grafana/public-read-access/disable/disable.go @@ -0,0 +1,115 @@ +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/argus/client" + argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/argus" +) + +const ( + instanceIdFlag = "instance-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + InstanceId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "disable", + Short: "Disables single sign-on for Grafana on Argus instances", + Long: fmt.Sprintf("%s\n%s", + "Disables single sign-on for Grafana on Argus instances.", + "When disabled for an instance, the generic OAuth2 authentication is used for that instance.", + ), + Args: args.NoArgs, + 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 --instance-id xxx"), + ), + 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(p) + if err != nil { + return err + } + + instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + if err != nil || instanceLabel == "" { + instanceLabel = model.InstanceId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to disable single sign-on for instance %q?", instanceLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, err := buildRequest(ctx, model, apiClient) + if err != nil { + return fmt.Errorf("build request: %w", err) + } + _, err = req.Execute() + if err != nil { + return fmt.Errorf("disable single sign-on: %w", err) + } + + p.Info("Disabled single sign-on for instance %q\n", instanceLabel) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "Instance ID") + + err := flags.MarkFlagsRequired(cmd, instanceIdFlag) + cobra.CheckErr(err) +} + +func parseInput(cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + return &inputModel{ + GlobalFlagModel: globalFlags, + InstanceId: flags.FlagToStringValue(cmd, instanceIdFlag), + }, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient argusUtils.ArgusClient) (argus.ApiUpdateGrafanaConfigsRequest, error) { + req := apiClient.UpdateGrafanaConfigs(ctx, model.InstanceId, model.ProjectId) + payload, err := argusUtils.GetPartialUpdateGrafanaConfigsPayload(ctx, apiClient, model.InstanceId, model.ProjectId, utils.Ptr(false), nil) + if err != nil { + return req, fmt.Errorf("build request payload: %w", err) + } + req = req.UpdateGrafanaConfigsPayload(*payload) + return req, nil +} diff --git a/internal/cmd/argus/grafana/public-read-access/disable/disable_test.go b/internal/cmd/argus/grafana/public-read-access/disable/disable_test.go new file mode 100644 index 000000000..b654bbb32 --- /dev/null +++ b/internal/cmd/argus/grafana/public-read-access/disable/disable_test.go @@ -0,0 +1,269 @@ +package disable + +import ( + "context" + "fmt" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + 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" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &argus.APIClient{} +var testProjectId = uuid.NewString() +var testInstanceId = uuid.NewString() + +type argusClientMocked struct { + getGrafanaConfigsFails bool + getGrafanaConfigsResp *argus.GrafanaConfigs +} + +func (c *argusClientMocked) GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*argus.GetInstanceResponse, error) { + return testClient.GetInstanceExecute(ctx, instanceId, projectId) +} + +func (c *argusClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) argus.ApiUpdateGrafanaConfigsRequest { + return testClient.UpdateGrafanaConfigs(ctx, instanceId, projectId) +} + +func (c *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*argus.GrafanaConfigs, error) { + if c.getGrafanaConfigsFails { + return nil, fmt.Errorf("get payload failed") + } + return c.getGrafanaConfigsResp, nil +} + +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, + }, + InstanceId: testInstanceId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.GrafanaConfigs { + gc := argus.GrafanaConfigs{ + GenericOauth: &argus.GrafanaOauth{ + ApiUrl: utils.Ptr("apiUrl"), + AuthUrl: utils.Ptr("authUrl"), + Enabled: utils.Ptr(true), + Name: utils.Ptr("name"), + OauthClientId: utils.Ptr("oauthClientId"), + OauthClientSecret: utils.Ptr("oauthClientSecret"), + RoleAttributePath: utils.Ptr("roleAttributePath"), + RoleAttributeStrict: utils.Ptr(true), + Scopes: utils.Ptr("scopes"), + TokenUrl: utils.Ptr("tokenUrl"), + UsePkce: utils.Ptr(true), + }, + PublicReadAccess: utils.Ptr(false), + UseStackitSso: utils.Ptr(false), + } + for _, mod := range mods { + mod(&gc) + } + return &gc +} + +func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *argus.UpdateGrafanaConfigsPayload { + payload := &argus.UpdateGrafanaConfigsPayload{ + GenericOauth: argusUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), + PublicReadAccess: fixtureGrafanaConfigs().PublicReadAccess, + UseStackitSso: utils.Ptr(false), + } + for _, mod := range mods { + mod(payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *argus.ApiUpdateGrafanaConfigsRequest)) argus.ApiUpdateGrafanaConfigsRequest { + request := testClient.UpdateGrafanaConfigs(testCtx, testInstanceId, testProjectId) + request = request.UpdateGrafanaConfigsPayload(*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: "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 := 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(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 + getGrafanaConfigsFails bool + getGrafanaConfigsResp *argus.GrafanaConfigs + isValid bool + expectedRequest argus.ApiUpdateGrafanaConfigsRequest + }{ + { + description: "base", + model: fixtureInputModel(), + getGrafanaConfigsResp: fixtureGrafanaConfigs(), + isValid: true, + expectedRequest: fixtureRequest(), + }, + { + description: "nil generic oauth", + model: fixtureInputModel(), + getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *argus.GrafanaConfigs) { + gc.GenericOauth = nil + }), + isValid: true, + expectedRequest: fixtureRequest(func(request *argus.ApiUpdateGrafanaConfigsRequest) { + *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *argus.UpdateGrafanaConfigsPayload) { + payload.GenericOauth = nil + })) + }), + }, + { + description: "get grafana configs fails", + model: fixtureInputModel(), + getGrafanaConfigsFails: true, + isValid: false, + }, + { + description: "no grafana configs", + model: fixtureInputModel(), + getGrafanaConfigsResp: nil, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &argusClientMocked{ + getGrafanaConfigsFails: tt.getGrafanaConfigsFails, + getGrafanaConfigsResp: tt.getGrafanaConfigsResp, + } + request, err := buildRequest(testCtx, tt.model, client) + 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/argus/grafana/public-read-access/enable/enable.go b/internal/cmd/argus/grafana/public-read-access/enable/enable.go new file mode 100644 index 000000000..711e68fb1 --- /dev/null +++ b/internal/cmd/argus/grafana/public-read-access/enable/enable.go @@ -0,0 +1,115 @@ +package enable + +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/argus/client" + argusUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/argus/utils" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" + + "github.com/spf13/cobra" + "github.com/stackitcloud/stackit-sdk-go/services/argus" +) + +const ( + instanceIdFlag = "instance-id" +) + +type inputModel struct { + *globalflags.GlobalFlagModel + InstanceId string +} + +func NewCmd(p *print.Printer) *cobra.Command { + cmd := &cobra.Command{ + Use: "enable", + Short: "Enables single sign-on for Grafana on Argus instances", + Long: fmt.Sprintf("%s\n%s", + "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.", + ), + Args: args.NoArgs, + 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 --instance-id xxx"), + ), + 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(p) + if err != nil { + return err + } + + instanceLabel, err := argusUtils.GetInstanceName(ctx, apiClient, model.InstanceId, model.ProjectId) + if err != nil || instanceLabel == "" { + instanceLabel = model.InstanceId + } + + if !model.AssumeYes { + prompt := fmt.Sprintf("Are you sure you want to enable single sign-on for instance %q?", instanceLabel) + err = p.PromptForConfirmation(prompt) + if err != nil { + return err + } + } + + // Call API + req, err := buildRequest(ctx, model, apiClient) + if err != nil { + return fmt.Errorf("build request: %w", err) + } + _, err = req.Execute() + if err != nil { + return fmt.Errorf("enable single sign-on: %w", err) + } + + p.Info("Enabled single sign-on for instance %q\n", instanceLabel) + return nil + }, + } + configureFlags(cmd) + return cmd +} + +func configureFlags(cmd *cobra.Command) { + cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "Instance ID") + + err := flags.MarkFlagsRequired(cmd, instanceIdFlag) + cobra.CheckErr(err) +} + +func parseInput(cmd *cobra.Command) (*inputModel, error) { + globalFlags := globalflags.Parse(cmd) + if globalFlags.ProjectId == "" { + return nil, &errors.ProjectIdError{} + } + + return &inputModel{ + GlobalFlagModel: globalFlags, + InstanceId: flags.FlagToStringValue(cmd, instanceIdFlag), + }, nil +} + +func buildRequest(ctx context.Context, model *inputModel, apiClient argusUtils.ArgusClient) (argus.ApiUpdateGrafanaConfigsRequest, error) { + req := apiClient.UpdateGrafanaConfigs(ctx, model.InstanceId, model.ProjectId) + payload, err := argusUtils.GetPartialUpdateGrafanaConfigsPayload(ctx, apiClient, model.InstanceId, model.ProjectId, utils.Ptr(true), nil) + if err != nil { + return req, fmt.Errorf("build request payload: %w", err) + } + req = req.UpdateGrafanaConfigsPayload(*payload) + return req, nil +} diff --git a/internal/cmd/argus/grafana/public-read-access/enable/enable_test.go b/internal/cmd/argus/grafana/public-read-access/enable/enable_test.go new file mode 100644 index 000000000..7544b81b4 --- /dev/null +++ b/internal/cmd/argus/grafana/public-read-access/enable/enable_test.go @@ -0,0 +1,269 @@ +package enable + +import ( + "context" + "fmt" + "testing" + + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + 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" +) + +var projectIdFlag = globalflags.ProjectIdFlag + +type testCtxKey struct{} + +var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") +var testClient = &argus.APIClient{} +var testProjectId = uuid.NewString() +var testInstanceId = uuid.NewString() + +type argusClientMocked struct { + getGrafanaConfigsFails bool + getGrafanaConfigsResp *argus.GrafanaConfigs +} + +func (c *argusClientMocked) GetInstanceExecute(ctx context.Context, instanceId, projectId string) (*argus.GetInstanceResponse, error) { + return testClient.GetInstanceExecute(ctx, instanceId, projectId) +} + +func (c *argusClientMocked) UpdateGrafanaConfigs(ctx context.Context, instanceId, projectId string) argus.ApiUpdateGrafanaConfigsRequest { + return testClient.UpdateGrafanaConfigs(ctx, instanceId, projectId) +} + +func (c *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ string) (*argus.GrafanaConfigs, error) { + if c.getGrafanaConfigsFails { + return nil, fmt.Errorf("get payload failed") + } + return c.getGrafanaConfigsResp, nil +} + +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, + }, + InstanceId: testInstanceId, + } + for _, mod := range mods { + mod(model) + } + return model +} + +func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.GrafanaConfigs { + gc := argus.GrafanaConfigs{ + GenericOauth: &argus.GrafanaOauth{ + ApiUrl: utils.Ptr("apiUrl"), + AuthUrl: utils.Ptr("authUrl"), + Enabled: utils.Ptr(true), + Name: utils.Ptr("name"), + OauthClientId: utils.Ptr("oauthClientId"), + OauthClientSecret: utils.Ptr("oauthClientSecret"), + RoleAttributePath: utils.Ptr("roleAttributePath"), + RoleAttributeStrict: utils.Ptr(true), + Scopes: utils.Ptr("scopes"), + TokenUrl: utils.Ptr("tokenUrl"), + UsePkce: utils.Ptr(true), + }, + PublicReadAccess: utils.Ptr(false), + UseStackitSso: utils.Ptr(false), + } + for _, mod := range mods { + mod(&gc) + } + return &gc +} + +func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *argus.UpdateGrafanaConfigsPayload { + payload := &argus.UpdateGrafanaConfigsPayload{ + GenericOauth: argusUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), + PublicReadAccess: fixtureGrafanaConfigs().PublicReadAccess, + UseStackitSso: utils.Ptr(true), + } + for _, mod := range mods { + mod(payload) + } + return payload +} + +func fixtureRequest(mods ...func(request *argus.ApiUpdateGrafanaConfigsRequest)) argus.ApiUpdateGrafanaConfigsRequest { + request := testClient.UpdateGrafanaConfigs(testCtx, testInstanceId, testProjectId) + request = request.UpdateGrafanaConfigsPayload(*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: "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 := 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(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 + getGrafanaConfigsFails bool + getGrafanaConfigsResp *argus.GrafanaConfigs + isValid bool + expectedRequest argus.ApiUpdateGrafanaConfigsRequest + }{ + { + description: "base", + model: fixtureInputModel(), + getGrafanaConfigsResp: fixtureGrafanaConfigs(), + isValid: true, + expectedRequest: fixtureRequest(), + }, + { + description: "nil generic oauth", + model: fixtureInputModel(), + getGrafanaConfigsResp: fixtureGrafanaConfigs(func(gc *argus.GrafanaConfigs) { + gc.GenericOauth = nil + }), + isValid: true, + expectedRequest: fixtureRequest(func(request *argus.ApiUpdateGrafanaConfigsRequest) { + *request = request.UpdateGrafanaConfigsPayload(*fixturePayload(func(payload *argus.UpdateGrafanaConfigsPayload) { + payload.GenericOauth = nil + })) + }), + }, + { + description: "get grafana configs fails", + model: fixtureInputModel(), + getGrafanaConfigsFails: true, + isValid: false, + }, + { + description: "no grafana configs", + model: fixtureInputModel(), + getGrafanaConfigsResp: nil, + isValid: false, + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + client := &argusClientMocked{ + getGrafanaConfigsFails: tt.getGrafanaConfigsFails, + getGrafanaConfigsResp: tt.getGrafanaConfigsResp, + } + request, err := buildRequest(testCtx, tt.model, client) + 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/argus/grafana/public-read-access/public_read_access.go b/internal/cmd/argus/grafana/public-read-access/public_read_access.go new file mode 100644 index 000000000..6b2cf37cb --- /dev/null +++ b/internal/cmd/argus/grafana/public-read-access/public_read_access.go @@ -0,0 +1,33 @@ +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/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: "single-sign-on", + Short: "Enable or disable single sign-on for Grafana in Argus instances", + Long: fmt.Sprintf("%s\n%s", + "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.", + ), + 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)) +} From 8b23682b368361cc66201aa7f7bc3894fb286b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Wed, 17 Apr 2024 14:27:16 +0100 Subject: [PATCH 2/6] Adaptations for the public-read-access commands --- internal/cmd/argus/grafana/grafana.go | 2 ++ .../public-read-access/disable/disable.go | 18 +++++++++--------- .../public-read-access/disable/disable_test.go | 4 ++-- .../public-read-access/enable/enable.go | 18 +++++++++--------- .../public-read-access/enable/enable_test.go | 4 ++-- .../public-read-access/public_read_access.go | 14 +++++++------- 6 files changed, 31 insertions(+), 29 deletions(-) diff --git a/internal/cmd/argus/grafana/grafana.go b/internal/cmd/argus/grafana/grafana.go index 0ce98f4c8..19ed4368a 100644 --- a/internal/cmd/argus/grafana/grafana.go +++ b/internal/cmd/argus/grafana/grafana.go @@ -2,6 +2,7 @@ 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/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" @@ -24,5 +25,6 @@ func NewCmd(p *print.Printer) *cobra.Command { func addSubcommands(cmd *cobra.Command, p *print.Printer) { cmd.AddCommand(describe.NewCmd(p)) + cmd.AddCommand(publicreadaccess.NewCmd(p)) cmd.AddCommand(singlesignon.NewCmd(p)) } diff --git a/internal/cmd/argus/grafana/public-read-access/disable/disable.go b/internal/cmd/argus/grafana/public-read-access/disable/disable.go index 090320e4c..82b9e0b62 100644 --- a/internal/cmd/argus/grafana/public-read-access/disable/disable.go +++ b/internal/cmd/argus/grafana/public-read-access/disable/disable.go @@ -30,16 +30,16 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "disable", - Short: "Disables single sign-on for Grafana on Argus instances", + Short: "Disables public read access for Grafana on Argus instances", Long: fmt.Sprintf("%s\n%s", - "Disables single sign-on for Grafana on Argus instances.", - "When disabled for an instance, the generic OAuth2 authentication is used for that instance.", + "Disables public read access for Grafana on Argus instances.", + "When disabled, a login is required to access the Grafana dashboards without of the instance logging in. Otherwise, anyone can access the dashboards.", ), Args: args.NoArgs, 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 --instance-id xxx"), + `Disable public read access for Grafana on an Argus instance with ID "xxx"`, + "$ stackit argus grafana public-read-access disable --instance-id xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -60,7 +60,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 instance %q?", instanceLabel) + prompt := fmt.Sprintf("Are you sure you want to disable public read access for instance %q?", instanceLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -74,10 +74,10 @@ func NewCmd(p *print.Printer) *cobra.Command { } _, err = req.Execute() if err != nil { - return fmt.Errorf("disable single sign-on: %w", err) + return fmt.Errorf("disable public read access: %w", err) } - p.Info("Disabled single sign-on for instance %q\n", instanceLabel) + p.Info("Disabled public read access for instance %q\n", instanceLabel) return nil }, } @@ -106,7 +106,7 @@ func parseInput(cmd *cobra.Command) (*inputModel, error) { func buildRequest(ctx context.Context, model *inputModel, apiClient argusUtils.ArgusClient) (argus.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 := argusUtils.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/argus/grafana/public-read-access/disable/disable_test.go index b654bbb32..06c6a3148 100644 --- a/internal/cmd/argus/grafana/public-read-access/disable/disable_test.go +++ b/internal/cmd/argus/grafana/public-read-access/disable/disable_test.go @@ -96,8 +96,8 @@ func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.Grafan func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *argus.UpdateGrafanaConfigsPayload { payload := &argus.UpdateGrafanaConfigsPayload{ GenericOauth: argusUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), - PublicReadAccess: fixtureGrafanaConfigs().PublicReadAccess, - UseStackitSso: utils.Ptr(false), + PublicReadAccess: utils.Ptr(false), + UseStackitSso: fixtureGrafanaConfigs().UseStackitSso, } for _, mod := range mods { mod(payload) diff --git a/internal/cmd/argus/grafana/public-read-access/enable/enable.go b/internal/cmd/argus/grafana/public-read-access/enable/enable.go index 711e68fb1..13b597171 100644 --- a/internal/cmd/argus/grafana/public-read-access/enable/enable.go +++ b/internal/cmd/argus/grafana/public-read-access/enable/enable.go @@ -30,16 +30,16 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ Use: "enable", - Short: "Enables single sign-on for Grafana on Argus instances", + Short: "Enables public read access for Grafana on Argus instances", Long: fmt.Sprintf("%s\n%s", - "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.", + "Enables public read access for Grafana on Argus instances.", + "When enabled, anyone can access the Grafana dashboards without of the instance logging in. Otherwise, a login is required.", ), Args: args.NoArgs, 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 --instance-id xxx"), + `Enable public read access for Grafana on an Argus instance with ID "xxx"`, + "$ stackit argus grafana public-read-access enable --instance-id xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -60,7 +60,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 instance %q?", instanceLabel) + prompt := fmt.Sprintf("Are you sure you want to enable public read access for instance %q?", instanceLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -74,10 +74,10 @@ func NewCmd(p *print.Printer) *cobra.Command { } _, err = req.Execute() if err != nil { - return fmt.Errorf("enable single sign-on: %w", err) + return fmt.Errorf("enable public read access: %w", err) } - p.Info("Enabled single sign-on for instance %q\n", instanceLabel) + p.Info("Enabled public read access for instance %q\n", instanceLabel) return nil }, } @@ -106,7 +106,7 @@ func parseInput(cmd *cobra.Command) (*inputModel, error) { func buildRequest(ctx context.Context, model *inputModel, apiClient argusUtils.ArgusClient) (argus.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 := argusUtils.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/argus/grafana/public-read-access/enable/enable_test.go index 7544b81b4..bdd7eb30e 100644 --- a/internal/cmd/argus/grafana/public-read-access/enable/enable_test.go +++ b/internal/cmd/argus/grafana/public-read-access/enable/enable_test.go @@ -96,8 +96,8 @@ func fixtureGrafanaConfigs(mods ...func(gc *argus.GrafanaConfigs)) *argus.Grafan func fixturePayload(mods ...func(payload *argus.UpdateGrafanaConfigsPayload)) *argus.UpdateGrafanaConfigsPayload { payload := &argus.UpdateGrafanaConfigsPayload{ GenericOauth: argusUtils.ToPayloadGenericOAuth(fixtureGrafanaConfigs().GenericOauth), - PublicReadAccess: fixtureGrafanaConfigs().PublicReadAccess, - UseStackitSso: utils.Ptr(true), + PublicReadAccess: utils.Ptr(true), + UseStackitSso: fixtureGrafanaConfigs().UseStackitSso, } for _, mod := range mods { mod(payload) diff --git a/internal/cmd/argus/grafana/public-read-access/public_read_access.go b/internal/cmd/argus/grafana/public-read-access/public_read_access.go index 6b2cf37cb..03da90f1d 100644 --- a/internal/cmd/argus/grafana/public-read-access/public_read_access.go +++ b/internal/cmd/argus/grafana/public-read-access/public_read_access.go @@ -1,10 +1,10 @@ -package singlesignon +package publicreadaccess 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/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/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" @@ -14,11 +14,11 @@ import ( func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "single-sign-on", - Short: "Enable or disable single sign-on for Grafana in Argus instances", + Use: "public-read-access", + Short: "Enable or disable public read access for Grafana in Argus instances", Long: fmt.Sprintf("%s\n%s", - "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.", + "Enable or disable public read access for Grafana in Argus instances.", + "When enabled, anyone can access the Grafana dashboards without of the instance logging in. Otherwise, a login is required.", ), Args: args.NoArgs, Run: utils.CmdHelp, From 4806665a0ad65b7f3581c12d0b35242adef0c706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Wed, 17 Apr 2024 14:27:33 +0100 Subject: [PATCH 3/6] Update docs --- docs/stackit_argus_grafana.md | 1 + ...tackit_argus_grafana_public-read-access.md | 35 ++++++++++++++++ ...rgus_grafana_public-read-access_disable.md | 41 +++++++++++++++++++ ...argus_grafana_public-read-access_enable.md | 41 +++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 docs/stackit_argus_grafana_public-read-access.md create mode 100644 docs/stackit_argus_grafana_public-read-access_disable.md create mode 100644 docs/stackit_argus_grafana_public-read-access_enable.md diff --git a/docs/stackit_argus_grafana.md b/docs/stackit_argus_grafana.md index c1ce6b5b5..c6743ac86 100644 --- a/docs/stackit_argus_grafana.md +++ b/docs/stackit_argus_grafana.md @@ -30,5 +30,6 @@ stackit argus grafana [flags] * [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_public-read-access.md b/docs/stackit_argus_grafana_public-read-access.md new file mode 100644 index 000000000..9c91f6a0d --- /dev/null +++ b/docs/stackit_argus_grafana_public-read-access.md @@ -0,0 +1,35 @@ +## 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 without of the instance 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"] + -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 new file mode 100644 index 000000000..3e8acc2e4 --- /dev/null +++ b/docs/stackit_argus_grafana_public-read-access_disable.md @@ -0,0 +1,41 @@ +## 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 without of the instance logging in. Otherwise, anyone can access the dashboards. + +``` +stackit argus grafana public-read-access disable [flags] +``` + +### Examples + +``` + Disable public read access for Grafana on an Argus instance with ID "xxx" + $ stackit argus grafana public-read-access disable --instance-id xxx +``` + +### Options + +``` + -h, --help Help for "stackit argus grafana public-read-access disable" + --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"] + -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 new file mode 100644 index 000000000..990388b7c --- /dev/null +++ b/docs/stackit_argus_grafana_public-read-access_enable.md @@ -0,0 +1,41 @@ +## 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 without of the instance logging in. Otherwise, a login is required. + +``` +stackit argus grafana public-read-access enable [flags] +``` + +### Examples + +``` + Enable public read access for Grafana on an Argus instance with ID "xxx" + $ stackit argus grafana public-read-access enable --instance-id xxx +``` + +### Options + +``` + -h, --help Help for "stackit argus grafana public-read-access enable" + --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"] + -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 + From 1bbc532940baba2be2ef1682e7d39d3541ad2295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Wed, 17 Apr 2024 14:59:13 +0100 Subject: [PATCH 4/6] Improvements after review --- docs/stackit_argus_grafana_public-read-access.md | 2 +- docs/stackit_argus_grafana_public-read-access_disable.md | 2 +- docs/stackit_argus_grafana_public-read-access_enable.md | 2 +- .../argus/grafana/public-read-access/disable/disable.go | 8 ++++---- .../cmd/argus/grafana/public-read-access/enable/enable.go | 8 ++++---- .../grafana/public-read-access/public_read_access.go | 2 +- .../cmd/argus/grafana/single-sign-on/disable/disable.go | 6 +++--- .../cmd/argus/grafana/single-sign-on/enable/enable.go | 6 +++--- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/stackit_argus_grafana_public-read-access.md b/docs/stackit_argus_grafana_public-read-access.md index 9c91f6a0d..bc0f7791e 100644 --- a/docs/stackit_argus_grafana_public-read-access.md +++ b/docs/stackit_argus_grafana_public-read-access.md @@ -5,7 +5,7 @@ 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 without of the instance logging in. Otherwise, a login is required. +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] diff --git a/docs/stackit_argus_grafana_public-read-access_disable.md b/docs/stackit_argus_grafana_public-read-access_disable.md index 3e8acc2e4..a15abe603 100644 --- a/docs/stackit_argus_grafana_public-read-access_disable.md +++ b/docs/stackit_argus_grafana_public-read-access_disable.md @@ -5,7 +5,7 @@ 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 without of the instance logging in. Otherwise, anyone can access the dashboards. +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 [flags] diff --git a/docs/stackit_argus_grafana_public-read-access_enable.md b/docs/stackit_argus_grafana_public-read-access_enable.md index 990388b7c..8e098dfb6 100644 --- a/docs/stackit_argus_grafana_public-read-access_enable.md +++ b/docs/stackit_argus_grafana_public-read-access_enable.md @@ -5,7 +5,7 @@ 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 without of the instance logging in. Otherwise, a login is required. +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 [flags] diff --git a/internal/cmd/argus/grafana/public-read-access/disable/disable.go b/internal/cmd/argus/grafana/public-read-access/disable/disable.go index 82b9e0b62..aff871f8d 100644 --- a/internal/cmd/argus/grafana/public-read-access/disable/disable.go +++ b/internal/cmd/argus/grafana/public-read-access/disable/disable.go @@ -33,7 +33,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Short: "Disables public read access for Grafana on Argus instances", Long: fmt.Sprintf("%s\n%s", "Disables public read access for Grafana on Argus instances.", - "When disabled, a login is required to access the Grafana dashboards without of the instance logging in. Otherwise, anyone can access the dashboards.", + "When disabled, a login is required to access the Grafana dashboards of the instance. Otherwise, anyone can access the dashboards.", ), Args: args.NoArgs, Example: examples.Build( @@ -60,7 +60,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to disable public read access for instance %q?", instanceLabel) + prompt := fmt.Sprintf("Are you sure you want to disable Grafana public read access for instance %q?", instanceLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -74,10 +74,10 @@ func NewCmd(p *print.Printer) *cobra.Command { } _, err = req.Execute() if err != nil { - return fmt.Errorf("disable public read access: %w", err) + return fmt.Errorf("disable grafana public read access: %w", err) } - p.Info("Disabled public read access for instance %q\n", instanceLabel) + p.Info("Disabled Grafana public read access for instance %q\n", instanceLabel) return nil }, } diff --git a/internal/cmd/argus/grafana/public-read-access/enable/enable.go b/internal/cmd/argus/grafana/public-read-access/enable/enable.go index 13b597171..489b92a27 100644 --- a/internal/cmd/argus/grafana/public-read-access/enable/enable.go +++ b/internal/cmd/argus/grafana/public-read-access/enable/enable.go @@ -33,7 +33,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Short: "Enables public read access for Grafana on Argus instances", Long: fmt.Sprintf("%s\n%s", "Enables public read access for Grafana on Argus instances.", - "When enabled, anyone can access the Grafana dashboards without of the instance logging in. Otherwise, a login is required.", + "When enabled, anyone can access the Grafana dashboards of the instance without logging in. Otherwise, a login is required.", ), Args: args.NoArgs, Example: examples.Build( @@ -60,7 +60,7 @@ func NewCmd(p *print.Printer) *cobra.Command { } if !model.AssumeYes { - prompt := fmt.Sprintf("Are you sure you want to enable public read access for instance %q?", instanceLabel) + prompt := fmt.Sprintf("Are you sure you want to enable Grafana public read access for instance %q?", instanceLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -74,10 +74,10 @@ func NewCmd(p *print.Printer) *cobra.Command { } _, err = req.Execute() if err != nil { - return fmt.Errorf("enable public read access: %w", err) + return fmt.Errorf("enable grafana public read access: %w", err) } - p.Info("Enabled public read access for instance %q\n", instanceLabel) + p.Info("Enabled Grafana public read access for instance %q\n", instanceLabel) return nil }, } diff --git a/internal/cmd/argus/grafana/public-read-access/public_read_access.go b/internal/cmd/argus/grafana/public-read-access/public_read_access.go index 03da90f1d..736a6e265 100644 --- a/internal/cmd/argus/grafana/public-read-access/public_read_access.go +++ b/internal/cmd/argus/grafana/public-read-access/public_read_access.go @@ -18,7 +18,7 @@ func NewCmd(p *print.Printer) *cobra.Command { Short: "Enable or disable public read access for Grafana in Argus instances", Long: fmt.Sprintf("%s\n%s", "Enable or disable public read access for Grafana in Argus instances.", - "When enabled, anyone can access the Grafana dashboards without of the instance logging in. Otherwise, a login is required.", + "When enabled, anyone can access the Grafana dashboards of the instance without logging in. Otherwise, a login is required.", ), Args: args.NoArgs, Run: utils.CmdHelp, diff --git a/internal/cmd/argus/grafana/single-sign-on/disable/disable.go b/internal/cmd/argus/grafana/single-sign-on/disable/disable.go index 090320e4c..1cc0a916e 100644 --- a/internal/cmd/argus/grafana/single-sign-on/disable/disable.go +++ b/internal/cmd/argus/grafana/single-sign-on/disable/disable.go @@ -60,7 +60,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 instance %q?", instanceLabel) + prompt := fmt.Sprintf("Are you sure you want to disable single sign-on for Grafana for instance %q?", instanceLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -74,10 +74,10 @@ func NewCmd(p *print.Printer) *cobra.Command { } _, err = req.Execute() if err != nil { - return fmt.Errorf("disable single sign-on: %w", err) + return fmt.Errorf("disable single sign-on for grafana: %w", err) } - p.Info("Disabled single sign-on for instance %q\n", instanceLabel) + p.Info("Disabled single sign-on for Grafana for instance %q\n", instanceLabel) return nil }, } diff --git a/internal/cmd/argus/grafana/single-sign-on/enable/enable.go b/internal/cmd/argus/grafana/single-sign-on/enable/enable.go index 711e68fb1..ec3bc153d 100644 --- a/internal/cmd/argus/grafana/single-sign-on/enable/enable.go +++ b/internal/cmd/argus/grafana/single-sign-on/enable/enable.go @@ -60,7 +60,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 instance %q?", instanceLabel) + prompt := fmt.Sprintf("Are you sure you want to enable single sign-on for Grafana for instance %q?", instanceLabel) err = p.PromptForConfirmation(prompt) if err != nil { return err @@ -74,10 +74,10 @@ func NewCmd(p *print.Printer) *cobra.Command { } _, err = req.Execute() if err != nil { - return fmt.Errorf("enable single sign-on: %w", err) + return fmt.Errorf("enable single sign-on for grafana: %w", err) } - p.Info("Enabled single sign-on for instance %q\n", instanceLabel) + p.Info("Enabled single sign-on for Grafana for instance %q\n", instanceLabel) return nil }, } From 3f939330a3625e30e820f2649f334970a87ef2d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Wed, 17 Apr 2024 15:20:53 +0100 Subject: [PATCH 5/6] Move instance ID to argument --- ...rgus_grafana_public-read-access_disable.md | 5 +-- ...argus_grafana_public-read-access_enable.md | 5 +-- ...it_argus_grafana_single-sign-on_disable.md | 5 +-- ...kit_argus_grafana_single-sign-on_enable.md | 5 +-- .../public-read-access/disable/disable.go | 21 +++------ .../disable/disable_test.go | 45 ++++++++++++++++--- .../public-read-access/enable/enable.go | 21 +++------ .../public-read-access/enable/enable_test.go | 45 ++++++++++++++++--- .../grafana/single-sign-on/disable/disable.go | 21 +++------ .../single-sign-on/disable/disable_test.go | 45 ++++++++++++++++--- .../grafana/single-sign-on/enable/enable.go | 21 +++------ .../single-sign-on/enable/enable_test.go | 45 ++++++++++++++++--- 12 files changed, 196 insertions(+), 88 deletions(-) diff --git a/docs/stackit_argus_grafana_public-read-access_disable.md b/docs/stackit_argus_grafana_public-read-access_disable.md index a15abe603..a3667d054 100644 --- a/docs/stackit_argus_grafana_public-read-access_disable.md +++ b/docs/stackit_argus_grafana_public-read-access_disable.md @@ -8,7 +8,7 @@ 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 [flags] +stackit argus grafana public-read-access disable INSTANCE_ID [flags] ``` ### Examples @@ -21,8 +21,7 @@ stackit argus grafana public-read-access disable [flags] ### Options ``` - -h, --help Help for "stackit argus grafana public-read-access disable" - --instance-id string Instance ID + -h, --help Help for "stackit argus grafana public-read-access disable" ``` ### Options inherited from parent commands diff --git a/docs/stackit_argus_grafana_public-read-access_enable.md b/docs/stackit_argus_grafana_public-read-access_enable.md index 8e098dfb6..10a9a95f3 100644 --- a/docs/stackit_argus_grafana_public-read-access_enable.md +++ b/docs/stackit_argus_grafana_public-read-access_enable.md @@ -8,7 +8,7 @@ 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 [flags] +stackit argus grafana public-read-access enable INSTANCE_ID [flags] ``` ### Examples @@ -21,8 +21,7 @@ stackit argus grafana public-read-access enable [flags] ### Options ``` - -h, --help Help for "stackit argus grafana public-read-access enable" - --instance-id string Instance ID + -h, --help Help for "stackit argus grafana public-read-access enable" ``` ### Options inherited from parent commands diff --git a/docs/stackit_argus_grafana_single-sign-on_disable.md b/docs/stackit_argus_grafana_single-sign-on_disable.md index 143273e20..86431a0e5 100644 --- a/docs/stackit_argus_grafana_single-sign-on_disable.md +++ b/docs/stackit_argus_grafana_single-sign-on_disable.md @@ -8,7 +8,7 @@ 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 [flags] +stackit argus grafana single-sign-on disable INSTANCE_ID [flags] ``` ### Examples @@ -21,8 +21,7 @@ stackit argus grafana single-sign-on disable [flags] ### Options ``` - -h, --help Help for "stackit argus grafana single-sign-on disable" - --instance-id string Instance ID + -h, --help Help for "stackit argus grafana single-sign-on disable" ``` ### Options inherited from parent commands diff --git a/docs/stackit_argus_grafana_single-sign-on_enable.md b/docs/stackit_argus_grafana_single-sign-on_enable.md index ad83abb99..3a8c6c14f 100644 --- a/docs/stackit_argus_grafana_single-sign-on_enable.md +++ b/docs/stackit_argus_grafana_single-sign-on_enable.md @@ -8,7 +8,7 @@ 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 [flags] +stackit argus grafana single-sign-on enable INSTANCE_ID [flags] ``` ### Examples @@ -21,8 +21,7 @@ stackit argus grafana single-sign-on enable [flags] ### Options ``` - -h, --help Help for "stackit argus grafana single-sign-on enable" - --instance-id string Instance ID + -h, --help Help for "stackit argus grafana single-sign-on enable" ``` ### Options inherited from parent commands diff --git a/internal/cmd/argus/grafana/public-read-access/disable/disable.go b/internal/cmd/argus/grafana/public-read-access/disable/disable.go index aff871f8d..a671412a1 100644 --- a/internal/cmd/argus/grafana/public-read-access/disable/disable.go +++ b/internal/cmd/argus/grafana/public-read-access/disable/disable.go @@ -7,7 +7,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/argus/client" @@ -19,7 +18,7 @@ import ( ) const ( - instanceIdFlag = "instance-id" + instanceIdArg = "INSTANCE_ID" ) type inputModel struct { @@ -29,13 +28,13 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "disable", + Use: fmt.Sprintf("disable %s", instanceIdArg), Short: "Disables public read access for Grafana on Argus instances", Long: fmt.Sprintf("%s\n%s", "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.", ), - Args: args.NoArgs, + Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( `Disable public read access for Grafana on an Argus instance with ID "xxx"`, @@ -43,7 +42,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(cmd) + model, err := parseInput(cmd, args) if err != nil { return err } @@ -81,18 +80,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return nil }, } - configureFlags(cmd) return cmd } -func configureFlags(cmd *cobra.Command) { - cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "Instance ID") +func parseInput(cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + instanceId := inputArgs[0] - err := flags.MarkFlagsRequired(cmd, instanceIdFlag) - cobra.CheckErr(err) -} - -func parseInput(cmd *cobra.Command) (*inputModel, error) { globalFlags := globalflags.Parse(cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} @@ -100,7 +93,7 @@ func parseInput(cmd *cobra.Command) (*inputModel, error) { return &inputModel{ GlobalFlagModel: globalFlags, - InstanceId: flags.FlagToStringValue(cmd, instanceIdFlag), + InstanceId: instanceId, }, nil } diff --git a/internal/cmd/argus/grafana/public-read-access/disable/disable_test.go b/internal/cmd/argus/grafana/public-read-access/disable/disable_test.go index 06c6a3148..9ef2296f9 100644 --- a/internal/cmd/argus/grafana/public-read-access/disable/disable_test.go +++ b/internal/cmd/argus/grafana/public-read-access/disable/disable_test.go @@ -44,10 +44,19 @@ func (c *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ str return c.getGrafanaConfigsResp, nil } +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{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + projectIdFlag: testProjectId, } for _, mod := range mods { mod(flagValues) @@ -117,23 +126,27 @@ func fixtureRequest(mods ...func(request *argus.ApiUpdateGrafanaConfigsRequest)) 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{}, + 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) }), @@ -141,6 +154,7 @@ func TestParseInput(t *testing.T) { }, { description: "project id invalid 1", + argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[projectIdFlag] = "" }), @@ -148,11 +162,24 @@ func TestParseInput(t *testing.T) { }, { description: "project id invalid 2", + argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[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 { @@ -173,6 +200,14 @@ func TestParseInput(t *testing.T) { } } + 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 { @@ -181,7 +216,7 @@ func TestParseInput(t *testing.T) { t.Fatalf("error validating flags: %v", err) } - model, err := parseInput(cmd) + model, err := parseInput(cmd, tt.argValues) if err != nil { if !tt.isValid { return diff --git a/internal/cmd/argus/grafana/public-read-access/enable/enable.go b/internal/cmd/argus/grafana/public-read-access/enable/enable.go index 489b92a27..9aa175c05 100644 --- a/internal/cmd/argus/grafana/public-read-access/enable/enable.go +++ b/internal/cmd/argus/grafana/public-read-access/enable/enable.go @@ -7,7 +7,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/argus/client" @@ -19,7 +18,7 @@ import ( ) const ( - instanceIdFlag = "instance-id" + instanceIdArg = "INSTANCE_ID" ) type inputModel struct { @@ -29,13 +28,13 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "enable", + Use: fmt.Sprintf("enable %s", instanceIdArg), Short: "Enables public read access for Grafana on Argus instances", Long: fmt.Sprintf("%s\n%s", "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.", ), - Args: args.NoArgs, + Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( `Enable public read access for Grafana on an Argus instance with ID "xxx"`, @@ -43,7 +42,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(cmd) + model, err := parseInput(cmd, args) if err != nil { return err } @@ -81,18 +80,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return nil }, } - configureFlags(cmd) return cmd } -func configureFlags(cmd *cobra.Command) { - cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "Instance ID") +func parseInput(cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + instanceId := inputArgs[0] - err := flags.MarkFlagsRequired(cmd, instanceIdFlag) - cobra.CheckErr(err) -} - -func parseInput(cmd *cobra.Command) (*inputModel, error) { globalFlags := globalflags.Parse(cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} @@ -100,7 +93,7 @@ func parseInput(cmd *cobra.Command) (*inputModel, error) { return &inputModel{ GlobalFlagModel: globalFlags, - InstanceId: flags.FlagToStringValue(cmd, instanceIdFlag), + InstanceId: instanceId, }, nil } diff --git a/internal/cmd/argus/grafana/public-read-access/enable/enable_test.go b/internal/cmd/argus/grafana/public-read-access/enable/enable_test.go index bdd7eb30e..1e0794bdd 100644 --- a/internal/cmd/argus/grafana/public-read-access/enable/enable_test.go +++ b/internal/cmd/argus/grafana/public-read-access/enable/enable_test.go @@ -44,10 +44,19 @@ func (c *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ str return c.getGrafanaConfigsResp, nil } +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{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + projectIdFlag: testProjectId, } for _, mod := range mods { mod(flagValues) @@ -117,23 +126,27 @@ func fixtureRequest(mods ...func(request *argus.ApiUpdateGrafanaConfigsRequest)) 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{}, + 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) }), @@ -141,6 +154,7 @@ func TestParseInput(t *testing.T) { }, { description: "project id invalid 1", + argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[projectIdFlag] = "" }), @@ -148,11 +162,24 @@ func TestParseInput(t *testing.T) { }, { description: "project id invalid 2", + argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[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 { @@ -173,6 +200,14 @@ func TestParseInput(t *testing.T) { } } + 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 { @@ -181,7 +216,7 @@ func TestParseInput(t *testing.T) { t.Fatalf("error validating flags: %v", err) } - model, err := parseInput(cmd) + model, err := parseInput(cmd, tt.argValues) if err != nil { if !tt.isValid { return diff --git a/internal/cmd/argus/grafana/single-sign-on/disable/disable.go b/internal/cmd/argus/grafana/single-sign-on/disable/disable.go index 1cc0a916e..67d52fd59 100644 --- a/internal/cmd/argus/grafana/single-sign-on/disable/disable.go +++ b/internal/cmd/argus/grafana/single-sign-on/disable/disable.go @@ -7,7 +7,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/argus/client" @@ -19,7 +18,7 @@ import ( ) const ( - instanceIdFlag = "instance-id" + instanceIdArg = "INSTANCE_ID" ) type inputModel struct { @@ -29,13 +28,13 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "disable", + Use: fmt.Sprintf("disable %s", instanceIdArg), Short: "Disables single sign-on for Grafana on Argus instances", Long: fmt.Sprintf("%s\n%s", "Disables single sign-on for Grafana on Argus instances.", "When disabled for an instance, the generic OAuth2 authentication is used for that instance.", ), - Args: args.NoArgs, + Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( `Disable single sign-on for Grafana on an Argus instance with ID "xxx"`, @@ -43,7 +42,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(cmd) + model, err := parseInput(cmd, args) if err != nil { return err } @@ -81,18 +80,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return nil }, } - configureFlags(cmd) return cmd } -func configureFlags(cmd *cobra.Command) { - cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "Instance ID") +func parseInput(cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + instanceId := inputArgs[0] - err := flags.MarkFlagsRequired(cmd, instanceIdFlag) - cobra.CheckErr(err) -} - -func parseInput(cmd *cobra.Command) (*inputModel, error) { globalFlags := globalflags.Parse(cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} @@ -100,7 +93,7 @@ func parseInput(cmd *cobra.Command) (*inputModel, error) { return &inputModel{ GlobalFlagModel: globalFlags, - InstanceId: flags.FlagToStringValue(cmd, instanceIdFlag), + InstanceId: instanceId, }, nil } diff --git a/internal/cmd/argus/grafana/single-sign-on/disable/disable_test.go b/internal/cmd/argus/grafana/single-sign-on/disable/disable_test.go index b654bbb32..32cdd0449 100644 --- a/internal/cmd/argus/grafana/single-sign-on/disable/disable_test.go +++ b/internal/cmd/argus/grafana/single-sign-on/disable/disable_test.go @@ -44,10 +44,19 @@ func (c *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ str return c.getGrafanaConfigsResp, nil } +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{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + projectIdFlag: testProjectId, } for _, mod := range mods { mod(flagValues) @@ -117,23 +126,27 @@ func fixtureRequest(mods ...func(request *argus.ApiUpdateGrafanaConfigsRequest)) 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{}, + 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) }), @@ -141,6 +154,7 @@ func TestParseInput(t *testing.T) { }, { description: "project id invalid 1", + argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[projectIdFlag] = "" }), @@ -148,11 +162,24 @@ func TestParseInput(t *testing.T) { }, { description: "project id invalid 2", + argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[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 { @@ -173,6 +200,14 @@ func TestParseInput(t *testing.T) { } } + 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 { @@ -181,7 +216,7 @@ func TestParseInput(t *testing.T) { t.Fatalf("error validating flags: %v", err) } - model, err := parseInput(cmd) + model, err := parseInput(cmd, tt.argValues) if err != nil { if !tt.isValid { return diff --git a/internal/cmd/argus/grafana/single-sign-on/enable/enable.go b/internal/cmd/argus/grafana/single-sign-on/enable/enable.go index ec3bc153d..b782d0dcf 100644 --- a/internal/cmd/argus/grafana/single-sign-on/enable/enable.go +++ b/internal/cmd/argus/grafana/single-sign-on/enable/enable.go @@ -7,7 +7,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/argus/client" @@ -19,7 +18,7 @@ import ( ) const ( - instanceIdFlag = "instance-id" + instanceIdArg = "INSTANCE_ID" ) type inputModel struct { @@ -29,13 +28,13 @@ type inputModel struct { func NewCmd(p *print.Printer) *cobra.Command { cmd := &cobra.Command{ - Use: "enable", + Use: fmt.Sprintf("enable %s", instanceIdArg), Short: "Enables single sign-on for Grafana on Argus instances", Long: fmt.Sprintf("%s\n%s", "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.", ), - Args: args.NoArgs, + Args: args.SingleArg(instanceIdArg, utils.ValidateUUID), Example: examples.Build( examples.NewExample( `Enable single sign-on for Grafana on an Argus instance with ID "xxx"`, @@ -43,7 +42,7 @@ func NewCmd(p *print.Printer) *cobra.Command { ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - model, err := parseInput(cmd) + model, err := parseInput(cmd, args) if err != nil { return err } @@ -81,18 +80,12 @@ func NewCmd(p *print.Printer) *cobra.Command { return nil }, } - configureFlags(cmd) return cmd } -func configureFlags(cmd *cobra.Command) { - cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "Instance ID") +func parseInput(cmd *cobra.Command, inputArgs []string) (*inputModel, error) { + instanceId := inputArgs[0] - err := flags.MarkFlagsRequired(cmd, instanceIdFlag) - cobra.CheckErr(err) -} - -func parseInput(cmd *cobra.Command) (*inputModel, error) { globalFlags := globalflags.Parse(cmd) if globalFlags.ProjectId == "" { return nil, &errors.ProjectIdError{} @@ -100,7 +93,7 @@ func parseInput(cmd *cobra.Command) (*inputModel, error) { return &inputModel{ GlobalFlagModel: globalFlags, - InstanceId: flags.FlagToStringValue(cmd, instanceIdFlag), + InstanceId: instanceId, }, nil } diff --git a/internal/cmd/argus/grafana/single-sign-on/enable/enable_test.go b/internal/cmd/argus/grafana/single-sign-on/enable/enable_test.go index 7544b81b4..c95378136 100644 --- a/internal/cmd/argus/grafana/single-sign-on/enable/enable_test.go +++ b/internal/cmd/argus/grafana/single-sign-on/enable/enable_test.go @@ -44,10 +44,19 @@ func (c *argusClientMocked) GetGrafanaConfigsExecute(_ context.Context, _, _ str return c.getGrafanaConfigsResp, nil } +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{ - projectIdFlag: testProjectId, - instanceIdFlag: testInstanceId, + projectIdFlag: testProjectId, } for _, mod := range mods { mod(flagValues) @@ -117,23 +126,27 @@ func fixtureRequest(mods ...func(request *argus.ApiUpdateGrafanaConfigsRequest)) 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{}, + 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) }), @@ -141,6 +154,7 @@ func TestParseInput(t *testing.T) { }, { description: "project id invalid 1", + argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[projectIdFlag] = "" }), @@ -148,11 +162,24 @@ func TestParseInput(t *testing.T) { }, { description: "project id invalid 2", + argValues: fixtureArgValues(), flagValues: fixtureFlagValues(func(flagValues map[string]string) { flagValues[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 { @@ -173,6 +200,14 @@ func TestParseInput(t *testing.T) { } } + 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 { @@ -181,7 +216,7 @@ func TestParseInput(t *testing.T) { t.Fatalf("error validating flags: %v", err) } - model, err := parseInput(cmd) + model, err := parseInput(cmd, tt.argValues) if err != nil { if !tt.isValid { return From e874ab9aee38aae2175f1c30dbc348188a9c1ead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Palet?= Date: Wed, 17 Apr 2024 15:27:49 +0100 Subject: [PATCH 6/6] Adapt examples --- docs/stackit_argus_grafana_public-read-access_disable.md | 2 +- docs/stackit_argus_grafana_public-read-access_enable.md | 2 +- docs/stackit_argus_grafana_single-sign-on_disable.md | 2 +- docs/stackit_argus_grafana_single-sign-on_enable.md | 2 +- .../cmd/argus/grafana/public-read-access/disable/disable.go | 2 +- internal/cmd/argus/grafana/public-read-access/enable/enable.go | 2 +- internal/cmd/argus/grafana/single-sign-on/disable/disable.go | 2 +- internal/cmd/argus/grafana/single-sign-on/enable/enable.go | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/stackit_argus_grafana_public-read-access_disable.md b/docs/stackit_argus_grafana_public-read-access_disable.md index a3667d054..9f1b821f3 100644 --- a/docs/stackit_argus_grafana_public-read-access_disable.md +++ b/docs/stackit_argus_grafana_public-read-access_disable.md @@ -15,7 +15,7 @@ stackit argus grafana public-read-access disable INSTANCE_ID [flags] ``` Disable public read access for Grafana on an Argus instance with ID "xxx" - $ stackit argus grafana public-read-access disable --instance-id xxx + $ stackit argus grafana public-read-access disable xxx ``` ### Options diff --git a/docs/stackit_argus_grafana_public-read-access_enable.md b/docs/stackit_argus_grafana_public-read-access_enable.md index 10a9a95f3..b66012713 100644 --- a/docs/stackit_argus_grafana_public-read-access_enable.md +++ b/docs/stackit_argus_grafana_public-read-access_enable.md @@ -15,7 +15,7 @@ stackit argus grafana public-read-access enable INSTANCE_ID [flags] ``` Enable public read access for Grafana on an Argus instance with ID "xxx" - $ stackit argus grafana public-read-access enable --instance-id xxx + $ stackit argus grafana public-read-access enable xxx ``` ### Options diff --git a/docs/stackit_argus_grafana_single-sign-on_disable.md b/docs/stackit_argus_grafana_single-sign-on_disable.md index 86431a0e5..0baf8e753 100644 --- a/docs/stackit_argus_grafana_single-sign-on_disable.md +++ b/docs/stackit_argus_grafana_single-sign-on_disable.md @@ -15,7 +15,7 @@ stackit argus grafana single-sign-on disable INSTANCE_ID [flags] ``` Disable single sign-on for Grafana on an Argus instance with ID "xxx" - $ stackit argus grafana single-sign-on disable --instance-id xxx + $ stackit argus grafana single-sign-on disable xxx ``` ### Options diff --git a/docs/stackit_argus_grafana_single-sign-on_enable.md b/docs/stackit_argus_grafana_single-sign-on_enable.md index 3a8c6c14f..34bb9c6a6 100644 --- a/docs/stackit_argus_grafana_single-sign-on_enable.md +++ b/docs/stackit_argus_grafana_single-sign-on_enable.md @@ -15,7 +15,7 @@ stackit argus grafana single-sign-on enable INSTANCE_ID [flags] ``` Enable single sign-on for Grafana on an Argus instance with ID "xxx" - $ stackit argus grafana single-sign-on enable --instance-id xxx + $ stackit argus grafana single-sign-on enable xxx ``` ### Options diff --git a/internal/cmd/argus/grafana/public-read-access/disable/disable.go b/internal/cmd/argus/grafana/public-read-access/disable/disable.go index a671412a1..e06157372 100644 --- a/internal/cmd/argus/grafana/public-read-access/disable/disable.go +++ b/internal/cmd/argus/grafana/public-read-access/disable/disable.go @@ -38,7 +38,7 @@ func NewCmd(p *print.Printer) *cobra.Command { 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 --instance-id xxx"), + "$ stackit argus grafana public-read-access disable xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/argus/grafana/public-read-access/enable/enable.go b/internal/cmd/argus/grafana/public-read-access/enable/enable.go index 9aa175c05..df0ccbd3b 100644 --- a/internal/cmd/argus/grafana/public-read-access/enable/enable.go +++ b/internal/cmd/argus/grafana/public-read-access/enable/enable.go @@ -38,7 +38,7 @@ func NewCmd(p *print.Printer) *cobra.Command { 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 --instance-id xxx"), + "$ stackit argus grafana public-read-access enable xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/argus/grafana/single-sign-on/disable/disable.go b/internal/cmd/argus/grafana/single-sign-on/disable/disable.go index 67d52fd59..1a69a516c 100644 --- a/internal/cmd/argus/grafana/single-sign-on/disable/disable.go +++ b/internal/cmd/argus/grafana/single-sign-on/disable/disable.go @@ -38,7 +38,7 @@ func NewCmd(p *print.Printer) *cobra.Command { 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 --instance-id xxx"), + "$ stackit argus grafana single-sign-on disable xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/internal/cmd/argus/grafana/single-sign-on/enable/enable.go b/internal/cmd/argus/grafana/single-sign-on/enable/enable.go index b782d0dcf..7c6c1179f 100644 --- a/internal/cmd/argus/grafana/single-sign-on/enable/enable.go +++ b/internal/cmd/argus/grafana/single-sign-on/enable/enable.go @@ -38,7 +38,7 @@ func NewCmd(p *print.Printer) *cobra.Command { 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 --instance-id xxx"), + "$ stackit argus grafana single-sign-on enable xxx"), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background()