diff --git a/archive.go b/archive.go index 5bd898e..0eedee5 100644 --- a/archive.go +++ b/archive.go @@ -15,20 +15,37 @@ import ( "github.com/fujiwara/lambroll/wildcard" ) +type ArchiveOption struct { + Src string `help:"function zip archive or src dir" default:"."` + Dest string `help:"destination file path" default:"archive.zip"` + + ExcludeFileOption +} + // Archive archives zip -func (app *App) Archive(ctx context.Context, opt DeployOption) error { - excludes, err := expandExcludeFile(opt.ExcludeFile) - if err != nil { - return fmt.Errorf("failed to parse exclude file: %w", err) +func (app *App) Archive(ctx context.Context, opt *ArchiveOption) error { + if err := opt.Expand(); err != nil { + return err } - opt.excludes = append(opt.excludes, excludes...) zipfile, _, err := createZipArchive(opt.Src, opt.excludes) if err != nil { return err } defer zipfile.Close() - _, err = io.Copy(os.Stdout, zipfile) + var w io.WriteCloser + if opt.Dest == "-" { + log.Printf("[info] writing zip archive to stdout") + w = os.Stdout + } else { + log.Printf("[info] writing zip archive to %s", opt.Dest) + w, err = os.Create(opt.Dest) + if err != nil { + return fmt.Errorf("failed to create %s: %w", opt.Dest, err) + } + defer w.Close() + } + _, err = io.Copy(w, zipfile) return err } @@ -132,7 +149,6 @@ func addToZip(z *zip.Writer, path, relpath string, info os.FileInfo) error { func (app *App) uploadFunctionToS3(ctx context.Context, f *os.File, bucket, key string) (string, error) { svc := s3.NewFromConfig(app.awsConfig) log.Printf("[debug] PutObjcet to s3://%s/%s", bucket, key) - // TODO multipart upload res, err := svc.PutObject(ctx, &s3.PutObjectInput{ Bucket: aws.String(bucket), Key: aws.String(key), diff --git a/cli.go b/cli.go index 0854963..47afa92 100644 --- a/cli.go +++ b/cli.go @@ -35,10 +35,9 @@ type CLIOptions struct { List *ListOption `cmd:"list" help:"list functions"` Rollback *RollbackOption `cmd:"rollback" help:"rollback function"` Invoke *InvokeOption `cmd:"invoke" help:"invoke function"` - Archive *DeployOption `cmd:"archive" help:"archive function"` + Archive *ArchiveOption `cmd:"archive" help:"archive function"` Logs *LogsOption `cmd:"logs" help:"show logs of function"` Diff *DiffOption `cmd:"diff" help:"show diff of function"` - Render *RenderOption `cmd:"render" help:"render function.json"` Versions *VersionsOption `cmd:"versions" help:"show versions of function"` Version struct{} `cmd:"version" help:"show version"` @@ -109,25 +108,23 @@ func dispatchCLI(ctx context.Context, sub string, usage func(), opts *CLIOptions } switch sub { case "init": - return app.Init(ctx, *opts.Init) + return app.Init(ctx, opts.Init) case "list": - return app.List(ctx, *opts.List) + return app.List(ctx, opts.List) case "deploy": - return app.Deploy(ctx, *opts.Deploy) + return app.Deploy(ctx, opts.Deploy) case "invoke": - return app.Invoke(ctx, *opts.Invoke) + return app.Invoke(ctx, opts.Invoke) case "logs": - return app.Logs(ctx, *opts.Logs) + return app.Logs(ctx, opts.Logs) case "versions": - return app.Versions(ctx, *opts.Versions) + return app.Versions(ctx, opts.Versions) case "archive": - return app.Archive(ctx, *opts.Archive) + return app.Archive(ctx, opts.Archive) case "rollback": - return app.Rollback(ctx, *opts.Rollback) - case "render": - return app.Render(ctx, *opts.Render) + return app.Rollback(ctx, opts.Rollback) case "diff": - return app.Diff(ctx, *opts.Diff) + return app.Diff(ctx, opts.Diff) default: usage() } diff --git a/create.go b/create.go index f38a8a4..8d6935c 100644 --- a/create.go +++ b/create.go @@ -33,7 +33,7 @@ func prepareZipfile(src string, excludes []string) (*os.File, os.FileInfo, error return nil, nil, fmt.Errorf("src %s is not found", src) } -func (app *App) prepareFunctionCodeForDeploy(ctx context.Context, opt DeployOption, fn *Function) error { +func (app *App) prepareFunctionCodeForDeploy(ctx context.Context, opt *DeployOption, fn *Function) error { if fn.PackageType == types.PackageTypeImage { if fn.Code == nil || fn.Code.ImageUri == nil { return fmt.Errorf("PackageType=Image requires Code.ImageUri in function definition") @@ -91,7 +91,7 @@ func (app *App) prepareFunctionCodeForDeploy(ctx context.Context, opt DeployOpti return nil } -func (app *App) create(ctx context.Context, opt DeployOption, fn *Function) error { +func (app *App) create(ctx context.Context, opt *DeployOption, fn *Function) error { err := app.prepareFunctionCodeForDeploy(ctx, opt, fn) if err != nil { return fmt.Errorf("failed to prepare function code: %w", err) diff --git a/deploy.go b/deploy.go index d4bc3c3..fa0d351 100644 --- a/deploy.go +++ b/deploy.go @@ -17,7 +17,6 @@ import ( // DeployOption represens an option for Deploy() type DeployOption struct { Src string `help:"function zip archive or src dir" default:"."` - ExcludeFile string `help:"exclude file" default:".lambdaignore"` Publish bool `help:"publish function" default:"true"` AliasName string `help:"alias name for publish" default:"current"` AliasToLatest bool `help:"set alias to unpublished $LATEST version" default:"false"` @@ -25,7 +24,7 @@ type DeployOption struct { SkipArchive bool `help:"skip to create zip archive. requires Code.S3Bucket and Code.S3Key in function definition" default:"false"` KeepVersions int `help:"Number of latest versions to keep. Older versions will be deleted. (Optional value: default 0)." default:"0"` - excludes []string + ExcludeFileOption } func (opt DeployOption) label() string { @@ -68,12 +67,10 @@ func (opt *DeployOption) String() string { } // Deploy deployes a new lambda function code -func (app *App) Deploy(ctx context.Context, opt DeployOption) error { - excludes, err := expandExcludeFile(opt.ExcludeFile) - if err != nil { - return fmt.Errorf("failed to parse exclude-file: %w", err) +func (app *App) Deploy(ctx context.Context, opt *DeployOption) error { + if err := opt.Expand(); err != nil { + return err } - opt.excludes = append(opt.excludes, excludes...) log.Printf("[debug] %s", opt.String()) fn, err := app.loadFunction(app.functionFilePath) diff --git a/diff.go b/diff.go index d489f59..c32343d 100644 --- a/diff.go +++ b/diff.go @@ -17,20 +17,17 @@ import ( // DiffOption represents options for Diff() type DiffOption struct { - Src string `help:"function zip archive or src dir" default:"."` - CodeSha256 bool `help:"diff of code sha256" default:"false"` - ExcludeFile string `help:"exclude file" default:".lambrollignore"` + Src string `help:"function zip archive or src dir" default:"."` + CodeSha256 bool `help:"diff of code sha256" default:"false"` - excludes []string + ExcludeFileOption } // Diff prints diff of function.json compared with latest function -func (app *App) Diff(ctx context.Context, opt DiffOption) error { - excludes, err := expandExcludeFile(opt.ExcludeFile) - if err != nil { - return fmt.Errorf("failed to parse exclude-file: %w", err) +func (app *App) Diff(ctx context.Context, opt *DiffOption) error { + if err := opt.Expand(); err != nil { + return err } - opt.excludes = append(opt.excludes, excludes...) newFunc, err := app.loadFunction(app.functionFilePath) if err != nil { diff --git a/init.go b/init.go index 27ce75b..1be0278 100644 --- a/init.go +++ b/init.go @@ -23,7 +23,7 @@ type InitOption struct { } // Init initializes function.json -func (app *App) Init(ctx context.Context, opt InitOption) error { +func (app *App) Init(ctx context.Context, opt *InitOption) error { res, err := app.lambda.GetFunction(ctx, &lambda.GetFunctionInput{ FunctionName: opt.FunctionName, }) diff --git a/invoke.go b/invoke.go index 655a120..cf5b8f9 100644 --- a/invoke.go +++ b/invoke.go @@ -24,7 +24,7 @@ type InvokeOption struct { } // Invoke invokes function -func (app *App) Invoke(ctx context.Context, opt InvokeOption) error { +func (app *App) Invoke(ctx context.Context, opt *InvokeOption) error { fn, err := app.loadFunction(app.functionFilePath) if err != nil { return fmt.Errorf("failed to load function: %w", err) diff --git a/list.go b/list.go index e7cb00c..7d943a6 100644 --- a/list.go +++ b/list.go @@ -15,7 +15,7 @@ type ListOption struct { } // List lists lambda functions -func (app *App) List(ctx context.Context, opt ListOption) error { +func (app *App) List(ctx context.Context, opt *ListOption) error { var marker *string for { res, err := app.lambda.ListFunctions(ctx, &lambda.ListFunctionsInput{ diff --git a/logs.go b/logs.go index 52a641a..f7e106d 100644 --- a/logs.go +++ b/logs.go @@ -17,7 +17,7 @@ type LogsOption struct { FilterPattern *string `help:"The filter pattern to use"` } -func (app *App) Logs(ctx context.Context, opt LogsOption) error { +func (app *App) Logs(ctx context.Context, opt *LogsOption) error { fn, err := app.loadFunction(app.functionFilePath) if err != nil { return fmt.Errorf("failed to load function: %w", err) diff --git a/option.go b/option.go index d05d7e3..5c14f27 100644 --- a/option.go +++ b/option.go @@ -1,3 +1,20 @@ package lambroll +import "fmt" + // Option represents common option. + +type ExcludeFileOption struct { + ExcludeFile string `help:"exclude file" default:".lambdaignore"` + + excludes []string +} + +func (opt *ExcludeFileOption) Expand() error { + excludes, err := expandExcludeFile(opt.ExcludeFile) + if err != nil { + return fmt.Errorf("failed to parse exclude-file: %w", err) + } + opt.excludes = append(opt.excludes, excludes...) + return nil +} diff --git a/rollback.go b/rollback.go index 94b2bcf..bd96aa0 100644 --- a/rollback.go +++ b/rollback.go @@ -27,7 +27,7 @@ func (opt RollbackOption) label() string { } // Rollback rollbacks function -func (app *App) Rollback(ctx context.Context, opt RollbackOption) error { +func (app *App) Rollback(ctx context.Context, opt *RollbackOption) error { fn, err := app.loadFunction(app.functionFilePath) if err != nil { return fmt.Errorf("failed to load function: %w", err) diff --git a/tags.go b/tags.go index cdb1010..d0b2633 100644 --- a/tags.go +++ b/tags.go @@ -11,7 +11,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/lambda/types" ) -func (app *App) updateTags(ctx context.Context, fn *Function, opt DeployOption) error { +func (app *App) updateTags(ctx context.Context, fn *Function, opt *DeployOption) error { if fn.Tags == nil { log.Println("[debug] Tags not defined in function.json skip updating tags") return nil diff --git a/versions.go b/versions.go index 3eacdec..faf02e0 100644 --- a/versions.go +++ b/versions.go @@ -72,7 +72,7 @@ func (v versionsOutput) TSV() string { } // Versions manages the versions of a Lambda function -func (app *App) Versions(ctx context.Context, opt VersionsOption) error { +func (app *App) Versions(ctx context.Context, opt *VersionsOption) error { newFunc, err := app.loadFunction(app.functionFilePath) if err != nil { return fmt.Errorf("failed to load function: %w", err)