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

Add Support for List of Tag Maps #18

Merged
merged 20 commits into from
May 16, 2018
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
98 changes: 95 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,93 @@ resource "aws_instance" "eg_prod_bastion_xyz" {
vpc_security_group_ids = ["${aws_security_group.eg_prod_bastion_xyz.id}"]
}
```
### Advanced Example 2

Here is a more complex example with an autoscaling group that has a different tagging schema than other resources and requires its tags to be in this format, which this module can generate:
```hcl
tags = [
{
key = Name,
propagate_at_launch = 1,
value = namespace-stage-jamie
},
{
key = Namespace,
propagate_at_launch = 1,
value = namespace
},
{
key = Stage,
propagate_at_launch = 1,
value = stage
}
]
```

Autoscaling group using propagating tagging below (full example: examples/autoscalinggroup/main.tf)

```hcl
################################
# terraform-null-label example #
################################
module "label" {
source = "../../"
namespace = "cp"
stage = "prod"
name = "app"

tags = {
BusinessUnit = "Finance"
ManagedBy = "Terraform"
}

additional_tag_map = {
propagate_at_launch = "true"
}
}

#######################
# Launch template #
#######################
resource "aws_launch_template" "default" {
# terraform-null-label example used here: Set template name prefix
name_prefix = "${module.label.id}-"
image_id = "${data.aws_ami.amazon_linux.id}"
instance_type = "t2.micro"
instance_initiated_shutdown_behavior = "terminate"

vpc_security_group_ids = ["${data.aws_security_group.default.id}"]

monitoring {
enabled = false
}
# terraform-null-label example used here: Set tags on volumes
tag_specifications {
resource_type = "volume"
tags = "${module.label.tags}"
}
}

