diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 83babef..427c122 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -5,8 +5,8 @@ jobs: strategy: matrix: go: - - "1.19" - "1.20" + - "1.21" name: Build runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e606f8..67d7ac4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,9 +12,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: - go-version: "1.20" + go-version: "1.21" check-latest: true - name: Check out code into the Go module directory diff --git a/archive.go b/archive.go index dcfa450..7baa0e9 100644 --- a/archive.go +++ b/archive.go @@ -2,24 +2,24 @@ package lambroll import ( "archive/zip" + "context" + "fmt" "io" - "io/ioutil" "log" "os" "path/filepath" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/s3" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/fujiwara/lambroll/wildcard" - "github.com/pkg/errors" ) // Archive archives zip -func (app *App) Archive(opt DeployOption) error { +func (app *App) Archive(ctx context.Context, opt DeployOption) error { excludes, err := expandExcludeFile(*opt.ExcludeFile) if err != nil { - return errors.Wrap(err, "failed to parse exclude file") + return fmt.Errorf("failed to parse exclude file: %w", err) } opt.Excludes = append(opt.Excludes, excludes...) @@ -36,7 +36,7 @@ func loadZipArchive(src string) (*os.File, os.FileInfo, error) { log.Printf("[info] reading zip archive from %s", src) r, err := zip.OpenReader(src) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to open zip file %s", src) + return nil, nil, fmt.Errorf("failed to open zip file %s: %w", src, err) } for _, f := range r.File { header := f.FileHeader @@ -50,7 +50,7 @@ func loadZipArchive(src string) (*os.File, os.FileInfo, error) { r.Close() info, err := os.Stat(src) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to stat %s", src) + return nil, nil, fmt.Errorf("failed to stat %s: %w", src, err) } log.Printf("[info] zip archive %d bytes", info.Size()) fh, err := os.Open(src) @@ -60,9 +60,9 @@ func loadZipArchive(src string) (*os.File, os.FileInfo, error) { // createZipArchive creates a zip archive func createZipArchive(src string, excludes []string) (*os.File, os.FileInfo, error) { log.Printf("[info] creating zip archive from %s", src) - tmpfile, err := ioutil.TempFile("", "archive") + tmpfile, err := os.CreateTemp("", "archive") if err != nil { - return nil, nil, errors.Wrap(err, "failed to open tempFile") + return nil, nil, fmt.Errorf("failed to open tempFile: %w", err) } w := zip.NewWriter(tmpfile) err = filepath.Walk(src, func(path string, info os.FileInfo, err error) error { @@ -83,7 +83,7 @@ func createZipArchive(src string, excludes []string) (*os.File, os.FileInfo, err return addToZip(w, path, relpath, info) }) if err := w.Close(); err != nil { - return nil, nil, errors.Wrap(err, "failed to create zip archive") + return nil, nil, fmt.Errorf("failed to create zip archive: %w", err) } tmpfile.Seek(0, os.SEEK_SET) stat, _ := tmpfile.Stat() @@ -129,11 +129,11 @@ func addToZip(z *zip.Writer, path, relpath string, info os.FileInfo) error { return err } -func (app *App) uploadFunctionToS3(f *os.File, bucket, key string) (string, error) { - svc := s3.New(app.sess) +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(&s3.PutObjectInput{ + res, err := svc.PutObject(ctx, &s3.PutObjectInput{ Bucket: aws.String(bucket), Key: aws.String(key), Body: f, diff --git a/cmd/lambroll/main.go b/cmd/lambroll/main.go index 333ddf1..cb25724 100644 --- a/cmd/lambroll/main.go +++ b/cmd/lambroll/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "log" "os" @@ -134,34 +135,35 @@ func _main() int { } log.SetOutput(filter) - app, err := lambroll.New(&opt) + app, err := lambroll.New(context.TODO(), &opt) if err != nil { log.Println("[error]", err) return 1 } + ctx := context.TODO() log.Printf("[info] lambroll %s with %s", Version, *function) switch command { case "init": - err = app.Init(initOption) + err = app.Init(ctx, initOption) case "list": - err = app.List(listOption) + err = app.List(ctx, listOption) case "deploy": - err = app.Deploy(deployOption) + err = app.Deploy(ctx, deployOption) case "rollback": - err = app.Rollback(rollbackOption) + err = app.Rollback(ctx, rollbackOption) case "delete": - err = app.Delete(deleteOption) + err = app.Delete(ctx, deleteOption) case "invoke": - err = app.Invoke(invokeOption) + err = app.Invoke(ctx, invokeOption) case "archive": - err = app.Archive(archiveOption) + err = app.Archive(ctx, archiveOption) case "logs": - err = app.Logs(logsOption) + err = app.Logs(ctx, logsOption) case "diff": - err = app.Diff(diffOption) + err = app.Diff(ctx, diffOption) case "versions": - err = app.Versions(versionsOption) + err = app.Versions(ctx, versionsOption) } if err != nil { diff --git a/create.go b/create.go index bc448ef..6b9f98b 100644 --- a/create.go +++ b/create.go @@ -3,20 +3,20 @@ package lambroll import ( "context" "fmt" - "io/ioutil" + "io" "log" "os" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/lambda" - "github.com/pkg/errors" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/aws/aws-sdk-go-v2/service/lambda/types" ) var directUploadThreshold = int64(50 * 1024 * 1024) // 50MB func prepareZipfile(src string, excludes []string) (*os.File, os.FileInfo, error) { if fi, err := os.Stat(src); err != nil { - return nil, nil, errors.Wrapf(err, "src %s is not found", src) + return nil, nil, fmt.Errorf("src %s is not found: %w", src, err) } else if fi.IsDir() { zipfile, info, err := createZipArchive(src, excludes) if err != nil { @@ -33,23 +33,23 @@ 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(opt DeployOption, fn *Function) error { - if aws.StringValue(fn.PackageType) == packageTypeImage { +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 errors.New("PackageType=Image requires Code.ImageUri in function definition") + return fmt.Errorf("PackageType=Image requires Code.ImageUri in function definition") } // deploy docker image. no need to preprare log.Printf("[info] using docker image %s", *fn.Code.ImageUri) if fn.ImageConfig == nil { - fn.ImageConfig = &lambda.ImageConfig{} // reset explicitly + fn.ImageConfig = &types.ImageConfig{} // reset explicitly } return nil } if opt.SkipArchive != nil && *opt.SkipArchive { if fn.Code == nil || fn.Code.S3Bucket == nil || fn.Code.S3Key == nil { - return errors.New("--skip-archive requires Code.S3Bucket and Code.S3key elements in function definition") + return fmt.Errorf("--skip-archive requires Code.S3Bucket and Code.S3key elements in function definition") } return nil } @@ -63,9 +63,9 @@ func (app *App) prepareFunctionCodeForDeploy(opt DeployOption, fn *Function) err if fn.Code != nil { if bucket, key := fn.Code.S3Bucket, fn.Code.S3Key; bucket != nil && key != nil { log.Printf("[info] uploading function %d bytes to s3://%s/%s", info.Size(), *bucket, *key) - versionID, err := app.uploadFunctionToS3(zipfile, *bucket, *key) + versionID, err := app.uploadFunctionToS3(ctx, zipfile, *bucket, *key) if err != nil { - errors.Wrapf(err, "failed to upload function zip to s3://%s/%s", *bucket, *key) + fmt.Errorf("failed to upload function zip to s3://%s/%s: %w", *bucket, *key, err) } if versionID != "" { log.Printf("[info] object created as version %s", versionID) @@ -75,37 +75,35 @@ func (app *App) prepareFunctionCodeForDeploy(opt DeployOption, fn *Function) err fn.Code.S3ObjectVersion = nil } } else { - return errors.New("Code.S3Bucket or Code.S3Key are not defined") + return fmt.Errorf("Code.S3Bucket or Code.S3Key are not defined") } } else { // try direct upload if s := info.Size(); s > directUploadThreshold { return fmt.Errorf("cannot use a zip file for update function directly. Too large file %d bytes. Please define Code.S3Bucket and Code.S3Key in function.json", s) } - b, err := ioutil.ReadAll(zipfile) + b, err := io.ReadAll(zipfile) if err != nil { - return errors.Wrap(err, "failed to read zipfile content") + return fmt.Errorf("failed to read zipfile content: %w", err) } - fn.Code = &lambda.FunctionCode{ZipFile: b} + fn.Code = &types.FunctionCode{ZipFile: b} } return nil } -func (app *App) create(opt DeployOption, fn *Function) error { - ctx := context.Background() - err := app.prepareFunctionCodeForDeploy(opt, fn) +func (app *App) create(ctx context.Context, opt DeployOption, fn *Function) error { + err := app.prepareFunctionCodeForDeploy(ctx, opt, fn) if err != nil { - return errors.Wrap(err, "failed to prepare function code") + return fmt.Errorf("failed to prepare function code: %w", err) } log.Println("[info] creating function", opt.label()) - log.Println("[debug]\n", fn.String()) version := "(created)" if !*opt.DryRun { - fn.Publish = opt.Publish + fn.Publish = *opt.Publish res, err := app.createFunction(ctx, fn) if err != nil { - return errors.Wrap(err, "failed to create function") + return fmt.Errorf("failed to create function: %w", err) } if res.Version != nil { version = *res.Version @@ -115,7 +113,7 @@ func (app *App) create(opt DeployOption, fn *Function) error { } } - if err := app.updateTags(fn, opt); err != nil { + if err := app.updateTags(ctx, fn, opt); err != nil { return err } @@ -125,23 +123,22 @@ func (app *App) create(opt DeployOption, fn *Function) error { log.Printf("[info] creating alias set %s to version %s %s", *opt.AliasName, version, opt.label()) if !*opt.DryRun { - alias, err := app.lambda.CreateAlias(&lambda.CreateAliasInput{ + _, err := app.lambda.CreateAlias(ctx, &lambda.CreateAliasInput{ FunctionName: fn.FunctionName, FunctionVersion: aws.String(version), Name: aws.String(*opt.AliasName), }) if err != nil { - return errors.Wrap(err, "failed to create alias") + return fmt.Errorf("failed to create alias: %w", err) } log.Println("[info] alias created") - log.Printf("[debug]\n%s", alias.String()) } return nil } -func (app *App) createFunction(ctx context.Context, fn *lambda.CreateFunctionInput) (*lambda.FunctionConfiguration, error) { - if res, err := app.lambda.CreateFunctionWithContext(ctx, fn); err != nil { - return nil, errors.Wrap(err, "failed to create function") +func (app *App) createFunction(ctx context.Context, fn *lambda.CreateFunctionInput) (*lambda.CreateFunctionOutput, error) { + if res, err := app.lambda.CreateFunction(ctx, fn); err != nil { + return nil, fmt.Errorf("failed to create function: %w", err) } else { return res, app.waitForLastUpdateStatusSuccessful(ctx, *fn.FunctionName) } diff --git a/delete.go b/delete.go index 9c779db..c34f9c6 100644 --- a/delete.go +++ b/delete.go @@ -1,10 +1,11 @@ package lambroll import ( + "context" + "fmt" "log" - "github.com/aws/aws-sdk-go/service/lambda" - "github.com/pkg/errors" + "github.com/aws/aws-sdk-go-v2/service/lambda" ) // DeleteOption represents options for Delete() @@ -21,10 +22,10 @@ func (opt DeleteOption) label() string { } // Delete deletes function -func (app *App) Delete(opt DeleteOption) error { +func (app *App) Delete(ctx context.Context, opt DeleteOption) error { fn, err := app.loadFunction(*opt.FunctionFilePath) if err != nil { - return errors.Wrap(err, "failed to load function") + return fmt.Errorf("failed to load function: %w", err) } log.Println("[info] deleting function", *fn.FunctionName, opt.label()) @@ -32,11 +33,11 @@ func (app *App) Delete(opt DeleteOption) error { if *opt.DryRun { return nil } - _, err = app.lambda.DeleteFunction(&lambda.DeleteFunctionInput{ + _, err = app.lambda.DeleteFunction(ctx, &lambda.DeleteFunctionInput{ FunctionName: fn.FunctionName, }) if err != nil { - return errors.Wrap(err, "failed to delete function") + return fmt.Errorf("failed to delete function: %w", err) } return nil diff --git a/deploy.go b/deploy.go index 6ada5a7..1190dbc 100644 --- a/deploy.go +++ b/deploy.go @@ -4,14 +4,14 @@ import ( "bytes" "context" "encoding/json" - "io/ioutil" + "errors" + "fmt" "log" "os" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/lambda" - "github.com/pkg/errors" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/aws/aws-sdk-go-v2/service/lambda/types" ) // DeployOption represens an option for Deploy() @@ -42,7 +42,7 @@ type versionAlias struct { // Expand expands ExcludeFile contents to Excludes func expandExcludeFile(file string) ([]string, error) { - b, err := ioutil.ReadFile(file) + b, err := os.ReadFile(file) if err != nil { if os.IsNotExist(err) { return nil, nil @@ -68,29 +68,26 @@ func (opt *DeployOption) String() string { } // Deploy deployes a new lambda function code -func (app *App) Deploy(opt DeployOption) error { - ctx := context.Background() +func (app *App) Deploy(ctx context.Context, opt DeployOption) error { excludes, err := expandExcludeFile(*opt.ExcludeFile) if err != nil { - return errors.Wrap(err, "failed to parse exclude-file") + return fmt.Errorf("failed to parse exclude-file: %w", err) } opt.Excludes = append(opt.Excludes, excludes...) log.Printf("[debug] %s", opt.String()) fn, err := app.loadFunction(*opt.FunctionFilePath) if err != nil { - return errors.Wrap(err, "failed to load function") + return fmt.Errorf("failed to load function: %w", err) } log.Printf("[info] starting deploy function %s", *fn.FunctionName) - if current, err := app.lambda.GetFunction(&lambda.GetFunctionInput{ + if current, err := app.lambda.GetFunction(ctx, &lambda.GetFunctionInput{ FunctionName: fn.FunctionName, }); err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case lambda.ErrCodeResourceNotFoundException: - return app.create(opt, fn) - } + var nfe *types.ResourceNotFoundException + if errors.As(err, &nfe) { + return app.create(ctx, opt, fn) } return err } else if err := validateUpdateFunction(current.Configuration, current.Code, fn); err != nil { @@ -98,8 +95,8 @@ func (app *App) Deploy(opt DeployOption) error { } fillDefaultValues(fn) - if err := app.prepareFunctionCodeForDeploy(opt, fn); err != nil { - return errors.Wrap(err, "failed to prepare function code for deploy") + if err := app.prepareFunctionCodeForDeploy(ctx, opt, fn); err != nil { + return fmt.Errorf("failed to prepare function code for deploy: %w", err) } log.Println("[info] updating function configuration", opt.label()) @@ -122,26 +119,28 @@ func (app *App) Deploy(opt DeployOption) error { SnapStart: fn.SnapStart, } if env := fn.Environment; env == nil || env.Variables == nil { - confIn.Environment = &lambda.Environment{ - Variables: map[string]*string{}, // set empty variables explicitly + confIn.Environment = &types.Environment{ + Variables: map[string]string{}, // set empty variables explicitly } } else { confIn.Environment = env } - log.Printf("[debug]\n%s", confIn.String()) + log.Printf("[debug]\n%s", ToJSONString(confIn)) var newerVersion string if !*opt.DryRun { - if _, err := app.updateFunctionConfiguration(ctx, confIn); err != nil { - return errors.Wrap(err, "failed to update function configuration") + proc := func(ctx context.Context) error { + return app.updateFunctionConfiguration(ctx, confIn) + } + if err := app.ensureLastUpdateStatusSuccessful(ctx, *fn.FunctionName, "updating function configuration", proc); err != nil { + return fmt.Errorf("failed to update function configuration: %w", err) } } - if err := app.updateTags(fn, opt); err != nil { + if err := app.updateTags(ctx, fn, opt); err != nil { return err } - log.Println("[info] updating function code", opt.label()) codeIn := &lambda.UpdateFunctionCodeInput{ Architectures: fn.Architectures, FunctionName: fn.FunctionName, @@ -152,14 +151,19 @@ func (app *App) Deploy(opt DeployOption) error { ImageUri: fn.Code.ImageUri, } if *opt.DryRun { - codeIn.DryRun = aws.Bool(true) + codeIn.DryRun = true } else { - codeIn.Publish = opt.Publish + codeIn.Publish = *opt.Publish } - log.Printf("[debug]\n%s", codeIn.String()) - res, err := app.updateFunctionCode(ctx, codeIn) - if err != nil { + var res *lambda.UpdateFunctionCodeOutput + proc := func(ctx context.Context) error { + var err error + // set res outside of this function + res, err = app.updateFunctionCode(ctx, codeIn) + return err + } + if err := app.ensureLastUpdateStatusSuccessful(ctx, *fn.FunctionName, "updating function code", proc); err != nil { return err } if res.Version != nil { @@ -173,130 +177,121 @@ func (app *App) Deploy(opt DeployOption) error { return nil } if *opt.Publish || *opt.AliasToLatest { - err := app.updateAliases(*fn.FunctionName, versionAlias{newerVersion, *opt.AliasName}) + err := app.updateAliases(ctx, *fn.FunctionName, versionAlias{newerVersion, *opt.AliasName}) if err != nil { return err } } if *opt.KeepVersions > 0 { // Ignore zero-value. - return app.deleteVersions(*fn.FunctionName, *opt.KeepVersions) + return app.deleteVersions(ctx, *fn.FunctionName, *opt.KeepVersions) } return nil } -func (app *App) updateFunctionConfiguration(ctx context.Context, in *lambda.UpdateFunctionConfigurationInput) (*lambda.FunctionConfiguration, error) { - if err := app.waitForLastUpdateStatusSuccessful(ctx, *in.FunctionName); err != nil { - return nil, err - } - +func (app *App) updateFunctionConfiguration(ctx context.Context, in *lambda.UpdateFunctionConfigurationInput) error { retrier := retryPolicy.Start(ctx) for retrier.Continue() { - res, err := app.lambda.UpdateFunctionConfigurationWithContext(ctx, in) + _, err := app.lambda.UpdateFunctionConfiguration(ctx, in) if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case lambda.ErrCodeResourceConflictException: - log.Println("[debug] retrying", aerr.Message()) - continue - } + var rce *types.ResourceConflictException + if errors.As(err, &rce) { + log.Println("[debug] retrying", rce.Error()) + continue } - return nil, errors.Wrap(err, "failed to update function configuration") + return fmt.Errorf("failed to update function configuration: %w", err) } - log.Println("[info] updated function configuration successfully") - return res, nil + return nil } - return nil, errors.New("failed to update function configuration (max retries reached)") + return fmt.Errorf("failed to update function configuration (max retries reached)") } -func (app *App) updateFunctionCode(ctx context.Context, in *lambda.UpdateFunctionCodeInput) (*lambda.FunctionConfiguration, error) { - if err := app.waitForLastUpdateStatusSuccessful(ctx, *in.FunctionName); err != nil { - return nil, err - } - - var res *lambda.FunctionConfiguration +func (app *App) updateFunctionCode(ctx context.Context, in *lambda.UpdateFunctionCodeInput) (*lambda.UpdateFunctionCodeOutput, error) { + var res *lambda.UpdateFunctionCodeOutput retrier := retryPolicy.Start(ctx) for retrier.Continue() { var err error - res, err = app.lambda.UpdateFunctionCodeWithContext(ctx, in) + res, err = app.lambda.UpdateFunctionCode(ctx, in) if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case lambda.ErrCodeResourceConflictException: - log.Println("[debug] retrying", aerr.Message()) - continue - } + var rce *types.ResourceConflictException + if errors.As(err, &rce) { + log.Println("[debug] retrying", err) + continue } - return nil, errors.Wrap(err, "failed to update function code") + return nil, fmt.Errorf("failed to update function code: %w", err) } - log.Println("[info] update function code request was accepted") break } + return res, nil +} - if !retrier.Continue() { - return nil, errors.New("failed to update function code (max retries reached)") +func (app *App) ensureLastUpdateStatusSuccessful(ctx context.Context, name string, msg string, code func(ctx context.Context) error) error { + log.Println("[info]", msg, "...") + if err := app.waitForLastUpdateStatusSuccessful(ctx, name); err != nil { + return err } - - if err := app.waitForLastUpdateStatusSuccessful(ctx, *in.FunctionName); err != nil { - return nil, err + if err := code(ctx); err != nil { + return err } - log.Println("[info] updated function code successfully") - - return res, nil + log.Println("[info]", msg, "accepted. waiting for LastUpdateStatus to be successful.") + if err := app.waitForLastUpdateStatusSuccessful(ctx, name); err != nil { + return err + } + log.Println("[info]", msg, "successfully") + return nil } func (app *App) waitForLastUpdateStatusSuccessful(ctx context.Context, name string) error { retrier := retryPolicy.Start(ctx) for retrier.Continue() { - res, err := app.lambda.GetFunction(&lambda.GetFunctionInput{ + res, err := app.lambda.GetFunction(ctx, &lambda.GetFunctionInput{ FunctionName: aws.String(name), }) if err != nil { log.Println("[warn] failed to get function, retrying", err) continue } else { - state := aws.StringValue(res.Configuration.State) - last := aws.StringValue(res.Configuration.LastUpdateStatus) + state := res.Configuration.State + last := res.Configuration.LastUpdateStatus log.Printf("[info] State:%s LastUpdateStatus:%s", state, last) - if last == lambda.LastUpdateStatusSuccessful { + if last == types.LastUpdateStatusSuccessful { return nil } - log.Printf("[info] waiting for LastUpdateStatus %s", lambda.LastUpdateStatusSuccessful) + log.Printf("[info] waiting for LastUpdateStatus %s", types.LastUpdateStatusSuccessful) } } - return errors.New("max retries reached") + return fmt.Errorf("max retries reached") } -func (app *App) updateAliases(functionName string, vs ...versionAlias) error { +func (app *App) updateAliases(ctx context.Context, functionName string, vs ...versionAlias) error { for _, v := range vs { log.Printf("[info] updating alias set %s to version %s", v.Name, v.Version) - alias, err := app.lambda.UpdateAlias(&lambda.UpdateAliasInput{ + _, err := app.lambda.UpdateAlias(ctx, &lambda.UpdateAliasInput{ FunctionName: aws.String(functionName), FunctionVersion: aws.String(v.Version), Name: aws.String(v.Name), }) if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case lambda.ErrCodeResourceNotFoundException: - log.Printf("[info] alias %s is not found. creating alias", v.Name) - alias, err = app.lambda.CreateAlias(&lambda.CreateAliasInput{ - FunctionName: aws.String(functionName), - FunctionVersion: aws.String(v.Version), - Name: aws.String(v.Name), - }) + var nfe *types.ResourceNotFoundException + if errors.As(err, &nfe) { + log.Printf("[info] alias %s is not found. creating alias", v.Name) + _, err := app.lambda.CreateAlias(ctx, &lambda.CreateAliasInput{ + FunctionName: aws.String(functionName), + FunctionVersion: aws.String(v.Version), + Name: aws.String(v.Name), + }) + if err != nil { + return fmt.Errorf("failed to create alias: %w", err) } - } - if err != nil { - return errors.Wrap(err, "failed to update alias") + } else { + return fmt.Errorf("failed to update alias: %w", err) } } log.Println("[info] alias updated") - log.Printf("[debug]\n%s", alias.String()) } return nil } -func (app *App) deleteVersions(functionName string, keepVersions int) error { +func (app *App) deleteVersions(ctx context.Context, functionName string, keepVersions int) error { if keepVersions <= 0 { log.Printf("[info] specify --keep-versions") return nil @@ -307,21 +302,17 @@ func (app *App) deleteVersions(functionName string, keepVersions int) error { } // versions will be set asc order, like 1 to N - versions := []*lambda.FunctionConfiguration{} - + versions := []types.FunctionConfiguration{} for { - req, resp := app.lambda.ListVersionsByFunctionRequest(params) - if err := req.Send(); err != nil { - return err + res, err := app.lambda.ListVersionsByFunction(ctx, params) + if err != nil { + return fmt.Errorf("failed to list versions: %w", err) } - - versions = append(versions, resp.Versions...) - - if resp.NextMarker != nil { - params.Marker = resp.NextMarker + versions = append(versions, res.Versions...) + if res.NextMarker != nil { + params.Marker = res.NextMarker continue } - break } @@ -335,12 +326,12 @@ func (app *App) deleteVersions(functionName string, keepVersions int) error { } log.Printf("[info] deleting function version: %s", *v.Version) - _, err := app.lambda.DeleteFunction(&lambda.DeleteFunctionInput{ + _, err := app.lambda.DeleteFunction(ctx, &lambda.DeleteFunctionInput{ FunctionName: aws.String(functionName), Qualifier: v.Version, }) if err != nil { - return errors.Wrap(err, "failed to delete version") + return fmt.Errorf("failed to delete version: %w", err) } } diff --git a/diff.go b/diff.go index 84692ce..c6d56c3 100644 --- a/diff.go +++ b/diff.go @@ -1,17 +1,19 @@ package lambroll import ( + "context" "crypto/sha256" "encoding/base64" "fmt" "io" "strings" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/lambda" "github.com/fatih/color" "github.com/kylelemons/godebug/diff" - "github.com/pkg/errors" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/aws/aws-sdk-go-v2/service/lambda/types" ) // DiffOption represents options for Diff() @@ -24,35 +26,36 @@ type DiffOption struct { } // Diff prints diff of function.json compared with latest function -func (app *App) Diff(opt DiffOption) error { +func (app *App) Diff(ctx context.Context, opt DiffOption) error { excludes, err := expandExcludeFile(*opt.ExcludeFile) if err != nil { - return errors.Wrap(err, "failed to parse exclude-file") + return fmt.Errorf("failed to parse exclude-file: %w", err) } opt.Excludes = append(opt.Excludes, excludes...) newFunc, err := app.loadFunction(*opt.FunctionFilePath) if err != nil { - return errors.Wrap(err, "failed to load function") + return fmt.Errorf("failed to load function: %w", err) } fillDefaultValues(newFunc) name := *newFunc.FunctionName - var latest *lambda.FunctionConfiguration - var code *lambda.FunctionCodeLocation + var latest *types.FunctionConfiguration + var code *types.FunctionCodeLocation var tags Tags - var currentCodeSha256, packageType string - if res, err := app.lambda.GetFunction(&lambda.GetFunctionInput{ + var currentCodeSha256 string + var packageType types.PackageType + if res, err := app.lambda.GetFunction(ctx, &lambda.GetFunctionInput{ FunctionName: &name, }); err != nil { - return errors.Wrapf(err, "failed to GetFunction %s", name) + return fmt.Errorf("failed to GetFunction %s: %w", name, err) } else { latest = res.Configuration code = res.Code tags = res.Tags currentCodeSha256 = *res.Configuration.CodeSha256 - packageType = *res.Configuration.PackageType + packageType = res.Configuration.PackageType } latestFunc := newFunctionFrom(latest, code, tags) @@ -60,7 +63,7 @@ func (app *App) Diff(opt DiffOption) error { newJSON, _ := marshalJSON(newFunc) if ds := diff.Diff(string(latestJSON), string(newJSON)); ds != "" { - fmt.Println(color.RedString("---" + app.functionArn(name))) + fmt.Println(color.RedString("---" + app.functionArn(ctx, name))) fmt.Println(color.GreenString("+++" + *opt.FunctionFilePath)) fmt.Println(coloredDiff(ds)) } @@ -69,9 +72,9 @@ func (app *App) Diff(opt DiffOption) error { return err } - if aws.BoolValue(opt.CodeSha256) { - if strings.ToLower(packageType) != "zip" { - return errors.New("code-sha256 is only supported for Zip package type") + if aws.ToBool(opt.CodeSha256) { + if packageType != types.PackageTypeZip { + return fmt.Errorf("code-sha256 is only supported for Zip package type") } zipfile, _, err := prepareZipfile(*opt.Src, opt.Excludes) if err != nil { @@ -84,7 +87,7 @@ func (app *App) Diff(opt DiffOption) error { newCodeSha256 := base64.StdEncoding.EncodeToString(h.Sum(nil)) prefix := "CodeSha256: " if ds := diff.Diff(prefix+currentCodeSha256, prefix+newCodeSha256); ds != "" { - fmt.Println(color.RedString("---" + app.functionArn(name))) + fmt.Println(color.RedString("---" + app.functionArn(ctx, name))) fmt.Println(color.GreenString("+++" + "--src=" + *opt.Src)) fmt.Println(coloredDiff(ds)) } diff --git a/function_test.go b/function_test.go index 9868f3d..4363b4f 100644 --- a/function_test.go +++ b/function_test.go @@ -1,18 +1,19 @@ package lambroll import ( + "context" "os" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/lambda" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/lambda/types" ) func TestLoadFunction(t *testing.T) { os.Setenv("FUNCTION_NAME", "test") envfiles := []string{"test/env"} path := "test/terraform.tfstate" - app, err := New(&Option{ + app, err := New(context.Background(), &Option{ TFState: &path, PrefixedTFState: &map[string]string{ "prefix1_": "test/terraform_1.tfstate", @@ -43,40 +44,40 @@ func TestLoadFunction(t *testing.T) { if *fn.FileSystemConfigs[0].Arn != "arn:aws:elasticfilesystem:ap-northeast-1:123456789012:access-point/fsap-04fc0858274e7dd9a" { t.Errorf("unexpected fileSystemConfigs %v", *&fn.FileSystemConfigs) } - if *fn.Environment.Variables["JSON"] != `{"foo":"bar"}` { + if fn.Environment.Variables["JSON"] != `{"foo":"bar"}` { t.Errorf("unexpected environment %v", fn.Environment.Variables) } - if *fn.Environment.Variables["PREFIXED_TFSTATE_1"] != "arn:aws:iam::123456789012:role/test_lambda_role_1" { + if fn.Environment.Variables["PREFIXED_TFSTATE_1"] != "arn:aws:iam::123456789012:role/test_lambda_role_1" { t.Errorf("unexpected environment %v", fn.Environment.Variables) } - if *fn.Environment.Variables["PREFIXED_TFSTATE_2"] != "arn:aws:iam::123456789012:role/test_lambda_role_2" { + if fn.Environment.Variables["PREFIXED_TFSTATE_2"] != "arn:aws:iam::123456789012:role/test_lambda_role_2" { t.Errorf("unexpected environment %v", fn.Environment.Variables) } - if *fn.VpcConfig.SecurityGroupIds[0] != "sg-01a9b01eab0a3c154" { + if fn.VpcConfig.SecurityGroupIds[0] != "sg-01a9b01eab0a3c154" { t.Errorf("unexpected SecurityGroupIds %v", fn.VpcConfig.SecurityGroupIds) } arch := fn.Architectures - if len(arch) != 2 || *arch[0] != "x86_64" || *arch[1] != "arm64" { + if len(arch) != 2 || arch[0] != "x86_64" || arch[1] != "arm64" { t.Errorf("unexpected Architectures %v", fn.Architectures) } if *fn.EphemeralStorage.Size != 1024 { t.Errorf("unexpected EphemeralStorage %v", fn.EphemeralStorage) } - t.Log(fn.String()) + t.Log(fn) } } func TestNewFunction(t *testing.T) { - conf := &lambda.FunctionConfiguration{ + conf := &types.FunctionConfiguration{ FunctionName: aws.String("hello"), - MemorySize: aws.Int64(128), - Runtime: aws.String("nodejs18.x"), - Timeout: aws.Int64(3), + MemorySize: aws.Int32(128), + Runtime: types.RuntimeNodejs18x, + Timeout: aws.Int32(3), Handler: aws.String("index.handler"), Role: aws.String("arn:aws:iam::0123456789012:role/YOUR_LAMBDA_ROLE_NAME"), } - tags := map[string]*string{ - "foo": aws.String("bar"), + tags := map[string]string{ + "foo": "bar", } fn := newFunctionFrom(conf, nil, tags) if *fn.FunctionName != "hello" { @@ -85,8 +86,8 @@ func TestNewFunction(t *testing.T) { if *fn.MemorySize != 128 { t.Errorf("unexpected memory size got %d", *fn.MemorySize) } - if *fn.Runtime != "nodejs18.x" { - t.Errorf("unexpected runtime got %s", *fn.Runtime) + if fn.Runtime != types.RuntimeNodejs18x { + t.Errorf("unexpected runtime got %s", fn.Runtime) } if *fn.Timeout != 3 { t.Errorf("unexpected timeout got %d", *fn.Timeout) @@ -97,7 +98,7 @@ func TestNewFunction(t *testing.T) { if *fn.Role != "arn:aws:iam::0123456789012:role/YOUR_LAMBDA_ROLE_NAME" { t.Errorf("unexpected role got %s", *fn.Role) } - if *fn.Tags["foo"] != "bar" { + if fn.Tags["foo"] != "bar" { t.Errorf("unexpected tags got %v", fn.Tags) } if fn.SnapStart != nil { diff --git a/go.mod b/go.mod index 4e58610..6ccd8e0 100644 --- a/go.mod +++ b/go.mod @@ -1,22 +1,100 @@ module github.com/fujiwara/lambroll -go 1.15 +go 1.20 require ( github.com/Songmu/prompter v0.5.0 github.com/alecthomas/kingpin v2.2.6+incompatible - github.com/aws/aws-sdk-go v1.44.147 + github.com/aws/aws-sdk-go-v2 v1.18.1 + github.com/aws/aws-sdk-go-v2/config v1.18.27 + github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.36.0 + github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 github.com/fatih/color v1.13.0 github.com/fujiwara/logutils v1.1.0 - github.com/fujiwara/tfstate-lookup v0.4.2 + github.com/fujiwara/tfstate-lookup v1.1.2 github.com/go-test/deep v1.0.7 github.com/google/go-cmp v0.5.9 github.com/google/go-jsonnet v0.17.0 github.com/hashicorp/go-envparse v0.0.0-20200406174449-d9cfd743a15e github.com/kayac/go-config v0.6.0 github.com/kylelemons/godebug v1.1.0 - github.com/mattn/go-isatty v0.0.14 + github.com/mattn/go-isatty v0.0.17 github.com/olekukonko/tablewriter v0.0.5 - github.com/pkg/errors v0.9.1 github.com/shogo82148/go-retry v1.1.0 ) + +require ( + cloud.google.com/go v0.81.0 // indirect + cloud.google.com/go/storage v1.15.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect + github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 // indirect + github.com/BurntSushi/toml v0.3.1 // indirect + github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect + github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.26 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.54 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.26 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.29 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.12.12 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12 // indirect + github.com/aws/smithy-go v1.13.5 // indirect + github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/googleapis/gax-go/v2 v2.0.5 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.1 // indirect + github.com/hashicorp/go-slug v0.8.1 // indirect + github.com/hashicorp/go-tfe v1.2.0 // indirect + github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d // indirect + github.com/itchyny/gojq v0.12.11 // indirect + github.com/itchyny/timefmt-go v0.1.5 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jstemmer/go-junit-report v0.9.1 // indirect + github.com/mattn/go-colorable v0.1.9 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + go.opencensus.io v0.23.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect + golang.org/x/mod v0.8.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/term v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect + golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect + golang.org/x/tools v0.6.0 // indirect + google.golang.org/api v0.45.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20210420162539-3c870d7478d2 // indirect + google.golang.org/grpc v1.37.0 // indirect + google.golang.org/protobuf v1.26.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/go.sum b/go.sum index d7d57b6..464f114 100644 --- a/go.sum +++ b/go.sum @@ -39,57 +39,100 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.15.0 h1:Ljj+ZXVEhCr/1+4ZhvtteN1ND7UUsNTlduGclLh8GO0= cloud.google.com/go/storage v1.15.0/go.mod h1:mjjQMoxxyGH7Jr8K5qrx6N2O0AHsczI61sMNn03GIZI= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= -github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= -github.com/Azure/azure-sdk-for-go v56.2.0+incompatible h1:2GrG1JkTSMqLquy1pqVsjeRJhNtZLjss2+rx8ogZXx4= -github.com/Azure/azure-sdk-for-go v56.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-storage-blob-go v0.14.0 h1:1BCg74AmVdYwO3dlKwtFU1V0wU2PZdREkXvAmZJRUlM= -github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 h1:uqM+VoHjVH6zdlkLF2b6O0ZANcHoj3rO0PoQ3jglUJA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2/go.mod h1:twTKAa1E6hLmSDjLhaCkbTMQKc7p/rNLU40rLxGEOCI= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 h1:ECsQtyERDVz3NP3kvDOTLvbQhqWp/x9EsGKtb4ogUr8= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.3.0 h1:LcJtQjCXJUm1s7JpUHZvu+bpgURhCatxVNbGADXniX0= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.3.0/go.mod h1:+OgGVo0Httq7N5oayfvaLQ/Jq+2gJdqfp++Hyyl7Tws= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 h1:u/LLAOFgsMv7HmNL4Qufg58y+qElGOt5qv0z1mURkRY= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= -github.com/Azure/go-autorest/autorest v0.11.19 h1:7/IqD2fEYVha1EPeaiytVKhzmPV223pfkRIQUGOK2IE= -github.com/Azure/go-autorest/autorest v0.11.19/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.11/go.mod h1:nBKAnTomx8gDtl+3ZCJv2v0KACFHWTB2drffI1B68Pk= -github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.8 h1:TzPg6B6fTZ0G1zBf3T54aI7p3cAT6u//TOXGPmFMOXg= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.8/go.mod h1:kxyKZTSfKh8OVFWPAgOgQ/frrJgeYQJPyR5fLFmXko4= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 h1:dMOmEJfkLKW/7JsokJqkyoYSgmR08hi9KrhjZb+JALY= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM= +github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= -github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 h1:UE9n9rkJF62ArLb1F3DEjRt8O3jLwMWdSoypKV4f3MU= +github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Songmu/prompter v0.5.0 h1:uf60xlFItY5nW+rlLJ2XIUfaUReo4gUEeftuUeHpio8= github.com/Songmu/prompter v0.5.0/go.mod h1:S4Eg25l60kPlnfB2ttFVpvBKYw7RKJexzB3gzpAansY= -github.com/alecthomas/go-thrift v0.0.0-20170109061633-7914173639b2/go.mod h1:CxCgO+NdpMdi9SsTlGbc0W+/UNxO3I0AabOEJZ3w61w= github.com/alecthomas/kingpin v2.2.6+incompatible h1:5svnBTFgJjZvGKyYBtMB0+m5wvrbUHiqye8wRJMlnYI= github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= -github.com/alecthomas/kong v0.2.1/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI= -github.com/alecthomas/participle v0.4.2-0.20191220090139-9fbceec1d131 h1:iPgE4wTIM/fgSreWdpxnKXxaGOgGwfPqc2aVPq2BFSU= -github.com/alecthomas/participle v0.4.2-0.20191220090139-9fbceec1d131/go.mod h1:T8u4bQOSMwrkTWOSyt8/jSFPEnRtd0FKFMjVfYBlqPs= -github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/aws/aws-sdk-go v1.40.28/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.44.147 h1:C/YQv0QAvRHio4cESBTFGh8aI/JM9VdRislDIOz/Dx4= -github.com/aws/aws-sdk-go v1.44.147/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go-v2 v1.17.5/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2 v1.18.1 h1:+tefE750oAb7ZQGzla6bLkOwfcQCEtC5y2RqoqCeqKo= +github.com/aws/aws-sdk-go-v2 v1.18.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= +github.com/aws/aws-sdk-go-v2/config v1.18.14/go.mod h1:0pI6JQBHKwd0JnwAZS3VCapLKMO++UL2BOkWwyyzTnA= +github.com/aws/aws-sdk-go-v2/config v1.18.27 h1:Az9uLwmssTE6OGTpsFqOnaGpLnKDqNYOJzWuC6UAYzA= +github.com/aws/aws-sdk-go-v2/config v1.18.27/go.mod h1:0My+YgmkGxeqjXZb5BYme5pc4drjTnM+x1GJ3zv42Nw= +github.com/aws/aws-sdk-go-v2/credentials v1.13.14/go.mod h1:85ckagDuzdIOnZRwws1eLKnymJs3ZM1QwVC1XcuNGOY= +github.com/aws/aws-sdk-go-v2/credentials v1.13.26 h1:qmU+yhKmOCyujmuPY7tf5MxR/RKyZrOPO3V4DobiTUk= +github.com/aws/aws-sdk-go-v2/credentials v1.13.26/go.mod h1:GoXt2YC8jHUBbA4jr+W3JiemnIbkXOfxSXcisUsZ3os= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.23/go.mod h1:mOtmAg65GT1HIL/HT/PynwPbS+UG0BgCZ6vhkPqnxWo= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4 h1:LxK/bitrAr4lnh9LnIS6i7zWbCOdMsfzKFBI6LUCS0I= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4/go.mod h1:E1hLXN/BL2e6YizK1zFlYd8vsfi2GTjbjBazinMmeaM= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.54 h1:u4Cyifho7bnp6NeTCS8zAuxqzycHla4PSJvwXlU8ELI= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.54/go.mod h1:a8gjZYNkBoxPMaA4mIoBT1M+4rOAcJUgFeaxVopMS+k= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.29/go.mod h1:Dip3sIGv485+xerzVv24emnjX5Sg88utCL8fwGmCeWg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34 h1:A5UqQEmPaCFpedKouS4v+dHCTUo2sKqhoKO9U5kxyWo= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34/go.mod h1:wZpTEecJe0Btj3IYnDx/VlUzor9wm3fJHyvLpQF0VwY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.23/go.mod h1:mr6c4cHC+S/MMkrjtSlG4QA36kOznDep+0fga5L/fGQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28 h1:srIVS45eQuewqz6fKKu6ZGXaq6FuFg5NzgQBAM6g8Y4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28/go.mod h1:7VRpKQQedkfIEXb4k52I7swUnZP0wohVajJMRn3vsUw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.30/go.mod h1:vsbq62AOBwQ1LJ/GWKFxX8beUEYeRp/Agitrxee2/qM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 h1:LWA+3kDM8ly001vJ1X1waCuLJdtTl48gwkPKWy9sosI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35/go.mod h1:0Eg1YjxE0Bhn56lx+SHJwCzhW+2JGtizsrx+lCqrfm0= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.21/go.mod h1:QtIEat7ksHH8nFItljyvMI0dGj8lipK2XZ4PhNihTEU= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.26 h1:wscW+pnn3J1OYnanMnza5ZVYXLX4cKk5rAvUAl4Qu+c= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.26/go.mod h1:MtYiox5gvyB+OyP0Mr0Sm/yzbEAIPL9eijj/ouHAPw0= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.24/go.mod h1:QelGeWBVRh9PbbXsfXKTFlU9FjT6W2yP+dW5jMQzOkg= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.29 h1:zZSLP3v3riMOP14H7b4XP0uyfREDQOYv2cqIrvTXDNQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.29/go.mod h1:z7EjRjVwZ6pWcWdI2H64dKttvzaP99jRIj5hphW0M5U= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.23/go.mod h1:9uPh+Hrz2Vn6oMnQYiUi/zbh3ovbnQk19YKINkQny44= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28 h1:bkRyG4a929RCnpVSTvLM2j/T4ls015ZhhYApbmYs15s= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28/go.mod h1:jj7znCIg05jXlaGBlFMGP8+7UN3VtCkRBG2spnmRQkU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.23/go.mod h1:FJhZWVWBCcgAF8jbep7pxQ1QUsjzTwa9tvEXGw2TDRo= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.3 h1:dBL3StFxHtpBzJJ/mNEsjXVgfO+7jR0dAIEwLqMapEA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.3/go.mod h1:f1QyiAsvIv4B49DmCqrhlXqyaR+0IxMmyX+1P+AnzOM= +github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0 h1:xzyM5ZR9kZW0/Bkw5EiihOy6B+BYclp5K+yb6OHjc7s= +github.com/aws/aws-sdk-go-v2/service/lambda v1.37.0/go.mod h1:Q8zQi5nZpjUF/H55dKEpKfEvFWJkgZzjjqvDb2AR5b4= +github.com/aws/aws-sdk-go-v2/service/s3 v1.30.4/go.mod h1:Dze3kNt4T+Dgb8YCfuIFSBLmE6hadKNxqfdF0Xmqz1I= +github.com/aws/aws-sdk-go-v2/service/s3 v1.36.0 h1:lEmQ1XSD9qLk+NZXbgvLJI/IiTz7OIR2TYUTFH25EI4= +github.com/aws/aws-sdk-go-v2/service/s3 v1.36.0/go.mod h1:aVbf0sko/TsLWHx30c/uVu7c62+0EAJ3vbxaJga0xCw= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.3/go.mod h1:jtLIhd+V+lft6ktxpItycqHqiVXrPIRjWIsFIlzMriw= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.12 h1:nneMBM2p79PGWBQovYO/6Xnc2ryRMw3InnDJq1FHkSY= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.12/go.mod h1:HuCOxYsF21eKrerARYO6HapNeh9GBNq7fius2AcwodY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.3/go.mod h1:zVwRrfdSmbRZWkUkWjOItY7SOalnFnq/Yg2LVPqDjwc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12 h1:2qTR7IFk7/0IN/adSFhYu9Xthr0zVFTgBrmPldILn80= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12/go.mod h1:E4VrHCPzmVB/KFXtqBGKb3c8zpbNBgKe3fisDNLAW5w= +github.com/aws/aws-sdk-go-v2/service/sts v1.18.4/go.mod h1:1mKZHLLpDMHTNSYPJ7qrcnCQdHCWsNQaT0xRvq2u80s= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 h1:XFJ2Z6sNUUcAz9poj+245DMkrHE4h2j5I9/xD50RHfE= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.2/go.mod h1:dp0yLPsLBOi++WTxzCjA/oZqi6NPIhoR+uF7GeMU9eg= +github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= +github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -101,9 +144,9 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= +github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -111,22 +154,22 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 h1:Ghm4eQYC0nEPnSJdVkTrXpu9KtoVCSo1hg7mtI7G9KU= -github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fujiwara/logutils v1.1.0 h1:JAYmqW40d/ZjzouB01sfZiaTxwNe4hwmB6lLajZqm1s= github.com/fujiwara/logutils v1.1.0/go.mod h1:pdb/Uk70rjQWEmFm/OvYH7OG8meZt1fEIqC0qZbvro4= -github.com/fujiwara/tfstate-lookup v0.4.2 h1:RmhlHIMLVqNWHxaBasap+L5LO7pKorAbpIVQrktYCzY= -github.com/fujiwara/tfstate-lookup v0.4.2/go.mod h1:F56Bz3W497ZJA0ijFLVgcYeAVuhtbzvV6/hMtu6f2Ek= +github.com/fujiwara/tfstate-lookup v1.1.2 h1:1KASUmZ7O4stmwFijF9jVu9EOMSJwDX0Q+TflWHUWUA= +github.com/fujiwara/tfstate-lookup v1.1.2/go.mod h1:nsGf6IyU4o6VqJQihWaLS8zw/1zr7Rmek4Xqmv6/b6I= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -171,12 +214,13 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-jsonnet v0.17.0 h1:/9NIEfhK1NQRKl3sP2536b2+x5HnZMdql7x3yK/l8JY= github.com/google/go-jsonnet v0.17.0/go.mod h1:sOcuej3UW1vpPTZOr8L7RQimqai1a57bt5j22LzGZCw= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -195,36 +239,35 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-envparse v0.0.0-20200406174449-d9cfd743a15e h1:v1d9+AJMP6i4p8BSKNU0InuvmIAdZjQLNN19V86AG4Q= github.com/hashicorp/go-envparse v0.0.0-20200406174449-d9cfd743a15e/go.mod h1:/NlxCzN2D4C4L2uDE6ux/h6jM+n98VFQM14nnCIfHJU= -github.com/hashicorp/go-retryablehttp v0.5.2 h1:AoISa4P4IsW0/m4T6St8Yw38gTl5GtBAgfkhYh1xAz4= -github.com/hashicorp/go-retryablehttp v0.5.2/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-slug v0.7.0 h1:8HIi6oreWPtnhpYd8lIGQBgp4rXzDWQTOhfILZm+nok= -github.com/hashicorp/go-slug v0.7.0/go.mod h1:Ib+IWBYfEfJGI1ZyXMGNbu2BU+aa3Dzu41RKLH301v4= -github.com/hashicorp/go-tfe v0.17.1 h1:rKk8rfxkohCDTPjZbbe2sYjBKl8Qs4Lnqv3iE4g9yNw= -github.com/hashicorp/go-tfe v0.17.1/go.mod h1:PJOKM4yKS61uJPjvKNRIZrEhsoWrPyytIikpx1X37x8= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= +github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-slug v0.8.1 h1:srN7ivgAjHfZddYY1DjBaihRCFy20+vCcOrlx1O2AfE= +github.com/hashicorp/go-slug v0.8.1/go.mod h1:Ib+IWBYfEfJGI1ZyXMGNbu2BU+aa3Dzu41RKLH301v4= +github.com/hashicorp/go-tfe v1.2.0 h1:L29LCo/qIjOqBUjfiUsZSAzBdxmsOLzwnwZpA+68WW8= +github.com/hashicorp/go-tfe v1.2.0/go.mod h1:tJF/OlAXzVbmjiimAPLplSLgwg6kZDUOy0MzHuMwvF4= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/jsonapi v0.0.0-20210518035559-1e50d74c8db3 h1:mzwkutymYIXR5oQT9YnfbLuuw7LZmksiHKRPUTN5ijo= -github.com/hashicorp/jsonapi v0.0.0-20210518035559-1e50d74c8db3/go.mod h1:Yog5+CPEM3c99L1CL2CFCYoSzgWm5vTU58idbRUaLik= -github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI= +github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d h1:9ARUJJ1VVynB176G1HCwleORqCaXm/Vx0uUi0dL26I0= +github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d/go.mod h1:Yog5+CPEM3c99L1CL2CFCYoSzgWm5vTU58idbRUaLik= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/itchyny/astgen-go v0.0.0-20200116103543-aaa595cf980e/go.mod h1:9Gyr9nZoENI+woes+xm+BFhmvYmAp6bPtXD866pQH9g= -github.com/itchyny/go-flags v1.5.0/go.mod h1:lenkYuCobuxLBAd/HGFE4LRoW8D3B6iXRQfWYJ+MNbA= -github.com/itchyny/gojq v0.9.0 h1:i8KSE5ehGU3PSnQ716raWVJIuIRpTdtJ2U8X+RY3+7s= -github.com/itchyny/gojq v0.9.0/go.mod h1:gzGMMdm17KzrO9WNNtxP7F+U52KlLeoQeFCbLW9vgrg= -github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4= -github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= +github.com/itchyny/gojq v0.12.11 h1:YhLueoHhHiN4mkfM+3AyJV6EPcCxKZsOnYf+aVSwaQw= +github.com/itchyny/gojq v0.12.11/go.mod h1:o3FT8Gkbg/geT4pLI0tF3hvip5F3Y/uskjRz9OYa38g= +github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= +github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -243,36 +286,31 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= -github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= -github.com/lestrrat-go/strftime v1.0.1 h1:o7qz5pmLzPDLyGW4lG6JvTKPUfTFXwe+vOamIYWtnVU= -github.com/lestrrat-go/strftime v1.0.1/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI= -github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/pbnjay/strptime v0.0.0-20140226051138-5c05b0d668c9 h1:4lfz0keanz7/gAlvJ7lAe9zmE08HXxifBZJC0AdeGKo= -github.com/pbnjay/strptime v0.0.0-20140226051138-5c05b0d668c9/go.mod h1:6Hr+C/olSdkdL3z68MlyXWzwhvwmwN7KuUFXGb3PoOk= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -280,19 +318,14 @@ github.com/shogo82148/go-retry v1.1.0 h1:eNBmDFO0ekhF7GEx8Ie5fUmoqH/O1pSIcdivdBP github.com/shogo82148/go-retry v1.1.0/go.mod h1:NCS+03WD76BaTewJNwgyj3ukqcwNTodfy1SWHmbLZaU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.0/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tebeka/strftime v0.1.3 h1:5HQXOqWKYRFfNyBMNVc9z5+QzuBtIXy03psIhtdJYto= -github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -306,10 +339,10 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -344,8 +377,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -358,7 +391,6 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -380,10 +412,9 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -408,7 +439,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -421,7 +452,6 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -438,7 +468,6 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -453,16 +482,15 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210317153231-de623e64d2a6/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -471,13 +499,13 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w= +golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -524,8 +552,8 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -636,7 +664,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -646,11 +673,11 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/init.go b/init.go index f1ec90c..36b6323 100644 --- a/init.go +++ b/init.go @@ -1,6 +1,8 @@ package lambroll import ( + "context" + "errors" "fmt" "io" "log" @@ -8,10 +10,9 @@ import ( "os" "strings" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/lambda" - "github.com/pkg/errors" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/aws/aws-sdk-go-v2/service/lambda/types" ) // InitOption represents options for Init() @@ -21,36 +22,33 @@ type InitOption struct { } // Init initializes function.json -func (app *App) Init(opt InitOption) error { - res, err := app.lambda.GetFunction(&lambda.GetFunctionInput{ +func (app *App) Init(ctx context.Context, opt InitOption) error { + res, err := app.lambda.GetFunction(ctx, &lambda.GetFunctionInput{ FunctionName: opt.FunctionName, }) - var c *lambda.FunctionConfiguration + var c *types.FunctionConfiguration exists := true if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case lambda.ErrCodeResourceNotFoundException: - log.Printf("[info] function %s is not found", *opt.FunctionName) - c = &lambda.FunctionConfiguration{ - FunctionName: opt.FunctionName, - MemorySize: aws.Int64(128), - Runtime: aws.String("nodejs18.x"), - Timeout: aws.Int64(3), - Handler: aws.String("index.handler"), - Role: aws.String( - fmt.Sprintf( - "arn:aws:iam::%s:role/YOUR_LAMBDA_ROLE_NAME", - app.AWSAccountID(), - ), + var nfe *types.ResourceNotFoundException + if errors.As(err, &nfe) { + log.Printf("[info] function %s is not found", *opt.FunctionName) + c = &types.FunctionConfiguration{ + FunctionName: opt.FunctionName, + MemorySize: aws.Int32(128), + Runtime: types.RuntimeNodejs18x, + Timeout: aws.Int32(3), + Handler: aws.String("index.handler"), + Role: aws.String( + fmt.Sprintf( + "arn:aws:iam::%s:role/YOUR_LAMBDA_ROLE_NAME", + app.AWSAccountID(ctx), ), - } - exists = false - default: + ), } + exists = false } if c == nil { - return errors.Wrap(err, "failed to GetFunction"+*opt.FunctionName) + return fmt.Errorf("failed to GetFunction %s: %w", *opt.FunctionName, err) } } else { log.Printf("[info] function %s found", *opt.FunctionName) @@ -59,13 +57,13 @@ func (app *App) Init(opt InitOption) error { var tags Tags if exists { - arn := app.functionArn(*c.FunctionName) + arn := app.functionArn(ctx, *c.FunctionName) log.Printf("[debug] listing tags of %s", arn) - res, err := app.lambda.ListTags(&lambda.ListTagsInput{ + res, err := app.lambda.ListTags(ctx, &lambda.ListTagsInput{ Resource: aws.String(arn), }) if err != nil { - return errors.Wrap(err, "faled to list tags") + return fmt.Errorf("faled to list tags: %w", err) } tags = res.Tags } @@ -97,12 +95,12 @@ func (app *App) Init(opt InitOption) error { func download(url, path string) error { resp, err := http.Get(url) if err != nil { - return errors.Wrapf(err, "failed to get %s", url) + return fmt.Errorf("failed to get %s: %w", url, err) } defer resp.Body.Close() f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, os.FileMode(0644)) if err != nil { - return errors.Wrapf(err, "failed to open file %s", path) + return fmt.Errorf("failed to open file %s: %w", path, err) } _, err = io.Copy(f, resp.Body) return err diff --git a/invoke.go b/invoke.go index 1f1bc9c..0e36ef8 100644 --- a/invoke.go +++ b/invoke.go @@ -2,6 +2,7 @@ package lambroll import ( "bufio" + "context" "encoding/base64" "encoding/json" "fmt" @@ -9,10 +10,10 @@ import ( "log" "os" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/lambda" "github.com/mattn/go-isatty" - "github.com/pkg/errors" + + "github.com/aws/aws-sdk-go-v2/service/lambda" + typesv2 "github.com/aws/aws-sdk-go-v2/service/lambda/types" ) // InvokeOption represents option for Invoke() @@ -24,19 +25,20 @@ type InvokeOption struct { } // Invoke invokes function -func (app *App) Invoke(opt InvokeOption) error { +func (app *App) Invoke(ctx context.Context, opt InvokeOption) error { fn, err := app.loadFunction(*opt.FunctionFilePath) if err != nil { - return errors.Wrap(err, "failed to load function") + return fmt.Errorf("failed to load function: %w", err) } - var invocationType, logType *string + var invocationType typesv2.InvocationType + var logType typesv2.LogType if *opt.Async { - invocationType = aws.String("Event") + invocationType = typesv2.InvocationTypeEvent } else { - invocationType = aws.String("RequestResponse") + invocationType = typesv2.InvocationTypeRequestResponse } if *opt.LogTail { - logType = aws.String("Tail") + logType = typesv2.LogTypeTail } if isatty.IsTerminal(os.Stdin.Fd()) { @@ -54,7 +56,7 @@ PAYLOAD: if err == io.EOF { break } - return errors.Wrap(err, "failed to decode payload as JSON") + return fmt.Errorf("failed to decode payload as JSON: %w", err) } b, _ := json.Marshal(payload) in := &lambda.InvokeInput{ @@ -66,8 +68,8 @@ PAYLOAD: if len(*opt.Qualifier) > 0 { in.Qualifier = opt.Qualifier } - log.Println("[debug] invoking function", in.String()) - res, err := app.lambda.Invoke(in) + log.Println("[debug] invoking function", in) + res, err := app.lambda.Invoke(ctx, in) if err != nil { log.Println("[error] failed to invoke function", err.Error()) continue PAYLOAD @@ -76,7 +78,7 @@ PAYLOAD: stdout.Write([]byte("\n")) stdout.Flush() - log.Printf("[info] StatusCode:%d", *res.StatusCode) + log.Printf("[info] StatusCode:%d", res.StatusCode) if res.ExecutedVersion != nil { log.Printf("[info] ExecutionVersion:%s", *res.ExecutedVersion) } diff --git a/json.go b/json.go new file mode 100644 index 0000000..a7a729e --- /dev/null +++ b/json.go @@ -0,0 +1,64 @@ +package lambroll + +import ( + "encoding/json" + "log" +) + +func isEmptyValue(value interface{}) bool { + switch v := value.(type) { + case nil: + return true + case string: + return v == "" + case bool: + return !v + case map[string]interface{}: + return len(v) == 0 + case []interface{}: + return len(v) == 0 + default: + return false + } +} + +func omitEmptyValues(data interface{}) interface{} { + switch v := data.(type) { + case map[string]interface{}: + nonEmptyMap := make(map[string]interface{}) + for key, value := range v { + nonEmptyValue := omitEmptyValues(value) + if !isEmptyValue(nonEmptyValue) { + nonEmptyMap[key] = nonEmptyValue + } + } + if len(nonEmptyMap) != 0 { + return nonEmptyMap + } + case []interface{}: + nonEmptyList := make([]interface{}, 0) + for _, value := range v { + nonEmptyValue := omitEmptyValues(value) + if !isEmptyValue(nonEmptyValue) { + nonEmptyList = append(nonEmptyList, nonEmptyValue) + } + } + if len(nonEmptyList) != 0 { + return nonEmptyList + } + default: + if !isEmptyValue(v) { + return v + } + } + return nil +} + +func ToJSONString(v interface{}) string { + b, err := json.Marshal(v) + if err != nil { + log.Println("[warn] failed to marshal json:", err) + return "" + } + return string(b) +} diff --git a/lambroll.go b/lambroll.go index 23d2c6f..658a08a 100644 --- a/lambroll.go +++ b/lambroll.go @@ -1,6 +1,7 @@ package lambroll import ( + "context" "fmt" "log" "os" @@ -8,16 +9,16 @@ import ( "text/template" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/endpoints" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/lambda" - "github.com/aws/aws-sdk-go/service/sts" + "github.com/aws/aws-sdk-go-v2/aws" + awsconfig "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/aws/aws-sdk-go-v2/service/lambda/types" + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/aws/aws-sdk-go-v2/service/sts" "github.com/fujiwara/tfstate-lookup/tfstate" "github.com/google/go-jsonnet" "github.com/hashicorp/go-envparse" "github.com/kayac/go-config" - "github.com/pkg/errors" "github.com/shogo82148/go-retry" ) @@ -31,16 +32,18 @@ var retryPolicy = retry.Policy{ } // Function represents configuration of Lambda function +//type Function = lambda.CreateFunctionInput + type Function = lambda.CreateFunctionInput // Tags represents tags of function -type Tags = map[string]*string +type Tags = map[string]string -func (app *App) functionArn(name string) string { +func (app *App) functionArn(ctx context.Context, name string) string { return fmt.Sprintf( "arn:aws:lambda:%s:%s:function:%s", - *app.sess.Config.Region, - app.AWSAccountID(), + app.awsConfig.Region, + app.AWSAccountID(ctx), name, ) } @@ -75,55 +78,66 @@ var ( // App represents lambroll application type App struct { - sess *session.Session - lambda *lambda.Lambda accountID string profile string loader *config.Loader + awsConfig aws.Config + lambda *lambda.Client + extStr map[string]string extCode map[string]string } -// New creates an application -func New(opt *Option) (*App, error) { - for _, envfile := range *opt.Envfile { - if err := exportEnvFile(envfile); err != nil { - return nil, err - } - } - - awsCfg := &aws.Config{} +func newAwsConfig(ctx context.Context, opt *Option) (aws.Config, error) { + var region string if opt.Region != nil && *opt.Region != "" { - awsCfg.Region = aws.String(*opt.Region) + region = aws.ToString(opt.Region) + } + optFuncs := []func(*awsconfig.LoadOptions) error{ + awsconfig.WithRegion(region), } if opt.Endpoint != nil && *opt.Endpoint != "" { - customResolverFunc := func(service, region string, optFns ...func(*endpoints.Options)) (endpoints.ResolvedEndpoint, error) { - switch service { - case endpoints.S3ServiceID, endpoints.LambdaServiceID, endpoints.StsServiceID: - return endpoints.ResolvedEndpoint{ - URL: *opt.Endpoint, + customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) { + if service == lambda.ServiceID || service == sts.ServiceID || service == s3.ServiceID { + return aws.Endpoint{ + PartitionID: "aws", + URL: *opt.Endpoint, + SigningRegion: region, }, nil - default: - return endpoints.DefaultResolver().EndpointFor(service, region, optFns...) } + // returning EndpointNotFoundError will allow the service to fallback to it's default resolution + return aws.Endpoint{}, &aws.EndpointNotFoundError{} + }) + optFuncs = append(optFuncs, awsconfig.WithEndpointResolverWithOptions(customResolver)) + } + if opt.Profile != nil && *opt.Profile != "" { + optFuncs = append(optFuncs, awsconfig.WithSharedConfigProfile(*opt.Profile)) + } + return awsconfig.LoadDefaultConfig(ctx, optFuncs...) +} + +// New creates an application +func New(ctx context.Context, opt *Option) (*App, error) { + for _, envfile := range *opt.Envfile { + if err := exportEnvFile(envfile); err != nil { + return nil, err } - awsCfg.EndpointResolver = endpoints.ResolverFunc(customResolverFunc) } - sessOpt := session.Options{ - Config: *awsCfg, - SharedConfigState: session.SharedConfigEnable, + + v2cfg, err := newAwsConfig(ctx, opt) + if err != nil { + return nil, err } + var profile string if opt.Profile != nil && *opt.Profile != "" { - sessOpt.Profile = *opt.Profile profile = *opt.Profile } - sess := session.Must(session.NewSessionWithOptions(sessOpt)) loader := config.New() if opt.TFState != nil && *opt.TFState != "" { - funcs, err := tfstate.FuncMap(*opt.TFState) + funcs, err := tfstate.FuncMap(ctx, *opt.TFState) if err != nil { return nil, err } @@ -133,10 +147,10 @@ func New(opt *Option) (*App, error) { prefixedFuncs := make(template.FuncMap) for prefix, path := range *opt.PrefixedTFState { if prefix == "" { - return nil, errors.New("--prefixed-tfstate option cannot have empty key") + return nil, fmt.Errorf("--prefixed-tfstate option cannot have empty key") } - funcs, err := tfstate.FuncMap(path) + funcs, err := tfstate.FuncMap(ctx, path) if err != nil { return nil, err } @@ -149,10 +163,11 @@ func New(opt *Option) (*App, error) { } app := &App{ - sess: sess, - lambda: lambda.New(sess), profile: profile, loader: loader, + + awsConfig: v2cfg, + lambda: lambda.NewFromConfig(v2cfg), } if opt.ExtStr != nil { app.extStr = *opt.ExtStr @@ -165,12 +180,12 @@ func New(opt *Option) (*App, error) { } // AWSAccountID returns AWS account ID in current session -func (app *App) AWSAccountID() string { +func (app *App) AWSAccountID(ctx context.Context) string { if app.accountID != "" { return app.accountID } - svc := sts.New(app.sess) - r, err := svc.GetCallerIdentity(&sts.GetCallerIdentityInput{}) + svc := sts.NewFromConfig(app.awsConfig) + r, err := svc.GetCallerIdentity(ctx, &sts.GetCallerIdentityInput{}) if err != nil { log.Println("[warn] failed to get caller identity", err) return "" @@ -209,42 +224,12 @@ func (app *App) loadFunction(path string) (*Function, error) { } var fn Function if err := unmarshalJSON(src, &fn, path); err != nil { - return nil, errors.Wrapf(err, "failed to load %s", path) + return nil, fmt.Errorf("failed to load %s: %w", path, err) } return &fn, nil } -func fillDefaultValues(fn *Function) { - if len(fn.Architectures) == 0 { - fn.Architectures = []*string{aws.String("x86_64")} - } - if fn.Description == nil { - fn.Description = aws.String("") - } - if fn.MemorySize == nil { - fn.MemorySize = aws.Int64(128) - } - if fn.TracingConfig == nil { - fn.TracingConfig = &lambda.TracingConfig{ - Mode: aws.String("PassThrough"), - } - } - if fn.EphemeralStorage == nil { - fn.EphemeralStorage = &lambda.EphemeralStorage{ - Size: aws.Int64(512), - } - } - if fn.Timeout == nil { - fn.Timeout = aws.Int64(3) - } - if fn.SnapStart == nil { - fn.SnapStart = &lambda.SnapStart{ - ApplyOn: aws.String("None"), - } - } -} - -func newFunctionFrom(c *lambda.FunctionConfiguration, code *lambda.FunctionCodeLocation, tags Tags) *Function { +func newFunctionFrom(c *types.FunctionConfiguration, code *types.FunctionCodeLocation, tags Tags) *Function { fn := &Function{ Architectures: c.Architectures, Description: c.Description, @@ -262,36 +247,38 @@ func newFunctionFrom(c *lambda.FunctionConfiguration, code *lambda.FunctionCodeL } if e := c.Environment; e != nil { - fn.Environment = &lambda.Environment{ + fn.Environment = &types.Environment{ Variables: e.Variables, } } if i := c.ImageConfigResponse; i != nil { - fn.ImageConfig = &lambda.ImageConfig{ - Command: i.ImageConfig.Command, - EntryPoint: i.ImageConfig.EntryPoint, - WorkingDirectory: i.ImageConfig.WorkingDirectory, + if ic := i.ImageConfig; ic != nil { + fn.ImageConfig = &types.ImageConfig{ + Command: i.ImageConfig.Command, + EntryPoint: i.ImageConfig.EntryPoint, + WorkingDirectory: i.ImageConfig.WorkingDirectory, + } } } for _, layer := range c.Layers { - fn.Layers = append(fn.Layers, layer.Arn) + fn.Layers = append(fn.Layers, *layer.Arn) } if t := c.TracingConfig; t != nil { - fn.TracingConfig = &lambda.TracingConfig{ + fn.TracingConfig = &types.TracingConfig{ Mode: t.Mode, } } if v := c.VpcConfig; v != nil && *v.VpcId != "" { - fn.VpcConfig = &lambda.VpcConfig{ + fn.VpcConfig = &types.VpcConfig{ SubnetIds: v.SubnetIds, SecurityGroupIds: v.SecurityGroupIds, } } - if (code != nil && aws.StringValue(code.RepositoryType) == "ECR") || aws.StringValue(fn.PackageType) == packageTypeImage { + if (code != nil && aws.ToString(code.RepositoryType) == "ECR") || fn.PackageType == types.PackageTypeImage { log.Printf("[debug] Image URL=%s", *code.ImageUri) - fn.PackageType = aws.String(packageTypeImage) - fn.Code = &lambda.FunctionCode{ + fn.PackageType = types.PackageTypeImage + fn.Code = &types.FunctionCode{ ImageUri: code.ImageUri, } } @@ -301,11 +288,41 @@ func newFunctionFrom(c *lambda.FunctionConfiguration, code *lambda.FunctionCodeL return fn } -func newSnapStart(s *lambda.SnapStartResponse) *lambda.SnapStart { +func fillDefaultValues(fn *Function) { + if len(fn.Architectures) == 0 { + fn.Architectures = []types.Architecture{types.ArchitectureX8664} + } + if fn.Description == nil { + fn.Description = aws.String("") + } + if fn.MemorySize == nil { + fn.MemorySize = aws.Int32(128) + } + if fn.TracingConfig == nil { + fn.TracingConfig = &types.TracingConfig{ + Mode: types.TracingModePassThrough, + } + } + if fn.EphemeralStorage == nil { + fn.EphemeralStorage = &types.EphemeralStorage{ + Size: aws.Int32(512), + } + } + if fn.Timeout == nil { + fn.Timeout = aws.Int32(3) + } + if fn.SnapStart == nil { + fn.SnapStart = &types.SnapStart{ + ApplyOn: types.SnapStartApplyOnNone, + } + } +} + +func newSnapStart(s *types.SnapStartResponse) *types.SnapStart { if s == nil { return nil } - return &lambda.SnapStart{ + return &types.SnapStart{ ApplyOn: s.ApplyOn, } } @@ -331,13 +348,13 @@ func exportEnvFile(file string) error { return nil } -var errCannotUpdateImageAndZip = errors.New("cannot update function code between Image and Zip") +var errCannotUpdateImageAndZip = fmt.Errorf("cannot update function code between Image and Zip") -func validateUpdateFunction(currentConf *lambda.FunctionConfiguration, currentCode *lambda.FunctionCodeLocation, newFn *lambda.CreateFunctionInput) error { +func validateUpdateFunction(currentConf *types.FunctionConfiguration, currentCode *types.FunctionCodeLocation, newFn *lambda.CreateFunctionInput) error { newCode := newFn.Code // new=Image - if newCode != nil && newCode.ImageUri != nil || aws.StringValue(newFn.PackageType) == packageTypeImage { + if newCode != nil && newCode.ImageUri != nil || newFn.PackageType == packageTypeImage { // current=Zip if currentCode == nil || currentCode.ImageUri == nil { return errCannotUpdateImageAndZip @@ -345,7 +362,7 @@ func validateUpdateFunction(currentConf *lambda.FunctionConfiguration, currentCo } // current=Image - if currentCode != nil && currentCode.ImageUri != nil || aws.StringValue(currentConf.PackageType) == packageTypeImage { + if currentCode != nil && currentCode.ImageUri != nil || currentConf.PackageType == types.PackageTypeImage { // new=Zip if newCode == nil || newCode.ImageUri == nil { return errCannotUpdateImageAndZip diff --git a/list.go b/list.go index eab8549..e7cb00c 100644 --- a/list.go +++ b/list.go @@ -1,12 +1,13 @@ package lambroll import ( + "context" + "fmt" "log" "os" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/lambda" - "github.com/pkg/errors" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/lambda" ) // ListOption represents options for List() @@ -14,25 +15,25 @@ type ListOption struct { } // List lists lambda functions -func (app *App) List(opt ListOption) error { +func (app *App) List(ctx context.Context, opt ListOption) error { var marker *string for { - res, err := app.lambda.ListFunctions(&lambda.ListFunctionsInput{ - MaxItems: aws.Int64(50), + res, err := app.lambda.ListFunctions(ctx, &lambda.ListFunctionsInput{ + MaxItems: aws.Int32(50), }) if err != nil { - return errors.Wrap(err, "failed to ListFunctions") + return fmt.Errorf("failed to ListFunctions: %w", err) } for _, c := range res.Functions { - arn := app.functionArn(*c.FunctionName) + arn := app.functionArn(ctx, *c.FunctionName) log.Printf("[debug] listing tags of %s", arn) - res, err := app.lambda.ListTags(&lambda.ListTagsInput{ + res, err := app.lambda.ListTags(ctx, &lambda.ListTagsInput{ Resource: aws.String(arn), }) if err != nil { - return errors.Wrap(err, "faled to list tags") + return fmt.Errorf("faled to list tags: %w", err) } - b, _ := marshalJSON(newFunctionFrom(c, nil, res.Tags)) + b, _ := marshalJSON(newFunctionFrom(&c, nil, res.Tags)) os.Stdout.Write(b) } if marker = res.NextMarker; marker == nil { diff --git a/logs.go b/logs.go index ffa351d..c71b8af 100644 --- a/logs.go +++ b/logs.go @@ -1,13 +1,13 @@ package lambroll import ( + "context" + "fmt" "log" "os" "os/exec" "strings" "syscall" - - "github.com/pkg/errors" ) type LogsOption struct { @@ -18,17 +18,17 @@ type LogsOption struct { FilterPattern *string } -func (app *App) Logs(opt LogsOption) error { +func (app *App) Logs(ctx context.Context, opt LogsOption) error { fn, err := app.loadFunction(*opt.FunctionFilePath) if err != nil { - return errors.Wrap(err, "failed to load function") + return fmt.Errorf("failed to load function: %w", err) } logGroup := "/aws/lambda/" + *fn.FunctionName command := []string{ "aws", "--profile", app.profile, - "--region", *app.sess.Config.Region, + "--region", app.awsConfig.Region, "logs", "tail", logGroup, @@ -51,7 +51,7 @@ func (app *App) Logs(opt LogsOption) error { } log.Println("[debug] invoking command", strings.Join(command, " ")) if err := syscall.Exec(bin, command, os.Environ()); err != nil { - return errors.Wrap(err, "failed to invoke aws logs tail") + return fmt.Errorf("failed to invoke aws logs tail: %w", err) } return nil } diff --git a/rollback.go b/rollback.go index b83e729..6734af8 100644 --- a/rollback.go +++ b/rollback.go @@ -1,14 +1,16 @@ package lambroll import ( + "context" + "errors" + "fmt" "log" "strconv" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/lambda" - "github.com/pkg/errors" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/aws/aws-sdk-go-v2/service/lambda/types" ) // RollbackOption represents option for Rollback() @@ -26,26 +28,26 @@ func (opt RollbackOption) label() string { } // Rollback rollbacks function -func (app *App) Rollback(opt RollbackOption) error { +func (app *App) Rollback(ctx context.Context, opt RollbackOption) error { fn, err := app.loadFunction(*opt.FunctionFilePath) if err != nil { - return errors.Wrap(err, "failed to load function") + return fmt.Errorf("failed to load function: %w", err) } log.Printf("[info] starting rollback function %s", *fn.FunctionName) - res, err := app.lambda.GetAlias(&lambda.GetAliasInput{ + res, err := app.lambda.GetAlias(ctx, &lambda.GetAliasInput{ FunctionName: fn.FunctionName, Name: aws.String(CurrentAliasName), }) if err != nil { - return errors.Wrap(err, "failed to get alias") + return fmt.Errorf("failed to get alias: %w", err) } currentVersion := *res.FunctionVersion cv, err := strconv.ParseInt(currentVersion, 10, 64) if err != nil { - return errors.Wrapf(err, "failed to pase %s as int", currentVersion) + return fmt.Errorf("failed to pase %s as int: %w", currentVersion, err) } var prevVersion string @@ -53,19 +55,18 @@ VERSIONS: for v := cv - 1; v > 0; v-- { log.Printf("[debug] get function version %d", v) vs := strconv.FormatInt(v, 10) - res, err := app.lambda.GetFunction(&lambda.GetFunctionInput{ + res, err := app.lambda.GetFunction(ctx, &lambda.GetFunctionInput{ FunctionName: fn.FunctionName, Qualifier: aws.String(vs), }) if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case lambda.ErrCodeResourceNotFoundException: - log.Printf("[debug] version %s not found", vs) - continue VERSIONS - } + var nfe *types.ResourceNotFoundException + if errors.As(err, &nfe) { + log.Printf("[debug] version %s not found", vs) + continue VERSIONS + } else { + return fmt.Errorf("failed to get function: %w", err) } - return errors.Wrap(err, "failed to get function") } prevVersion = *res.Configuration.Version break @@ -78,7 +79,7 @@ VERSIONS: if *opt.DryRun { return nil } - err = app.updateAliases(*fn.FunctionName, versionAlias{Version: prevVersion, Name: CurrentAliasName}) + err = app.updateAliases(ctx, *fn.FunctionName, versionAlias{Version: prevVersion, Name: CurrentAliasName}) if err != nil { return err } @@ -87,18 +88,18 @@ VERSIONS: return nil } - return app.deleteFunctionVersion(*fn.FunctionName, currentVersion) + return app.deleteFunctionVersion(ctx, *fn.FunctionName, currentVersion) } -func (app *App) deleteFunctionVersion(functionName, version string) error { +func (app *App) deleteFunctionVersion(ctx context.Context, functionName, version string) error { for { log.Printf("[debug] checking aliased version") - res, err := app.lambda.GetAlias(&lambda.GetAliasInput{ + res, err := app.lambda.GetAlias(ctx, &lambda.GetAliasInput{ FunctionName: aws.String(functionName), Name: aws.String(CurrentAliasName), }) if err != nil { - return errors.Wrap(err, "failed to get alias") + return fmt.Errorf("failed to get alias: %w", err) } if *res.FunctionVersion == version { log.Printf("[debug] version %s still has alias %s, retrying", version, CurrentAliasName) @@ -108,12 +109,12 @@ func (app *App) deleteFunctionVersion(functionName, version string) error { break } log.Printf("[info] deleting function version %s", version) - _, err := app.lambda.DeleteFunction(&lambda.DeleteFunctionInput{ + _, err := app.lambda.DeleteFunction(ctx, &lambda.DeleteFunctionInput{ FunctionName: aws.String(functionName), Qualifier: aws.String(version), }) if err != nil { - return errors.Wrap(err, "failed to delete version") + return fmt.Errorf("failed to delete version: %w", err) } return nil } diff --git a/tags.go b/tags.go index 00838b0..b6d1a0d 100644 --- a/tags.go +++ b/tags.go @@ -1,34 +1,31 @@ package lambroll import ( + "context" + "errors" + "fmt" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/lambda" - "github.com/pkg/errors" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/aws/aws-sdk-go-v2/service/lambda/types" ) -func (app *App) updateTags(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 } - arn := app.functionArn(*fn.FunctionName) - tags, err := app.lambda.ListTags(&lambda.ListTagsInput{ + arn := app.functionArn(ctx, *fn.FunctionName) + tags, err := app.lambda.ListTags(ctx, &lambda.ListTagsInput{ Resource: aws.String(arn), }) if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case lambda.ErrCodeResourceNotFoundException: - // at create - tags, err = &lambda.ListTagsOutput{}, nil - default: - } - } - if err != nil { - return errors.Wrapf(err, "failed to list tags of %s", arn) + var nfe *types.ResourceNotFoundException + if errors.As(err, &nfe) { + tags, err = &lambda.ListTagsOutput{}, nil + } else { + return fmt.Errorf("failed to list tags of %s: %w", arn, err) } } log.Printf("[debug] %d tags found", len(tags.Tags)) @@ -43,12 +40,12 @@ func (app *App) updateTags(fn *Function, opt DeployOption) error { if n := len(setTags); n > 0 { log.Printf("[info] setting %d tags %s", n, opt.label()) if !*opt.DryRun { - _, err = app.lambda.TagResource(&lambda.TagResourceInput{ + _, err = app.lambda.TagResource(ctx, &lambda.TagResourceInput{ Resource: aws.String(arn), Tags: setTags, }) if err != nil { - return errors.Wrap(err, "failed to tag resource") + return fmt.Errorf("failed to tag resource: %w", err) } } } @@ -56,12 +53,12 @@ func (app *App) updateTags(fn *Function, opt DeployOption) error { if n := len(removeTagKeys); n > 0 { log.Printf("[info] removing %d tags %s", n, opt.label()) if !*opt.DryRun { - _, err = app.lambda.UntagResource(&lambda.UntagResourceInput{ + _, err = app.lambda.UntagResource(ctx, &lambda.UntagResourceInput{ Resource: aws.String(arn), TagKeys: removeTagKeys, }) if err != nil { - return errors.Wrap(err, "failed to untag resource") + return fmt.Errorf("failed to untag resource: %w", err) } } } @@ -70,23 +67,23 @@ func (app *App) updateTags(fn *Function, opt DeployOption) error { } // mergeTags merges old/new tags -func mergeTags(oldTags, newTags Tags) (sets Tags, removes []*string) { +func mergeTags(oldTags, newTags Tags) (sets Tags, removes []string) { sets = make(Tags) - removes = make([]*string, 0) + removes = make([]string, 0) for key, oldValue := range oldTags { if newValue, ok := newTags[key]; ok { - if *newValue != *oldValue { - log.Printf("[debug] update tag %s=%s", key, *newValue) + if newValue != oldValue { + log.Printf("[debug] update tag %s=%s", key, newValue) sets[key] = newValue } } else { log.Printf("[debug] remove tag %s", key) - removes = append(removes, aws.String(key)) + removes = append(removes, key) } } for key, newValue := range newTags { if _, ok := oldTags[key]; !ok { - log.Printf("[debug] add tag %s=%s", key, *newValue) + log.Printf("[debug] add tag %s=%s", key, newValue) sets[key] = newValue } } diff --git a/tags_test.go b/tags_test.go index 274f74b..84e7442 100644 --- a/tags_test.go +++ b/tags_test.go @@ -7,8 +7,8 @@ import ( "github.com/go-test/deep" ) -type tags = map[string]*string -type keys = []*string +type tags = map[string]string +type keys = []string type tagsTestCase struct { oldTags tags newTags tags @@ -21,28 +21,28 @@ func s(s string) *string { } var mergeTagsCase = []tagsTestCase{ - tagsTestCase{ - oldTags: tags{"Foo": s("FOO"), "Bar": s("BAR"), "Tee": s("TEE")}, - newTags: tags{"Foo": s("FOO"), "Baz": s("BAZ"), "Tee": s("TEEEE")}, - setTags: tags{"Baz": s("BAZ"), "Tee": s("TEEEE")}, - removeKeys: keys{s("Bar")}, + { + oldTags: tags{"Foo": "FOO", "Bar": "BAR", "Tee": "TEE"}, + newTags: tags{"Foo": "FOO", "Baz": "BAZ", "Tee": "TEEEE"}, + setTags: tags{"Baz": "BAZ", "Tee": "TEEEE"}, + removeKeys: keys{"Bar"}, }, - tagsTestCase{ + { oldTags: tags{}, - newTags: tags{"Foo": s("FOO"), "Bar": s("BAR")}, - setTags: tags{"Foo": s("FOO"), "Bar": s("BAR")}, + newTags: tags{"Foo": "FOO", "Bar": "BAR"}, + setTags: tags{"Foo": "FOO", "Bar": "BAR"}, removeKeys: keys{}, }, - tagsTestCase{ - oldTags: tags{"Foo": s("Foo"), "Bar": s("Bar")}, - newTags: tags{"Bar": s("Bar")}, + { + oldTags: tags{"Foo": "Foo", "Bar": "Bar"}, + newTags: tags{"Bar": "Bar"}, setTags: tags{}, - removeKeys: keys{s("Foo")}, + removeKeys: keys{"Foo"}, }, - tagsTestCase{ - oldTags: tags{"A": s("A")}, - newTags: tags{"A": s("B")}, - setTags: tags{"A": s("B")}, + { + oldTags: tags{"A": "A"}, + newTags: tags{"A": "B"}, + setTags: tags{"A": "B"}, removeKeys: keys{}, }, } diff --git a/utils.go b/utils.go index 4915897..125bbd4 100644 --- a/utils.go +++ b/utils.go @@ -4,13 +4,11 @@ import ( "bytes" "encoding/json" "fmt" - "io/ioutil" "log" "os" "strings" "github.com/Songmu/prompter" - "github.com/aws/aws-sdk-go/private/protocol/json/jsonutil" ) func (app *App) saveFile(path string, b []byte, mode os.FileMode) error { @@ -20,18 +18,23 @@ func (app *App) saveFile(path string, b []byte, mode os.FileMode) error { return nil } } - return ioutil.WriteFile(path, b, mode) + return os.WriteFile(path, b, mode) } func marshalJSON(s interface{}) ([]byte, error) { - var buf bytes.Buffer - b, err := jsonutil.BuildJSON(s) + b, err := json.Marshal(s) if err != nil { return nil, err } - json.Indent(&buf, b, "", " ") - buf.WriteString("\n") - return buf.Bytes(), nil + x := make(map[string]interface{}) + if err := json.Unmarshal(b, &x); err != nil { + return nil, err + } + if b, err := json.MarshalIndent(omitEmptyValues(x), "", " "); err != nil { + return nil, err + } else { + return append(b, '\n'), nil + } } func unmarshalJSON(src []byte, v interface{}, path string) error { diff --git a/versions.go b/versions.go index 41bc558..cf58695 100644 --- a/versions.go +++ b/versions.go @@ -2,15 +2,17 @@ package lambroll import ( "bytes" + "context" "encoding/json" "fmt" "strings" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/lambda" "github.com/olekukonko/tablewriter" - "github.com/pkg/errors" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/lambda" + "github.com/aws/aws-sdk-go-v2/service/lambda/types" ) // VersionsOption represents options for Versions() @@ -71,25 +73,25 @@ func (v versionsOutput) TSV() string { } // Versions manages the versions of a Lambda function -func (app *App) Versions(opt VersionsOption) error { +func (app *App) Versions(ctx context.Context, opt VersionsOption) error { newFunc, err := app.loadFunction(*opt.FunctionFilePath) if err != nil { - return errors.Wrap(err, "failed to load function") + return fmt.Errorf("failed to load function: %w", err) } name := *newFunc.FunctionName if *opt.Delete { - return app.deleteVersions(name, *opt.KeepVersions) + return app.deleteVersions(ctx, name, *opt.KeepVersions) } aliases := make(map[string][]string) var nextAliasMarker *string for { - res, err := app.lambda.ListAliases(&lambda.ListAliasesInput{ + res, err := app.lambda.ListAliases(ctx, &lambda.ListAliasesInput{ FunctionName: &name, Marker: nextAliasMarker, }) if err != nil { - return errors.Wrap(err, "failed to list aliases") + return fmt.Errorf("failed to list aliases: %w", err) } for _, alias := range res.Aliases { aliases[*alias.FunctionVersion] = append(aliases[*alias.FunctionVersion], *alias.Name) @@ -105,15 +107,15 @@ func (app *App) Versions(opt VersionsOption) error { } } - var versions []*lambda.FunctionConfiguration + var versions []types.FunctionConfiguration var nextMarker *string for { - res, err := app.lambda.ListVersionsByFunction(&lambda.ListVersionsByFunctionInput{ + res, err := app.lambda.ListVersionsByFunction(ctx, &lambda.ListVersionsByFunctionInput{ FunctionName: &name, Marker: nextMarker, }) if err != nil { - return errors.Wrap(err, "failed to list versions") + return fmt.Errorf("failed to list versions: %w", err) } versions = append(versions, res.Versions...) if nextMarker = res.NextMarker; nextMarker == nil { @@ -123,18 +125,18 @@ func (app *App) Versions(opt VersionsOption) error { vo := make(versionsOutputs, 0, len(versions)) for _, v := range versions { - if aws.StringValue(v.Version) == versionLatest { + if aws.ToString(v.Version) == versionLatest { continue } lm, err := time.Parse("2006-01-02T15:04:05.999-0700", *v.LastModified) if err != nil { - return errors.Wrap(err, "failed to parse last modified") + return fmt.Errorf("failed to parse last modified: %w", err) } vo = append(vo, versionsOutput{ Version: *v.Version, Aliases: aliases[*v.Version], LastModified: lm, - Runtime: *v.Runtime, + Runtime: string(v.Runtime), }) }