Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added elastic beanstalk support #46

Merged
merged 1 commit into from
Nov 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Tags are critical to managing AWS resources at scale. Awstaghelper provides a co
* [Kinesis Firehose](#kinesis-firehose)
* [Iam User](#iam-user)
* [Iam Role](#iam-role)
* [Elastic Beanstalk](#elastic-beanstalk)
* [ECR](#ecr)
* [ELBv2](#elbv2)
* [Global parameters](#global-parameters)
* [Contributing](#contributing)
* [License](#license)
Expand Down Expand Up @@ -272,10 +275,52 @@ Example:

#### Tag role

Read csv and tag iam user - `awstaghelper iam tag-role`
Read csv and tag iam role - `awstaghelper iam tag-role`
Example:
`awstaghelper iam tag-role --filename roleTag.csv --profile main`

### Elastic Beanstalk

#### Get elastic beanstalk tags

Get list of elastic beanstalk environnement with required tags - `awstaghelper eb get-eb-tags`
Example:
`awstaghelper eb get-eb-tags --filename ebTag.csv --tags Name,Owner --profile main`

#### Tag elastic beanstalk environnement

Read csv and tag elastic beanstalk environnement - `awstaghelper eb tag-eb`
Example:
`awstaghelper eb tag-eb --filename ebTag.csv --profile main`

### ECR

#### Get ecr tags

Get list of ecr with required tags - `awstaghelper ecr get-repository-tags`
Example:
`awstaghelper ecr get-repository-tags --filename ecrTag.csv --tags Name,Owner --profile main`

#### Tag ecr

Read csv and tag ecr - `awstaghelper ecr tag-repository`
Example:
`awstaghelper ecr tag-repository --filename ecrTag.csv --profile main`

### ELBv2

#### Get elbv2 tags

Get list of elbv2 with required tags - `awstaghelper elb get-elbv2-tags`
Example:
`awstaghelper elb get-elbv2-tags --filename elbv2Tag.csv --tags Name,Owner --profile main`

#### Tag elbv2

Read csv and tag elbv2 - `awstaghelper elb tag-elbv2`
Example:
`awstaghelper elb tag-elbv2 --filename elbv2Tag.csv --profile main`

## Global parameters

`filename` - path where to write or read data. Supported by every option. Default `awsTags.csv`
Expand Down
71 changes: 71 additions & 0 deletions cmd/elasticbeanstalk.go
Original file line number Diff line number Diff line change
@@ -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 is the package for the CLI of awstaghelper
package cmd

import (
"awstaghelper/pkg"
"github.com/aws/aws-sdk-go/service/elasticbeanstalk"

"github.com/spf13/cobra"
)

// ebCmd represents the ecr command
var ebCmd = &cobra.Command{
Use: "eb",
Short: "Root command for interaction with AWS elastic bean stalk services",
Long: `Root command for interaction with AWS elastic bean stalk services.`,
}

var getEbTagsCmd = &cobra.Command{
Use: "get-eb-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-eb 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 := elasticbeanstalk.New(sess)
pkg.WriteCsv(pkg.ParseEBTags(tags, client), filename)
},
}

var tagEbCmd = &cobra.Command{
Use: "tag-eb",
Short: "Read csv and tag eb e with csv data",
Long: `Read csv generated with get-eb-tags command and tag elastic bean stalk 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 := elasticbeanstalk.New(sess)
csvData := pkg.ReadCsv(filename)
pkg.TagEbEnvironments(csvData, client)
},
}

func init() {
rootCmd.AddCommand(ebCmd)
ebCmd.AddCommand(getEbTagsCmd)
ebCmd.AddCommand(tagEbCmd)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module awstaghelper
go 1.15

require (
github.com/aws/aws-sdk-go v1.35.28
github.com/aws/aws-sdk-go v1.35.33
github.com/mitchellh/go-homedir v1.1.0
github.com/spf13/cobra v1.1.1
github.com/spf13/viper v1.7.1
Expand Down
13 changes: 9 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
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.35.28 h1:S2LuRnfC8X05zgZLC8gy/Sb82TGv2Cpytzbzz7tkeHc=
github.com/aws/aws-sdk-go v1.35.28/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go v1.35.33 h1:8qPRZqCRok5i7VNN51k/Ky7CuyoXMdSs4mUfKyCqvPw=
github.com/aws/aws-sdk-go v1.35.33/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
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=
Expand Down Expand Up @@ -204,6 +204,7 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
Expand Down Expand Up @@ -236,8 +237,8 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand All @@ -260,10 +261,14 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
64 changes: 64 additions & 0 deletions pkg/elasticbeanstalk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package pkg

import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/service/elasticbeanstalk"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elasticbeanstalk/elasticbeanstalkiface"
)

// getEBEnvironments return all elastic bean stalk environments from specified region
func getEBEnvironments(client elasticbeanstalkiface.ElasticBeanstalkAPI) *elasticbeanstalk.EnvironmentDescriptionsMessage {
input := &elasticbeanstalk.DescribeEnvironmentsInput{}

result, err := client.DescribeEnvironments(input)
if err != nil {
log.Fatal("Not able to get list of elastic bean stalk environments ", err)
}

return result
}

// ParseEBTags parse output from getEBInstances and return eb id and specified tags.
func ParseEBTags(tagsToRead string, client elasticbeanstalkiface.ElasticBeanstalkAPI) [][]string {
instancesOutput := getEBEnvironments(client)
rows := addHeadersToCsv(tagsToRead, "Arn")
for _, ebEnv := range instancesOutput.Environments {
ebTags, err := client.ListTagsForResource(&elasticbeanstalk.ListTagsForResourceInput{ResourceArn: ebEnv.EnvironmentArn})
if err != nil {
fmt.Println("Not able to get elastic bean stalk tags ", err)
}
tags := map[string]string{}
for _, tag := range ebTags.ResourceTags {
tags[*tag.Key] = *tag.Value
}
rows = addTagsToCsv(tagsToRead, tags, rows, *ebEnv.EnvironmentArn)
}
return rows
}

// TagEbEnvironments tag eb environments. Take as input data from csv file. Where first column is arn
func TagEbEnvironments(csvData [][]string, client elasticbeanstalkiface.ElasticBeanstalkAPI) {
for r := 1; r < len(csvData); r++ {
var tags []*elasticbeanstalk.Tag
for c := 1; c < len(csvData[0]); c++ {
tags = append(tags, &elasticbeanstalk.Tag{
Key: &csvData[0][c],
Value: &csvData[r][c],
})
}

input := &elasticbeanstalk.UpdateTagsForResourceInput{
ResourceArn: aws.String(csvData[r][0]),
TagsToAdd: tags,
}

_, err := client.UpdateTagsForResource(input)
if awsErrorHandle(err) {
return
}
}
}
87 changes: 87 additions & 0 deletions pkg/elasticbeanstalk_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package pkg

import (
"github.com/aws/aws-sdk-go/service/elasticbeanstalk"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elasticbeanstalk/elasticbeanstalkiface"
"github.com/stretchr/testify/assert"
)

type mockedEBEnv struct {
elasticbeanstalkiface.ElasticBeanstalkAPI
respDescribeEnvironments elasticbeanstalk.EnvironmentDescriptionsMessage
respListTagsForResource elasticbeanstalk.ListTagsForResourceOutput
}

func (m *mockedEBEnv) DescribeEnvironments(*elasticbeanstalk.DescribeEnvironmentsInput) (*elasticbeanstalk.EnvironmentDescriptionsMessage, error) {
return &m.respDescribeEnvironments, nil
}

func (m *mockedEBEnv) ListTagsForResource(*elasticbeanstalk.ListTagsForResourceInput) (*elasticbeanstalk.ListTagsForResourceOutput, error) {
return &m.respListTagsForResource, nil
}

func TestEBEnvironments(t *testing.T) {
cases := []*mockedEBEnv{
{
respDescribeEnvironments: describeEnvironmentsResponse,
},
}

expectedResult := &describeEnvironmentsResponse

for _, c := range cases {
t.Run("getEBEnvironments", func(t *testing.T) {
result := getEBEnvironments(c)
assertions := assert.New(t)
assertions.EqualValues(expectedResult, result)
})

}
}

func TestParseEBEnvironmentsTags(t *testing.T) {
cases := []*mockedEBEnv{
{
respDescribeEnvironments: describeEnvironmentsResponse,
respListTagsForResource: listTagsForEBEnvironments,
},
}

expectedResult := [][]string{
{"Arn", "Name", "Owner"},
{"arn:aws:elasticbeanstalk:us-east-1:12345678:environment/test-app/test-env", "test-eb1", "mpostument"},
}

for _, c := range cases {
t.Run("ParseEBTags", func(t *testing.T) {
result := ParseEBTags("Name,Owner", c)
assertions := assert.New(t)
assertions.EqualValues(expectedResult, result)
})

}
}

var describeEnvironmentsResponse = elasticbeanstalk.EnvironmentDescriptionsMessage{
Environments: []*elasticbeanstalk.EnvironmentDescription{
{
EnvironmentArn: aws.String("arn:aws:elasticbeanstalk:us-east-1:12345678:environment/test-app/test-env"),
},
},
}

var listTagsForEBEnvironments = elasticbeanstalk.ListTagsForResourceOutput{
ResourceTags: []*elasticbeanstalk.Tag{
{
Key: aws.String("Name"),
Value: aws.String("test-eb1"),
},
{
Key: aws.String("Owner"),
Value: aws.String("mpostument"),
},
},
}