######################
# Autoscaling group #
######################
resource "aws_autoscaling_group" "default" {
# terraform-null-label example used here: Set ASG name prefix
name_prefix = "${module.label.id}-"
vpc_zone_identifier = ["${data.aws_subnet_ids.all.ids}"]
max_size = "1"
min_size = "1"
desired_capacity = "1"

launch_template = {
id = "${aws_launch_template.default.id}"
version = "$$Latest"
}

# terraform-null-label example used here: Set tags on ASG and EC2 Servers
tags = ["${module.label.tags_as_list_of_maps}"]
}
```

## Input

Expand All @@ -134,6 +221,7 @@ resource "aws_instance" "eg_prod_bastion_xyz" {
| namespace |__REQUIRED__ |Namespace, which could be your organization name, e.g. 'cp' or 'cloudposse'|
| stage |__REQUIRED__ |Stage, e.g. 'prod', 'staging', 'dev', or 'test'|
| tags |{} |Additional tags (e.g. `map('BusinessUnit`,`XYZ`)|
| additional_tag_map | {} | additional tags that get appended to each map in the list of maps, for the output `tags_as_list_of_maps` |

**WARNING** Any tags passed as an input to this module will *override* the tags generated by this module.

Expand All @@ -147,7 +235,8 @@ resource "aws_instance" "eg_prod_bastion_xyz" {
| name | Normalized name |
| namespace | Normalized namespace |
| stage | Normalized stage |
| tags | Merge input tags with our tags. Note: `Name` has a special meaning in AWS and we need to disamgiuate it by using the computed `id` |
| tags | Merged input tags with our tags. Note: `Name` has a special meaning in AWS and we need to disamgiuate it by using the computed `id` |
| tags_as_list_of_maps | Merged input tags and our tags output as list of maps that contain the tags for use on certain resource types. |

## Help

Expand Down Expand Up @@ -213,8 +302,8 @@ or [hire us][hire] to help build your next cloud-platform.

### Contributors

|[![Erik Osterman][erik_img]][erik_web]<br/>[Erik Osterman][erik_web] |[![Igor Rodionov][igor_img]][igor_web]<br/>[Igor Rodionov][igor_img] |[![Konstantin B][konstantin_img]][konstantin_web]<br/>[Konstantin B][konstantin_web] |[![Andriy Knysh][andriy_img]][andriy_web]<br/>[Andriy Knysh][andriy_web] |[![Sergey Vasilyev][sergey_img]][sergey_web]<br/>[Sergey Vasilyev][sergey_web] |
|---|---|---|---|---|
|[![Erik Osterman][erik_img]][erik_web]<br/>[Erik Osterman][erik_web] |[![Igor Rodionov][igor_img]][igor_web]<br/>[Igor Rodionov][igor_img] |[![Konstantin B][konstantin_img]][konstantin_web]<br/>[Konstantin B][konstantin_web] |[![Andriy Knysh][andriy_img]][andriy_web]<br/>[Andriy Knysh][andriy_web] |[![Sergey Vasilyev][sergey_img]][sergey_web]<br/>[Sergey Vasilyev][sergey_web] | [![Jamie Nelson][bitflight_img]][bitflight_web]<br/>[Jamie Nelson][bitflight_web] |
|---|---|---|---|---|---|

[andriy_img]: https://avatars0.githubusercontent.com/u/7356997?v=4&u=ed9ce1c9151d552d985bdf5546772e14ef7ab617&s=144
[andriy_web]: https://github.com/aknysh/
Expand All @@ -236,3 +325,6 @@ or [hire us][hire] to help build your next cloud-platform.

[vladimir_img]: https://avatars1.githubusercontent.com/u/26582191?v=4&u=ed9ce1c9151d552d985bdf5546772e14ef7ab617&s=144
[vladimir_web]: https://github.com/SweetOps/

[bitflight_img]: https://avatars0.githubusercontent.com/u/25075504?s=144&u=ac7e53bda3706cb9d51907808574b6d342703b3e&v=4
[bitflight_web]: https://github.com/Jamie-BitFlight
122 changes: 122 additions & 0 deletions examples/autoscalinggroup/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
################################
# terraform-null-label example #
################################
module "label" {
source = "../../"
namespace = "cp"
stage = "prod"
name = "app"

tags = {
BusinessUnit = "Finance"
ManagedBy = "Terraform"
}

additional_tag_map = {
propagate_at_launch = "true"
}
}

#######################
# Launch template #
#######################
resource "aws_launch_template" "default" {
# terraform-null-label example used here: Set template name prefix
name_prefix = "${module.label.id}-"
image_id = "${data.aws_ami.amazon_linux.id}"
instance_type = "t2.micro"
instance_initiated_shutdown_behavior = "terminate"

vpc_security_group_ids = ["${data.aws_security_group.default.id}"]

monitoring {
enabled = false
}

# terraform-null-label example used here: Set tags on volumes
tag_specifications {
resource_type = "volume"
tags = "${module.label.tags}"
}
}

######################
# Autoscaling group #
######################
resource "aws_autoscaling_group" "default" {
# terraform-null-label example used here: Set ASG name prefix
name_prefix = "${module.label.id}-"
vpc_zone_identifier = ["${data.aws_subnet_ids.all.ids}"]
max_size = "1"
min_size = "1"
desired_capacity = "1"

launch_template = {
id = "${aws_launch_template.default.id}"
version = "$$Latest"
}

# terraform-null-label example used here: Set tags on ASG and EC2 Servers
tags = ["${module.label.tags_as_list_of_maps}"]
}

# terraform-null-label example used here: Output list of tags applied in each format
output "tags_as_list_of_maps" {
value = ["${module.label.tags_as_list_of_maps}"]
}

output "tags" {
value = ["${module.label.tags}"]
}

################################
# Provider #
################################

provider "aws" {
region = "eu-west-1"
version = "~> 1.17"

# Make it faster by skipping unneeded checks here
skip_get_ec2_platforms = true
skip_metadata_api_check = true
skip_region_validation = true
skip_credentials_validation = true
skip_requesting_account_id = true
}

##############################################################
# Data sources to get VPC, subnets and security group details
##############################################################
data "aws_vpc" "default" {
default = true
}

data "aws_subnet_ids" "all" {
vpc_id = "${data.aws_vpc.default.id}"
}

data "aws_security_group" "default" {
vpc_id = "${data.aws_vpc.default.id}"
name = "default"
}

data "aws_ami" "amazon_linux" {
most_recent = true

filter {
name = "name"

values = [
"amzn-ami-hvm-*-x86_64-gp2",
]
}

filter {
name = "owner-alias"

values = [
"amazon",
]
}
}
43 changes: 29 additions & 14 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
resource "null_resource" "default" {
count = "${var.enabled == "true" ? 1 : 0}"

triggers = {
id = "${lower(join(var.delimiter, compact(concat(list(var.namespace, var.stage, var.name), var.attributes))))}"
name = "${lower(format("%v", var.name))}"
namespace = "${lower(format("%v", var.namespace))}"
stage = "${lower(format("%v", var.stage))}"
attributes = "${lower(format("%v", join(var.delimiter, compact(var.attributes))))}"
}

lifecycle {
create_before_destroy = true
}
locals {
enabled = "${var.enabled == "true" ? true : false }"
id = "${local.enabled ? lower(join(var.delimiter, compact(concat(list(var.namespace, var.stage, var.name), var.attributes)))) : ""}"
name = "${local.enabled ? lower(format("%v", var.name)) : ""}"
namespace = "${local.enabled ? lower(format("%v", var.namespace)) : ""}"
stage = "${local.enabled ? lower(format("%v", var.stage)) : ""}"
attributes = "${local.enabled ? lower(format("%v", join(var.delimiter, compact(var.attributes)))) : ""}"

tags = "${
merge(
map(
"Name", "${local.id}",
"Namespace", "${local.namespace}",
"Stage", "${local.stage}"
), var.tags
)
}"

tags_as_list_of_maps = ["${null_resource.tags_as_list_of_maps.*.triggers}"]
}

resource "null_resource" "tags_as_list_of_maps" {
count = "${length(keys(local.tags))}"

triggers = "${merge(map(
"key", "${element(keys(local.tags), count.index)}",
"value", "${element(values(local.tags), count.index)}"
),
var.additional_tag_map)}"
}
25 changes: 11 additions & 14 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -1,40 +1,37 @@
output "id" {
value = "${join("", null_resource.default.*.triggers.id)}"
value = "${local.id}"
description = "Disambiguated ID"
}

