From 746b1464bc2848e75bb77467a03b4f67ed56ada5 Mon Sep 17 00:00:00 2001 From: Maksym Postument <777rip777@gmail.com> Date: Tue, 21 Jul 2020 21:00:48 +0300 Subject: [PATCH] added elasticache support (#1) --- README.MD | 18 +++++++ cmd/elasticache.go | 71 ++++++++++++++++++++++++++++ cmd/lambda.go | 8 ++-- cmd/rds.go | 2 +- go.mod | 2 +- go.sum | 4 +- modules/elastiCacheHelper/getTags.go | 69 +++++++++++++++++++++++++++ modules/elastiCacheHelper/setTags.go | 42 ++++++++++++++++ 8 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 cmd/elasticache.go create mode 100644 modules/elastiCacheHelper/getTags.go create mode 100644 modules/elastiCacheHelper/setTags.go diff --git a/README.MD b/README.MD index 0269281..ec225a7 100644 --- a/README.MD +++ b/README.MD @@ -11,6 +11,7 @@ * [Rds](#rds) * [Lambda](#lambda) * [S3](#s3) + * [ElastiCache](#elasticache) * [Global parameters](#global-parameters) * [Contributing](#contributing) * [License](#license) @@ -93,6 +94,23 @@ Read csv and tag s3 - `awstaghelper s3 tag-s3` Default filename `ec2Tags.csv` Example: `awstaghelper s3 tag-s3 --filename ec2Tag.csv --profile main` + +### Elasticache + +#### Get elasticache tags + +Get list of s3 with required tags - `awstaghelper elasticache get-elasticache-tags` +Default filename `elasticacheTags.csv` +Default tags list `Environment,Project` +Example: +`awstaghelper elasticache get-elasticache-tags --filename elasticacheTag.csv --tags Name,Owner --profile main` + +#### Tag s3 + +Read csv and tag s3 - `awstaghelper elasticache tag-elasticache` +Default filename `elasticacheTags.csv` +Example: +`awstaghelper elasticache tag-elasticache --filename elasticacheTag.csv --profile main` ## Global parameters diff --git a/cmd/elasticache.go b/cmd/elasticache.go new file mode 100644 index 0000000..45fcf22 --- /dev/null +++ b/cmd/elasticache.go @@ -0,0 +1,71 @@ +/* +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/modules/common" + "awstaghelper/modules/elastiCacheHelper" + "github.com/spf13/cobra" +) + +// elasticacheCmd represents the elasticache command +var elasticacheCmd = &cobra.Command{ + Use: "elasticache", + Short: "Root command for interaction with AWS elasticache services", + Long: `Root command for interaction with AWS elasticache services.`, + //Run: func(cmd *cobra.Command, args []string) { + // fmt.Println("elasticache called") + //}, +} + +var getElastiCacheCmd = &cobra.Command{ + Use: "get-elasticache-tags", + Short: "Write elasticache arn and required tags to csv", + Long: `Write to csv data with elasticache arn and required tags to csv. +This csv can be used with tag-elasticache 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. Default elasticacheTags.csv`, + 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 := common.GetSession(region, profile) + common.WriteCsv(elastiCacheHelper.ParseElastiCacheTags(tags, *sess), filename) + }, +} + +var tagElastiCacheCmd = &cobra.Command{ + Use: "tag-elasticache", + Short: "Read csv and tag elasticache with csv data", + Long: `Read csv generated with get-elasticache-tags command and tag elasticache instances 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 := common.GetSession(region, profile) + csvData := common.ReadCsv(filename) + elastiCacheHelper.TagElasticache(csvData, *sess) + }, +} + +func init() { + rootCmd.AddCommand(elasticacheCmd) + elasticacheCmd.AddCommand(getElastiCacheCmd) + elasticacheCmd.AddCommand(tagElastiCacheCmd) + elasticacheCmd.PersistentFlags().StringP("tags", "t", "Name,Environment", "Tags you want to read") + elasticacheCmd.PersistentFlags().StringP("filename", "f", "elasticacheTags.csv", "Filename where to store write") +} diff --git a/cmd/lambda.go b/cmd/lambda.go index 8bdbc42..d1a2bc2 100644 --- a/cmd/lambda.go +++ b/cmd/lambda.go @@ -33,11 +33,11 @@ var lambdaCmd = &cobra.Command{ var getLambdaCmd = &cobra.Command{ Use: "get-lambda-tags", - Short: "Write ec2 id and required tags to csv", - Long: `Write to csv data with ec2 id and required tags to csv. -This csv can be used with tag-ec2 command to tag aws environment. + Short: "Write lambda id and required tags to csv", + Long: `Write to csv data with lambda id and required tags to csv. +This csv can be used with tag-lambda 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. Default ec2Tags.csv`, +Csv filename can be specified with flag filename. Default lambdaTags.csv`, Run: func(cmd *cobra.Command, args []string) { tags, _ := cmd.Flags().GetString("tags") filename, _ := cmd.Flags().GetString("filename") diff --git a/cmd/rds.go b/cmd/rds.go index 04f6627..377fbd1 100644 --- a/cmd/rds.go +++ b/cmd/rds.go @@ -35,7 +35,7 @@ var getRdsCmd = &cobra.Command{ Use: "get-rds-tags", Short: "Write rds arn and required tags to csv", Long: `Write to csv data with rds arn and required tags to csv. -This csv can be used with tagEc2 command to tag aws environment. +This csv can be used with tag-rds 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. Default rdsTags.csv`, Run: func(cmd *cobra.Command, args []string) { diff --git a/go.mod b/go.mod index 14dcb5d..731eed3 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module awstaghelper go 1.14 require ( - github.com/aws/aws-sdk-go v1.33.7 + github.com/aws/aws-sdk-go v1.33.8 github.com/mitchellh/go-homedir v1.1.0 github.com/spf13/cobra v1.0.0 github.com/spf13/viper v1.7.0 diff --git a/go.sum b/go.sum index ca781a6..0b16b07 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +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.33.7 h1:vOozL5hmWHHriRviVTQnUwz8l05RS0rehmEFymI+/x8= -github.com/aws/aws-sdk-go v1.33.7/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.33.8 h1:2/sOfb9oPHTRZ0lxinoaTPDcYwNa1H/SpKP4nVRBwmg= +github.com/aws/aws-sdk-go v1.33.8/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/modules/elastiCacheHelper/getTags.go b/modules/elastiCacheHelper/getTags.go new file mode 100644 index 0000000..a0b3dbc --- /dev/null +++ b/modules/elastiCacheHelper/getTags.go @@ -0,0 +1,69 @@ +package elastiCacheHelper + +import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/elasticache" + "github.com/aws/aws-sdk-go/service/sts" + "log" + "strings" +) + +// getInstances return all ElastiCache from specified region +func getInstances(session session.Session) []*elasticache.CacheCluster { + client := elasticache.New(&session) + input := &elasticache.DescribeCacheClustersInput{} + + var result []*elasticache.CacheCluster + + err := client.DescribeCacheClustersPages(input, + func(page *elasticache.DescribeCacheClustersOutput, lastPage bool) bool { + result = append(result, page.CacheClusters...) + return !lastPage + }) + if err != nil { + log.Fatal("Not able to get instances", err) + return nil + } + return result +} + +// ParseElastiCacheTags parse output from getInstances and return arn and specified tags. +func ParseElastiCacheTags(tagsToRead string, session session.Session) [][]string { + instancesOutput := getInstances(session) + client := elasticache.New(&session) + stsClient := sts.New(&session) + callerIdentity, err := stsClient.GetCallerIdentity(&sts.GetCallerIdentityInput{}) + if err != nil { + log.Fatal("Not able to get elasticache tags", err) + } + var rows [][]string + headers := []string{"Arn"} + headers = append(headers, strings.Split(tagsToRead, ",")...) + rows = append(rows, headers) + for _, elasticCacheInstance := range instancesOutput { + + clusterArn := fmt.Sprintf("arn:aws:elasticache:%s:%s:cluster:%s", + *session.Config.Region, *callerIdentity.Account, *elasticCacheInstance.CacheClusterId) + + input := &elasticache.ListTagsForResourceInput{ + ResourceName: aws.String(clusterArn), + } + elasticCacheTag, err := client.ListTagsForResource(input) + if err != nil { + fmt.Println("Not able to get elasticache tags", err) + } + tags := map[string]string{} + for _, tag := range elasticCacheTag.TagList { + tags[*tag.Key] = *tag.Value + } + + var resultTags []string + for _, key := range strings.Split(tagsToRead, ",") { + resultTags = append(resultTags, tags[key]) + } + rows = append(rows, append([]string{clusterArn}, resultTags...)) + } + return rows +} diff --git a/modules/elastiCacheHelper/setTags.go b/modules/elastiCacheHelper/setTags.go new file mode 100644 index 0000000..a69b74c --- /dev/null +++ b/modules/elastiCacheHelper/setTags.go @@ -0,0 +1,42 @@ +package elastiCacheHelper + +import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/elasticache" +) + +// TagElasticache tag instances. Take as input data from csv file. Where first column id +func TagElasticache(csvData [][]string, session session.Session) { + client := elasticache.New(&session) + + var tags []*elasticache.Tag + for r := 1; r < len(csvData); r++ { + for c := 1; c < len(csvData[0]); c++ { + tags = append(tags, &elasticache.Tag{ + Key: &csvData[0][c], + Value: &csvData[r][c], + }) + } + + input := &elasticache.AddTagsToResourceInput{ + ResourceName: aws.String(csvData[r][0]), + Tags: tags, + } + + _, 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()) + } + return + } + } +}