From f0b67f28fdbd7b83f0debd8a3af4609c00255d82 Mon Sep 17 00:00:00 2001 From: mpostument <777rip777@gmail.com> Date: Fri, 4 Sep 2020 15:02:57 +0300 Subject: [PATCH] added ecr support --- cmd/ecr.go | 69 ++++++++++++++++++++++++++++++++++ cmd/lambda.go | 5 --- cmd/s3.go | 5 +-- go.mod | 2 +- go.sum | 6 +-- pkg/aws.go | 16 ++++++++ pkg/cloudfront.go | 18 ++------- pkg/cloudwatch.go | 36 +++--------------- pkg/config_rule.go | 18 ++------- pkg/csv.go | 9 +++++ pkg/ec2.go | 19 ++-------- pkg/ecr.go | 73 ++++++++++++++++++++++++++++++++++++ pkg/ecr_test.go | 87 +++++++++++++++++++++++++++++++++++++++++++ pkg/elastic_search.go | 19 ++-------- pkg/elasticache.go | 19 ++-------- pkg/elb.go | 19 ++-------- pkg/iam.go | 30 +++------------ pkg/kinesis.go | 37 ++++-------------- pkg/lambda.go | 19 ++-------- pkg/rds.go | 18 ++------- pkg/redshift.go | 19 ++-------- pkg/s3.go | 17 ++------- 22 files changed, 306 insertions(+), 254 deletions(-) create mode 100644 cmd/ecr.go create mode 100644 pkg/ecr.go create mode 100644 pkg/ecr_test.go diff --git a/cmd/ecr.go b/cmd/ecr.go new file mode 100644 index 0000000..568c640 --- /dev/null +++ b/cmd/ecr.go @@ -0,0 +1,69 @@ +/* +Copyright © 2020 Maksym Postument 777rip777@gmail.com + +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. +*/ +package cmd + +import ( + "awstaghelper/pkg" + "github.com/aws/aws-sdk-go/service/ecr" + + "github.com/spf13/cobra" +) + +// ecrCmd represents the ecr command +var ecrCmd = &cobra.Command{ + Use: "ecr", + Short: "Root command for interaction with AWS ecr services", + Long: `Root command for interaction with AWS ecr services.`, +} + +var getEcrTagsCmd = &cobra.Command{ + Use: "get-repository-tags", + Short: "Write arn and required tags to csv", + Long: `Write to csv data with arn and required tags to csv. +This csv can be used with tag-repository command to tag aws environment. +Specify list of tags which should be read using tags flag: --tags Name,Env,Project. +Csv filename can be specified with flag filename.`, + Run: func(cmd *cobra.Command, args []string) { + tags, _ := cmd.Flags().GetString("tags") + filename, _ := cmd.Flags().GetString("filename") + profile, _ := cmd.Flags().GetString("profile") + region, _ := cmd.Flags().GetString("region") + sess := pkg.GetSession(region, profile) + client := ecr.New(sess) + pkg.WriteCsv(pkg.ParseEcrRepositoriesTags(tags, client), filename) + }, +} + +var tagEcrRepoCmd = &cobra.Command{ + Use: "tag-repository", + Short: "Read csv and tag ecr repository with csv data", + Long: `Read csv generated with get-repository-tags command and tag ecr repository with tags from csv.`, + Run: func(cmd *cobra.Command, args []string) { + filename, _ := cmd.Flags().GetString("filename") + profile, _ := cmd.Flags().GetString("profile") + region, _ := cmd.Flags().GetString("region") + sess := pkg.GetSession(region, profile) + client := ecr.New(sess) + csvData := pkg.ReadCsv(filename) + pkg.TagEcrRepo(csvData, client) + }, +} + +func init() { + rootCmd.AddCommand(ecrCmd) + ecrCmd.AddCommand(tagEcrRepoCmd) + ecrCmd.AddCommand(getEcrTagsCmd) +} diff --git a/cmd/lambda.go b/cmd/lambda.go index 3437fd1..962ebaa 100644 --- a/cmd/lambda.go +++ b/cmd/lambda.go @@ -27,9 +27,6 @@ var lambdaCmd = &cobra.Command{ Use: "lambda", Short: "Root command for interaction with AWS lambda services", Long: `Root command for interaction with AWS lambda services.`, - //Run: func(cmd *cobra.Command, args []string) { - // fmt.Println("lambda called") - //}, } var getLambdaCmd = &cobra.Command{ @@ -69,6 +66,4 @@ func init() { rootCmd.AddCommand(lambdaCmd) lambdaCmd.AddCommand(getLambdaCmd) lambdaCmd.AddCommand(tagLambdaCmd) - lambdaCmd.PersistentFlags().StringP("tags", "t", "Name,Environment", "Tags you want to read") - lambdaCmd.PersistentFlags().StringP("filename", "f", "lambdaTags.csv", "Filename where to store write") } diff --git a/cmd/s3.go b/cmd/s3.go index 2df0fe4..fe279e0 100644 --- a/cmd/s3.go +++ b/cmd/s3.go @@ -1,5 +1,5 @@ /* -Copyright © 2020 NAME HERE +Copyright © 2020 Maksym Postument 777rip777@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -27,9 +27,6 @@ var s3Cmd = &cobra.Command{ Use: "s3", Short: "Root command for interaction with AWS s3 services", Long: `Root command for interaction with AWS s3 services.`, - //Run: func(cmd *cobra.Command, args []string) { - // fmt.Println("s3 called") - //}, } var getS3Cmd = &cobra.Command{ diff --git a/go.mod b/go.mod index 83b7b91..4198572 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module awstaghelper go 1.14 require ( - github.com/aws/aws-sdk-go v1.34.14 + github.com/aws/aws-sdk-go v1.34.17 github.com/mitchellh/go-homedir v1.1.0 github.com/spf13/cobra v1.0.0 github.com/spf13/viper v1.7.1 diff --git a/go.sum b/go.sum index 23f1164..50a0f4b 100644 --- a/go.sum +++ b/go.sum @@ -21,10 +21,8 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go v1.34.13 h1:wwNWSUh4FGJxXVOVVNj2lWI8wTe5hK8sGWlK7ziEcgg= -github.com/aws/aws-sdk-go v1.34.13/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.34.14 h1:G0jUdSDSp63P0oo/N3c/ldo7s8mYW3Kh/GPIJ+oESVQ= -github.com/aws/aws-sdk-go v1.34.14/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.34.17 h1:9OzUgRrLmYm2mbfFx4v+2nBEg+Cvape1cvn9C3RNWTE= +github.com/aws/aws-sdk-go v1.34.17/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= diff --git a/pkg/aws.go b/pkg/aws.go index e8fe70e..66a5bd6 100644 --- a/pkg/aws.go +++ b/pkg/aws.go @@ -2,6 +2,7 @@ package pkg import ( "fmt" + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" @@ -22,3 +23,18 @@ func GetSession(region string, profile string) *session.Session { return sess } + +func awsErrorHandle(err error) bool { + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + default: + fmt.Println(aerr.Error()) + } + } else { + fmt.Println(err.Error()) + } + return true + } + return false +} diff --git a/pkg/cloudfront.go b/pkg/cloudfront.go index 77642a2..df2f1c1 100644 --- a/pkg/cloudfront.go +++ b/pkg/cloudfront.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/cloudfront" "github.com/aws/aws-sdk-go/service/cloudfront/cloudfrontiface" ) @@ -26,10 +25,7 @@ func getDistributions(client cloudfrontiface.CloudFrontAPI) *cloudfront.ListDist // ParseDistributionsTags parse output from getDistributions and return distribution arn and specified tags. func ParseDistributionsTags(tagsToRead string, client cloudfrontiface.CloudFrontAPI) [][]string { instancesOutput := getDistributions(client) - var rows [][]string - headers := []string{"Arn"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Arn") for _, distribution := range instancesOutput.DistributionList.Items { input := &cloudfront.ListTagsForResourceInput{ @@ -55,8 +51,8 @@ func ParseDistributionsTags(tagsToRead string, client cloudfrontiface.CloudFront // TagDistribution tag cloudfront distribution. Take as input data from csv file. Where first column Arn func TagDistribution(csvData [][]string, client cloudfrontiface.CloudFrontAPI) { - var tags cloudfront.Tags for r := 1; r < len(csvData); r++ { + var tags cloudfront.Tags for c := 1; c < len(csvData[0]); c++ { tags.Items = append(tags.Items, &cloudfront.Tag{ Key: &csvData[0][c], @@ -70,15 +66,7 @@ func TagDistribution(csvData [][]string, client cloudfrontiface.CloudFrontAPI) { } _, err := client.TagResource(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/cloudwatch.go b/pkg/cloudwatch.go index a5b37f0..e569ddd 100644 --- a/pkg/cloudwatch.go +++ b/pkg/cloudwatch.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/cloudwatch" "github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" @@ -34,10 +33,7 @@ func getCWAlarm(client cloudwatchiface.CloudWatchAPI) []*cloudwatch.MetricAlarm // ParseCwAlarmTags parse output from getCWAlarm and return alarm arn and specified tags. func ParseCwAlarmTags(tagsToRead string, client cloudwatchiface.CloudWatchAPI) [][]string { instancesOutput := getCWAlarm(client) - var rows [][]string - headers := []string{"Arn"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Arn") for _, alarm := range instancesOutput { input := &cloudwatch.ListTagsForResourceInput{ @@ -82,10 +78,7 @@ func getCWLogGroups(client cloudwatchlogsiface.CloudWatchLogsAPI) []*cloudwatchl // ParseCwLogGroupTags parse output from getInstances and return logGroupName and specified tags. func ParseCwLogGroupTags(tagsToRead string, client cloudwatchlogsiface.CloudWatchLogsAPI) [][]string { instancesOutput := getCWLogGroups(client) - var rows [][]string - headers := []string{"LogGroupName"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "LogGroupName") for _, logGroup := range instancesOutput { input := &cloudwatchlogs.ListTagsLogGroupInput{ @@ -111,8 +104,8 @@ func ParseCwLogGroupTags(tagsToRead string, client cloudwatchlogsiface.CloudWatc // TagCloudWatchAlarm tag cloudwatch alarms. Take as input data from csv file. Where first column Arn func TagCloudWatchAlarm(csvData [][]string, client cloudwatchiface.CloudWatchAPI) { - var tags []*cloudwatch.Tag for r := 1; r < len(csvData); r++ { + var tags []*cloudwatch.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &cloudwatch.Tag{ Key: &csvData[0][c], @@ -126,15 +119,7 @@ func TagCloudWatchAlarm(csvData [][]string, client cloudwatchiface.CloudWatchAPI } _, err := client.TagResource(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } @@ -142,9 +127,8 @@ func TagCloudWatchAlarm(csvData [][]string, client cloudwatchiface.CloudWatchAPI // TagCloudWatchLogGroups tag cloudwatch log groups. Take as input data from csv file. Where first column LogGroupName func TagCloudWatchLogGroups(csvData [][]string, client cloudwatchlogsiface.CloudWatchLogsAPI) { - - tags := make(map[string]*string) for r := 1; r < len(csvData); r++ { + tags := make(map[string]*string) for c := 1; c < len(csvData[0]); c++ { tags[csvData[0][c]] = &csvData[r][c] } @@ -155,15 +139,7 @@ func TagCloudWatchLogGroups(csvData [][]string, client cloudwatchlogsiface.Cloud } _, err := client.TagLogGroup(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/config_rule.go b/pkg/config_rule.go index 78c5c5f..ebad49a 100644 --- a/pkg/config_rule.go +++ b/pkg/config_rule.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/configservice" "github.com/aws/aws-sdk-go/service/configservice/configserviceiface" ) @@ -26,10 +25,7 @@ func getConfigRules(client configserviceiface.ConfigServiceAPI) *configservice.D // ParseConfigRuleTags parse output from getCWAlarm and return alarm arn and specified tags. func ParseConfigRuleTags(tagsToRead string, client configserviceiface.ConfigServiceAPI) [][]string { instancesOutput := getConfigRules(client) - var rows [][]string - headers := []string{"Arn"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Arn") for _, rule := range instancesOutput.ConfigRules { input := &configservice.ListTagsForResourceInput{ @@ -55,8 +51,8 @@ func ParseConfigRuleTags(tagsToRead string, client configserviceiface.ConfigServ // TagConfigRule tag config rules. Take as input data from csv file. Where first column Arn func TagConfigRule(csvData [][]string, client configserviceiface.ConfigServiceAPI) { - var tags []*configservice.Tag for r := 1; r < len(csvData); r++ { + var tags []*configservice.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &configservice.Tag{ Key: &csvData[0][c], @@ -70,15 +66,7 @@ func TagConfigRule(csvData [][]string, client configserviceiface.ConfigServiceAP } _, err := client.TagResource(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/csv.go b/pkg/csv.go index 15045e2..57a73b2 100644 --- a/pkg/csv.go +++ b/pkg/csv.go @@ -4,6 +4,7 @@ import ( "encoding/csv" "log" "os" + "strings" ) func WriteCsv(data [][]string, filename string) { @@ -38,3 +39,11 @@ func ReadCsv(filename string) [][]string { return csvLines } + +func addHeaders(tagsToRead string, resourceIdHeader string) [][]string { + var rows [][]string + headers := []string{resourceIdHeader} + headers = append(headers, strings.Split(tagsToRead, ",")...) + rows = append(rows, headers) + return rows +} diff --git a/pkg/ec2.go b/pkg/ec2.go index 71cee56..6044483 100644 --- a/pkg/ec2.go +++ b/pkg/ec2.go @@ -1,12 +1,10 @@ package pkg import ( - "fmt" "log" "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" ) @@ -31,10 +29,7 @@ func getEC2Instances(client ec2iface.EC2API) []*ec2.Reservation { // ParseEC2Tags parse output from getEC2Instances and return instances id and specified tags. func ParseEC2Tags(tagsToRead string, client ec2iface.EC2API) [][]string { instancesOutput := getEC2Instances(client) - var rows [][]string - headers := []string{"Id"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Id") for _, reservation := range instancesOutput { for _, instance := range reservation.Instances { tags := map[string]string{} @@ -53,8 +48,8 @@ func ParseEC2Tags(tagsToRead string, client ec2iface.EC2API) [][]string { // TagEc2 tag instances. Take as input data from csv file. Where first column id func TagEc2(csvData [][]string, client ec2iface.EC2API) { - var tags []*ec2.Tag for r := 1; r < len(csvData); r++ { + var tags []*ec2.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &ec2.Tag{ Key: &csvData[0][c], @@ -70,15 +65,7 @@ func TagEc2(csvData [][]string, client ec2iface.EC2API) { } _, err := client.CreateTags(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/ecr.go b/pkg/ecr.go new file mode 100644 index 0000000..e1669c0 --- /dev/null +++ b/pkg/ecr.go @@ -0,0 +1,73 @@ +package pkg + +import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ecr" + "github.com/aws/aws-sdk-go/service/ecr/ecriface" + "log" + "strings" +) + +func getEcrRepositories(client ecriface.ECRAPI) []*ecr.Repository { + input := &ecr.DescribeRepositoriesInput{} + + var result []*ecr.Repository + + err := client.DescribeRepositoriesPages(input, + func(page *ecr.DescribeRepositoriesOutput, lastPage bool) bool { + result = append(result, page.Repositories...) + return !lastPage + }) + if err != nil { + log.Fatal("Not able to get ecr repositories", err) + return nil + } + return result +} + +// ParseEcrRepositoriesTags parse output from getEcrRepositories and return repo arn and specified tags. +func ParseEcrRepositoriesTags(tagsToRead string, client ecriface.ECRAPI) [][]string { + repoList := getEcrRepositories(client) + rows := addHeaders(tagsToRead, "Arn") + for _, repo := range repoList { + repoTags, err := client.ListTagsForResource(&ecr.ListTagsForResourceInput{ResourceArn: repo.RepositoryArn}) + if err != nil { + fmt.Println("Not able to get ecr tags", err) + } + tags := map[string]string{} + for _, tag := range repoTags.Tags { + tags[*tag.Key] = *tag.Value + } + + var resultTags []string + for _, key := range strings.Split(tagsToRead, ",") { + resultTags = append(resultTags, tags[key]) + } + rows = append(rows, append([]string{*repo.RepositoryArn}, resultTags...)) + } + return rows +} + +// TagEcrRepo tag ecr repo. Take as input data from csv file. Where first column is name +func TagEcrRepo(csvData [][]string, client ecriface.ECRAPI) { + for r := 1; r < len(csvData); r++ { + var tags []*ecr.Tag + for c := 1; c < len(csvData[0]); c++ { + tags = append(tags, &ecr.Tag{ + Key: &csvData[0][c], + Value: &csvData[r][c], + }) + } + + input := &ecr.TagResourceInput{ + ResourceArn: aws.String(csvData[r][0]), + Tags: tags, + } + + _, err := client.TagResource(input) + if awsErrorHandle(err) { + return + } + } +} diff --git a/pkg/ecr_test.go b/pkg/ecr_test.go new file mode 100644 index 0000000..8fe87a9 --- /dev/null +++ b/pkg/ecr_test.go @@ -0,0 +1,87 @@ +package pkg + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ecr" + "github.com/aws/aws-sdk-go/service/ecr/ecriface" + "github.com/stretchr/testify/assert" + "testing" +) + +type mockedEcrRepo struct { + ecriface.ECRAPI + respDescribeRepositories ecr.DescribeRepositoriesOutput + respListTagsForResource ecr.ListTagsForResourceOutput +} + +func (m *mockedEcrRepo) DescribeRepositoriesPages(input *ecr.DescribeRepositoriesInput, pageFunc func(*ecr.DescribeRepositoriesOutput, bool) bool) error { + pageFunc(&m.respDescribeRepositories, true) + return nil +} + +func (m *mockedEcrRepo) ListTagsForResource(*ecr.ListTagsForResourceInput) (*ecr.ListTagsForResourceOutput, error) { + return &m.respListTagsForResource, nil +} + +func TestGetEcrRepositories(t *testing.T) { + cases := []*mockedEcrRepo{ + { + respDescribeRepositories: describeRepositoriesResponse, + }, + } + + expectedResult := describeRepositoriesResponse.Repositories + + for _, c := range cases { + t.Run("getEcrRepositories", func(t *testing.T) { + result := getEcrRepositories(c) + assertions := assert.New(t) + assertions.EqualValues(expectedResult, result) + }) + + } +} + +func TestParseEcrRepositoriesTags(t *testing.T) { + cases := []*mockedEcrRepo{ + { + respDescribeRepositories: describeRepositoriesResponse, + respListTagsForResource: listTagsForEcrResourceResponse, + }, + } + + expectedResult := [][]string{ + {"Arn", "Name", "Owner"}, + {"arn:aws:ecr:region:012345678910:repository/test-repo1", "test-repo1", "mpostument"}, + } + + for _, c := range cases { + t.Run("ParseEcrRepositoriesTags", func(t *testing.T) { + result := ParseEcrRepositoriesTags("Name,Owner", c) + assertions := assert.New(t) + assertions.EqualValues(expectedResult, result) + }) + + } +} + +var describeRepositoriesResponse = ecr.DescribeRepositoriesOutput{ + Repositories: []*ecr.Repository{ + { + RepositoryArn: aws.String("arn:aws:ecr:region:012345678910:repository/test-repo1"), + }, + }, +} + +var listTagsForEcrResourceResponse = ecr.ListTagsForResourceOutput{ + Tags: []*ecr.Tag{ + { + Key: aws.String("Name"), + Value: aws.String("test-repo1"), + }, + { + Key: aws.String("Owner"), + Value: aws.String("mpostument"), + }, + }, +} diff --git a/pkg/elastic_search.go b/pkg/elastic_search.go index 06a0609..ed4651c 100644 --- a/pkg/elastic_search.go +++ b/pkg/elastic_search.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/elasticsearchservice" "github.com/aws/aws-sdk-go/service/elasticsearchservice/elasticsearchserviceiface" "github.com/aws/aws-sdk-go/service/sts" @@ -31,10 +30,7 @@ func ParseElasticSearchTags(tagsToRead string, client elasticsearchserviceiface. if err != nil { log.Fatal("Not able to get account id", err) } - var rows [][]string - headers := []string{"Arn"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Arn") for _, elasticCacheInstance := range instancesOutput.DomainNames { clusterArn := fmt.Sprintf("arn:aws:es:%s:%s:domain/%s", @@ -63,9 +59,8 @@ func ParseElasticSearchTags(tagsToRead string, client elasticsearchserviceiface. // TagElasticSearch tag instances. Take as input data from csv file. Where first column id func TagElasticSearch(csvData [][]string, client elasticsearchserviceiface.ElasticsearchServiceAPI) { - - var tags []*elasticsearchservice.Tag for r := 1; r < len(csvData); r++ { + var tags []*elasticsearchservice.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &elasticsearchservice.Tag{ Key: &csvData[0][c], @@ -79,15 +74,7 @@ func TagElasticSearch(csvData [][]string, client elasticsearchserviceiface.Elast } _, err := client.AddTags(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/elasticache.go b/pkg/elasticache.go index 4c7f8b6..0ae6ba7 100644 --- a/pkg/elasticache.go +++ b/pkg/elasticache.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/elasticache" "github.com/aws/aws-sdk-go/service/elasticache/elasticacheiface" "github.com/aws/aws-sdk-go/service/sts" @@ -38,10 +37,7 @@ func ParseElastiCacheClusterTags(tagsToRead string, client elasticacheiface.Elas if err != nil { log.Fatal("Not able to get account id", err) } - var rows [][]string - headers := []string{"Arn"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Arn") for _, elasticCacheInstance := range instancesOutput { clusterArn := fmt.Sprintf("arn:aws:elasticache:%s:%s:cluster:%s", @@ -70,9 +66,8 @@ func ParseElastiCacheClusterTags(tagsToRead string, client elasticacheiface.Elas // TagElastiCache tag instances. Take as input data from csv file. Where first column id func TagElastiCache(csvData [][]string, client elasticacheiface.ElastiCacheAPI) { - - var tags []*elasticache.Tag for r := 1; r < len(csvData); r++ { + var tags []*elasticache.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &elasticache.Tag{ Key: &csvData[0][c], @@ -86,15 +81,7 @@ func TagElastiCache(csvData [][]string, client elasticacheiface.ElastiCacheAPI) } _, err := client.AddTagsToResource(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/elb.go b/pkg/elb.go index 12e6303..db78d0f 100644 --- a/pkg/elb.go +++ b/pkg/elb.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/elbv2" "github.com/aws/aws-sdk-go/service/elbv2/elbv2iface" ) @@ -32,10 +31,7 @@ func getElbV2(client elbv2iface.ELBV2API) []*elbv2.LoadBalancer { // ParseElbV2Tags parse output from getInstances and return instances id and specified tags. func ParseElbV2Tags(tagsToRead string, client elbv2iface.ELBV2API) [][]string { instancesOutput := getElbV2(client) - var rows [][]string - headers := []string{"Arn"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Arn") for _, elb := range instancesOutput { elbTags, err := client.DescribeTags(&elbv2.DescribeTagsInput{ResourceArns: []*string{elb.LoadBalancerArn}}) if err != nil { @@ -59,9 +55,8 @@ func ParseElbV2Tags(tagsToRead string, client elbv2iface.ELBV2API) [][]string { // TagElbV2 tag elbv2(application and network). Take as input data from csv file. Where first column id func TagElbV2(csvData [][]string, client elbv2iface.ELBV2API) { - - var tags []*elbv2.Tag for r := 1; r < len(csvData); r++ { + var tags []*elbv2.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &elbv2.Tag{ Key: &csvData[0][c], @@ -75,15 +70,7 @@ func TagElbV2(csvData [][]string, client elbv2iface.ELBV2API) { } _, err := client.AddTags(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/iam.go b/pkg/iam.go index 26f2a7c..87d41fb 100644 --- a/pkg/iam.go +++ b/pkg/iam.go @@ -3,7 +3,6 @@ package pkg import ( "fmt" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/iam" "github.com/aws/aws-sdk-go/service/iam/iamiface" "log" @@ -55,8 +54,8 @@ func ParseIamUserTags(tagsToRead string, client iamiface.IAMAPI) [][]string { // TagIamUser tag iam user. Take as input data from csv file. Where first column is name func TagIamUser(csvData [][]string, client iamiface.IAMAPI) { - var tags []*iam.Tag for r := 1; r < len(csvData); r++ { + var tags []*iam.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &iam.Tag{ Key: &csvData[0][c], @@ -70,15 +69,7 @@ func TagIamUser(csvData [][]string, client iamiface.IAMAPI) { } _, err := client.TagUser(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } @@ -104,10 +95,7 @@ func getIamRoles(client iamiface.IAMAPI) []*iam.Role { // ParseIamRolesTags parse output from getIamRoles and return roles and specified tags. func ParseIamRolesTags(tagsToRead string, client iamiface.IAMAPI) [][]string { usersList := getIamRoles(client) - var rows [][]string - headers := []string{"RoleName"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "RoleName") for _, role := range usersList { roleTags, err := client.ListRoleTags(&iam.ListRoleTagsInput{RoleName: role.RoleName}) if err != nil { @@ -129,8 +117,8 @@ func ParseIamRolesTags(tagsToRead string, client iamiface.IAMAPI) [][]string { // TagIamRole tag iam user. Take as input data from csv file. Where first column is name func TagIamRole(csvData [][]string, client iamiface.IAMAPI) { - var tags []*iam.Tag for r := 1; r < len(csvData); r++ { + var tags []*iam.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &iam.Tag{ Key: &csvData[0][c], @@ -144,15 +132,7 @@ func TagIamRole(csvData [][]string, client iamiface.IAMAPI) { } _, err := client.TagRole(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/kinesis.go b/pkg/kinesis.go index 35e168a..6b52478 100644 --- a/pkg/kinesis.go +++ b/pkg/kinesis.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/firehose" "github.com/aws/aws-sdk-go/service/firehose/firehoseiface" "github.com/aws/aws-sdk-go/service/kinesis" @@ -27,10 +26,7 @@ func getFirehoses(client firehoseiface.FirehoseAPI) *firehose.ListDeliveryStream // ParseKinesisTags parse output from getFirehoses and return firehose name and specified tags. func ParseFirehoseTags(tagsToRead string, client firehoseiface.FirehoseAPI) [][]string { instancesOutput := getFirehoses(client) - var rows [][]string - headers := []string{"Name"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Name") for _, stream := range instancesOutput.DeliveryStreamNames { input := &firehose.ListTagsForDeliveryStreamInput{ @@ -75,10 +71,7 @@ func getStreams(client kinesisiface.KinesisAPI) []*string { // ParseKinesisTags parse output from getStreams and return kinesis arn and specified tags. func ParseKinesisTags(tagsToRead string, client kinesisiface.KinesisAPI) [][]string { instancesOutput := getStreams(client) - var rows [][]string - headers := []string{"Name"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Name") for _, stream := range instancesOutput { input := &kinesis.ListTagsForStreamInput{ @@ -104,8 +97,8 @@ func ParseKinesisTags(tagsToRead string, client kinesisiface.KinesisAPI) [][]str // TagFirehose tag kinesis firehose. Take as input data from csv file. Where first column name func TagFirehose(csvData [][]string, client firehoseiface.FirehoseAPI) { - var tags []*firehose.Tag for r := 1; r < len(csvData); r++ { + var tags []*firehose.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &firehose.Tag{ Key: &csvData[0][c], @@ -119,15 +112,8 @@ func TagFirehose(csvData [][]string, client firehoseiface.FirehoseAPI) { } _, err := client.TagDeliveryStream(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + tags = nil + if awsErrorHandle(err) { return } } @@ -135,9 +121,8 @@ func TagFirehose(csvData [][]string, client firehoseiface.FirehoseAPI) { // TagKinesisStream tag kinesis stream. Take as input data from csv file. Where first column id func TagKinesisStream(csvData [][]string, client kinesisiface.KinesisAPI) { - - tags := make(map[string]*string) for r := 1; r < len(csvData); r++ { + tags := make(map[string]*string) for c := 1; c < len(csvData[0]); c++ { tags[csvData[0][c]] = &csvData[r][c] } @@ -148,15 +133,7 @@ func TagKinesisStream(csvData [][]string, client kinesisiface.KinesisAPI) { } _, err := client.AddTagsToStream(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/lambda.go b/pkg/lambda.go index e203387..d17a3fa 100644 --- a/pkg/lambda.go +++ b/pkg/lambda.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/lambda" "github.com/aws/aws-sdk-go/service/lambda/lambdaiface" ) @@ -32,10 +31,7 @@ func getLambdaFunctions(client lambdaiface.LambdaAPI) []*lambda.FunctionConfigur // ParseLambdaFunctionTags parse output from getLambdaFunctions and return arn and specified tags. func ParseLambdaFunctionTags(tagsToRead string, client lambdaiface.LambdaAPI) [][]string { instancesOutput := getLambdaFunctions(client) - var rows [][]string - headers := []string{"Arn"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Arn") for _, lambdaOutput := range instancesOutput { lambdaTags, err := client.ListTags(&lambda.ListTagsInput{Resource: lambdaOutput.FunctionArn}) if err != nil { @@ -57,9 +53,8 @@ func ParseLambdaFunctionTags(tagsToRead string, client lambdaiface.LambdaAPI) [] // TagLambda tag instances. Take as input data from csv file. Where first column id func TagLambda(csvData [][]string, client lambdaiface.LambdaAPI) { - - tags := make(map[string]*string) for r := 1; r < len(csvData); r++ { + tags := make(map[string]*string) for c := 1; c < len(csvData[0]); c++ { tags[csvData[0][c]] = &csvData[r][c] } @@ -70,15 +65,7 @@ func TagLambda(csvData [][]string, client lambdaiface.LambdaAPI) { } _, err := client.TagResource(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/rds.go b/pkg/rds.go index 4326674..441772a 100644 --- a/pkg/rds.go +++ b/pkg/rds.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/rds" "github.com/aws/aws-sdk-go/service/rds/rdsiface" ) @@ -32,10 +31,7 @@ func getRDSInstances(client rdsiface.RDSAPI) []*rds.DBInstance { // ParseRDSTags parse output from getRDSInstances and return arn and specified tags. func ParseRDSTags(tagsToRead string, client rdsiface.RDSAPI) [][]string { instancesOutput := getRDSInstances(client) - var rows [][]string - headers := []string{"Arn"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Arn") for _, dbInstances := range instancesOutput { rdsTags, err := client.ListTagsForResource(&rds.ListTagsForResourceInput{ResourceName: dbInstances.DBInstanceArn}) if err != nil { @@ -56,8 +52,8 @@ func ParseRDSTags(tagsToRead string, client rdsiface.RDSAPI) [][]string { // TagRDS tag rds instances. Take as input data from csv file. Where first column arn func TagRDS(csvData [][]string, client rdsiface.RDSAPI) { - var tags []*rds.Tag for r := 1; r < len(csvData); r++ { + var tags []*rds.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &rds.Tag{ Key: &csvData[0][c], @@ -71,15 +67,7 @@ func TagRDS(csvData [][]string, client rdsiface.RDSAPI) { } _, err := client.AddTagsToResource(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/redshift.go b/pkg/redshift.go index 2b8e4bd..322d973 100644 --- a/pkg/redshift.go +++ b/pkg/redshift.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/redshift" "github.com/aws/aws-sdk-go/service/redshift/redshiftiface" "github.com/aws/aws-sdk-go/service/sts" @@ -39,11 +38,7 @@ func ParseRedshiftTags(tagsToRead string, client redshiftiface.RedshiftAPI, stsC if err != nil { log.Fatal("Not able to get account id", err) } - - var rows [][]string - headers := []string{"Arn"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Arn") for _, redshiftInstances := range instancesOutput { clusterArn := fmt.Sprintf("arn:aws:redshift:%s:%s:cluster:%s", region, *callerIdentity.Account, *redshiftInstances.ClusterIdentifier) @@ -66,8 +61,8 @@ func ParseRedshiftTags(tagsToRead string, client redshiftiface.RedshiftAPI, stsC // TagRedShift tag rds instances. Take as input data from csv file. Where first column arn func TagRedShift(csvData [][]string, client redshiftiface.RedshiftAPI) { - var tags []*redshift.Tag for r := 1; r < len(csvData); r++ { + var tags []*redshift.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &redshift.Tag{ Key: &csvData[0][c], @@ -81,15 +76,7 @@ func TagRedShift(csvData [][]string, client redshiftiface.RedshiftAPI) { } _, err := client.CreateTags(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } } diff --git a/pkg/s3.go b/pkg/s3.go index 0c770c2..7f0c72d 100644 --- a/pkg/s3.go +++ b/pkg/s3.go @@ -26,10 +26,7 @@ func getBuckets(client s3iface.S3API) *s3.ListBucketsOutput { // ParseS3Tags parse output from getBuckets and return instances id and specified tags. func ParseS3Tags(tagsToRead string, client s3iface.S3API) [][]string { s3Output := getBuckets(client) - var rows [][]string - headers := []string{"Name"} - headers = append(headers, strings.Split(tagsToRead, ",")...) - rows = append(rows, headers) + rows := addHeaders(tagsToRead, "Name") for _, bucket := range s3Output.Buckets { s3Tags, err := client.GetBucketTagging(&s3.GetBucketTaggingInput{Bucket: bucket.Name}) if err != nil { @@ -56,8 +53,8 @@ func ParseS3Tags(tagsToRead string, client s3iface.S3API) [][]string { // TagS3 tag instances. Take as input data from csv file. Where first column id func TagS3(csvData [][]string, client s3iface.S3API) { - var tags []*s3.Tag for r := 1; r < len(csvData); r++ { + var tags []*s3.Tag for c := 1; c < len(csvData[0]); c++ { tags = append(tags, &s3.Tag{ Key: &csvData[0][c], @@ -73,15 +70,7 @@ func TagS3(csvData [][]string, client s3iface.S3API) { } _, err := client.PutBucketTagging(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - default: - fmt.Println(aerr.Error()) - } - } else { - fmt.Println(err.Error()) - } + if awsErrorHandle(err) { return } }