output "name" {
value = "${join("", null_resource.default.*.triggers.name)}"
value = "${local.name}"
description = "Normalized name"
}

output "namespace" {
value = "${join("", null_resource.default.*.triggers.namespace)}"
value = "${local.namespace}"
description = "Normalized namespace"
}

output "stage" {
value = "${join("", null_resource.default.*.triggers.stage)}"
value = "${local.stage}"
description = "Normalized stage"
}

output "attributes" {
value = "${join("", null_resource.default.*.triggers.attributes)}"
value = "${local.attributes}"
description = "Normalized attributes"
}

# Merge input tags with our tags.
# Note: `Name` has a special meaning in AWS and we need to disamgiuate it by using the computed `id`
output "tags" {
value = "${
merge(
map(
"Name", "${join("", null_resource.default.*.triggers.id)}",
"Namespace", "${join("", null_resource.default.*.triggers.namespace)}",
"Stage", "${join("", null_resource.default.*.triggers.stage)}"
), var.tags
)
}"
value = "${local.tags}"

description = "Normalized Tag map"
}

output "tags_as_list_of_maps" {
value = ["${local.tags_as_list_of_maps}"]
description = "Additional tags as a list of maps, which can be used in several AWS resources"
}
8 changes: 7 additions & 1 deletion variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,11 @@ variable "attributes" {
variable "tags" {
type = "map"
default = {}
description = "Additional tags (e.g. `map('BusinessUnit`,`XYZ`)"
description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`"
}

variable "additional_tag_map" {
type = "map"
default = {}
description = "Additional tags for appending to each tag map."
}