From 882767f9203bfc94b36c57a19e5f0731b0d20e7c Mon Sep 17 00:00:00 2001 From: yutachaos <18604471+yutachaos@users.noreply.github.com> Date: Thu, 26 Nov 2020 16:32:20 +0900 Subject: [PATCH] Added version stage option --- .golangci.yaml | 4 +- Makefile | 4 +- README.md | 2 + cmd/secret-plan/main.go | 17 +++++--- internal/secret/aws.go | 75 ++++++++++++++++------------------ internal/secret/aws_test.go | 80 +++++++------------------------------ internal/secret/secret.go | 10 +++-- 7 files changed, 75 insertions(+), 117 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index edcee0f..b0a549d 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -13,4 +13,6 @@ linters: - testpackage - lll - errorlint - - gosimple \ No newline at end of file + - gosimple + - gci + - golint \ No newline at end of file diff --git a/Makefile b/Makefile index 5706cea..0f4465f 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,16 @@ -.PHONY: test +.PHONY: build build: go build -o secret-plan ./cmd/secret-plan/main.go +.PHONY: test test: go test -v ./... .PHONY: fmt fmt: go fmt ./... + gofumpt -w -s ./.. .PHONY: lint lint: diff --git a/README.md b/README.md index 7d0de0b..76c9de2 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ For secret value diff and save tool.(e.g aws secretsmanager) - Value to be registered in Secret - --version-id - Specify the version-id to be acquired (optional). +- --version-stage + - Whether to specify version-stage(AWS only) - --dry-run - If your want to use diff only. - --is-file diff --git a/cmd/secret-plan/main.go b/cmd/secret-plan/main.go index 1642b44..f6f1a36 100644 --- a/cmd/secret-plan/main.go +++ b/cmd/secret-plan/main.go @@ -46,6 +46,11 @@ func NewApp() *cli.App { Usage: "Whether to specify version-id", Required: false, }, + &cli.StringFlag{ + Name: "version-stage", + Usage: "Whether to specify version-stage(AWS only)", + Required: false, + }, &cli.BoolFlag{ Name: "dry-run", Usage: "dry run", @@ -86,9 +91,9 @@ func Run(ctx *cli.Context) (err error) { versionID := ctx.String("version-id") - sec := secret.NewSecret() + sec := secret.NewSecret(ctx) - currentSecret, secretExist, err := sec.Get(secretName, versionID) + currentSecret, err := sec.Get(secretName, versionID) if err != nil { return err } @@ -106,14 +111,14 @@ func Run(ctx *cli.Context) (err error) { } if approve() { - err := sec.Save(secretName, secretValue, secretExist) + err := sec.Save(secretName, secretValue) if err != nil { return err } + } else { + fmt.Println("No Updated.") } - fmt.Println("No Updated.") - return nil } @@ -143,6 +148,8 @@ func approve() bool { for scanner.Scan() { if scanner.Text() != "yes" { return false + } else { + break } } diff --git a/internal/secret/aws.go b/internal/secret/aws.go index 3bc5da5..871c653 100644 --- a/internal/secret/aws.go +++ b/internal/secret/aws.go @@ -3,16 +3,19 @@ package secret import ( "fmt" + "github.com/urfave/cli/v2" + "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/secretsmanager" "github.com/aws/aws-sdk-go/service/secretsmanager/secretsmanageriface" ) type aws struct { - client secretsmanageriface.SecretsManagerAPI + client secretsmanageriface.SecretsManagerAPI + versionStage string } -func newAws() *aws { +func newAws(ctx *cli.Context) *aws { opts := session.Options{ SharedConfigState: session.SharedConfigEnable, } @@ -23,13 +26,15 @@ func newAws() *aws { } client := secretsmanager.New(sess) + versionStage := ctx.String("version-stage") return &aws{ - client: client, + client: client, + versionStage: versionStage, } } -func (a *aws) Get(name string, versionID string) (currentSecret string, secretExist bool, err error) { +func (a *aws) Get(name string, versionID string) (currentSecret string, err error) { input := secretsmanager.GetSecretValueInput{ SecretId: &name, } @@ -37,60 +42,48 @@ func (a *aws) Get(name string, versionID string) (currentSecret string, secretEx input.VersionId = &versionID } + if a.versionStage != "" { + input.VersionStage = &a.versionStage + } + _, err = a.client.DescribeSecret(&secretsmanager.DescribeSecretInput{ SecretId: &name, }) - secretExist = true + if err != nil { + return "", err + } + var currentSecretValue string + + secretValueOutput, err := a.client.GetSecretValue(&input) if err != nil { switch err.(type) { case *secretsmanager.ResourceNotFoundException: - secretExist = false - break default: - return "", secretExist, err - } - } - - var currentSecretValue string - - if secretExist { - secretValueOutput, err := a.client.GetSecretValue(&input) - if err != nil { - switch err.(type) { - case *secretsmanager.ResourceNotFoundException: - break - default: - return "", secretExist, err - } - } else { - currentSecretValue = *secretValueOutput.SecretString + return "", err } + } else { + currentSecretValue = *secretValueOutput.SecretString } - return currentSecretValue, secretExist, nil + return currentSecretValue, nil } -func (a *aws) Save(name string, content string, secretExist bool) (err error) { - if secretExist { - output, err := a.client.PutSecretValue(&secretsmanager.PutSecretValueInput{SecretId: &name, SecretString: &content}) - if err != nil { - return err - } - - versionID := *output.VersionId - fmt.Printf("Update. Version: %s \n", versionID) - } else { - output, err := a.client.CreateSecret(&secretsmanager.CreateSecretInput{Name: &name, SecretString: &content}) - if err != nil { - return err - } +func (a *aws) Save(name string, content string) (err error) { + input := secretsmanager.PutSecretValueInput{SecretId: &name, SecretString: &content} + if a.versionStage != "" { + input.VersionStages = []*string{&a.versionStage} + } - versionID := *output.VersionId - fmt.Printf("Create. Version: %s \n", versionID) + output, err := a.client.PutSecretValue(&input) + if err != nil { + return err } + versionID := *output.VersionId + fmt.Printf("Update. Version: %s \n", versionID) + return nil } diff --git a/internal/secret/aws_test.go b/internal/secret/aws_test.go index 609f8b1..fd782d2 100644 --- a/internal/secret/aws_test.go +++ b/internal/secret/aws_test.go @@ -12,10 +12,9 @@ import ( type fakeAws struct { secretsmanageriface.SecretsManagerAPI - fakeDescribeSecret func(*secretsmanager.DescribeSecretOutput, error) (*secretsmanager.DescribeSecretOutput, error) - fakeGetSecretValue func(*secretsmanager.GetSecretValueOutput, error) (*secretsmanager.GetSecretValueOutput, error) - fakePutSecretValue func(*secretsmanager.PutSecretValueOutput, error) (*secretsmanager.PutSecretValueOutput, error) - fakeGetCreateSecret func(*secretsmanager.CreateSecretOutput, error) (*secretsmanager.CreateSecretOutput, error) + fakeDescribeSecret func(*secretsmanager.DescribeSecretOutput, error) (*secretsmanager.DescribeSecretOutput, error) + fakeGetSecretValue func(*secretsmanager.GetSecretValueOutput, error) (*secretsmanager.GetSecretValueOutput, error) + fakePutSecretValue func(*secretsmanager.PutSecretValueOutput, error) (*secretsmanager.PutSecretValueOutput, error) } type describeSecretOutput struct { @@ -33,11 +32,6 @@ type putSecretValueOutput struct { err error } -type createSecretOutput struct { - output *secretsmanager.CreateSecretOutput - err error -} - func (f fakeAws) DescribeSecret(*secretsmanager.DescribeSecretInput) (output *secretsmanager.DescribeSecretOutput, err error) { return f.fakeDescribeSecret(output, err) } @@ -50,10 +44,6 @@ func (f fakeAws) PutSecretValue(*secretsmanager.PutSecretValueInput) (output *se return f.fakePutSecretValue(output, err) } -func (f fakeAws) CreateSecret(*secretsmanager.CreateSecretInput) (output *secretsmanager.CreateSecretOutput, err error) { - return f.fakeGetCreateSecret(output, err) -} - func TestGet(t *testing.T) { t.Parallel() @@ -62,7 +52,6 @@ func TestGet(t *testing.T) { versionID string mockDescribeSecret describeSecretOutput mockGetSecretValue getSecretValueOutput - secretExist bool err error currentSecret string }{ @@ -77,7 +66,6 @@ func TestGet(t *testing.T) { output: &secretsmanager.GetSecretValueOutput{SecretString: toStrPtr("name2")}, err: nil, }, - secretExist: true, err: nil, currentSecret: "name2", }, @@ -92,8 +80,7 @@ func TestGet(t *testing.T) { output: &secretsmanager.GetSecretValueOutput{SecretString: toStrPtr("")}, err: nil, }, - secretExist: false, - err: nil, + err: &secretsmanager.ResourceNotFoundException{}, currentSecret: "", }, { @@ -107,7 +94,6 @@ func TestGet(t *testing.T) { output: &secretsmanager.GetSecretValueOutput{SecretString: toStrPtr("")}, err: &secretsmanager.ResourceNotFoundException{}, }, - secretExist: true, err: nil, currentSecret: "", }, @@ -127,9 +113,8 @@ func TestGet(t *testing.T) { }, }, } - currentSecret, secretExist, err := mockAws.Get(test.secretName, test.versionID) + currentSecret, err := mockAws.Get(test.secretName, test.versionID) - assert.Equal(t, test.secretExist, secretExist) assert.Equal(t, test.err, err) assert.Equal(t, test.currentSecret, currentSecret) }) @@ -142,67 +127,35 @@ func TestSave(t *testing.T) { tests := []struct { secretName string secretValue string - secretExist bool mockPutSecretValue putSecretValueOutput - mockCreateSecret createSecretOutput err error stdout string }{ { - secretName: "name1", - secretExist: true, - mockPutSecretValue: putSecretValueOutput{ - output: &secretsmanager.PutSecretValueOutput{VersionId: toStrPtr("updated versionID1")}, - err: nil, - }, - mockCreateSecret: createSecretOutput{ - output: &secretsmanager.CreateSecretOutput{}, - err: nil, - }, - err: nil, - stdout: "Update. Version: updated versionID1 \n", - }, - { - secretName: "name2", - secretExist: true, + secretName: "name1", mockPutSecretValue: putSecretValueOutput{ - output: &secretsmanager.PutSecretValueOutput{VersionId: toStrPtr("updated versionID2")}, - err: nil, - }, - mockCreateSecret: createSecretOutput{ - output: &secretsmanager.CreateSecretOutput{}, + output: &secretsmanager.PutSecretValueOutput{VersionId: toStrPtr("versionID1")}, err: nil, }, err: nil, - stdout: "Update. Version: updated versionID2 \n", + stdout: "Update. Version: versionID1 \n", }, { - secretName: "name3", - secretExist: false, + secretName: "name2", mockPutSecretValue: putSecretValueOutput{ - output: &secretsmanager.PutSecretValueOutput{}, + output: &secretsmanager.PutSecretValueOutput{VersionId: toStrPtr("versionID2")}, err: nil, }, - mockCreateSecret: createSecretOutput{ - output: &secretsmanager.CreateSecretOutput{VersionId: toStrPtr("updated versionID3")}, - err: nil, - }, - stdout: "Create. Version: updated versionID3 \n", err: nil, + stdout: "Update. Version: versionID2 \n", }, { - secretName: "name3", - secretExist: false, + secretName: "name3", mockPutSecretValue: putSecretValueOutput{ - output: &secretsmanager.PutSecretValueOutput{}, - err: nil, - }, - mockCreateSecret: createSecretOutput{ - output: &secretsmanager.CreateSecretOutput{VersionId: toStrPtr("updated versionID3")}, + output: &secretsmanager.PutSecretValueOutput{VersionId: toStrPtr("versionID3")}, err: &secretsmanager.InvalidRequestException{}, }, - stdout: "", - err: &secretsmanager.InvalidRequestException{}, + err: &secretsmanager.InvalidRequestException{}, }, } @@ -215,14 +168,11 @@ func TestSave(t *testing.T) { fakePutSecretValue: func(*secretsmanager.PutSecretValueOutput, error) (*secretsmanager.PutSecretValueOutput, error) { return test.mockPutSecretValue.output, test.mockPutSecretValue.err }, - fakeGetCreateSecret: func(*secretsmanager.CreateSecretOutput, error) (*secretsmanager.CreateSecretOutput, error) { - return test.mockCreateSecret.output, test.mockCreateSecret.err - }, }, } var err error stdout := capture.Stdout(func() { - err = mockAws.Save(test.secretName, test.secretValue, test.secretExist) + err = mockAws.Save(test.secretName, test.secretValue) }) assert.Equal(t, test.err, err) assert.Equal(t, test.stdout, stdout.String()) diff --git a/internal/secret/secret.go b/internal/secret/secret.go index 6f025c8..32619ae 100644 --- a/internal/secret/secret.go +++ b/internal/secret/secret.go @@ -1,12 +1,14 @@ package secret +import "github.com/urfave/cli/v2" + type Secret interface { - Get(name string, versionID string) (currentSecret string, secretExist bool, err error) - Save(name string, content string, secretExist bool) (err error) + Get(name string, versionID string) (currentSecret string, err error) + Save(name string, content string) (err error) } -func NewSecret() Secret { - secret := newAws() +func NewSecret(ctx *cli.Context) Secret { + secret := newAws(ctx) return secret }