From af20e9a633ccadc2e6bc732e87e6d5fea90493cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diogo=20Ferr=C3=A3o?= Date: Mon, 18 Mar 2024 10:49:52 +0000 Subject: [PATCH 1/3] Onboard Secrets Manager (ACLs): describe command --- .../instance/describe/describe.go | 34 +++++++++++--- .../instance/describe/describe_test.go | 44 +++++++++++++++++-- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/internal/cmd/secrets-manager/instance/describe/describe.go b/internal/cmd/secrets-manager/instance/describe/describe.go index de466a50c..286758c15 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe.go +++ b/internal/cmd/secrets-manager/instance/describe/describe.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -52,14 +53,21 @@ func NewCmd() *cobra.Command { return err } - // Call API - req := buildRequest(ctx, model, apiClient) - resp, err := req.Execute() + // Call API to get instance details + req := buildGetInstanceRequest(ctx, model, apiClient) + instance, err := req.Execute() if err != nil { return fmt.Errorf("read Secrets Manager instance: %w", err) } - return outputResult(cmd, model.OutputFormat, resp) + // Call API to get instance acls + listACLsReq := buildListACLsRequest(ctx, model, apiClient) + aclList, err := listACLsReq.Execute() + if err != nil { + return fmt.Errorf("read Secrets Manager instance ACLs: %w", err) + } + + return outputResult(cmd, model.OutputFormat, instance, aclList) }, } return cmd @@ -79,12 +87,17 @@ func parseInput(cmd *cobra.Command, inputArgs []string) (*inputModel, error) { }, nil } -func buildRequest(ctx context.Context, model *inputModel, apiClient *secretsmanager.APIClient) secretsmanager.ApiGetInstanceRequest { +func buildGetInstanceRequest(ctx context.Context, model *inputModel, apiClient *secretsmanager.APIClient) secretsmanager.ApiGetInstanceRequest { req := apiClient.GetInstance(ctx, model.ProjectId, model.InstanceId) return req } -func outputResult(cmd *cobra.Command, outputFormat string, instance *secretsmanager.Instance) error { +func buildListACLsRequest(ctx context.Context, model *inputModel, apiClient *secretsmanager.APIClient) secretsmanager.ApiListACLsRequest { + req := apiClient.ListACLs(ctx, model.ProjectId, model.InstanceId) + return req +} + +func outputResult(cmd *cobra.Command, outputFormat string, instance *secretsmanager.Instance, aclList *secretsmanager.AclList) error { switch outputFormat { case globalflags.PrettyOutputFormat: @@ -101,6 +114,15 @@ func outputResult(cmd *cobra.Command, outputFormat string, instance *secretsmana table.AddSeparator() table.AddRow("CREATION DATE", *instance.CreationStartDate) table.AddSeparator() + // Only show ACL if it's present and not empty + if aclList != nil && aclList.Acls != nil && len(*aclList.Acls) > 0 { + var res string + for _, acl := range *aclList.Acls { + res += *acl.Cidr + "," + } + res = strings.TrimSuffix(res, ",") + table.AddRow("ACL", res) + } err := table.Display(cmd) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/secrets-manager/instance/describe/describe_test.go b/internal/cmd/secrets-manager/instance/describe/describe_test.go index 0c03949fe..da65fa1cc 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe_test.go +++ b/internal/cmd/secrets-manager/instance/describe/describe_test.go @@ -54,7 +54,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { return model } -func fixtureRequest(mods ...func(request *secretsmanager.ApiGetInstanceRequest)) secretsmanager.ApiGetInstanceRequest { +func fixtureGetInstanceRequest(mods ...func(request *secretsmanager.ApiGetInstanceRequest)) secretsmanager.ApiGetInstanceRequest { request := testClient.GetInstance(testCtx, testProjectId, testInstanceId) for _, mod := range mods { mod(&request) @@ -62,6 +62,14 @@ func fixtureRequest(mods ...func(request *secretsmanager.ApiGetInstanceRequest)) return request } +func fixtureListACLsRequest(mods ...func(request *secretsmanager.ApiListACLsRequest)) secretsmanager.ApiListACLsRequest { + request := testClient.ListACLs(testCtx, testProjectId, testInstanceId) + for _, mod := range mods { + mod(&request) + } + return request +} + func TestParseInput(t *testing.T) { tests := []struct { description string @@ -186,7 +194,7 @@ func TestParseInput(t *testing.T) { } } -func TestBuildRequest(t *testing.T) { +func TestBuildGetInstanceRequest(t *testing.T) { tests := []struct { description string model *inputModel @@ -195,13 +203,41 @@ func TestBuildRequest(t *testing.T) { { description: "base", model: fixtureInputModel(), - expectedRequest: fixtureRequest(), + expectedRequest: fixtureGetInstanceRequest(), + }, + } + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + request := buildGetInstanceRequest(testCtx, tt.model, testClient) + + diff := cmp.Diff(request, tt.expectedRequest, + cmp.AllowUnexported(tt.expectedRequest), + cmpopts.EquateComparable(testCtx), + ) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + }) + } +} + +func TestBuildGetACLsRequest(t *testing.T) { + tests := []struct { + description string + model *inputModel + expectedRequest secretsmanager.ApiListACLsRequest + }{ + { + description: "base", + model: fixtureInputModel(), + expectedRequest: fixtureListACLsRequest(), }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - request := buildRequest(testCtx, tt.model, testClient) + request := buildListACLsRequest(testCtx, tt.model, testClient) diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), From f9e5abd7ff4d1eded5712336400cefc8dcaf890e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diogo=20Ferr=C3=A3o?= Date: Mon, 18 Mar 2024 14:15:25 +0000 Subject: [PATCH 2/3] update json output --- internal/cmd/secrets-manager/instance/describe/describe.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/cmd/secrets-manager/instance/describe/describe.go b/internal/cmd/secrets-manager/instance/describe/describe.go index 286758c15..4f50241be 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe.go +++ b/internal/cmd/secrets-manager/instance/describe/describe.go @@ -130,7 +130,12 @@ func outputResult(cmd *cobra.Command, outputFormat string, instance *secretsmana return nil default: - details, err := json.MarshalIndent(instance, "", " ") + output := struct { + *secretsmanager.Instance + *secretsmanager.AclList + }{instance, aclList} + + details, err := json.MarshalIndent(output, "", " ") if err != nil { return fmt.Errorf("marshal Secrets Manager instance: %w", err) } From e00f6e2ef3fb2bded8e69a3064281f9104793cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diogo=20Ferr=C3=A3o?= Date: Tue, 19 Mar 2024 22:34:32 +0000 Subject: [PATCH 3/3] improve code to print ACLs --- .../cmd/secrets-manager/instance/describe/describe.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/cmd/secrets-manager/instance/describe/describe.go b/internal/cmd/secrets-manager/instance/describe/describe.go index 4f50241be..559f42f73 100644 --- a/internal/cmd/secrets-manager/instance/describe/describe.go +++ b/internal/cmd/secrets-manager/instance/describe/describe.go @@ -116,12 +116,13 @@ func outputResult(cmd *cobra.Command, outputFormat string, instance *secretsmana table.AddSeparator() // Only show ACL if it's present and not empty if aclList != nil && aclList.Acls != nil && len(*aclList.Acls) > 0 { - var res string + var cidrs []string + for _, acl := range *aclList.Acls { - res += *acl.Cidr + "," + cidrs = append(cidrs, *acl.Cidr) } - res = strings.TrimSuffix(res, ",") - table.AddRow("ACL", res) + + table.AddRow("ACL", strings.Join(cidrs, ",")) } err := table.Display(cmd) if err != nil {