diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cafb64d..d21635a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Release to Production +name: Release on: push: diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 59d34f9..359e13a 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -1,12 +1,11 @@ -name: PR-Review +name: Pull Request Checks on: pull_request: + types: [opened, synchronize, reopened, ready_for_review] branches: [ main ] env: GITHUB_TOKEN: ${{ github.token }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} LINT_VERSION: "1.25.1" permissions: @@ -14,7 +13,21 @@ permissions: packages: write jobs: + + run-ci: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + if: ${{ !github.event.pull_request.draft }} + steps: + # If the condition above is not met, aka, the PR is not in draft status, then this step is skipped. + # Because this step is part of the critical path, omission of this step will result in remaining CI steps not gettinge executed. + # As of 8/8/2022 there is now way to enforce this beahvior in GitHub Actions CI. + - run: exit 0 + test: + needs: [run-ci] outputs: VERSION: ${{ steps.go.outputs.version }} name: Test @@ -33,6 +46,9 @@ jobs: - name: Generate AWS region file + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: | aws ec2 describe-regions --all-regions --region us-east-1 --query "Regions[].RegionName" --output text >> cmd/aws-regions.txt @@ -42,15 +58,25 @@ jobs: args: -v - name: Execute Go tests - run: go get && go test -v ./... + run: make tests-coverage + + - name: Codecov Upload + uses: codecov/codecov-action@v3.1.4 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - name: Test CLI + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: | - go test -coverprofile=go.txt -v ./... go run main.go clean -r us-west-2 go run main.go version - name: build & execute + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: | echo "--------------------------------------------------" go build -ldflags="-X 'github.com/karl-cardenas-coding/go-lambda-cleanup/cmd.VersionString=0.0.0'" -o=glc -v @@ -79,9 +105,4 @@ jobs: build-args: VERSION=${{steps.dependencies.outputs.VERSION}} platforms: linux/amd64,linux/arm64 push: true - tags: ghcr.io/${{ github.repository }}:test - - - uses: actions/upload-artifact@v1 - with: - name: test-results - path: go.txt \ No newline at end of file + tags: ghcr.io/${{ github.repository }}:test \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3601a36..6cf2b16 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,12 +1,10 @@ -name: Test & Validate +name: Branch Tests on: push: branches-ignore: [ main ] env: GITHUB_TOKEN: ${{ github.token }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} LINT_VERSION: "1.25.1" @@ -27,6 +25,9 @@ jobs: uses: actions/checkout@v3 - name: Generate AWS region file + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: | aws ec2 describe-regions --all-regions --region us-east-1 --query "Regions[].RegionName" --output text >> cmd/aws-regions.txt @@ -35,24 +36,22 @@ jobs: with: args: -v - - name: Execute Go tests - run: go test -v ./... + run: make tests-coverage - name: Test CLI + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: | - go get - go test -coverprofile=go.txt -v ./... go run main.go clean -r us-west-2 go run main.go version - name: build & execute + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: | echo "--------------------------------------------------" go build -ldflags="-X 'github.com/karl-cardenas-coding/go-lambda-cleanup/cmd.VersionString=0.0.0'" -o=glc -v - ./glc clean -r us-west-2 - - - uses: actions/upload-artifact@v1 - with: - name: test-results - path: go.txt \ No newline at end of file + ./glc clean -r us-west-2 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 68deeae..3a1b6ba 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,5 @@ terraform.tfvars lambda.zip main .DS_STORE -main \ No newline at end of file +main +coverage.out diff --git a/Dockerfile b/Dockerfile index 4f5028d..b26acc1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # Copyright (c) karl-cardenas-coding # SPDX-License-Identifier: MIT -FROM golang:1.21.3-alpine3.18 as builder +FROM golang:1.21.4-alpine3.18 as builder LABEL org.opencontainers.image.source="http://github.com/karl-cardenas-coding/go-lambda-cleanup" LABEL org.opencontainers.image.description "A solution for removing previous versions of AWS Lambdas" diff --git a/Makefile b/Makefile index e0a4d0b..d4d5703 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ -aws-regions.txt: +.PHONY: license + +aws-regions: aws ec2 describe-regions --region us-east-1 --all-regions --query "Regions[].RegionName" --output text > cmd/aws-regions.txt license: @@ -21,4 +23,18 @@ build: ## Build the binary file tests: ## Run tests @echo "Running tests" - go test -race -shuffle on ./... \ No newline at end of file + go test -race ./... + + +tests-coverage: ## Start Go Test with code coverage + @echo "Running Go Tests with code coverage" + go test -race -shuffle on -cover -coverprofile=coverage.out -covermode=atomic ./... + +view-coverage: ## View the code coverage + @echo "Viewing the code coverage" + go tool cover -html=coverage.out + + +nil: ## Check for nil errors + @echo "Checking for nil errors" + ~/go/bin/nilaway ./... \ No newline at end of file diff --git a/README.md b/README.md index 3ee267c..65e488c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ # go-lambda-cleanup -[![Main](https://github.com/karl-cardenas-coding/go-lambda-cleanup/actions/workflows/build.yml/badge.svg)](https://github.com/karl-cardenas-coding/go-lambda-cleanup/actions/workflows/build.yml) +[![Go Reference](https://pkg.go.dev/badge/github.com/karl-cardenas-coding/go-lambda-cleanup.svg)](https://pkg.go.dev/github.com/karl-cardenas-coding/go-lambda-cleanup) [![Go version](https://img.shields.io/github/go-mod/go-version/karl-cardenas-coding/go-lambda-cleanup)](https://golang.org/dl/) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) +[![codecov](https://codecov.io/gh/karl-cardenas-coding/go-lambda-cleanup/graph/badge.svg?token=S8SY4ZA2ZA)](https://codecov.io/gh/karl-cardenas-coding/go-lambda-cleanup) + [![Go Report Card](https://goreportcard.com/badge/github.com/karl-cardenas-coding/go-lambda-cleanup)](https://goreportcard.com/report/github.com/karl-cardenas-coding/go-lambda-cleanup) +
@@ -18,7 +21,7 @@
go-lambda-cleanup is distributed as a single binary. [Download](https://github.com/karl-cardenas-coding/go-lambda-cleanup/releases) the binary and install go-lambda-cleanup in a directory in your system's [PATH](https://superuser.com/questions/284342/what-are-path-and-other-environment-variables-and-how-can-i-set-or-use-them). `/usr/local/bin` is the recommended path for UNIX/LINUX environments.
```shell
-VERSION=2.0.9
+VERSION=2.0.10
wget https://github.com/karl-cardenas-coding/go-lambda-cleanup/releases/download/v$VERSION/go-lambda-cleanup-v$VERSION-linux-amd64.zip
unzip go-lambda-cleanup-v$VERSION-linux-amd64.zip
sudo mv glc /usr/local/bin/
@@ -29,7 +32,7 @@ sudo mv glc /usr/local/bin/
go-lambda-cleanup is also available as a Docker image. Check out the [GitHub Packages](https://github.com/karl-cardenas-coding/go-lambda-cleanup/pkgs/container/go-lambda-cleanup) page for this repository to learn more about the available images.
```
-VERSION=2.0.9
+VERSION=2.0.10
docker pull ghcr.io/karl-cardenas-coding/go-lambda-cleanup:$VERSION
```
@@ -253,7 +256,7 @@ on:
# At 04:00 on every day
- cron: '0 04 * * *'
env:
- VERSION: 2.0.9
+ VERSION: 2.0.10
jobs:
build:
diff --git a/cmd/clean.go b/cmd/clean.go
index d67a9fd..80d13c7 100644
--- a/cmd/clean.go
+++ b/cmd/clean.go
@@ -23,7 +23,7 @@ import (
"github.com/aws/aws-sdk-go-v2/service/lambda"
"github.com/aws/aws-sdk-go-v2/service/lambda/types"
"github.com/dustin/go-humanize"
- internal "github.com/karl-cardenas-coding/go-lambda-cleanup/internal"
+ internal "github.com/karl-cardenas-coding/go-lambda-cleanup/v2/internal"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -35,9 +35,6 @@ const (
)
var (
- ctx context.Context
- CustomeDeleteList []string
- svc *lambda.Client
//go:embed aws-regions.txt
f embed.FS
)
@@ -50,13 +47,15 @@ var cleanCmd = &cobra.Command{
Use: "clean",
Short: "Removes all former versions of AWS lambdas except for the $LATEST version",
Long: `Removes all former versions of AWS lambdas except for the $LATEST version. The user also has the ability specify n-? version to retain.`,
- Run: func(cmd *cobra.Command, args []string) {
- ctx = context.Background()
+ RunE: func(cmd *cobra.Command, args []string) error {
+ ctx := context.Background()
var (
- awsEnvRegion string
- awsEnvProfile string
- config cliConfig
+ awsEnvRegion string
+ awsEnvProfile string
+ config cliConfig
+ err error
+ customeDeleteList []string
)
config = GlobalCliConfig
@@ -64,12 +63,19 @@ var cleanCmd = &cobra.Command{
awsEnvProfile = os.Getenv("AWS_PROFILE")
if *config.RegionFlag == "" {
if awsEnvRegion != "" {
- *config.RegionFlag = validateRegion(f, awsEnvRegion)
+ *config.RegionFlag, err = validateRegion(f, awsEnvRegion)
+ if err != nil {
+ return err
+ }
+
} else {
- log.Fatal("ERROR: Missing region flag and AWS_DEFAULT_REGION env variable. Please use -r and provide a valid AWS region.")
+ return errors.New("missing region flag and AWS_DEFAULT_REGION env variable. Please use -r and provide a valid AWS region")
}
} else {
- *config.RegionFlag = validateRegion(f, *config.RegionFlag)
+ *config.RegionFlag, err = validateRegion(f, *config.RegionFlag)
+ if err != nil {
+ return err
+ }
}
// Create a list of AWS Configurations Options
@@ -106,40 +112,45 @@ var cleanCmd = &cobra.Command{
if *config.LambdaListFile != "" {
log.Info("******** CUSTOM LAMBDA LIST PROVIDED ********")
- customList, err := internal.GenerateLambdaDeleteList(LambdaListFile)
+ list, err := internal.GenerateLambdaDeleteList(*config.LambdaListFile)
if err != nil {
+ log.Infof("an issue occurred while processing %s", *config.LambdaListFile)
log.Info(err.Error())
}
- CustomeDeleteList = customList
+ customeDeleteList = list
}
cfg, err := awsConfig.LoadDefaultConfig(ctx, awsConfigOptions...)
if err != nil {
- log.Fatal("ERROR ESTABLISHING AWS SESSION")
+ return errors.New("ERROR ESTABLISHING AWS SESSION")
}
creds, err := cfg.Credentials.Retrieve(ctx)
if err != nil {
- log.Fatal("ERROR RETRIEVING AWS CREDENTIALS")
+ return errors.New("ERROR RETRIEVING AWS CREDENTIALS")
}
if creds.Expired() {
- log.Fatal("AWS CREDENTIALS EXPIRED")
+ return errors.New("AWS CREDENTIALS EXPIRED")
}
// svc = lambda.NewFromConfig(cfg)
- svc = lambda.NewFromConfig(cfg, func(o *lambda.Options) {
+ initSvc := lambda.NewFromConfig(cfg, func(o *lambda.Options) {
// Set the User-Agent for all AWS with the Lambda client
o.APIOptions = append(o.APIOptions, middleware.AddUserAgentKeyValue("go-lambda-cleanup", VersionString))
})
- err = executeClean(&config)
+ err = executeClean(ctx, &config, initSvc, customeDeleteList)
if err != nil {
- log.Fatal("ERROR: ", err)
+ return err
}
+
+ return err
},
}
-// An action function that removes Lambda versions
-func executeClean(config *cliConfig) error {
+// executeClean is the main function that executes the clean-up process
+// It takes a context, a pointer to a cliConfig struct, a pointer to a lambda client, and a list of custom lambdas to delete
+// An error is returned if the function fails to execute
+func executeClean(ctx context.Context, config *cliConfig, svc *lambda.Client, customList []string) error {
startTime := time.Now()
var (
@@ -151,7 +162,7 @@ func executeClean(config *cliConfig) error {
)
log.Info("Scanning AWS environment in " + *config.RegionFlag)
- lambdaList, err := getAllLambdas(ctx, svc, CustomeDeleteList)
+ lambdaList, err := getAllLambdas(ctx, svc, customList)
if err != nil {
log.Error("ERROR: ", err)
log.Fatal("ERROR: Failed to retrieve Lambda list.")
@@ -205,7 +216,7 @@ func executeClean(config *cliConfig) error {
log.Info("............")
- if DryRun {
+ if *config.DryRun {
numVerDeleted := countDeleteVersions(globalLambdaDeleteInputStructs)
log.Info(fmt.Sprintf("%d unique versions will be removed in an actual execution.", numVerDeleted))
spaceRemovedPreview := calculateSpaceRemoval(globalLambdaDeleteList)
@@ -223,7 +234,7 @@ func executeClean(config *cliConfig) error {
}
// Recalculate storage size
- updatedLambdaList, err := getAllLambdas(ctx, svc, CustomeDeleteList)
+ updatedLambdaList, err := getAllLambdas(ctx, svc, customList)
if err != nil {
log.Error("ERROR: ", err)
log.Fatal("ERROR: Failed to retrieve Lambda list.")
@@ -285,7 +296,8 @@ func displayDuration(startTime time.Time) {
log.Infof("Job Duration Time: %f%s", elapsedTime, timeUnit)
}
-// Generates a list of Lambda version delete structs
+// generateDeleteInputStructs takes a list of lambda.DeleteFunctionInput and a boolean value to determine if the user wants more details. The function returns a list of lambda.DeleteFunctionInput
+// An error is returned if the function fails to execute
func generateDeleteInputStructs(versionsList [][]types.FunctionConfiguration, details bool) ([][]lambda.DeleteFunctionInput, error) {
var (
returnError error
@@ -321,7 +333,8 @@ func generateDeleteInputStructs(versionsList [][]types.FunctionConfiguration, de
return output, returnError
}
-// Returns a count of versions in a slice of lambda.DeleteFunctionInput
+// calculateSpaceRemoval returns the total size of all the versions to be deleted.
+// The function takes a list of lambda.DeleteFunctionInput and returns an int
func calculateSpaceRemoval(deleteList [][]types.FunctionConfiguration) int {
var (
size int
@@ -338,7 +351,8 @@ func calculateSpaceRemoval(deleteList [][]types.FunctionConfiguration) int {
return size
}
-// Returns a count of versions in a slice of lambda.DeleteFunctionInput
+// countDeleteVersions returns the total number of versions to be deleted.
+// The function takes a list of lambda.DeleteFunctionInput and returns an int
func countDeleteVersions(deleteList [][]lambda.DeleteFunctionInput) int {
var (
versionsCount int
@@ -351,7 +365,9 @@ func countDeleteVersions(deleteList [][]lambda.DeleteFunctionInput) int {
return versionsCount
}
-// Deletes all Lambda versions specified in the input list
+// deleteLambdaVersion takes a list of lambda.DeleteFunctionInput and deletes all the versions in the list
+// The function takes a context, a pointer to a lambda client, and a list of lambda.DeleteFunctionInput. A variadic operator is used to allow the user to pass in multiple lists of lambda.DeleteFunctionInput
+// Use this function with caution as it will delete all the versions in the list.
func deleteLambdaVersion(ctx context.Context, svc *lambda.Client, deleteList ...[]lambda.DeleteFunctionInput) error {
var (
returnError error
@@ -376,7 +392,7 @@ func deleteLambdaVersion(ctx context.Context, svc *lambda.Client, deleteList ...
return returnError
}
-// Generate a list of Lambdas to remove based on the desired retain value
+// getLambdasToDeleteList takes a list of lambda.FunctionConfiguration and a int8 value to determine how many versions to retain. The function returns a list of lambda.FunctionConfiguration
func getLambdasToDeleteList(list []types.FunctionConfiguration, retainCount int8) []types.FunctionConfiguration {
var retainNumber int
// Ensure the passed in parameter is greater than zero
@@ -397,7 +413,7 @@ func getLambdasToDeleteList(list []types.FunctionConfiguration, retainCount int8
}
}
-// Return a list of all Lambdas in the respective AWS account
+// getAllLambdas returns a list of all available lambdas in the AWS environment. The function takes a context, a pointer to a lambda client, and a list of custom lambdas function names to delete
func getAllLambdas(ctx context.Context, svc *lambda.Client, customList []string) ([]types.FunctionConfiguration, error) {
var (
lambdasListOutput []types.FunctionConfiguration
@@ -438,14 +454,16 @@ func getAllLambdas(ctx context.Context, svc *lambda.Client, customList []string)
}
returnError = err
}
- lambdasListOutput = append(lambdasListOutput, *result.Configuration)
+ if result != nil && result.Configuration != nil {
+ lambdasListOutput = append(lambdasListOutput, *result.Configuration)
+ }
}
}
return lambdasListOutput, returnError
}
-// A function that returns all the version of a Lambda
+// getAllLambdaVersion returns a list of all available versions for a given lambda. The function takes a context, a pointer to a lambda client, and a lambda.FunctionConfiguration
func getAllLambdaVersion(
ctx context.Context,
svc *lambda.Client,
@@ -527,7 +545,7 @@ func (a byVersion) Less(i, j int) bool {
return one > two
}
-// A function that calculates the aggregate sum of all the functions' size
+// getLambdaStorage calculates the aggregate sum of all the functions' size
func getLambdaStorage(list []types.FunctionConfiguration) (int64, error) {
var (
sizeCounter int64
@@ -541,9 +559,12 @@ func getLambdaStorage(list []types.FunctionConfiguration) (int64, error) {
return sizeCounter, returnError
}
-// Validates that the user passed in a valid AWS Region
-func validateRegion(f embed.FS, input string) string {
+// validateRegion validates the user input to ensure it is a valid AWS region. The function takes a embed.FS and a string. The function returns a string and an error
+// An embedded file is used to validate the user input. The embedded file contains a list of all the AWS regions
+// Example of the embedded file: ap-south-2 ap-south-1 eu-south-1 eu-south-2 me-central-1 ca-central-1 eu-central-1 eu-central-2
+func validateRegion(f embed.FS, input string) (string, error) {
var output string
+ var err error
rawData, _ := f.ReadFile(regionFile)
regionsList := strings.Split(string(rawData), " ")
@@ -555,13 +576,14 @@ func validateRegion(f embed.FS, input string) string {
}
if output == "" {
- log.Fatal(input, " is an invalid AWS region. If this is an error please")
+ err = errors.New(input + " is an invalid AWS region. If this is an error please report it")
+ return "", err
}
- return output
+ return output, err
}
-// calculateFileSize returns the size of a file in bytes. The function takes a cliConfig paramter to determine the number format type to return
+// calculateFileSize returns the size of a file in bytes. The function takes a cliConfig parameter to determine the number format type to return
func calculateFileSize(value uint64, config *cliConfig) string {
if *config.SizeIEC {
return humanize.IBytes(value)
diff --git a/cmd/clean_test.go b/cmd/clean_test.go
index 0c53f31..7891c57 100644
--- a/cmd/clean_test.go
+++ b/cmd/clean_test.go
@@ -5,7 +5,11 @@ package cmd
import (
"bytes"
+ "context"
"embed"
+ "errors"
+ "fmt"
+ "os"
"regexp"
"sort"
"testing"
@@ -14,9 +18,14 @@ import (
_ "embed"
"github.com/aws/aws-sdk-go-v2/aws"
+ "github.com/aws/aws-sdk-go-v2/config"
+ "github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/lambda"
"github.com/aws/aws-sdk-go-v2/service/lambda/types"
+ "github.com/docker/go-connections/nat"
log "github.com/sirupsen/logrus"
+ "github.com/testcontainers/testcontainers-go"
+ "github.com/testcontainers/testcontainers-go/modules/localstack"
)
var (
@@ -51,17 +60,6 @@ func TestGetLambdaStorage(t *testing.T) {
}
}
-func TestValidateRegion(t *testing.T) {
- input := "us-east-1"
- want := "us-east-1"
- got := validateRegion(rr, input)
-
- if got != want {
- t.Fatalf("The provided input is valid, %s is a valid region", input)
- }
-
-}
-
func TestGetLambdasToDeleteList(t *testing.T) {
var (
retainNumber int8 = 2
@@ -341,29 +339,1473 @@ func TestCalculateFileSize(t *testing.T) {
if got2 != want2 {
t.Fatalf("Expected the size output to be %s but received %s instead", want2, got2)
}
+
}
func TestDisplayDuration(t *testing.T) {
- startTime := time.Now().Add(-time.Minute * 2)
var buf bytes.Buffer
log.SetOutput(&buf)
+ startTime := time.Now().Add(-time.Second * 30)
+
displayDuration(startTime)
got := buf.String()
- want := "time=.* level=.* msg=\"Job Duration Time: 2.000000m\"\n"
+ want := "time=.* level=.* msg=\"Job Duration Time: 30.00"
if match, _ := regexp.MatchString(want, got); !match {
t.Errorf("displayDuration() = %q, want %q", got, want)
}
-
buf.Reset()
- startTime = time.Now().Add(-time.Second * 30)
+}
- displayDuration(startTime)
+func TestDeleteLambdaVersionError(t *testing.T) {
- got = buf.String()
- want = "time=.* level=.* msg=\"Job Duration Time: 30.000000s\"\n"
- if match, _ := regexp.MatchString(want, got); !match {
- t.Errorf("displayDuration() = %q, want %q", got, want)
+ ctx := context.Background()
+ networkName := "localstack-network-v2"
+
+ localstackContainer, err := localstack.RunContainer(ctx,
+ localstack.WithNetwork(networkName, "localstack"),
+ testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
+ ContainerRequest: testcontainers.ContainerRequest{
+ Image: "localstack/localstack:latest",
+ Env: map[string]string{"SERVICES": "lambda"},
+ },
+ }),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // Clean up the container
+ defer func() {
+ if err := localstackContainer.Terminate(ctx); err != nil {
+ panic(err)
+ }
+ }()
+
+ lambdaClient, err := lambdaClient(ctx, localstackContainer)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String("us-east-1"),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(2),
+ }
+
+ deleteList := []lambda.DeleteFunctionInput{
+ {
+ FunctionName: aws.String("test"),
+ Qualifier: aws.String("1"),
+ },
+ }
+
+ err = deleteLambdaVersion(ctx, lambdaClient, deleteList)
+ if err == nil {
+ t.Errorf("expected an error to be returned but received %v", err)
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ })
+
+}
+
+func TestDeleteLambdaVersion(t *testing.T) {
+
+ ctx := context.Background()
+ networkName := "localstack-network-v2"
+
+ localstackContainer, err := localstack.RunContainer(ctx,
+ localstack.WithNetwork(networkName, "localstack"),
+ testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
+ ContainerRequest: testcontainers.ContainerRequest{
+ Image: "localstack/localstack:latest",
+ Env: map[string]string{"SERVICES": "lambda"},
+ },
+ }),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // Clean up the container
+ defer func() {
+ if err := localstackContainer.Terminate(ctx); err != nil {
+ panic(err)
+ }
+ }()
+
+ svc, err := getAWSCredentials(ctx, localstackContainer)
+ if err != nil {
+ panic(err)
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String("us-east-1"),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ bf, err := getZipPackage("../tests/handler.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = addFunctions(ctx, svc, bf)
+ if err != nil {
+ panic(err)
+ }
+
+ bf2, err := getZipPackage("../tests/handler2.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf2)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ deleteList := []lambda.DeleteFunctionInput{
+ {
+ FunctionName: aws.String("func1"),
+ Qualifier: aws.String("2"),
+ },
+ }
+
+ err = deleteLambdaVersion(ctx, svc, deleteList)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ result, err := listFunctionVersions(ctx, svc, "func1")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+ if result != 2 {
+ t.Errorf("expected 2 functions to be returned but received %v", result)
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ })
+
+}
+func TestGetAllLambdas(t *testing.T) {
+
+ ctx := context.Background()
+ networkName := "localstack-network-v2"
+
+ localstackContainer, err := localstack.RunContainer(ctx,
+ localstack.WithNetwork(networkName, "localstack"),
+ testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
+ ContainerRequest: testcontainers.ContainerRequest{
+ Image: "localstack/localstack:latest",
+ Env: map[string]string{"SERVICES": "lambda"},
+ },
+ }),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // Clean up the container
+ defer func() {
+ if err := localstackContainer.Terminate(ctx); err != nil {
+ panic(err)
+ }
+ }()
+
+ svc, err := getAWSCredentials(ctx, localstackContainer)
+ if err != nil {
+ panic(err)
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String("us-east-1"),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ bf, err := getZipPackage("../tests/handler.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = addFunctions(ctx, svc, bf)
+ if err != nil {
+ panic(err)
+ }
+
+ bf2, err := getZipPackage("../tests/handler2.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf2)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ lambdaListResult, err := getAllLambdas(ctx, svc, []string{})
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ result, err := listFunctions(ctx, svc)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ if len(lambdaListResult) != result {
+ t.Errorf("expected 3 functions to be returned but received %v", result)
+ }
+
+ lambdaListResult2, err := getAllLambdas(ctx, svc, []string{"func1"})
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ if len(lambdaListResult2) != 1 {
+ t.Errorf("Scenario 2: expected 1 functions to be returned but received %v", len(lambdaListResult2))
+ }
+
+ _, err = getAllLambdas(ctx, svc, []string{"func22"})
+ if err != nil {
+ t.Errorf("expected an error to be returned but received %v", err)
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ })
+
+}
+
+func TestGetAllLambdaVersion(t *testing.T) {
+
+ ctx := context.Background()
+ networkName := "localstack-network-v2"
+
+ localstackContainer, err := localstack.RunContainer(ctx,
+ localstack.WithNetwork(networkName, "localstack"),
+ testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
+ ContainerRequest: testcontainers.ContainerRequest{
+ Image: "localstack/localstack:latest",
+ Env: map[string]string{"SERVICES": "lambda"},
+ },
+ }),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // Clean up the container
+ defer func() {
+ if err := localstackContainer.Terminate(ctx); err != nil {
+ panic(err)
+ }
+ }()
+
+ svc, err := getAWSCredentials(ctx, localstackContainer)
+ if err != nil {
+ panic(err)
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String("us-east-1"),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ bf, err := getZipPackage("../tests/handler.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = addFunctions(ctx, svc, bf)
+ if err != nil {
+ panic(err)
+ }
+
+ bf2, err := getZipPackage("../tests/handler2.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf2)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ versions, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ if len(versions) != 3 {
+ t.Errorf("expected 3 versions to be returned but received %v", len(versions))
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(true),
+ Retain: aws.Int8(0),
+ }
+
+ })
+
+}
+func TestGetAllLambdaVersionWithAlias(t *testing.T) {
+
+ ctx := context.Background()
+ networkName := "localstack-network-v2"
+
+ localstackContainer, err := localstack.RunContainer(ctx,
+ localstack.WithNetwork(networkName, "localstack"),
+ testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
+ ContainerRequest: testcontainers.ContainerRequest{
+ Image: "localstack/localstack:latest",
+ Env: map[string]string{"SERVICES": "lambda"},
+ },
+ }),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // Clean up the container
+ defer func() {
+ if err := localstackContainer.Terminate(ctx); err != nil {
+ panic(err)
+ }
+ }()
+
+ svc, err := getAWSCredentials(ctx, localstackContainer)
+ if err != nil {
+ panic(err)
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String("us-east-1"),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(true),
+ Retain: aws.Int8(0),
+ }
+
+ bf, err := getZipPackage("../tests/handler.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = addFunctions(ctx, svc, bf)
+ if err != nil {
+ panic(err)
+ }
+
+ bf2, err := getZipPackage("../tests/handler2.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf2)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = publishAlias(ctx, svc, "func1", "DEMO", "2")
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ versions, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func1"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ if len(versions) != 2 {
+ t.Errorf("expected 2 versions to be returned but received %v", len(versions))
+ }
+
+ _, err = getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func22"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func22"),
+ }, GlobalCliConfig)
+ if err == nil {
+ t.Errorf("expected an error to be returned but received %v", err)
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ })
+
+}
+
+func TestExecuteClean(t *testing.T) {
+ ctx := context.TODO()
+ networkName := "localstack-network-v2"
+
+ localstackContainer, err := localstack.RunContainer(ctx,
+ localstack.WithNetwork(networkName, "localstack"),
+ testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
+ ContainerRequest: testcontainers.ContainerRequest{
+ Image: "localstack/localstack:latest",
+ Env: map[string]string{"SERVICES": "lambda"},
+ },
+ }),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // Clean up the container
+ defer func() {
+ if err := localstackContainer.Terminate(ctx); err != nil {
+ panic(err)
+ }
+ }()
+
+ svc, err := getAWSCredentials(ctx, localstackContainer)
+ if err != nil {
+ panic(err)
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ bf, err := getZipPackage("../tests/handler.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = addFunctions(ctx, svc, bf)
+ if err != nil {
+ panic(err)
+ }
+
+ bf2, err := getZipPackage("../tests/handler2.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf2)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = publishAlias(ctx, svc, "func1", "DEMO", "2")
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ err = executeClean(ctx, &GlobalCliConfig, svc, []string{})
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+}
+
+func TestCleanCMDDryRun(t *testing.T) {
+
+ ctx := context.TODO()
+ networkName := "localstack-network-v2"
+
+ localstackContainer, err := localstack.RunContainer(ctx,
+ localstack.WithNetwork(networkName, "localstack"),
+ testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
+ ContainerRequest: testcontainers.ContainerRequest{
+ Image: "localstack/localstack:latest",
+ Env: map[string]string{"SERVICES": "lambda"},
+ },
+ }),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // Clean up the container
+ defer func() {
+ if err := localstackContainer.Terminate(ctx); err != nil {
+ panic(err)
+ }
+ }()
+
+ provider, err := testcontainers.NewDockerProvider()
+ if err != nil {
+ panic(err)
+ }
+
+ host, err := provider.DaemonHost(ctx)
+ if err != nil {
+ panic(err)
+ }
+
+ mappedPort, err := localstackContainer.MappedPort(ctx, nat.Port("4566/tcp"))
+ if err != nil {
+ panic(err)
+ }
+
+ bf, err := getZipPackage("../tests/handler.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ svc, err := getAWSCredentials(ctx, localstackContainer)
+ if err != nil {
+ panic(err)
+ }
+
+ _, err = addFunctions(ctx, svc, bf)
+ if err != nil {
+ panic(err)
+ }
+
+ bf2, err := getZipPackage("../tests/handler2.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf2)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ bf3, err := getZipPackage("../tests/handler3.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf3)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String("us-east-1"),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(false),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ versions, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func1"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ if len(versions) != 4 {
+ t.Errorf("expected 4 versions to be returned but received %v", len(versions))
+ }
+
+ t.Logf("Pre-Clean # of versions: %v", len(versions))
+
+ os.Setenv("AWS_ENDPOINT_URL", fmt.Sprintf("http://%s:%d", host, mappedPort.Int()))
+ os.Setenv("AWS_EC2_METADATA_DISABLED", "true")
+ os.Setenv("AWS_ACCESS_KEY_ID", "test")
+ os.Setenv("AWS_SECRET_ACCESS_KEY", "test")
+
+ err = cleanCmd.RunE(cleanCmd, []string{})
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ actual, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func1"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ t.Logf("Post-Clean # of versions: %v", len(actual))
+
+ if len(actual) != 4 {
+ t.Errorf("expected 4 versions to be returned but received %v", len(actual))
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(2),
+ }
+
+ os.Unsetenv("AWS_ENDPOINT_URL")
+ os.Unsetenv("AWS_EC2_METADATA_DISABLED")
+ os.Unsetenv("AWS_ACCESS_KEY_ID")
+ os.Unsetenv("AWS_SECRET_ACCESS_KEY")
+
+ })
+
+}
+
+func TestCleanCMD(t *testing.T) {
+
+ ctx := context.TODO()
+ networkName := "localstack-network-v2"
+
+ localstackContainer, err := localstack.RunContainer(ctx,
+ localstack.WithNetwork(networkName, "localstack"),
+ testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
+ ContainerRequest: testcontainers.ContainerRequest{
+ Image: "localstack/localstack:latest",
+ Env: map[string]string{"SERVICES": "lambda"},
+ },
+ }),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // Clean up the container
+ defer func() {
+ if err := localstackContainer.Terminate(ctx); err != nil {
+ panic(err)
+ }
+ }()
+
+ provider, err := testcontainers.NewDockerProvider()
+ if err != nil {
+ panic(err)
+ }
+
+ host, err := provider.DaemonHost(ctx)
+ if err != nil {
+ panic(err)
+ }
+
+ mappedPort, err := localstackContainer.MappedPort(ctx, nat.Port("4566/tcp"))
+ if err != nil {
+ panic(err)
+ }
+
+ bf, err := getZipPackage("../tests/handler.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ svc, err := getAWSCredentials(ctx, localstackContainer)
+ if err != nil {
+ panic(err)
+ }
+
+ _, err = addFunctions(ctx, svc, bf)
+ if err != nil {
+ panic(err)
+ }
+
+ bf2, err := getZipPackage("../tests/handler2.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf2)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ bf3, err := getZipPackage("../tests/handler3.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf3)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String("us-east-1"),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(false),
+ Verbose: aws.Bool(false),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ versions, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func1"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ if len(versions) != 4 {
+ t.Errorf("expected 4 versions to be returned but received %v", len(versions))
+ }
+
+ t.Logf("Pre-Clean # of versions: %v", len(versions))
+
+ os.Setenv("AWS_ENDPOINT_URL", fmt.Sprintf("http://%s:%d", host, mappedPort.Int()))
+ os.Setenv("AWS_EC2_METADATA_DISABLED", "true")
+ os.Setenv("AWS_ACCESS_KEY_ID", "test")
+ os.Setenv("AWS_SECRET_ACCESS_KEY", "test")
+
+ err = cleanCmd.RunE(cleanCmd, []string{})
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ actual, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func1"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ t.Logf("Post-Clean # of versions: %v", len(actual))
+
+ if len(actual) != 2 {
+ t.Errorf("expected 2 versions to be returned but received %v", len(actual))
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(2),
+ }
+
+ os.Unsetenv("AWS_ENDPOINT_URL")
+ os.Unsetenv("AWS_EC2_METADATA_DISABLED")
+ os.Unsetenv("AWS_ACCESS_KEY_ID")
+ os.Unsetenv("AWS_SECRET_ACCESS_KEY")
+
+ })
+
+}
+
+func TestCleanCMDWithCustomList(t *testing.T) {
+
+ ctx := context.TODO()
+ networkName := "localstack-network-v2"
+
+ localstackContainer, err := localstack.RunContainer(ctx,
+ localstack.WithNetwork(networkName, "localstack"),
+ testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
+ ContainerRequest: testcontainers.ContainerRequest{
+ Image: "localstack/localstack:latest",
+ Env: map[string]string{"SERVICES": "lambda"},
+ },
+ }),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // Clean up the container
+ defer func() {
+ if err := localstackContainer.Terminate(ctx); err != nil {
+ panic(err)
+ }
+ }()
+
+ provider, err := testcontainers.NewDockerProvider()
+ if err != nil {
+ panic(err)
+ }
+
+ host, err := provider.DaemonHost(ctx)
+ if err != nil {
+ panic(err)
+ }
+
+ mappedPort, err := localstackContainer.MappedPort(ctx, nat.Port("4566/tcp"))
+ if err != nil {
+ panic(err)
+ }
+
+ bf, err := getZipPackage("../tests/handler.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ svc, err := getAWSCredentials(ctx, localstackContainer)
+ if err != nil {
+ panic(err)
+ }
+
+ _, err = addFunctions(ctx, svc, bf)
+ if err != nil {
+ panic(err)
+ }
+
+ bf2, err := getZipPackage("../tests/handler2.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf2)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ bf3, err := getZipPackage("../tests/handler3.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf3)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String("us-east-1"),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(false),
+ LambdaListFile: aws.String("../tests/custom.yml"),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ versions, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func1"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ if len(versions) != 4 {
+ t.Errorf("expected 4 versions to be returned but received %v", len(versions))
+ }
+
+ t.Logf("Pre-Clean # of versions: %v", len(versions))
+
+ os.Setenv("AWS_ENDPOINT_URL", fmt.Sprintf("http://%s:%d", host, mappedPort.Int()))
+ os.Setenv("AWS_EC2_METADATA_DISABLED", "true")
+ os.Setenv("AWS_ACCESS_KEY_ID", "test")
+ os.Setenv("AWS_SECRET_ACCESS_KEY", "test")
+
+ err = cleanCmd.RunE(cleanCmd, []string{})
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ actual, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func3"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ t.Logf("Post-Clean # of versions: %v", len(actual))
+
+ if len(actual) != 4 {
+ t.Errorf("expected 4 versions to be returned but received %v", len(actual))
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String("us-east-1"),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(false),
+ Verbose: aws.Bool(false),
+ LambdaListFile: aws.String("../tests/custom.yml"),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ err = cleanCmd.RunE(cleanCmd, []string{})
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ actual2, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func3"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ t.Logf("Post-Clean Non-Dry # of versions: %v", len(actual))
+
+ if len(actual2) != 2 {
+ t.Errorf("expected 2 versions to be returned but received %v", len(actual2))
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(2),
+ }
+
+ os.Unsetenv("AWS_ENDPOINT_URL")
+ os.Unsetenv("AWS_EC2_METADATA_DISABLED")
+ os.Unsetenv("AWS_ACCESS_KEY_ID")
+ os.Unsetenv("AWS_SECRET_ACCESS_KEY")
+
+ })
+
+}
+
+func TestAWSEnteryMissingEnvRegion(t *testing.T) {
+
+ expectedErr := "Missing region flag and AWS_DEFAULT_REGION env variable. Please use -r and provide a valid AWS region"
+
+ err := cleanCmd.RunE(cleanCmd, []string{"--profile", "default", "--retain", "2", "--dry-run"})
+ if err == nil && err.Error() != expectedErr {
+ t.Fatalf("Expected an error to be returned but received %v", err.Error())
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(2),
+ }
+
+ })
+
+}
+
+func TestAWSValidateRegion(t *testing.T) {
+
+ input := "us-east-1"
+ want := "us-east-1"
+ got, err := validateRegion(rr, input)
+ if err != nil || got != want {
+ t.Fatalf("The provided input is valid, %s is a valid region", input)
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ })
+
+}
+
+func TestValidateRegionWithEnv(t *testing.T) {
+
+ os.Setenv("AWS_DEFAULT_REGION", "not-valid")
+ expectedErr := "not-valid is an invalid AWS region. If this is an error please report it"
+ err := cleanCmd.RunE(cleanCmd, []string{"--profile", "default", "--retain", "2", "--dry-run"})
+ if err == nil || err.Error() != expectedErr {
+ t.Fatalf("Expected an error to be returned but received %v", err.Error())
+ }
+
+ os.Setenv("AWS_DEFAULT_REGION", "")
+ expectedErr = "missing region flag and AWS_DEFAULT_REGION env variable. Please use -r and provide a valid AWS region"
+ err = cleanCmd.RunE(cleanCmd, []string{"--profile", "default", "--retain", "2", "--dry-run"})
+ if err == nil || err.Error() != expectedErr {
+ t.Fatalf("Expected an error to be returned but received %v", err.Error())
+ }
+
+ // Set rootCmd to use the region flag
+ GlobalCliConfig.RegionFlag = aws.String("not-valid")
+ expectedErr = "not-valid is an invalid AWS region. If this is an error please report it"
+ err = cleanCmd.RunE(cleanCmd, []string{"--profile", "default", "--region", "not-valid", "--retain", "2", "--dry-run"})
+ if err == nil || err.Error() != expectedErr {
+ t.Fatalf("Expected an error to be returned but received %v", err.Error())
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(false),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ })
+
+}
+
+func TestAWSValidateRegionWithFlag(t *testing.T) {
+
+ expectedErr := "missing region flag and AWS_DEFAULT_REGION env variable. Please use -r and provide a valid AWS region"
+ err := cleanCmd.RunE(cleanCmd, []string{"--profile", "default", "--region", "not-valid", "--retain", "2", "--dry-run"})
+ if err == nil || err.Error() != expectedErr {
+ t.Fatalf("Expected an error to be returned but received %v", err.Error())
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ })
+}
+
+func TestAWSInvalidRegion(t *testing.T) {
+
+ input := "not-valid"
+ want := "not-valid is an invalid AWS region. If this is an error please report it"
+ got, err := validateRegion(rr, input)
+
+ if err == nil || err.Error() != want {
+ t.Fatalf("The provided input is invalid, %s is not a valid region", got)
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ })
+}
+
+/*
+
+THE CODE BELOW IS FOR TESTING PURPOSES ONLY
+
+
+*/
+
+// lambdaClient returns a lambda client configured to use the localstack containers
+func lambdaClient(ctx context.Context, l *localstack.LocalStackContainer) (*lambda.Client, error) {
+ mappedPort, err := l.MappedPort(ctx, nat.Port("4566/tcp"))
+ if err != nil {
+ return nil, err
+ }
+
+ provider, err := testcontainers.NewDockerProvider()
+ if err != nil {
+ return nil, err
+ }
+ defer provider.Close()
+
+ host, err := provider.DaemonHost(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ customResolver := aws.EndpointResolverWithOptionsFunc(
+ func(service, region string, opts ...interface{}) (aws.Endpoint, error) {
+ return aws.Endpoint{
+ PartitionID: "aws",
+ URL: fmt.Sprintf("http://%s:%d", host, mappedPort.Int()),
+ SigningRegion: region,
+ }, nil
+ })
+
+ awsCfg, err := config.LoadDefaultConfig(context.TODO(),
+ config.WithRegion("us-east-1"),
+ config.WithEndpointResolverWithOptions(customResolver),
+ config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider("aaaa", "bbbb", "cccc")),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ client := lambda.NewFromConfig(awsCfg, func(o *lambda.Options) {})
+
+ return client, nil
+}
+
+func addFunctions(ctx context.Context, svc *lambda.Client, zipPackage *bytes.Buffer) (string, error) {
+
+ list := []lambda.CreateFunctionInput{
+ {
+ Code: &types.FunctionCode{
+ ZipFile: zipPackage.Bytes(),
+ },
+ Description: aws.String("func1"),
+ FunctionName: aws.String("func1"),
+ Handler: aws.String("index.handler"),
+ Role: aws.String("arn:aws:iam::123456789012:role/lambda-role"),
+ Runtime: types.RuntimeNodejs18x,
+ Publish: true,
+ },
+ {
+ Code: &types.FunctionCode{
+ ZipFile: zipPackage.Bytes(),
+ },
+ Description: aws.String("func2"),
+ FunctionName: aws.String("func2"),
+ Handler: aws.String("index.handler"),
+ Role: aws.String("arn:aws:iam::123456789012:role/lambda-role"),
+ Runtime: types.RuntimeNodejs18x,
+ Publish: true,
+ },
+ {
+ Code: &types.FunctionCode{
+ ZipFile: zipPackage.Bytes(),
+ },
+ Description: aws.String("func3"),
+ FunctionName: aws.String("func3"),
+ Handler: aws.String("index.handler"),
+ Role: aws.String("arn:aws:iam::123456789012:role/lambda-role"),
+ Runtime: types.RuntimeNodejs18x,
+ Publish: true,
+ },
+ }
+
+ var result string
+
+ for _, input := range list {
+ var state types.State
+ item := input
+ output, err := svc.CreateFunction(ctx, &item)
+ if err != nil {
+ var resConflict *types.ResourceConflictException
+ if errors.As(err, &resConflict) {
+ log.Printf("Function %v already exists.\n", "test")
+ state = types.StateActive
+ } else {
+ log.Panicf("Couldn't create function %v. Here's why: %v\n", "test", err)
+ }
+ } else {
+ waiter := lambda.NewFunctionActiveV2Waiter(svc)
+ funcOutput, err := waiter.WaitForOutput(context.TODO(), &lambda.GetFunctionInput{
+ FunctionName: aws.String(*input.FunctionName)}, 2*time.Minute)
+ if err != nil {
+ log.Panicf("Couldn't wait for function %v to be active. Here's why: %v\n", "test", err)
+ } else {
+ state = funcOutput.Configuration.State
+ }
+ }
+
+ fmt.Println("Function ARN: ", *output.FunctionArn)
+
+ result += fmt.Sprintf("Function %v is %v\n", *input.FunctionName, state)
}
+
+ return fmt.Sprintf("Result: %v", result), nil
+}
+
+func listFunctions(ctx context.Context, svc *lambda.Client) (int, error) {
+
+ output, err := svc.ListFunctions(ctx, &lambda.ListFunctionsInput{})
+ if err != nil {
+ return 0, err
+ }
+
+ return len(output.Functions), err
+
+}
+
+func getAWSCredentials(ctx context.Context, l *localstack.LocalStackContainer) (*lambda.Client, error) {
+
+ provider, err := testcontainers.NewDockerProvider()
+ if err != nil {
+ return nil, err
+ }
+
+ host, err := provider.DaemonHost(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ mappedPort, err := l.MappedPort(ctx, nat.Port("4566/tcp"))
+ if err != nil {
+ return nil, err
+ }
+
+ customResolver := aws.EndpointResolverWithOptionsFunc(
+ func(service, region string, opts ...interface{}) (aws.Endpoint, error) {
+ return aws.Endpoint{
+ PartitionID: "aws",
+ URL: fmt.Sprintf("http://%s:%d", host, mappedPort.Int()),
+ SigningRegion: region,
+ }, nil
+ })
+ awsCfg, err := config.LoadDefaultConfig(context.TODO(),
+ config.WithSharedConfigFiles([]string{"/tests/config"}),
+ config.WithRegion("us-east-1"),
+ config.WithEndpointResolverWithOptions(customResolver),
+ config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider("aaaa", "bbbb", "cccc")),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ return lambda.NewFromConfig(awsCfg), nil
+
+}
+
+func updateFunctions(ctx context.Context, svc *lambda.Client, zipPackage bytes.Buffer) (string, error) {
+
+ list := []lambda.UpdateFunctionCodeInput{
+ {
+ FunctionName: aws.String("func1"),
+ ZipFile: zipPackage.Bytes(),
+ Publish: true,
+ },
+ {
+ FunctionName: aws.String("func2"),
+ ZipFile: zipPackage.Bytes(),
+ Publish: true,
+ },
+ {
+ FunctionName: aws.String("func3"),
+ ZipFile: zipPackage.Bytes(),
+ Publish: true,
+ },
+ }
+
+ var result string
+
+ for _, input := range list {
+ var state types.State
+ item := input
+ _, err := svc.UpdateFunctionCode(ctx, &item)
+ if err != nil {
+ var resConflict *types.ResourceConflictException
+ if errors.As(err, &resConflict) {
+ log.Printf("Function %v already exists.\n", "test")
+ state = types.StateActive
+ } else {
+ log.Panicf("Couldn't create function %v. Here's why: %v\n", "test", err)
+ }
+ } else {
+ waiter := lambda.NewFunctionActiveV2Waiter(svc)
+ funcOutput, err := waiter.WaitForOutput(context.TODO(), &lambda.GetFunctionInput{
+ FunctionName: aws.String(*input.FunctionName)}, 2*time.Minute)
+ if err != nil {
+ log.Panicf("Couldn't wait for function %v to be active. Here's why: %v\n", "test", err)
+ } else {
+ state = funcOutput.Configuration.State
+ }
+ }
+
+ result += fmt.Sprintf("Function %v was updated and the state is %v\n", *input.FunctionName, state)
+ }
+
+ return fmt.Sprintf("Result: %v", result), nil
+}
+
+func publishAlias(ctx context.Context, svc *lambda.Client, functionName string, aliasName string, version string) (string, error) {
+
+ input := lambda.CreateAliasInput{
+ FunctionName: aws.String(functionName),
+ FunctionVersion: aws.String(version),
+ Name: aws.String(aliasName),
+ Description: aws.String("Alias Test"),
+ }
+
+ _, err := svc.CreateAlias(ctx, &input)
+ if err != nil {
+ fmt.Println(err)
+ return "", err
+ }
+
+ return fmt.Sprintf("Alias %v was created for function %v", aliasName, functionName), nil
+}
+
+func getZipPackage(zipFile string) (*bytes.Buffer, error) {
+ _, err := os.Stat(zipFile)
+ if err != nil {
+ return nil, err
+ }
+
+ zipPackage, err := os.Open(zipFile)
+ if err != nil {
+ return nil, err
+ }
+
+ defer zipPackage.Close()
+
+ buf := new(bytes.Buffer)
+ _, err = buf.ReadFrom(zipPackage)
+ if err != nil {
+ return nil, err
+ }
+
+ return buf, err
+
+}
+
+func listFunctionVersions(ctx context.Context, svc *lambda.Client, funcName string) (int, error) {
+
+ output, err := svc.ListVersionsByFunction(ctx, &lambda.ListVersionsByFunctionInput{
+ FunctionName: aws.String(funcName),
+ })
+
+ if err != nil {
+ return 0, err
+ }
+
+ return len(output.Versions), nil
}
diff --git a/cmd/root.go b/cmd/root.go
index bcf1dfb..8608413 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -54,18 +54,14 @@ var rootCmd = &cobra.Command{
Use: "glc",
Short: "A CLI tool for cleaning up AWS Lambda versions",
Long: `A CLI tool for cleaning up AWS Lambda versions`,
- Run: func(cmd *cobra.Command, args []string) {
+ RunE: func(cmd *cobra.Command, args []string) error {
err := cmd.Help()
if err != nil {
- log.WithFields(log.Fields{
- "package": "cmd",
- "file": "root.go",
- "parent_function": "generateDocFlag",
- "function": "cmd.Help",
- "error": err,
- "data": nil,
- }).Fatal("Error outputting help!", IssueMSG)
+ log.Info("Error executing the CLI!")
+ return err
}
+
+ return err
},
}
@@ -105,18 +101,10 @@ func init() {
// Execute is the main execution function
func Execute() {
if err := rootCmd.Execute(); err != nil {
- if Verbose {
- log.WithFields(log.Fields{
- "package": "cmd",
- "file": "root.go",
- "function": "Execute",
- "error": err,
- "data": nil,
- }).Fatal("Error executing the CLI!", IssueMSG)
- } else {
- log.Fatal("Error executing the CLI!", IssueMSG)
- }
+ log.Error(err)
+ os.Exit(1)
}
+
}
// createHTTPClient creates an HTTP client with TLS
diff --git a/cmd/root_test.go b/cmd/root_test.go
new file mode 100644
index 0000000..ed3c168
--- /dev/null
+++ b/cmd/root_test.go
@@ -0,0 +1,297 @@
+// Copyright (c) karl-cardenas-coding
+// SPDX-License-Identifier: MIT
+
+package cmd
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/aws/aws-sdk-go-v2/aws"
+ "github.com/aws/aws-sdk-go-v2/service/lambda/types"
+ "github.com/docker/go-connections/nat"
+ "github.com/testcontainers/testcontainers-go"
+ "github.com/testcontainers/testcontainers-go/modules/localstack"
+)
+
+func TestRoot(t *testing.T) {
+
+ err := rootCmd.RunE(rootCmd, []string{})
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+}
+
+func TestRootCMD(t *testing.T) {
+ ctx := context.TODO()
+ networkName := "localstack-network-v2"
+
+ localstackContainer, err := localstack.RunContainer(ctx,
+ localstack.WithNetwork(networkName, "localstack"),
+ testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
+ ContainerRequest: testcontainers.ContainerRequest{
+ Image: "localstack/localstack:latest",
+ Env: map[string]string{"SERVICES": "lambda"},
+ },
+ }),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // Clean up the container
+ defer func() {
+ if err := localstackContainer.Terminate(ctx); err != nil {
+ panic(err)
+ }
+ }()
+
+ provider, err := testcontainers.NewDockerProvider()
+ if err != nil {
+ panic(err)
+ }
+
+ host, err := provider.DaemonHost(ctx)
+ if err != nil {
+ panic(err)
+ }
+
+ mappedPort, err := localstackContainer.MappedPort(ctx, nat.Port("4566/tcp"))
+ if err != nil {
+ panic(err)
+ }
+
+ bf, err := getZipPackage("../tests/handler.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ svc, err := getAWSCredentials(ctx, localstackContainer)
+ if err != nil {
+ panic(err)
+ }
+
+ _, err = addFunctions(ctx, svc, bf)
+ if err != nil {
+ panic(err)
+ }
+
+ bf2, err := getZipPackage("../tests/handler2.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf2)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String("us-east-1"),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(false),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ versions, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func1"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ if len(versions) != 3 {
+ t.Errorf("expected 3 versions to be returned but received %v", len(versions))
+ }
+
+ t.Logf("Pre-Clean # of versions: %v", len(versions))
+
+ os.Setenv("AWS_ENDPOINT_URL", fmt.Sprintf("http://%s:%d", host, mappedPort.Int()))
+ os.Setenv("AWS_EC2_METADATA_DISABLED", "true")
+ os.Setenv("AWS_ACCESS_KEY_ID", "test")
+ os.Setenv("AWS_SECRET_ACCESS_KEY", "test")
+
+ err = rootCmd.RunE(rootCmd, []string{})
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ actual, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func1"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ t.Logf("Post-Clean # of versions: %v", len(actual))
+
+ if len(actual) != 3 {
+ t.Errorf("expected 3 versions to be returned but received %v", len(actual))
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(2),
+ }
+
+ os.Unsetenv("AWS_ENDPOINT_URL")
+ os.Unsetenv("AWS_EC2_METADATA_DISABLED")
+ os.Unsetenv("AWS_ACCESS_KEY_ID")
+ os.Unsetenv("AWS_SECRET_ACCESS_KEY")
+
+ })
+}
+
+func TestRootExecute(t *testing.T) {
+ ctx := context.TODO()
+ networkName := "localstack-network-v2"
+
+ localstackContainer, err := localstack.RunContainer(ctx,
+ localstack.WithNetwork(networkName, "localstack"),
+ testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
+ ContainerRequest: testcontainers.ContainerRequest{
+ Image: "localstack/localstack:latest",
+ Env: map[string]string{"SERVICES": "lambda"},
+ },
+ }),
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ // Clean up the container
+ defer func() {
+ if err := localstackContainer.Terminate(ctx); err != nil {
+ panic(err)
+ }
+ }()
+
+ provider, err := testcontainers.NewDockerProvider()
+ if err != nil {
+ panic(err)
+ }
+
+ host, err := provider.DaemonHost(ctx)
+ if err != nil {
+ panic(err)
+ }
+
+ mappedPort, err := localstackContainer.MappedPort(ctx, nat.Port("4566/tcp"))
+ if err != nil {
+ panic(err)
+ }
+
+ bf, err := getZipPackage("../tests/handler.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ svc, err := getAWSCredentials(ctx, localstackContainer)
+ if err != nil {
+ panic(err)
+ }
+
+ _, err = addFunctions(ctx, svc, bf)
+ if err != nil {
+ panic(err)
+ }
+
+ bf2, err := getZipPackage("../tests/handler2.zip")
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ _, err = updateFunctions(ctx, svc, *bf2)
+ if err != nil {
+ t.Logf("expected no error to be returned but received %v", err)
+ }
+
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String("us-east-1"),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(false),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(0),
+ }
+
+ versions, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func1"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ if len(versions) != 3 {
+ t.Errorf("expected 3 versions to be returned but received %v", len(versions))
+ }
+
+ t.Logf("Pre-Clean # of versions: %v", len(versions))
+
+ os.Setenv("AWS_ENDPOINT_URL", fmt.Sprintf("http://%s:%d", host, mappedPort.Int()))
+ os.Setenv("AWS_EC2_METADATA_DISABLED", "true")
+ os.Setenv("AWS_ACCESS_KEY_ID", "test")
+ os.Setenv("AWS_SECRET_ACCESS_KEY", "test")
+
+ Execute()
+
+ actual, err := getAllLambdaVersion(ctx, svc, types.FunctionConfiguration{
+ FunctionName: aws.String("func1"),
+ FunctionArn: aws.String("arn:aws:lambda:us-east-1:000000000000:function:func1"),
+ }, GlobalCliConfig)
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ t.Logf("Post-Clean # of versions: %v", len(actual))
+
+ if len(actual) != 3 {
+ t.Errorf("expected 3 versions to be returned but received %v", len(actual))
+ }
+
+ t.Cleanup(func() {
+ GlobalCliConfig = cliConfig{
+ RegionFlag: aws.String(""),
+ CredentialsFile: aws.Bool(false),
+ ProfileFlag: aws.String(""),
+ DryRun: aws.Bool(true),
+ Verbose: aws.Bool(true),
+ LambdaListFile: aws.String(""),
+ MoreLambdaDetails: aws.Bool(true),
+ SizeIEC: aws.Bool(false),
+ SkipAliases: aws.Bool(false),
+ Retain: aws.Int8(2),
+ }
+
+ os.Unsetenv("AWS_ENDPOINT_URL")
+ os.Unsetenv("AWS_EC2_METADATA_DISABLED")
+ os.Unsetenv("AWS_ACCESS_KEY_ID")
+ os.Unsetenv("AWS_SECRET_ACCESS_KEY")
+
+ })
+}
diff --git a/cmd/version.go b/cmd/version.go
index 9cc2483..7fa741d 100644
--- a/cmd/version.go
+++ b/cmd/version.go
@@ -14,27 +14,31 @@ import (
)
func init() {
- rootCmd.AddCommand(versionCmd)
+ rootCmd.AddCommand(VersionCmd)
}
-var versionCmd = &cobra.Command{
+const (
+ url = "https://api.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/releases/latest"
+)
+
+var VersionCmd = &cobra.Command{
Use: "version",
Short: "Print the current version number of go-lambda-cleanup",
Long: `Prints the current version number of go-lambda-cleanup`,
- Run: func(cmd *cobra.Command, args []string) {
+ RunE: func(cmd *cobra.Command, args []string) error {
version := fmt.Sprintf("go-lambda-cleanup v%s", VersionString)
log.Info(version)
- _, message, err := checkForNewRelease(GlobalHTTPClient, VersionString, UserAgent)
+ _, message, err := checkForNewRelease(GlobalHTTPClient, VersionString, UserAgent, url)
if err != nil {
log.Error(err)
- log.Fatal("unable to check for new releases. " + IssueMSG)
+ return err
}
log.Info(message)
+ return err
},
}
-func checkForNewRelease(client *http.Client, currentVersion, useragent string) (bool, string, error) {
- const url string = "https://api.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/releases/latest"
+func checkForNewRelease(client *http.Client, currentVersion, useragent, url string) (bool, string, error) {
var (
output bool
message string
@@ -68,60 +72,76 @@ func checkForNewRelease(client *http.Client, currentVersion, useragent string) (
}).Debug("Error initaiting connection to, ", url, IssueMSG)
return output, message, err
}
- defer resp.Body.Close()
- // Unmarshal the JSON to the Github Release strcut
- if err := json.NewDecoder(resp.Body).Decode(&release); err != nil {
- log.WithFields(log.Fields{
- "package": "cmd",
- "file": "version.go",
- "parent_function": "checkForNewRelease",
- "function": "json.NewDecoder",
- "error": err,
- "data": nil,
- }).Debug("Error unmarshalling Github response", IssueMSG)
- return output, message, err
- }
+ if resp != nil && resp.Body != nil {
+ defer resp.Body.Close()
- cVersion, err := version.NewVersion(currentVersion)
- if err != nil {
- log.WithFields(log.Fields{
- "package": "cmd",
- "file": "version.go",
- "parent_function": "checkForNewRelease",
- "function": "version.NewVersion",
- "error": err,
- "data": nil,
- }).Debug("Error creating new version", IssueMSG)
- return output, message, err
- }
+ if resp.StatusCode != http.StatusOK {
+ log.WithFields(log.Fields{
+ "package": "cmd",
+ "file": "version.go",
+ "parent_function": "checkForNewRelease",
+ "function": "client.Do",
+ "error": err,
+ "data": nil,
+ }).Debug("Error initaiting connection to, ", url, IssueMSG)
+ return output, message, fmt.Errorf("error connecting to %s", url)
+ }
+ // Unmarshal the JSON to the Github Release strcut
+ if err := json.NewDecoder(resp.Body).Decode(&release); err != nil {
+ log.WithFields(log.Fields{
+ "package": "cmd",
+ "file": "version.go",
+ "parent_function": "checkForNewRelease",
+ "function": "json.NewDecoder",
+ "error": err,
+ "data": nil,
+ }).Debug("Error unmarshalling Github response", IssueMSG)
+ return output, message, err
+ }
- latestVersion, err := version.NewVersion(release.TagName[1:])
- if err != nil {
- log.WithFields(log.Fields{
- "package": "cmd",
- "file": "version.go",
- "parent_function": "checkForNewRelease",
- "function": "version.NewVersion",
- "error": err,
- "data": nil,
- }).Debug("Error creating new version", IssueMSG)
- return output, message, err
- }
+ cVersion, err := version.NewVersion(currentVersion)
+ if err != nil {
+ log.WithFields(log.Fields{
+ "package": "cmd",
+ "file": "version.go",
+ "parent_function": "checkForNewRelease",
+ "function": "version.NewVersion",
+ "error": err,
+ "data": nil,
+ }).Debug("Error creating new version", IssueMSG)
+ return output, message, err
+ }
- switch cVersion.Compare(latestVersion) {
- case -1:
- message = fmt.Sprintf("There is a new release available: %s \n Download it here - %s", release.TagName, release.HTMLURL)
- output = true
- case 0:
- message = "No new version available"
- output = true
- case 1:
- message = "You are running a pre-release version"
- output = true
- default:
- return output, message, fmt.Errorf("error comparing versions")
+ latestVersion, err := version.NewVersion(release.TagName[1:])
+ if err != nil {
+ log.WithFields(log.Fields{
+ "package": "cmd",
+ "file": "version.go",
+ "parent_function": "checkForNewRelease",
+ "function": "version.NewVersion",
+ "error": err,
+ "data": nil,
+ }).Debug("Error creating new version", IssueMSG)
+ return output, message, err
+ }
+
+ switch cVersion.Compare(latestVersion) {
+ case -1:
+ message = fmt.Sprintf("There is a new release available: %s \n Download it here - %s", release.TagName, release.HTMLURL)
+ output = true
+ case 0:
+ message = "No new version available"
+ output = true
+ case 1:
+ message = "You are running a pre-release version"
+ output = true
+ default:
+ return output, message, fmt.Errorf("error comparing versions")
+ }
+ } else {
+ return output, message, fmt.Errorf("error connecting to %s", url)
}
- return output, message, nil
+ return output, message, err
}
diff --git a/cmd/version_test.go b/cmd/version_test.go
index 499bff6..d3491b2 100644
--- a/cmd/version_test.go
+++ b/cmd/version_test.go
@@ -5,6 +5,8 @@ package cmd
import (
"fmt"
+ "net/http"
+ "net/http/httptest"
"testing"
)
@@ -20,7 +22,7 @@ func TestCheckForNewRelease(t *testing.T) {
useragent := fmt.Sprintf("go-lambda-cleanup/%s", version)
want := true
- got, msg, err := checkForNewRelease(client, version, useragent)
+ got, msg, err := checkForNewRelease(client, version, useragent, url)
if err != nil {
t.Fatalf("Error checking for new release: %s", err)
}
@@ -30,7 +32,7 @@ func TestCheckForNewRelease(t *testing.T) {
version = "100.0.0"
want2 := true
- got2, msg2, err := checkForNewRelease(client, version, useragent)
+ got2, msg2, err := checkForNewRelease(client, version, useragent, url)
if err != nil {
t.Fatalf("Error checking for new release: %s", err)
}
@@ -38,3 +40,321 @@ func TestCheckForNewRelease(t *testing.T) {
t.Fatalf("Error checking for new release: %s", err)
}
}
+
+func TestErrorPath(t *testing.T) {
+
+ mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ http.Error(w, "Mock error response", http.StatusInternalServerError)
+ }))
+ defer mockServer.Close()
+
+ // Override the base URL to use the mock server URL
+ baseURL := mockServer.URL
+
+ client := createHTTPClient()
+ version := "------"
+ useragent := fmt.Sprintf("go-lambda-cleanup/%s", version)
+
+ _, _, err := checkForNewRelease(client, version, useragent, baseURL)
+ if err == nil {
+ t.Fatalf("Error Expected: %s", err)
+ }
+}
+
+func TestErrorPathJSON(t *testing.T) {
+
+ mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ _, err := w.Write([]byte("invalid-json-payload"))
+ if err != nil {
+ t.Fatalf("Error writing to response writer: %s", err)
+ }
+ }))
+ defer mockServer.Close()
+
+ // Override the base URL to use the mock server URL
+ baseURL := mockServer.URL
+
+ client := createHTTPClient()
+ version := "------"
+ useragent := fmt.Sprintf("go-lambda-cleanup/%s", version)
+
+ _, _, err := checkForNewRelease(client, version, useragent, baseURL)
+ if err == nil {
+ t.Fatalf("Error Expected: %s", err)
+ }
+}
+
+func TestErrorURL(t *testing.T) {
+
+ client := createHTTPClient()
+ version := "------"
+ useragent := fmt.Sprintf("go-lambda-cleanup/%s", version)
+
+ got, want, err := checkForNewRelease(client, version, useragent, "http://localhost:1234")
+ if err == nil {
+ t.Fatalf("Error Expected: %s", err)
+ }
+ if got != false && want != IssueMSG {
+ t.Fatalf("Error Expected: %s", want)
+ }
+}
+
+func TestCheckForNewReleaseNoNewRelease(t *testing.T) {
+
+ var payload = []byte(`{
+ "url": "https://api.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/releases/127949448",
+ "assets_url": "https://api.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/releases/127949448/assets",
+ "upload_url": "https://uploads.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/releases/127949448/assets{?name,label}",
+ "html_url": "https://github.com/karl-cardenas-coding/go-lambda-cleanup/releases/tag/v2.0.10",
+ "id": 127949448,
+ "author": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "node_id": "RE_kwDOFGhZlc4HoFqI",
+ "tag_name": "v2.0.10",
+ "target_commitish": "main",
+ "name": "v2.0.10",
+ "draft": false,
+ "prerelease": false,
+ "created_at": "2023-11-03T22:18:26Z",
+ "published_at": "2023-11-03T22:18:37Z",
+ "assets": [
+ {
+ "url": "https://api.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/releases/assets/133848132",
+ "id": 133848132,
+ "node_id": "RA_kwDOFGhZlc4H-lxE",
+ "name": "go-lambda-cleanup-v2.0.10-darwin-amd64.zip",
+ "label": "",
+ "uploader": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "content_type": "application/zip",
+ "state": "uploaded",
+ "size": 8622699,
+ "download_count": 1,
+ "created_at": "2023-11-03T22:18:34Z",
+ "updated_at": "2023-11-03T22:18:35Z",
+ "browser_download_url": "https://github.com/karl-cardenas-coding/go-lambda-cleanup/releases/download/v2.0.10/go-lambda-cleanup-v2.0.10-darwin-amd64.zip"
+ },
+ {
+ "url": "https://api.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/releases/assets/133848129",
+ "id": 133848129,
+ "node_id": "RA_kwDOFGhZlc4H-lxB",
+ "name": "go-lambda-cleanup-v2.0.10-darwin-arm64.zip",
+ "label": "",
+ "uploader": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "content_type": "application/zip",
+ "state": "uploaded",
+ "size": 8269741,
+ "download_count": 2,
+ "created_at": "2023-11-03T22:18:33Z",
+ "updated_at": "2023-11-03T22:18:34Z",
+ "browser_download_url": "https://github.com/karl-cardenas-coding/go-lambda-cleanup/releases/download/v2.0.10/go-lambda-cleanup-v2.0.10-darwin-arm64.zip"
+ },
+ {
+ "url": "https://api.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/releases/assets/133848128",
+ "id": 133848128,
+ "node_id": "RA_kwDOFGhZlc4H-lxA",
+ "name": "go-lambda-cleanup-v2.0.10-linux-386.zip",
+ "label": "",
+ "uploader": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "content_type": "application/zip",
+ "state": "uploaded",
+ "size": 8169046,
+ "download_count": 2,
+ "created_at": "2023-11-03T22:18:32Z",
+ "updated_at": "2023-11-03T22:18:33Z",
+ "browser_download_url": "https://github.com/karl-cardenas-coding/go-lambda-cleanup/releases/download/v2.0.10/go-lambda-cleanup-v2.0.10-linux-386.zip"
+ },
+ {
+ "url": "https://api.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/releases/assets/133848138",
+ "id": 133848138,
+ "node_id": "RA_kwDOFGhZlc4H-lxK",
+ "name": "go-lambda-cleanup-v2.0.10-linux-amd64.zip",
+ "label": "",
+ "uploader": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "content_type": "application/zip",
+ "state": "uploaded",
+ "size": 8631978,
+ "download_count": 15,
+ "created_at": "2023-11-03T22:18:35Z",
+ "updated_at": "2023-11-03T22:18:36Z",
+ "browser_download_url": "https://github.com/karl-cardenas-coding/go-lambda-cleanup/releases/download/v2.0.10/go-lambda-cleanup-v2.0.10-linux-amd64.zip"
+ },
+ {
+ "url": "https://api.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/releases/assets/133848139",
+ "id": 133848139,
+ "node_id": "RA_kwDOFGhZlc4H-lxL",
+ "name": "go-lambda-cleanup-v2.0.10-windows-amd64.zip",
+ "label": "",
+ "uploader": {
+ "login": "github-actions[bot]",
+ "id": 41898282,
+ "node_id": "MDM6Qm90NDE4OTgyODI=",
+ "avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/github-actions%5Bbot%5D",
+ "html_url": "https://github.com/apps/github-actions",
+ "followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
+ "following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
+ "gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
+ "organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
+ "repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
+ "events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
+ "type": "Bot",
+ "site_admin": false
+ },
+ "content_type": "application/zip",
+ "state": "uploaded",
+ "size": 8759318,
+ "download_count": 1,
+ "created_at": "2023-11-03T22:18:36Z",
+ "updated_at": "2023-11-03T22:18:37Z",
+ "browser_download_url": "https://github.com/karl-cardenas-coding/go-lambda-cleanup/releases/download/v2.0.10/go-lambda-cleanup-v2.0.10-windows-amd64.zip"
+ }
+ ],
+ "tarball_url": "https://api.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/tarball/v2.0.10",
+ "zipball_url": "https://api.github.com/repos/karl-cardenas-coding/go-lambda-cleanup/zipball/v2.0.10",
+ "body": "## [2.0.10](https://github.com/karl-cardenas-coding/go-lambda-cleanup/compare/v2.0.9...v2.0.10) (2023-11-03)\n\n\n### Bug Fixes\n\n* updated dependencies ([778b9e2](https://github.com/karl-cardenas-coding/go-lambda-cleanup/commit/778b9e2a457544c1874582abdca089d2123578a1))\n\n\n\n"
+ }`)
+
+ mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+
+ // Write an invalid JSON payload to the response writer
+ _, err := w.Write(payload)
+ if err != nil {
+ t.Fatalf("Error writing to response writer: %s", err)
+ }
+ }))
+ defer mockServer.Close()
+
+ // Override the base URL to use the mock server URL
+ baseURL := mockServer.URL
+
+ client := createHTTPClient()
+ version := "2.0.10"
+ useragent := fmt.Sprintf("go-lambda-cleanup/%s", version)
+
+ want := false
+ got, msg, err := checkForNewRelease(client, version, useragent, baseURL)
+ if err != nil {
+ t.Fatalf("Error encountered: %s", err)
+ }
+
+ if got != want && msg != noVersionAvailable {
+ t.Fatalf("Error checking for new release: %s", msg)
+ }
+}
+
+func TestVersionCMD(t *testing.T) {
+
+ VersionString = "1.0.0"
+
+ err := VersionCmd.RunE(VersionCmd, []string{})
+ if err != nil {
+ t.Errorf("expected no error to be returned but received %v", err)
+ }
+
+ VersionString = "aaaa"
+ err = VersionCmd.RunE(VersionCmd, []string{})
+ if err == nil {
+ t.Errorf("expected an error to be returned but received %v", err)
+ }
+
+}
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 0000000..263b348
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,23 @@
+# Copyright (c) karl-cardenas-coding
+# SPDX-License-Identifier: MIT
+
+codecov:
+ require_ci_to_pass: true
+comment:
+ behavior: default
+ layout: reach,diff,flags,tree,reach
+ show_carryforward_flags: false
+coverage:
+ precision: 2
+ range:
+ - 60.0
+ - 85.0
+ round: down
+ status:
+ changes: true
+ default_rules:
+ flag_coverage_not_uploaded_behavior: include
+ patch: true
+ project: true
+github_checks:
+ annotations: true
\ No newline at end of file
diff --git a/documentation/open-source.md b/documentation/open-source.md
index 5e2f939..c2cc90c 100644
--- a/documentation/open-source.md
+++ b/documentation/open-source.md
@@ -2,8 +2,8 @@
## github.com/aws/aws-sdk-go-v2
* Name: github.com/aws/aws-sdk-go-v2
-* Version: v1.19.0
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/v1.19.0/LICENSE.txt)
+* Version: v1.23.1
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/v1.23.1/LICENSE.txt)
```
@@ -214,8 +214,8 @@
## github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream
* Name: github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream
-* Version: v1.4.10
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/aws/protocol/eventstream/v1.4.10/aws/protocol/eventstream/LICENSE.txt)
+* Version: v1.5.1
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/aws/protocol/eventstream/v1.5.1/aws/protocol/eventstream/LICENSE.txt)
```
@@ -426,8 +426,8 @@
## github.com/aws/aws-sdk-go-v2/config
* Name: github.com/aws/aws-sdk-go-v2/config
-* Version: v1.18.28
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/config/v1.18.28/config/LICENSE.txt)
+* Version: v1.25.5
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/config/v1.25.5/config/LICENSE.txt)
```
@@ -638,8 +638,8 @@
## github.com/aws/aws-sdk-go-v2/credentials
* Name: github.com/aws/aws-sdk-go-v2/credentials
-* Version: v1.13.27
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/credentials/v1.13.27/credentials/LICENSE.txt)
+* Version: v1.16.4
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/credentials/v1.16.4/credentials/LICENSE.txt)
```
@@ -850,8 +850,8 @@
## github.com/aws/aws-sdk-go-v2/feature/ec2/imds
* Name: github.com/aws/aws-sdk-go-v2/feature/ec2/imds
-* Version: v1.13.5
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/feature/ec2/imds/v1.13.5/feature/ec2/imds/LICENSE.txt)
+* Version: v1.14.5
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/feature/ec2/imds/v1.14.5/feature/ec2/imds/LICENSE.txt)
```
@@ -1062,8 +1062,8 @@
## github.com/aws/aws-sdk-go-v2/internal/configsources
* Name: github.com/aws/aws-sdk-go-v2/internal/configsources
-* Version: v1.1.35
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/configsources/v1.1.35/internal/configsources/LICENSE.txt)
+* Version: v1.2.4
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/configsources/v1.2.4/internal/configsources/LICENSE.txt)
```
@@ -1274,8 +1274,8 @@
## github.com/aws/aws-sdk-go-v2/internal/endpoints/v2
* Name: github.com/aws/aws-sdk-go-v2/internal/endpoints/v2
-* Version: v2.4.29
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/endpoints/v2.4.29/internal/endpoints/v2/LICENSE.txt)
+* Version: v2.5.4
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/endpoints/v2.5.4/internal/endpoints/v2/LICENSE.txt)
```
@@ -1486,8 +1486,8 @@
## github.com/aws/aws-sdk-go-v2/internal/ini
* Name: github.com/aws/aws-sdk-go-v2/internal/ini
-* Version: v1.3.36
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/ini/v1.3.36/internal/ini/LICENSE.txt)
+* Version: v1.7.1
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/ini/v1.7.1/internal/ini/LICENSE.txt)
```
@@ -1698,8 +1698,8 @@
## github.com/aws/aws-sdk-go-v2/internal/sync/singleflight
* Name: github.com/aws/aws-sdk-go-v2/internal/sync/singleflight
-* Version: v1.19.0
-* License: [BSD-3-Clause](https://github.com/aws/aws-sdk-go-v2/blob/v1.19.0/internal/sync/singleflight/LICENSE)
+* Version: v1.23.1
+* License: [BSD-3-Clause](https://github.com/aws/aws-sdk-go-v2/blob/v1.23.1/internal/sync/singleflight/LICENSE)
```
Copyright (c) 2009 The Go Authors. All rights reserved.
@@ -1731,13 +1731,225 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+```
+
+## github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding
+
+* Name: github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding
+* Version: v1.10.1
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/internal/accept-encoding/v1.10.1/service/internal/accept-encoding/LICENSE.txt)
+
+```
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
```
## github.com/aws/aws-sdk-go-v2/service/internal/presigned-url
* Name: github.com/aws/aws-sdk-go-v2/service/internal/presigned-url
-* Version: v1.9.29
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/internal/presigned-url/v1.9.29/service/internal/presigned-url/LICENSE.txt)
+* Version: v1.10.4
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/internal/presigned-url/v1.10.4/service/internal/presigned-url/LICENSE.txt)
```
@@ -1948,8 +2160,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## github.com/aws/aws-sdk-go-v2/service/lambda
* Name: github.com/aws/aws-sdk-go-v2/service/lambda
-* Version: v1.37.1
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/lambda/v1.37.1/service/lambda/LICENSE.txt)
+* Version: v1.48.1
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/lambda/v1.48.1/service/lambda/LICENSE.txt)
```
@@ -2160,8 +2372,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## github.com/aws/aws-sdk-go-v2/service/sso
* Name: github.com/aws/aws-sdk-go-v2/service/sso
-* Version: v1.12.13
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sso/v1.12.13/service/sso/LICENSE.txt)
+* Version: v1.17.3
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sso/v1.17.3/service/sso/LICENSE.txt)
```
@@ -2372,8 +2584,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## github.com/aws/aws-sdk-go-v2/service/ssooidc
* Name: github.com/aws/aws-sdk-go-v2/service/ssooidc
-* Version: v1.14.13
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssooidc/v1.14.13/service/ssooidc/LICENSE.txt)
+* Version: v1.20.1
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssooidc/v1.20.1/service/ssooidc/LICENSE.txt)
```
@@ -2584,8 +2796,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## github.com/aws/aws-sdk-go-v2/service/sts
* Name: github.com/aws/aws-sdk-go-v2/service/sts
-* Version: v1.19.3
-* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sts/v1.19.3/service/sts/LICENSE.txt)
+* Version: v1.25.4
+* License: [Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sts/v1.25.4/service/sts/LICENSE.txt)
```
@@ -2796,8 +3008,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## github.com/aws/smithy-go
* Name: github.com/aws/smithy-go
-* Version: v1.13.5
-* License: [Apache-2.0](https://github.com/aws/smithy-go/blob/v1.13.5/LICENSE)
+* Version: v1.17.0
+* License: [Apache-2.0](https://github.com/aws/smithy-go/blob/v1.17.0/LICENSE)
```
@@ -2981,8 +3193,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## github.com/aws/smithy-go/internal/sync/singleflight
* Name: github.com/aws/smithy-go/internal/sync/singleflight
-* Version: v1.13.5
-* License: [BSD-3-Clause](https://github.com/aws/smithy-go/blob/v1.13.5/internal/sync/singleflight/LICENSE)
+* Version: v1.17.0
+* License: [BSD-3-Clause](https://github.com/aws/smithy-go/blob/v1.17.0/internal/sync/singleflight/LICENSE)
```
Copyright (c) 2009 The Go Authors. All rights reserved.
@@ -3499,8 +3711,8 @@ THE SOFTWARE.
## github.com/spf13/cobra
* Name: github.com/spf13/cobra
-* Version: v1.7.0
-* License: [Apache-2.0](https://github.com/spf13/cobra/blob/v1.7.0/LICENSE.txt)
+* Version: v1.8.0
+* License: [Apache-2.0](https://github.com/spf13/cobra/blob/v1.8.0/LICENSE.txt)
```
Apache License
@@ -3721,8 +3933,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## golang.org/x/sys/unix
* Name: golang.org/x/sys/unix
-* Version: v0.10.0
-* License: [BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.10.0:LICENSE)
+* Version: v0.14.0
+* License: [BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.14.0:LICENSE)
```
Copyright (c) 2009 The Go Authors. All rights reserved.
diff --git a/go.mod b/go.mod
index b0d7f1e..55923a8 100644
--- a/go.mod
+++ b/go.mod
@@ -1,32 +1,77 @@
-module github.com/karl-cardenas-coding/go-lambda-cleanup
+module github.com/karl-cardenas-coding/go-lambda-cleanup/v2
go 1.21
require (
- github.com/aws/aws-sdk-go-v2 v1.22.1
- github.com/aws/aws-sdk-go-v2/config v1.22.0
- github.com/aws/aws-sdk-go-v2/credentials v1.15.1
- github.com/aws/aws-sdk-go-v2/service/lambda v1.43.0
+ github.com/aws/aws-sdk-go-v2 v1.23.1
+ github.com/aws/aws-sdk-go-v2/config v1.25.5
+ github.com/aws/aws-sdk-go-v2/credentials v1.16.4
+ github.com/aws/aws-sdk-go-v2/service/lambda v1.48.1
+ github.com/docker/go-connections v0.4.0
github.com/dustin/go-humanize v1.0.1
github.com/hashicorp/go-version v1.6.0
github.com/sirupsen/logrus v1.9.3
- github.com/spf13/cobra v1.7.0
+ github.com/spf13/cobra v1.8.0
+ github.com/testcontainers/testcontainers-go v0.26.0
+ github.com/testcontainers/testcontainers-go/modules/localstack v0.26.0
gopkg.in/yaml.v2 v2.4.0
)
require (
- github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.0 // indirect
- github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.2 // indirect
- github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.1 // indirect
- github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.1 // indirect
- github.com/aws/aws-sdk-go-v2/internal/ini v1.5.0 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.1 // indirect
- github.com/aws/aws-sdk-go-v2/service/sso v1.17.0 // indirect
- github.com/aws/aws-sdk-go-v2/service/ssooidc v1.19.0 // indirect
- github.com/aws/aws-sdk-go-v2/service/sts v1.25.0 // indirect
- github.com/aws/smithy-go v1.16.0 // indirect
+ dario.cat/mergo v1.0.0 // indirect
+ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
+ github.com/Microsoft/go-winio v0.6.1 // indirect
+ github.com/Microsoft/hcsshim v0.11.4 // indirect
+ github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 // indirect
+ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 // indirect
+ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 // indirect
+ github.com/aws/smithy-go v1.17.0 // indirect
+ github.com/cenkalti/backoff/v4 v4.2.1 // indirect
+ github.com/containerd/containerd v1.7.9 // indirect
+ github.com/containerd/log v0.1.0 // indirect
+ github.com/cpuguy83/dockercfg v0.3.1 // indirect
+ github.com/distribution/reference v0.5.0 // indirect
+ github.com/docker/distribution v2.8.3+incompatible // indirect
+ github.com/docker/docker v24.0.7+incompatible // indirect
+ github.com/docker/go-units v0.5.0 // indirect
+ github.com/go-ole/go-ole v1.3.0 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang/protobuf v1.5.3 // indirect
+ github.com/google/uuid v1.4.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
+ github.com/klauspost/compress v1.17.3 // indirect
+ github.com/kr/text v0.2.0 // indirect
+ github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect
+ github.com/magiconair/properties v1.8.7 // indirect
+ github.com/moby/patternmatcher v0.6.0 // indirect
+ github.com/moby/sys/sequential v0.5.0 // indirect
+ github.com/moby/term v0.5.0 // indirect
+ github.com/morikuni/aec v1.0.0 // indirect
+ github.com/opencontainers/go-digest v1.0.0 // indirect
+ github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
+ github.com/opencontainers/runc v1.1.10 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
+ github.com/shirou/gopsutil/v3 v3.23.10 // indirect
+ github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/spf13/pflag v1.0.5 // indirect
- golang.org/x/sys v0.13.0 // indirect
+ github.com/tklauser/go-sysconf v0.3.12 // indirect
+ github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/yusufpapurcu/wmi v1.2.3 // indirect
+ golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
+ golang.org/x/mod v0.14.0 // indirect
+ golang.org/x/net v0.18.0 // indirect
+ golang.org/x/sys v0.14.0 // indirect
+ golang.org/x/tools v0.15.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect
+ google.golang.org/grpc v1.59.0 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
)
diff --git a/go.sum b/go.sum
index ab6a6a6..1ed3833 100644
--- a/go.sum
+++ b/go.sum
@@ -1,67 +1,85 @@
-github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyDJ+k=
-github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
-github.com/aws/aws-sdk-go-v2 v1.22.1 h1:sjnni/AuoTXxHitsIdT0FwmqUuNUuHtufcVDErVFT9U=
-github.com/aws/aws-sdk-go-v2 v1.22.1/go.mod h1:Kd0OJtkW3Q0M0lUWGszapWjEvrXDzRW+D21JNsroB+c=
-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/aws/protocol/eventstream v1.5.0 h1:hHgLiIrTRtddC0AKcJr5s7i/hLgcpTt+q/FKxf1Zayk=
-github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.0/go.mod h1:w4I/v3NOWgD+qvs1NPEwhd++1h3XPHFaVxasfY6HlYQ=
-github.com/aws/aws-sdk-go-v2/config v1.18.28 h1:TINEaKyh1Td64tqFvn09iYpKiWjmHYrG1fa91q2gnqw=
-github.com/aws/aws-sdk-go-v2/config v1.18.28/go.mod h1:nIL+4/8JdAuNHEjn/gPEXqtnS02Q3NXB/9Z7o5xE4+A=
-github.com/aws/aws-sdk-go-v2/config v1.22.0 h1:9Mm99OalzZRz0ab5fpodMoHBApHS6pqRNp3M9NmzvDg=
-github.com/aws/aws-sdk-go-v2/config v1.22.0/go.mod h1:2eWgw5lps8fKI7LZVTrRTYP6HE6k/uEFUuTSHfXwqP0=
-github.com/aws/aws-sdk-go-v2/credentials v1.13.27 h1:dz0yr/yR1jweAnsCx+BmjerUILVPQ6FS5AwF/OyG1kA=
-github.com/aws/aws-sdk-go-v2/credentials v1.13.27/go.mod h1:syOqAek45ZXZp29HlnRS/BNgMIW6uiRmeuQsz4Qh2UE=
-github.com/aws/aws-sdk-go-v2/credentials v1.15.1 h1:hmf6lAm9hk7uLCfapZn/jL05lm6Uwdbn1B0fgjyuf4M=
-github.com/aws/aws-sdk-go-v2/credentials v1.15.1/go.mod h1:QTcHga3ZbQOneJuxmGBOCxiClxmp+TlvmjFexAnJ790=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 h1:kP3Me6Fy3vdi+9uHd7YLr6ewPxRL+PU6y15urfTaamU=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5/go.mod h1:Gj7tm95r+QsDoN2Fhuz/3npQvcZbkEf5mL70n3Xfluc=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.2 h1:gIeH4+o1MN/caGBWjoGQTUTIu94xD6fI5B2+TcwBf70=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.2/go.mod h1:wLyMIo/zPOhQhPXTddpfdkSleyigtFi8iMnC+2m/SK4=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 h1:hMUCiE3Zi5AHrRNGf5j985u0WyqI6r2NULhUfo0N/No=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35/go.mod h1:ipR5PvpSPqIqL5Mi82BxLnfMkHVbmco8kUwO2xrCi0M=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.1 h1:fi1ga6WysOyYb5PAf3Exd6B5GiSNpnZim4h1rhlBqx0=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.1/go.mod h1:V5CY8wNurvPUibTi9mwqUqpiFZ5LnioKWIFUDtIzdI8=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 h1:yOpYx+FTBdpk/g+sBU6Cb1H0U/TLEcYYp66mYqsPpcc=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29/go.mod h1:M/eUABlDbw2uVrdAn+UsI6M727qp2fxkp8K0ejcBDUY=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.1 h1:ZpaV/j48RlPc4AmOZuPv22pJliXjXq8/reL63YzyFnw=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.1/go.mod h1:R8aXraabD2e3qv1csxM14/X9WF4wFMIY0kH4YEtYD5M=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 h1:8r5m1BoAWkn0TDC34lUculryf7nUF25EgIMdjvGCkgo=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36/go.mod h1:Rmw2M1hMVTwiUhjwMoIBFWFJMhvJbct06sSidxInkhY=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.5.0 h1:DqOQvIfmGkXZUVJnl9VRk0AnxyS59tCtX9k1Pyss4Ak=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.5.0/go.mod h1:VV/Kbw9Mg1GWJOT9WK+oTL3cWZiXtapnNvDSRqTZLsg=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 h1:IiDolu/eLmuB18DRZibj77n1hHQT7z12jnGO7Ze3pLc=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29/go.mod h1:fDbkK4o7fpPXWn8YAPmTieAMuB9mk/VgvW64uaUqxd4=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.1 h1:2OXw3ppu1XsB6rqKEMV4tnecTjIY3PRV2U6IP6KPJQo=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.1/go.mod h1:FZB4AdakIqW/yERVdGJA6Z9jraax1beXfhBBnK2wwR8=
-github.com/aws/aws-sdk-go-v2/service/lambda v1.37.1 h1:BRdW2JcxZSsen77Y0WoWIWY4+H9EXT55uEPWZKIcDHY=
-github.com/aws/aws-sdk-go-v2/service/lambda v1.37.1/go.mod h1:zmdE2b9ZX8milexhZc3SeC3LwJRJpJ0k0fsuMBOSCEI=
-github.com/aws/aws-sdk-go-v2/service/lambda v1.43.0 h1:q5akeBhM1aVmSH5NwEKI4emlKIopKBzzG/3TQsSB4PQ=
-github.com/aws/aws-sdk-go-v2/service/lambda v1.43.0/go.mod h1:mgdh1gpiE0bOuEVeYN/B+TS39Irz7HDEr9x6ZvdWv/w=
-github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 h1:sWDv7cMITPcZ21QdreULwxOOAmE05JjEsT6fCDtDA9k=
-github.com/aws/aws-sdk-go-v2/service/sso v1.12.13/go.mod h1:DfX0sWuT46KpcqbMhJ9QWtxAIP1VozkDWf8VAkByjYY=
-github.com/aws/aws-sdk-go-v2/service/sso v1.17.0 h1:I/Oh3IxGPfHXiGnwM54TD6hNr/8TlUrBXAtTyGhR+zw=
-github.com/aws/aws-sdk-go-v2/service/sso v1.17.0/go.mod h1:H6NCMvDBqA+CvIaXzaSqM6LWtzv9BzZrqBOqz+PzRF8=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 h1:BFubHS/xN5bjl818QaroN6mQdjneYQ+AOx44KNXlyH4=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13/go.mod h1:BzqsVVFduubEmzrVtUFQQIQdFqvUItF8XUq2EnS8Wog=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.19.0 h1:irbXQkfVYIRaewYSXcu4yVk0m2T+JzZd0dkop7FjmO0=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.19.0/go.mod h1:4wPNCkM22+oRe71oydP66K50ojDUC33XutSMi2pEF/M=
-github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 h1:e5mnydVdCVWxP+5rPAGi2PYxC7u2OZgH1ypC114H04U=
-github.com/aws/aws-sdk-go-v2/service/sts v1.19.3/go.mod h1:yVGZA1CPkmUhBdA039jXNJJG7/6t+G+EBWmFq23xqnY=
-github.com/aws/aws-sdk-go-v2/service/sts v1.25.0 h1:sYIFy8tm1xQwRvVQ4CRuBGXKIg9sHNuG6+3UAQuoujk=
-github.com/aws/aws-sdk-go-v2/service/sts v1.25.0/go.mod h1:S/LOQUeYDfJeJpFCIJDMjy7dwL4aA33HUdVi+i7uH8k=
-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/aws/smithy-go v1.16.0 h1:gJZEH/Fqh+RsvlJ1Zt4tVAtV6bKkp3cC+R6FCZMNzik=
-github.com/aws/smithy-go v1.16.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
+dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
+github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
+github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
+github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
+github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
+github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w=
+github.com/aws/aws-sdk-go-v2 v1.23.1 h1:qXaFsOOMA+HsZtX8WoCa+gJnbyW7qyFFBlPqvTSzbaI=
+github.com/aws/aws-sdk-go-v2 v1.23.1/go.mod h1:i1XDttT4rnf6vxc9AuskLc6s7XBee8rlLilKlc03uAA=
+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 h1:ZY3108YtBNq96jNZTICHxN1gSBSbnvIdYwwqnvCV4Mc=
+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1/go.mod h1:t8PYl/6LzdAqsU4/9tz28V/kU+asFePvpOMkdul0gEQ=
+github.com/aws/aws-sdk-go-v2/config v1.25.5 h1:UGKm9hpQS2hoK8CEJ1BzAW8NbUpvwDJJ4lyqXSzu8bk=
+github.com/aws/aws-sdk-go-v2/config v1.25.5/go.mod h1:Bf4gDvy4ZcFIK0rqDu1wp9wrubNba2DojiPB2rt6nvI=
+github.com/aws/aws-sdk-go-v2/credentials v1.16.4 h1:i7UQYYDSJrtc30RSwJwfBKwLFNnBTiICqAJ0pPdum8E=
+github.com/aws/aws-sdk-go-v2/credentials v1.16.4/go.mod h1:Kdh/okh+//vQ/AjEt81CjvkTo64+/zIE4OewP7RpfXk=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 h1:KehRNiVzIfAcj6gw98zotVbb/K67taJE0fkfgM6vzqU=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5/go.mod h1:VhnExhw6uXy9QzetvpXDolo1/hjhx4u9qukBGkuUwjs=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 h1:LAm3Ycm9HJfbSCd5I+wqC2S9Ej7FPrgr5CQoOljJZcE=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4/go.mod h1:xEhvbJcyUf/31yfGSQBe01fukXwXJ0gxDp7rLfymWE0=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 h1:4GV0kKZzUxiWxSVpn/9gwR0g21NF1Jsyduzo9rHgC/Q=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4/go.mod h1:dYvTNAggxDZy6y1AF7YDwXsPuHFy/VNEpEI/2dWK9IU=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 h1:uR9lXYjdPX0xY+NhvaJ4dD8rpSRz5VY81ccIIoNG+lw=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 h1:rpkF4n0CyFcrJUG/rNNohoTmhtWlFTRI4BsZOh9PvLs=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1/go.mod h1:l9ymW25HOqymeU2m1gbUQ3rUIsTwKs8gYHXkqDQUhiI=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 h1:rdovz3rEu0vZKbzoMYPTehp0E8veoE9AyfzqCr5Eeao=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4/go.mod h1:aYCGNjyUCUelhofxlZyj63srdxWUSsBSGg5l6MCuXuE=
+github.com/aws/aws-sdk-go-v2/service/lambda v1.48.1 h1:xVOzP4rFi0kMXUQozqInP+Yy6zldr8WTpHeVEqxMtOY=
+github.com/aws/aws-sdk-go-v2/service/lambda v1.48.1/go.mod h1:7dj5Kak6A6QOeZxUgIDUWVG5+7upeEBY1ivtFDRLxSQ=
+github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 h1:CdsSOGlFF3Pn+koXOIpTtvX7st0IuGsZ8kJqcWMlX54=
+github.com/aws/aws-sdk-go-v2/service/sso v1.17.3/go.mod h1:oA6VjNsLll2eVuUoF2D+CMyORgNzPEW/3PyUdq6WQjI=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 h1:cbRqFTVnJV+KRpwFl76GJdIZJKKCdTPnjUZ7uWh3pIU=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1/go.mod h1:hHL974p5auvXlZPIjJTblXJpbkfK4klBczlsEaMCGVY=
+github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 h1:yEvZ4neOQ/KpUqyR+X0ycUTW/kVRNR4nDZ38wStHGAA=
+github.com/aws/aws-sdk-go-v2/service/sts v1.25.4/go.mod h1:feTnm2Tk/pJxdX+eooEsxvlvTWBvDm6CasRZ+JOs2IY=
+github.com/aws/smithy-go v1.17.0 h1:wWJD7LX6PBV6etBUwO0zElG0nWN9rUhp0WdYeHSHAaI=
+github.com/aws/smithy-go v1.17.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
+github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
+github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/containerd/containerd v1.7.9 h1:KOhK01szQbM80YfW1H6RZKh85PHGqY/9OcEZ35Je8sc=
+github.com/containerd/containerd v1.7.9/go.mod h1:0/W44LWEYfSHoxBtsHIiNU/duEkgpMokemafHVCpq9Y=
+github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
+github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
+github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E=
+github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
+github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
+github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
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/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
+github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
+github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
+github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
+github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
+github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
-github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
+github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -70,28 +88,140 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
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=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA=
+github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
+github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0=
+github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
+github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
+github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
+github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
+github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
+github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
+github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
+github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
+github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
+github.com/opencontainers/runc v1.1.10 h1:EaL5WeO9lv9wmS6SASjszOeQdSctvpbu0DdBQBizE40=
+github.com/opencontainers/runc v1.1.10/go.mod h1:+/R6+KmDlh+hOO8NkjmgkG9Qzvypzk0yXxAPYYR65+M=
+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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
+github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
+github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/shirou/gopsutil/v3 v3.23.10 h1:/N42opWlYzegYaVkWejXWJpbzKv2JDy3mrgGzKsh9hM=
+github.com/shirou/gopsutil/v3 v3.23.10/go.mod h1:JIE26kpucQi+innVlAUnIEOSBhBUkirr5b44yr55+WE=
+github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
+github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
+github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
+github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
-github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
+github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
+github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/testcontainers/testcontainers-go v0.26.0 h1:uqcYdoOHBy1ca7gKODfBd9uTHVK3a7UL848z09MVZ0c=
+github.com/testcontainers/testcontainers-go v0.26.0/go.mod h1:ICriE9bLX5CLxL9OFQ2N+2N+f+803LNJ1utJb1+Inx0=
+github.com/testcontainers/testcontainers-go/modules/localstack v0.26.0 h1:lpL04dHA9mGFBQLFcV+aEEh1Tf4ohXdIGgoj3J0bacM=
+github.com/testcontainers/testcontainers-go/modules/localstack v0.26.0/go.mod h1:1xkZPpkBu6coI7CyVn3DXUBnsVrZ+fd/Cc8lx6zk2mk=
+github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
+github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
+github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
+github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
+github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+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/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
+golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
+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.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
+golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
+golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
+golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
-golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
+golang.org/x/time v0.3.0/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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
+golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
+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=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc=
+google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
+google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
+gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
diff --git a/internal/config.go b/internal/config.go
index 851ca75..840a671 100644
--- a/internal/config.go
+++ b/internal/config.go
@@ -6,14 +6,13 @@ package internal
import (
"encoding/json"
"errors"
- "log"
"os"
"strings"
yaml "gopkg.in/yaml.v2"
)
-// This returns a list of Lambda names that are read from an input file.
+// GenerateLambdaDeleteList is a function that takes a file path as input and returns a list of Lambdas to be deleted
func GenerateLambdaDeleteList(filePath string) ([]string, error) {
var (
deleteListYaml CustomDeleteListYaml
@@ -45,7 +44,7 @@ func GenerateLambdaDeleteList(filePath string) ([]string, error) {
return output, err
}
-// This function reads a yaml input file and returns a list of Lambdas
+// readConfigFileYaml is a function that takes a file path as input and returns a list of Lambdas to be deleted. A YAML file is expected.
func readConfigFileYaml(file string) (CustomDeleteListYaml, error) {
var (
list CustomDeleteListYaml
@@ -53,17 +52,19 @@ func readConfigFileYaml(file string) (CustomDeleteListYaml, error) {
fileContent, err := os.ReadFile(file)
if err != nil {
- log.Fatal("unable to read the input file")
+ return list, errors.New("unable to read the input file")
}
err = yaml.Unmarshal(fileContent, &list)
if err != nil {
- err = errors.New("unable to unmarshall the YAML file")
+ return list, errors.New("unable to unmarshall the YAML file")
}
+
return list, err
+
}
-// This function reads a json input file and returns a list of Lambdas
+// readConfigFileJson is a function that takes a file path as input and returns a list of Lambdas to be deleted. A JSON file is expected.
func readConfigFileJson(file string) (CustomDeleteListJson, error) {
var (
list CustomDeleteListJson
@@ -71,36 +72,38 @@ func readConfigFileJson(file string) (CustomDeleteListJson, error) {
fileContent, err := os.ReadFile(file)
if err != nil {
- log.Fatal("unable to read the input file")
+ return list, errors.New("unable to read the input file")
}
err = json.Unmarshal(fileContent, &list)
if err != nil {
- err = errors.New("unable to unmarshall the json file")
+ return list, errors.New("unable to unmarshall the json file")
}
return list, err
}
-// This function validates the existence of an input file and ensures its prefix is json | yaml | yml
+// determineFileType validates the existence of an input file and ensures its prefix is json | yaml | yml
func determineFileType(file string) (string, error) {
f, err := os.Stat(file)
+ if err != nil {
+ return "none", errors.New("unable to read the input file")
+ }
var fileType string
- if err == nil {
- switch {
- case strings.HasSuffix(f.Name(), "yaml"):
- fileType = "yaml"
- case strings.HasSuffix(f.Name(), "json"):
- fileType = "json"
+ switch {
+ case strings.HasSuffix(f.Name(), "yaml"):
+ fileType = "yaml"
- case strings.HasSuffix(f.Name(), "yml"):
- fileType = "yaml"
+ case strings.HasSuffix(f.Name(), "json"):
+ fileType = "json"
- default:
- fileType = "none"
- err = errors.New("invalid file type provided. Must be of type json, yaml or yml")
- }
+ case strings.HasSuffix(f.Name(), "yml"):
+ fileType = "yaml"
+
+ default:
+ fileType = "none"
+ err = errors.New("invalid file type provided. Must be of type json, yaml or yml")
}
return fileType, err
diff --git a/internal/config_test.go b/internal/config_test.go
index db5d4f0..fa9af50 100644
--- a/internal/config_test.go
+++ b/internal/config_test.go
@@ -7,19 +7,32 @@ import (
"testing"
)
+func TestFileNotFound(t *testing.T) {
+
+ _, err := readConfigFileYaml("invalid.yaml")
+ if err == nil {
+ t.Fatalf("Failed to read the Yaml file. Expected error but received %d", err)
+ }
+}
+
func TestReadConfigFileYaml(t *testing.T) {
want := 2
- got, err := readConfigFileYaml("test.yaml")
+ got, err := readConfigFileYaml("../tests/test.yaml")
if len(got.Lambdas) != want || err != nil {
t.Fatalf("Failed to read the Yaml file. Expected %d but received %d", want, len(got.Lambdas))
}
+
+ _, err = readConfigFileYaml("test.json")
+ if err == nil {
+ t.Fatalf("Failed to read the Yaml file. Expected error but received %d", err)
+ }
}
func TestReadConfigFileYml(t *testing.T) {
want := 2
- got, err := readConfigFileYaml("test.yml")
+ got, err := readConfigFileYaml("../tests/test.yml")
if len(got.Lambdas) != want || err != nil {
t.Fatalf("Failed to read the Yaml file. Expected %d but received %d", want, len(got.Lambdas))
}
@@ -28,25 +41,40 @@ func TestReadConfigFileYml(t *testing.T) {
func TestReadConfigFileJson(t *testing.T) {
want := 2
- got, err := readConfigFileJson("test.json")
+ got, err := readConfigFileJson("../tests/test.json")
if len(got.Lambdas) != want || err != nil {
t.Fatalf("Failed to read the json file. Expected %d but received %d", want, len(got.Lambdas))
}
+
+ _, err = readConfigFileJson("test.yaml")
+ if err == nil {
+ t.Fatalf("Failed to read the json file. Expected error but received %d", err)
+ }
}
func TestDetermineFileTypeYaml(t *testing.T) {
want := "yaml"
- got, err := determineFileType("test.yaml")
+ got, err := determineFileType("../tests/test.yaml")
if got != want || err != nil {
t.Fatalf("Failed to read the json file. Expected %s but received %s", want, got)
}
}
+func TestDetermineFileTypeInvalid(t *testing.T) {
+
+ want := "none"
+ got, err := determineFileType("../tests/handler.zip")
+ if got != want && err == nil {
+ t.Fatalf("Failed to read the json file. Expected %s but received %s", want, got)
+ }
+
+}
+
func TestDetermineFileTypeYml(t *testing.T) {
want := "yaml"
- got, err := determineFileType("test.yml")
+ got, err := determineFileType("../tests/test.yml")
if got != want || err != nil {
t.Fatalf("Failed to read the json file. Expected %s but received %s", want, got)
}
@@ -55,18 +83,26 @@ func TestDetermineFileTypeYml(t *testing.T) {
func TestDetermineFileTypeJson(t *testing.T) {
want := "json"
- got, err := determineFileType("test.json")
+ got, err := determineFileType("../tests/test.json")
if got != want || err != nil {
t.Fatalf("Failed to read the json file. Expected %s but received %s", want, got)
}
}
+func TestInvalidJSON(t *testing.T) {
+
+ _, err := readConfigFileJson("../tests/invalid.json")
+ if err == nil {
+ t.Fatalf("An error was expected but received %s", err)
+ }
+}
+
func TestGenerateLambdaDeleteListJson(t *testing.T) {
want := []string{
"stopEC2-instances",
"putControls",
}
- got, err := GenerateLambdaDeleteList("test.json")
+ got, err := GenerateLambdaDeleteList("../tests/test.json")
if len(got) != len(want) || err != nil {
t.Fatalf("Failed to read the json file and expected content. Expected %d but received %d", len(want), len(got))
}
@@ -78,12 +114,43 @@ func TestGenerateLambdaDeleteListJson(t *testing.T) {
}
}
+func TestGenerateLambdaDeleteListInvalid(t *testing.T) {
+
+ _, err := GenerateLambdaDeleteList("../tests/invalid.json")
+ if err == nil {
+ t.Fatalf("An error was expected for an invalid JSON file but received %s", err)
+ }
+
+ _, err = GenerateLambdaDeleteList("../tests/invalid.yaml")
+ if err == nil {
+ t.Fatalf("An error was expected for an invalid YAML file but received %s", err)
+ }
+
+ _, err = GenerateLambdaDeleteList("../tests/handler.zip")
+ if err == nil {
+ t.Fatalf("An error was expected for an invalid file but received %s", err)
+ }
+
+ _, err = GenerateLambdaDeleteList("-.txt")
+ if err == nil {
+ t.Fatalf("An error was expected for an invalid file but received %s", err)
+ }
+}
+
+func TestInvalidYaml(t *testing.T) {
+
+ _, err := readConfigFileYaml("../tests/invalid.yaml")
+ if err == nil {
+ t.Fatalf("An error was expected but received %s", err)
+ }
+}
+
func TestGenerateLambdaDeleteListYaml(t *testing.T) {
want := []string{
"stopEC2-instances",
"putControls",
}
- got, err := GenerateLambdaDeleteList("test.yaml")
+ got, err := GenerateLambdaDeleteList("../tests/test.yaml")
if len(got) != len(want) || err != nil {
t.Fatalf("Failed to read the json file and expected content. Expected %d but received %d", len(want), len(got))
}
@@ -100,7 +167,7 @@ func TestGenerateLambdaDeleteListYml(t *testing.T) {
"stopEC2-instances",
"putControls",
}
- got, err := GenerateLambdaDeleteList("test.yml")
+ got, err := GenerateLambdaDeleteList("../tests/test.yml")
if len(got) != len(want) || err != nil {
t.Fatalf("Failed to read the json file and expected content. Expected %d but received %d", len(want), len(got))
}
diff --git a/main.go b/main.go
index 72cbecd..987d4ee 100644
--- a/main.go
+++ b/main.go
@@ -4,9 +4,10 @@
package main
import (
- "github.com/karl-cardenas-coding/go-lambda-cleanup/cmd"
+ "github.com/karl-cardenas-coding/go-lambda-cleanup/v2/cmd"
)
func main() {
cmd.Execute()
+
}
diff --git a/terraform/go.mod b/terraform/go.mod
deleted file mode 100644
index 7a5d89d..0000000
--- a/terraform/go.mod
+++ /dev/null
@@ -1,8 +0,0 @@
-module github.com/awsdocs/aws-lambda-developer-guide/sample-apps/blank-go
-
-go 1.14
-
-require (
- github.com/aws/aws-lambda-go v1.15.0
- github.com/aws/aws-sdk-go v1.29.33
-)
\ No newline at end of file
diff --git a/terraform/go.sum b/terraform/go.sum
deleted file mode 100644
index fa3ee7b..0000000
--- a/terraform/go.sum
+++ /dev/null
@@ -1,23 +0,0 @@
-github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/aws/aws-lambda-go v1.15.0 h1:QAhRWvXttl8TtBsODN+NzZETkci2mdN/paJ0+1hX/so=
-github.com/aws/aws-lambda-go v1.15.0/go.mod h1:FEwgPLE6+8wcGBTe5cJN3JWurd1Ztm9zN4jsXsjzKKw=
-github.com/aws/aws-sdk-go v1.29.33 h1:WP85+WHalTFQR2wYp5xR2sjiVAZXew2bBQXGU1QJBXI=
-github.com/aws/aws-sdk-go v1.29.33/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
-github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
-github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
-github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/terraform/main.go b/terraform/main.go
deleted file mode 100644
index eb949fe..0000000
--- a/terraform/main.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) karl-cardenas-coding
-// SPDX-License-Identifier: MIT
-
-package main
-
-import (
- "context"
- "encoding/json"
- "log"
- "os"
-
- "github.com/aws/aws-lambda-go/events"
- runtime "github.com/aws/aws-lambda-go/lambda"
- "github.com/aws/aws-lambda-go/lambdacontext"
- "github.com/aws/aws-sdk-go/aws/session"
- "github.com/aws/aws-sdk-go/service/lambda"
-)
-
-var client = lambda.New(session.New())
-
-func callLambda() (string, error) {
- input := &lambda.GetAccountSettingsInput{}
- req, resp := client.GetAccountSettingsRequest(input)
- err := req.Send()
- output, _ := json.Marshal(resp.AccountUsage)
- return string(output), err
-}
-
-func handleRequest(ctx context.Context, event events.SQSEvent) (string, error) {
- // event
- eventJson, _ := json.MarshalIndent(event, "", " ")
- log.Printf("EVENT: %s", eventJson)
- // environment variables
- log.Printf("REGION: %s", os.Getenv("AWS_REGION"))
- log.Println("ALL ENV VARS:")
- for _, element := range os.Environ() {
- log.Println(element)
- }
- // request context
- lc, _ := lambdacontext.FromContext(ctx)
- log.Printf("REQUEST ID: %s", lc.AwsRequestID)
- // global variable
- log.Printf("FUNCTION NAME: %s", lambdacontext.FunctionName)
- // context method
- deadline, _ := ctx.Deadline()
- log.Printf("DEADLINE: %s", deadline)
- // AWS SDK call
- usage, err := callLambda()
- if err != nil {
- return "ERROR", err
- }
- return usage, nil
-}
-
-func main() {
- runtime.Start(handleRequest)
-}
diff --git a/terraform/main.tf b/terraform/main.tf
deleted file mode 100644
index 260dbe3..0000000
--- a/terraform/main.tf
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright (c) karl-cardenas-coding
-# SPDX-License-Identifier: MIT
-
-terraform {
- required_providers {
- aws = {
- source = "hashicorp/aws"
- version = "~> 3.0"
- }
- }
-}
-
-# Configure the AWS Provider
-provider "aws" {
- region = "us-east-1"
- profile = var.profile
-}
-
-resource "aws_lambda_function" "test_lambda" {
- count = 55
- filename = "lambda.zip"
- function_name = "blank_go-${count.index}"
- role = aws_iam_role.iam_for_lambda.arn
- handler = "main"
- timeout = 30
- memory_size = 128
- runtime = "go1.x"
- tags = {
- Name = "blank_go-${count.index}"
- }
-
- depends_on = [
- data.archive_file.zip
- ]
-}
-
-variable "profile" {
- type = string
- description = "AWS Profile variable"
-}
-
-resource "aws_iam_role" "iam_for_lambda" {
- name = "iam_for_lambda"
-
- assume_role_policy = <