Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions internal/cli/commands/param/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import (

"github.com/urfave/cli/v3"

"github.com/mpyw/suve/internal/api/paramapi"
"github.com/mpyw/suve/internal/cli/output"
"github.com/mpyw/suve/internal/infra"
awsparam "github.com/mpyw/suve/internal/provider/aws/param"
"github.com/mpyw/suve/internal/usecase/param"
)

Expand Down Expand Up @@ -92,13 +91,13 @@ func action(ctx context.Context, cmd *cli.Command) error {
paramType = "SecureString"
}

client, err := infra.NewParamClient(ctx)
adapter, err := awsparam.NewAdapter(ctx)
if err != nil {
return fmt.Errorf("failed to initialize AWS client: %w", err)
}

r := &Runner{
UseCase: &param.CreateUseCase{Client: client},
UseCase: &param.CreateUseCase{Client: adapter},
Stdout: cmd.Root().Writer,
Stderr: cmd.Root().ErrWriter,
}
Expand All @@ -116,7 +115,7 @@ func (r *Runner) Run(ctx context.Context, opts Options) error {
result, err := r.UseCase.Execute(ctx, param.CreateInput{
Name: opts.Name,
Value: opts.Value,
Type: paramapi.ParameterType(opts.Type),
Type: opts.Type,
Description: opts.Description,
})
if err != nil {
Expand Down
57 changes: 29 additions & 28 deletions internal/cli/commands/param/create/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ package create_test
import (
"bytes"
"context"
"fmt"
"errors"
"testing"

"github.com/samber/lo"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/mpyw/suve/internal/api/paramapi"
appcli "github.com/mpyw/suve/internal/cli/commands"
"github.com/mpyw/suve/internal/cli/commands/param/create"
"github.com/mpyw/suve/internal/model"
"github.com/mpyw/suve/internal/usecase/param"
)

Expand Down Expand Up @@ -47,18 +46,16 @@ func TestCommand_Validation(t *testing.T) {
})
}

//nolint:lll // mock struct fields match AWS SDK interface signatures
type mockClient struct {
putParameterFunc func(ctx context.Context, params *paramapi.PutParameterInput, optFns ...func(*paramapi.Options)) (*paramapi.PutParameterOutput, error)
putParameterFunc func(ctx context.Context, p *model.Parameter, overwrite bool) (*model.ParameterWriteResult, error)
}

