From 5d3d8aa9f26de39c7aff74868c424adc5a0edb04 Mon Sep 17 00:00:00 2001 From: s-dwinter Date: Tue, 30 Apr 2024 13:07:27 +0900 Subject: [PATCH] Implement `ignore-not-found` option. --- internal/client/aws.go | 16 ++++++++++++---- internal/client/client.go | 5 +++-- internal/cmd/template.go | 4 +++- pkg/engine/engine.go | 2 +- pkg/engine/options.go | 10 +++++----- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/internal/client/aws.go b/internal/client/aws.go index f83cabc..5466bc8 100644 --- a/internal/client/aws.go +++ b/internal/client/aws.go @@ -22,7 +22,9 @@ import ( "fmt" kms "github.com/aws/aws-sdk-go-v2/service/secretsmanager" + kmsTypes "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" "github.com/aws/aws-sdk-go-v2/service/ssm" + ssmTypes "github.com/aws/aws-sdk-go-v2/service/ssm/types" "github.com/dwango/yashiro/pkg/config" ) @@ -46,7 +48,7 @@ func newAwsClient(cfg *config.AwsConfig) (Client, error) { }, nil } -func (c awsClient) GetValues(ctx context.Context, ignoreEmpty bool) (Values, error) { +func (c awsClient) GetValues(ctx context.Context, ignoreNotFound bool) (Values, error) { values := make(Values, len(c.parameterStoreValue)+len(c.secretsManagerValue)) for _, v := range c.parameterStoreValue { @@ -56,13 +58,14 @@ func (c awsClient) GetValues(ctx context.Context, ignoreEmpty bool) (Values, err }) if err != nil { + var notFoundErr *ssmTypes.ParameterNotFound + if ignoreNotFound && errors.As(err, ¬FoundErr) { + continue + } return nil, err } if err := values.SetValue(v, output.Parameter.Value); err != nil { - if ignoreEmpty && errors.Is(err, ErrValueIsEmpty) { - continue - } return nil, err } } @@ -71,7 +74,12 @@ func (c awsClient) GetValues(ctx context.Context, ignoreEmpty bool) (Values, err output, err := c.kmsClient.GetSecretValue(ctx, &kms.GetSecretValueInput{ SecretId: &v.Name, }) + if err != nil { + var notFoundErr *kmsTypes.ResourceNotFoundException + if ignoreNotFound && errors.As(err, ¬FoundErr) { + continue + } return nil, err } diff --git a/internal/client/client.go b/internal/client/client.go index 3a9c967..2a3d805 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -29,11 +29,12 @@ import ( var ( ErrNotfoundValueConfig = errors.New("not found value config") ErrValueIsEmpty = errors.New("value is empty") + ErrInvalidJSON = errors.New("invalid json string") ) // Client is the external stores client. type Client interface { - GetValues(ctx context.Context, ignoreEmpty bool) (Values, error) + GetValues(ctx context.Context, ignoreNotFound bool) (Values, error) } // New returns a new Client. @@ -63,7 +64,7 @@ func (v Values) SetValue(cfg config.Value, value *string) error { if cfg.GetIsJSON() { val = make(map[string]any) if err := json.Unmarshal([]byte(*value), &val); err != nil { - return fmt.Errorf("%w: invalid json string", err) + return fmt.Errorf("%w: %w", ErrInvalidJSON, err) } } else { val = *value diff --git a/internal/cmd/template.go b/internal/cmd/template.go index ba584ee..45ded00 100644 --- a/internal/cmd/template.go +++ b/internal/cmd/template.go @@ -38,6 +38,7 @@ const example = ` # specify single file. func newTemplateCommand() *cobra.Command { var configFile string + var ignoreNotFound bool cmd := cobra.Command{ Use: "template ", @@ -54,7 +55,7 @@ func newTemplateCommand() *cobra.Command { return err } - eng, err := engine.New(cfg) + eng, err := engine.New(cfg, engine.IgnoreNotFound(ignoreNotFound)) if err != nil { return err } @@ -70,6 +71,7 @@ func newTemplateCommand() *cobra.Command { f := cmd.Flags() f.StringVarP(&configFile, "config", "c", config.DefaultConfigFilename, "specify config file.") + f.BoolVar(&ignoreNotFound, "ignore-not-found", false, "ignore values are not found in the external store.") return &cmd } diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 20e2c2e..90341b0 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -56,7 +56,7 @@ func New(cfg *config.Config, option ...Option) (Engine, error) { } func (e engine) Render(ctx context.Context, text string, dest io.Writer) error { - values, err := e.client.GetValues(ctx, e.option.IgnoreEmpty) + values, err := e.client.GetValues(ctx, e.option.IgnoreNotFound) if err != nil { return err } diff --git a/pkg/engine/options.go b/pkg/engine/options.go index 9fc85e1..b0bad40 100644 --- a/pkg/engine/options.go +++ b/pkg/engine/options.go @@ -19,17 +19,17 @@ package engine // Option is configurable Engine behavior. type Option func(*opts) -// IgnoreEmpty ignores empty value from external store. -func IgnoreEmpty() Option { +// IgnoreNotFound ignores values are not found in the external store. +func IgnoreNotFound(b bool) Option { return func(o *opts) { - o.IgnoreEmpty = true + o.IgnoreNotFound = b } } type opts struct { - IgnoreEmpty bool + IgnoreNotFound bool } var defaultOpts = &opts{ - IgnoreEmpty: false, + IgnoreNotFound: false, }