Skip to content

Commit

Permalink
add tags to resources created through cli, part of #43
Browse files Browse the repository at this point in the history
tags for resources created through project lambdas are still not supported
  • Loading branch information
Ivan Vlasic committed Oct 12, 2021
1 parent 14644a3 commit c714cce
Show file tree
Hide file tree
Showing 21 changed files with 176 additions and 10 deletions.
1 change: 1 addition & 0 deletions api/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func (d *Deploy) terraformCreate() (*terraform.Terraform, error) {
RuntimeFunctionsBucket: d.req.Account.Functions.Bucket,
RuntimeFunctionsPath: d.req.Account.Functions.Path,
GlobalEnv: workspace.StageEnv(d.req.ProjectName, stage.Name),
ResourceTags: d.req.ResourceTags,
}
tf, err := terraform.Project(data)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions api/dto/dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type DeployRequest struct {
InfrastructureChanged bool
UpdatedFunctions []string
Account *workspace.Account
ResourceTags map[string]string
}

type DestroyRequest struct {
Expand Down Expand Up @@ -61,6 +62,7 @@ type SetupRequest struct {
FunctionsPath string
PublicKey string
ResourceSuffix string
ResourceTags map[string]string
Destroy bool
}

Expand Down
4 changes: 4 additions & 0 deletions api/setup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func (s *Setup) terraformCreate() (*dto.SetupResponse, error) {
FunctionsPath: s.req.FunctionsPath,
PublicKey: s.req.PublicKey,
ResourceSuffix: s.req.ResourceSuffix,
ResourceTags: s.req.ResourceTags,
}
tf, err := terraform.Setup(data)
if err != nil {
Expand Down Expand Up @@ -124,5 +125,8 @@ func (s *Setup) createBucket() error {
if err := s.awsClient.CreateS3Bucket(s.req.Bucket, s.awsClient.Region()); err != nil {
return fmt.Errorf("error creating bucket %s - %w", s.req.Bucket, err)
}
if err := s.awsClient.TagS3Bucket(s.req.Bucket, s.req.ResourceTags); err != nil {
return fmt.Errorf("error tagging bucket %s - %w", s.req.Bucket, err)
}
return nil
}
4 changes: 4 additions & 0 deletions api/setup/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ func TestTerraformRender(t *testing.T) {
FunctionsPath: "functions-path",
Region: "aws-region",
PublicKey: "public-key",
ResourceTags: map[string]string{
"tag1": "value1",
"tag2": "value2",
},
}
tf, err := terraform.Setup(data)
require.NoError(t, err)
Expand Down
27 changes: 22 additions & 5 deletions api/setup/testdata/create.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,30 @@ locals {
project_bucket = "bucket-name" # bucket for backend configuration/state
functions = {
"deploy" = {
method = "POST"
s3_key = "functions-path/deploy.zip"
memory_size = 512,
timeout = 900
layers = ["arn:aws:lambda:aws-region:553035198032:layer:git-lambda2:8", "arn:aws:lambda:aws-region:477361877445:layer:terraform-lambda:1"]
layers = ["arn:aws:lambda:aws-region:477361877445:layer:terraform-lambda:1"]
},
"data" = {
method = "POST"
s3_key = "functions-path/data.zip"
memory_size = 128,
timeout = 900
},
"security" = {
method = "GET"
s3_key = "functions-path/security.zip"
memory_size = 128,
timeout = 900,
},
"destroy" = {
method = "POST"
s3_key = "functions-path/destroy.zip"
memory_size = 512,
timeout = 900
layers = ["arn:aws:lambda:aws-region:553035198032:layer:git-lambda2:8", "arn:aws:lambda:aws-region:477361877445:layer:terraform-lambda:1"]
layers = ["arn:aws:lambda:aws-region:477361877445:layer:terraform-lambda:1"]
}
}
}
Expand All @@ -40,32 +44,45 @@ terraform {
provider "aws" {
region = "aws-region"
skip_get_ec2_platforms = true

default_tags {
tags = {
tag1 = "value1"
tag2 = "value2"
}
}
}

module "funcs" {
source = "../../modules/backend-funcs"
functions = local.functions
s3_bucket = local.functions_bucket
prefix = "mantil"
suffix = ""
}

module "iam" {
source = "../../modules/backend-iam"
backend_role_arn = module.funcs.role_arn
prefix = "mantil"
suffix = ""
}

module "api" {
source = "../../modules/api"
name_prefix = "mantil"
prefix = "mantil"
suffix = ""
functions_bucket = local.functions_bucket
functions_s3_path = local.functions_s3_path
integrations = [for f in module.funcs.functions :
{
type : "AWS_PROXY"
method : "POST"
method : local.functions[f.name].method
integration_method : "POST"
route : "/${f.name}"
uri : f.invoke_arn,
lambda_name : f.arn,
enable_auth : false,
enable_auth : true,
}
]
authorizer = {
Expand Down
14 changes: 13 additions & 1 deletion aws/cloudformation.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,25 @@ func (a *AWS) CloudFormation() *CloudFormation {
}
}

func (f *CloudFormation) CreateStack(name, templateBody string) error {
func (f *CloudFormation) CreateStack(name, templateBody string, resourceTags map[string]string) error {
csi := &cloudformation.CreateStackInput{
StackName: aws.String(name),
Capabilities: []types.Capability{types.CapabilityCapabilityNamedIam},
OnFailure: types.OnFailureDelete,
TemplateBody: aws.String(templateBody),
}

if resourceTags != nil {
tags := []types.Tag{}
for k, v := range resourceTags {
tags = append(tags, types.Tag{
Key: aws.String(k),
Value: aws.String(v),
})
}
csi.Tags = tags
}

cso, err := f.cli.CreateStack(context.Background(), csi)
if err != nil {
return log.Wrap(err, fmt.Sprintf("could not create stack %s", name))
Expand Down
9 changes: 9 additions & 0 deletions aws/cloudwatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ func (a *AWS) LambdaLogGroup(lambdaName string) string {
return fmt.Sprintf("/aws/lambda/%s", lambdaName)
}

func (a *AWS) TagLogGroup(name string, tags map[string]string) error {
tlgi := &cloudwatchlogs.TagLogGroupInput{
LogGroupName: aws.String(name),
Tags: tags,
}
_, err := a.cloudwatchClient.TagLogGroup(context.Background(), tlgi)
return err
}

func (a *AWS) FetchLogs(group string, filter string, start *int64) (chan LogEvent, error) {
events := make(chan LogEvent)
go func() {
Expand Down
22 changes: 22 additions & 0 deletions aws/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
s3Types "github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/aws/smithy-go"
)
Expand All @@ -33,6 +34,27 @@ func (a *AWS) CreateS3Bucket(name, region string) error {
return nil
}

func (a *AWS) TagS3Bucket(name string, tags map[string]string) error {
pbti := &s3.PutBucketTaggingInput{
Bucket: aws.String(name),
}
t := []types.Tag{}
for k, v := range tags {
t = append(t, types.Tag{
Key: aws.String(k),
Value: aws.String(v),
})
}
pbti.Tagging = &types.Tagging{
TagSet: t,
}
_, err := a.s3Client.PutBucketTagging(context.Background(), pbti)
if err != nil {
return fmt.Errorf("could not tag bucket %s - %w", name, err)
}
return nil
}

func (a *AWS) EmptyS3Bucket(name string) error {
return a.DeleteInS3Bucket(name, "")
}
Expand Down
1 change: 1 addition & 0 deletions cli/cmd/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ func (d *Cmd) deployRequest() (*workspace.Project, error) {
InfrastructureChanged: d.InfrastructureChanged(),
UpdatedFunctions: d.functionsDiff.updated,
Account: d.ctx.Account,
ResourceTags: d.ctx.ResourceTags(),
}
if err := d.ctx.RuntimeRequest("deploy", req, nil, true); err != nil {
return nil, err
Expand Down
18 changes: 18 additions & 0 deletions cli/cmd/project/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,14 @@ func (c *Context) StageRestEndpoint() (string, error) {
return c.Stage.Endpoints.Rest, nil
}

func (c *Context) ResourceTags() map[string]string {
tags := mergeMaps(c.Workspace.ResourceTags(), c.Project.ResourceTags())
if c.Stage != nil {
tags = mergeMaps(tags, c.Stage.ResourceTags())
}
return tags
}

func (c *Context) StageWsEndpoint() (string, error) {
if c.Stage == nil {
return "", ErrStageNotSet
Expand Down Expand Up @@ -360,3 +368,13 @@ export %s='%s'
workspace.EnvApiURL, stageURL,
), nil
}

func mergeMaps(ms ...map[string]string) map[string]string {
r := map[string]string{}
for _, m := range ms {
for k, v := range m {
r[k] = v
}
}
return r
}
9 changes: 8 additions & 1 deletion cli/cmd/setup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type Cmd struct {
override bool // TODO unused
workspacesStore workspace.Store
resourceName string
resourceTags map[string]string
}

func New(a *Args) (*Cmd, error) {
Expand Down Expand Up @@ -58,6 +59,7 @@ func (c *Cmd) Create() error {
return log.Wrap(err)
}
c.resourceName = ws.ResourceName(resourceNamePrefix)
c.resourceTags = ws.ResourceTags()
v := build.Version()
ac, err := ws.NewAccount(c.accountName, c.aws.AccountID(), c.aws.Region(),
v.FunctionsBucket(c.aws.Region()),
Expand Down Expand Up @@ -99,6 +101,7 @@ func (c *Cmd) create(ac *workspace.Account) error {
FunctionsPath: ac.Functions.Path,
PublicKey: ac.Keys.Public,
ResourceSuffix: ac.ResourceSuffix(),
ResourceTags: c.resourceTags,
}
rsp, err := c.invokeLambda(req)
if err != nil {
Expand Down Expand Up @@ -126,9 +129,13 @@ func (c *Cmd) createSetupStack(acf workspace.AccountFunctions) error {
if err != nil {
return log.Wrap(err, "render template failed")
}
if err := c.aws.CloudFormation().CreateStack(c.resourceName, t); err != nil {
if err := c.aws.CloudFormation().CreateStack(c.resourceName, t, c.resourceTags); err != nil {
return log.Wrap(err, "cloudformation failed")
}
// https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/919
if err := c.aws.TagLogGroup(c.aws.LambdaLogGroup(c.resourceName), c.resourceTags); err != nil {
return log.Wrap(err, "tagging setup lambda log group failed")
}
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion commands.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## mantil --version
```
mantil version v0.1.10-62-g5afe5ea
mantil version v0.1.10-66-g14644a3
```

## mantil --help
Expand Down
9 changes: 8 additions & 1 deletion terraform/templates/project.tf
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,15 @@ terraform {

provider "aws" {
region = local.aws_region

skip_get_ec2_platforms = true

default_tags {
tags = {
{{- range $key, $value := .ResourceTags}}
{{$key}} = "{{$value}}"
{{- end}}
}
}
}

module "funcs" {
Expand Down
8 changes: 8 additions & 0 deletions terraform/templates/setup.tf
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ terraform {
provider "aws" {
region = "{{.Region}}"
skip_get_ec2_platforms = true

default_tags {
tags = {
{{- range $key, $value := .ResourceTags}}
{{$key}} = "{{$value}}"
{{- end}}
}
}
}

module "funcs" {
Expand Down
2 changes: 2 additions & 0 deletions terraform/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type SetupTemplateData struct {
Region string
PublicKey string
ResourceSuffix string
ResourceTags map[string]string
}

// Prepare setup templates
Expand All @@ -70,6 +71,7 @@ type ProjectTemplateData struct {
RuntimeFunctionsBucket string
RuntimeFunctionsPath string
GlobalEnv map[string]string
ResourceTags map[string]string
// TODO: uskladi nazivlje u struct gore i ovdje FunctionsBucket i Path
}

Expand Down
8 changes: 8 additions & 0 deletions terraform/terraform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ func TestRenderSetup(t *testing.T) {
Region: "aws-region",
PublicKey: "public-key",
ResourceSuffix: "abcdef",
ResourceTags: map[string]string{
"tag1": "value1",
"tag2": "value2",
},
}
tf, err := renderSetup(data)
require.NoError(t, err)
Expand Down Expand Up @@ -68,6 +72,10 @@ func TestRenderProject(t *testing.T) {
"env1": "value1",
"env2": "value2",
},
ResourceTags: map[string]string{
"tag1": "value1",
"tag2": "value2",
},
}
tf, err := renderProject(data)
require.NoError(t, err)
Expand Down
8 changes: 7 additions & 1 deletion terraform/testdata/project.tf
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,14 @@ terraform {

provider "aws" {
region = local.aws_region

skip_get_ec2_platforms = true

default_tags {
tags = {
tag1 = "value1"
tag2 = "value2"
}
}
}

module "funcs" {
Expand Down
7 changes: 7 additions & 0 deletions terraform/testdata/setup.tf
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ terraform {
provider "aws" {
region = "aws-region"
skip_get_ec2_platforms = true

default_tags {
tags = {
tag1 = "value1"
tag2 = "value2"
}
}
}

module "funcs" {
Expand Down
Loading

0 comments on commit c714cce

Please sign in to comment.