//nolint:lll // mock function signature must match AWS SDK interface
func (m *mockClient) PutParameter(ctx context.Context, params *paramapi.PutParameterInput, optFns ...func(*paramapi.Options)) (*paramapi.PutParameterOutput, error) {
func (m *mockClient) PutParameter(ctx context.Context, p *model.Parameter, overwrite bool) (*model.ParameterWriteResult, error) {
if m.putParameterFunc != nil {
return m.putParameterFunc(ctx, params, optFns...)
return m.putParameterFunc(ctx, p, overwrite)
}

return nil, fmt.Errorf("PutParameter not mocked")
return nil, errors.New("PutParameter not mocked")
}

func TestRun(t *testing.T) {
Expand All @@ -79,15 +76,19 @@ func TestRun(t *testing.T) {
Type: "SecureString",
},
mock: &mockClient{
//nolint:lll // inline mock function in test table
putParameterFunc: func(_ context.Context, params *paramapi.PutParameterInput, _ ...func(*paramapi.Options)) (*paramapi.PutParameterOutput, error) {
assert.Equal(t, "/app/param", lo.FromPtr(params.Name))
assert.Equal(t, "test-value", lo.FromPtr(params.Value))
assert.Equal(t, paramapi.ParameterTypeSecureString, params.Type)
assert.False(t, lo.FromPtr(params.Overwrite))

return &paramapi.PutParameterOutput{
Version: 1,
putParameterFunc: func(_ context.Context, p *model.Parameter, overwrite bool) (*model.ParameterWriteResult, error) {
assert.Equal(t, "/app/param", p.Name)
assert.Equal(t, "test-value", p.Value)

if meta := p.AWSMeta(); meta != nil {
assert.Equal(t, "SecureString", meta.Type)
}

assert.False(t, overwrite)

return &model.ParameterWriteResult{
Name: "/app/param",
Version: "1",
}, nil
},
},
Expand All @@ -107,13 +108,13 @@ func TestRun(t *testing.T) {
Description: "Test description",
},
mock: &mockClient{
//nolint:lll // inline mock function in test table
putParameterFunc: func(_ context.Context, params *paramapi.PutParameterInput, _ ...func(*paramapi.Options)) (*paramapi.PutParameterOutput, error) {
assert.Equal(t, "Test description", lo.FromPtr(params.Description))
assert.False(t, lo.FromPtr(params.Overwrite))
putParameterFunc: func(_ context.Context, p *model.Parameter, overwrite bool) (*model.ParameterWriteResult, error) {
assert.Equal(t, "Test description", p.Description)
assert.False(t, overwrite)

return &paramapi.PutParameterOutput{
Version: 1,
return &model.ParameterWriteResult{
Name: "/app/param",
Version: "1",
}, nil
},
},
Expand All @@ -123,8 +124,8 @@ func TestRun(t *testing.T) {
opts: create.Options{Name: "/app/param", Value: "test-value", Type: "String"},
wantErr: "failed to create parameter",
mock: &mockClient{
putParameterFunc: func(_ context.Context, _ *paramapi.PutParameterInput, _ ...func(*paramapi.Options)) (*paramapi.PutParameterOutput, error) {
return nil, &paramapi.ParameterAlreadyExists{Message: lo.ToPtr("already exists")}
putParameterFunc: func(_ context.Context, _ *model.Parameter, _ bool) (*model.ParameterWriteResult, error) {
return nil, errors.New("parameter already exists")
},
},
},
Expand All @@ -133,8 +134,8 @@ func TestRun(t *testing.T) {
opts: create.Options{Name: "/app/param", Value: "test-value", Type: "String"},
wantErr: "failed to create parameter",
mock: &mockClient{
putParameterFunc: func(_ context.Context, _ *paramapi.PutParameterInput, _ ...func(*paramapi.Options)) (*paramapi.PutParameterOutput, error) {
return nil, fmt.Errorf("AWS error")
putParameterFunc: func(_ context.Context, _ *model.Parameter, _ bool) (*model.ParameterWriteResult, error) {
return nil, errors.New("AWS error")
},
},
},
Expand Down
5 changes: 3 additions & 2 deletions internal/cli/commands/param/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/mpyw/suve/internal/cli/confirm"
"github.com/mpyw/suve/internal/cli/output"
"github.com/mpyw/suve/internal/infra"
awsparam "github.com/mpyw/suve/internal/provider/aws/param"
"github.com/mpyw/suve/internal/usecase/param"
)

Expand Down Expand Up @@ -61,7 +62,7 @@ func action(ctx context.Context, cmd *cli.Command) error {
name := cmd.Args().First()
skipConfirm := cmd.Bool("yes")

client, err := infra.NewParamClient(ctx)
adapter, err := awsparam.NewAdapter(ctx)
if err != nil {
return fmt.Errorf("failed to initialize AWS client: %w", err)
}
Expand All @@ -72,7 +73,7 @@ func action(ctx context.Context, cmd *cli.Command) error {
identity, _ = infra.GetAWSIdentity(ctx)
}

useCase := &param.DeleteUseCase{Client: client}
useCase := &param.DeleteUseCase{Client: adapter}

// Show current value before confirming
if !skipConfirm {
Expand Down
33 changes: 14 additions & 19 deletions internal/cli/commands/param/delete/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ package delete_test
import (
"bytes"
"context"
"fmt"
"errors"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/mpyw/suve/internal/api/paramapi"
appcli "github.com/mpyw/suve/internal/cli/commands"
"github.com/mpyw/suve/internal/cli/commands/param/delete"
"github.com/mpyw/suve/internal/model"
"github.com/mpyw/suve/internal/usecase/param"
)

Expand All @@ -28,28 +28,25 @@ func TestCommand_Validation(t *testing.T) {
})
}

//nolint:lll // mock struct fields match AWS SDK interface signatures
type mockClient struct {
deleteParameterFunc func(ctx context.Context, params *paramapi.DeleteParameterInput, optFns ...func(*paramapi.Options)) (*paramapi.DeleteParameterOutput, error)
getParameterFunc func(ctx context.Context, params *paramapi.GetParameterInput, optFns ...func(*paramapi.Options)) (*paramapi.GetParameterOutput, error)
deleteParameterFunc func(ctx context.Context, name string) error
getParameterFunc func(ctx context.Context, name string, version string) (*model.Parameter, error)
}

//nolint:lll // mock function signature must match AWS SDK interface
func (m *mockClient) DeleteParameter(ctx context.Context, params *paramapi.DeleteParameterInput, optFns ...func(*paramapi.Options)) (*paramapi.DeleteParameterOutput, error) {
func (m *mockClient) DeleteParameter(ctx context.Context, name string) error {
if m.deleteParameterFunc != nil {
return m.deleteParameterFunc(ctx, params, optFns...)
return m.deleteParameterFunc(ctx, name)
}

return nil, fmt.Errorf("DeleteParameter not mocked")
return errors.New("DeleteParameter not mocked")
}

//nolint:lll // mock function signature must match AWS SDK interface
func (m *mockClient) GetParameter(ctx context.Context, params *paramapi.GetParameterInput, optFns ...func(*paramapi.Options)) (*paramapi.GetParameterOutput, error) {
func (m *mockClient) GetParameter(ctx context.Context, name string, version string) (*model.Parameter, error) {
if m.getParameterFunc != nil {
return m.getParameterFunc(ctx, params, optFns...)
return m.getParameterFunc(ctx, name, version)
}

return nil, &paramapi.ParameterNotFound{}
return nil, errors.New("not found")
}

func TestRun(t *testing.T) {
Expand All @@ -65,9 +62,8 @@ func TestRun(t *testing.T) {
name: "delete parameter",
opts: delete.Options{Name: "/app/param"},
mock: &mockClient{
//nolint:lll // inline mock
deleteParameterFunc: func(_ context.Context, _ *paramapi.DeleteParameterInput, _ ...func(*paramapi.Options)) (*paramapi.DeleteParameterOutput, error) {
return &paramapi.DeleteParameterOutput{}, nil
deleteParameterFunc: func(_ context.Context, _ string) error {
return nil
},
},
check: func(t *testing.T, output string) {
Expand All @@ -80,9 +76,8 @@ func TestRun(t *testing.T) {
name: "error from AWS",
opts: delete.Options{Name: "/app/param"},
mock: &mockClient{
//nolint:lll // inline mock
deleteParameterFunc: func(_ context.Context, _ *paramapi.DeleteParameterInput, _ ...func(*paramapi.Options)) (*paramapi.DeleteParameterOutput, error) {
return nil, fmt.Errorf("AWS error")
deleteParameterFunc: func(_ context.Context, _ string) error {
return errors.New("AWS error")
},
},
wantErr: true,
Expand Down
29 changes: 5 additions & 24 deletions internal/cli/commands/param/update/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ import (
"io"
"os"

"github.com/samber/lo"
"github.com/urfave/cli/v3"

"github.com/mpyw/suve/internal/api/paramapi"
"github.com/mpyw/suve/internal/cli/confirm"
"github.com/mpyw/suve/internal/cli/output"
"github.com/mpyw/suve/internal/infra"
awsparam "github.com/mpyw/suve/internal/provider/aws/param"
"github.com/mpyw/suve/internal/usecase/param"
)

Expand Down Expand Up @@ -100,17 +99,17 @@ func action(ctx context.Context, cmd *cli.Command) error {
name := cmd.Args().Get(0)
skipConfirm := cmd.Bool("yes")

client, err := infra.NewParamClient(ctx)
adapter, err := awsparam.NewAdapter(ctx)
if err != nil {
return fmt.Errorf("failed to initialize AWS client: %w", err)
}

uc := &param.UpdateUseCase{Client: client}
uc := &param.UpdateUseCase{Client: adapter}
newValue := cmd.Args().Get(1)

// Fetch current value and show diff before confirming
if !skipConfirm {
currentValue, _ := getCurrentValue(ctx, client, name)
currentValue, _ := uc.GetCurrentValue(ctx, name)
if currentValue != "" {
diff := output.Diff(name+" (AWS)", name+" (new)", currentValue, newValue)
if diff != "" {
Expand Down Expand Up @@ -159,7 +158,7 @@ func (r *Runner) Run(ctx context.Context, opts Options) error {
result, err := r.UseCase.Execute(ctx, param.UpdateInput{
Name: opts.Name,
Value: opts.Value,
Type: paramapi.ParameterType(opts.Type),
Type: opts.Type,
Description: opts.Description,
})
if err != nil {
Expand All @@ -170,21 +169,3 @@ func (r *Runner) Run(ctx context.Context, opts Options) error {

return nil
}

// getCurrentValue fetches the current parameter value.
// Returns the value if exists, empty string if not found.
func getCurrentValue(ctx context.Context, client paramapi.GetParameterAPI, name string) (string, bool) {
result, err := client.GetParameter(ctx, &paramapi.GetParameterInput{
Name: lo.ToPtr(name),
WithDecryption: lo.ToPtr(true),
})
if err != nil {
return "", false
}

if result.Parameter == nil || result.Parameter.Value == nil {
return "", false
}

return *result.Parameter.Value, true
}
Loading
Loading