619 lines
18 KiB
YAML
Executable File
619 lines
18 KiB
YAML
Executable File
name: terraform-null-label
|
||
tags:
|
||
- aws
|
||
- terraform
|
||
- terraform-modules
|
||
- naming-convention
|
||
- name
|
||
- namespace
|
||
- stage
|
||
categories:
|
||
- terraform-modules/supported
|
||
license: APACHE2
|
||
github_repo: cloudposse/terraform-null-label
|
||
badges:
|
||
- name: Latest Release
|
||
image: https://img.shields.io/github/release/cloudposse/terraform-null-label.svg
|
||
url: https://github.com/cloudposse/terraform-null-label/releases/latest
|
||
- name: Slack Community
|
||
image: https://slack.cloudposse.com/badge.svg
|
||
url: https://slack.cloudposse.com
|
||
related:
|
||
- name: terraform-terraform-label
|
||
description: Terraform Module to define a consistent naming convention by (namespace,
|
||
environment, stage, name, [attributes])
|
||
url: https://github.com/cloudposse/terraform-terraform-label
|
||
description: |-
|
||
Terraform module designed to generate consistent names and tags for resources. Use `terraform-null-label` to implement a strict naming convention.
|
||
|
||
This module generates names using the following convention by default: `{namespace}-{environment}-{stage}-{name}-{attributes}`.
|
||
However, it is highly configurable. The delimiter (e.g. `-`) is configurable. Each label item is optional (although you must provide at least one).
|
||
So if you prefer the term `stage` to `environment`
|
||
you can exclude environment and the label `id` will look like `{namespace}-{stage}-{name}-{attributes}`.
|
||
- If attributes are excluded but `namespace`, `stage`, and `environment` are included, `id` will look like `{namespace}-{environment}-{stage}-{name}`.
|
||
- If you want the attributes in a different order, you can specify that, too, with the `label_order` list.
|
||
- You can set a maximum length for the name, and the module will create a unique name that fits within that length.
|
||
- You can control the letter case of the generated labels which make up the `id` using `var.label_value_case`.
|
||
- The labels are also exported as tags. You can control the case of the tag names (keys) using `var.label_tag_case`.
|
||
|
||
It's recommended to use one `terraform-null-label` module for every unique resource of a given resource type.
|
||
For example, if you have 10 instances, there should be 10 different labels.
|
||
However, if you have multiple different kinds of resources (e.g. instances, security groups, file systems, and elastic ips), then they can all share the same label assuming they are logically related.
|
||
|
||
All [Cloud Posse modules](https://github.com/cloudposse?utf8=%E2%9C%93&q=terraform-&type=&language=) use this module to ensure resources can be instantiated multiple times within an account and without conflict.
|
||
|
||
**NOTE:** The `null` originally referred to the primary Terraform [provider](https://www.terraform.io/docs/providers/null/index.html) used in this module.
|
||
With Terraform 0.12, this module no longer needs any provider, but the name was kept for continuity.
|
||
|
||
- Releases of this module from `0.23.0` onward only work with Terraform 0.13 or newer.
|
||
- Releases of this module from `0.12.0` through `0.22.1` support `HCL2` and are compatible with Terraform 0.12 or newer.
|
||
- Releases of this module prior to `0.12.0` are compatible with earlier versions of terraform like Terraform 0.11.
|
||
usage: |-
|
||
### Defaults
|
||
|
||
Cloud Posse Terraform modules share a common `context` object that is meant to be passed from module to module.
|
||
The context object is a single object that contains all the input values for `terraform-null-label`.
|
||
However, each input value can also be specified individually by name as a standard Terraform variable,
|
||
and the value of those variables, when set to something other than `null`, will override the value
|
||
in the context object. In order to allow chaining of these objects, where the context object input to one
|
||
module is transformed and passed to the next module, all the variables default to `null` or empty collections.
|
||
The actual default values used when nothing is explicitly set are describe in the documentation below.
|
||
|
||
For example, the default value of `delimiter` is shown as `null`, but if you leave it set to null,
|
||
`terraform-null-label` will actually use the default delimiter `-` (hyphen).
|
||
|
||
A non-obvious but intentional consequence of this design is that once a module sets a non-default value,
|
||
future modules in the chain cannot reset the value back to the original default. Insted, the new setting
|
||
becomes the new default for downstream modules. Also, collections are not overwritten, they are merged,
|
||
so once a tag is added, it will remain in the tag set and cannot be removed, although its value can
|
||
be overwritten.
|
||
|
||
### Simple Example
|
||
|
||
```hcl
|
||
module "eg_prod_bastion_label" {
|
||
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=master"
|
||
namespace = "eg"
|
||
stage = "prod"
|
||
name = "bastion"
|
||
attributes = ["public"]
|
||
delimiter = "-"
|
||
|
||
tags = {
|
||
"BusinessUnit" = "XYZ",
|
||
"Snapshot" = "true"
|
||
}
|
||
}
|
||
```
|
||
|
||
This will create an `id` with the value of `eg-prod-bastion-public` because when generating `id`, the default order is `namespace`, `environment`, `stage`, `name`, `attributes`
|
||
(you can override it by using the `label_order` variable, see [Advanced Example 3](#advanced-example-3)).
|
||
|
||
Now reference the label when creating an instance:
|
||
|
||
```hcl
|
||
resource "aws_instance" "eg_prod_bastion_public" {
|
||
instance_type = "t1.micro"
|
||
tags = module.eg_prod_bastion_label.tags
|
||
}
|
||
```
|
||
|
||
Or define a security group:
|
||
|
||
```hcl
|
||
resource "aws_security_group" "eg_prod_bastion_public" {
|
||
vpc_id = var.vpc_id
|
||
name = module.eg_prod_bastion_label.id
|
||
tags = module.eg_prod_bastion_label.tags
|
||
egress {
|
||
from_port = 0
|
||
to_port = 0
|
||
protocol = "-1"
|
||
cidr_blocks = ["0.0.0.0/0"]
|
||
}
|
||
}
|
||
```
|
||
|
||
|
||
### Advanced Example
|
||
|
||
Here is a more complex example with two instances using two different labels. Note how efficiently the tags are defined for both the instance and the security group.
|
||
|
||
<details><summary>Click to show</summary>
|
||
|
||
```hcl
|
||
module "eg_prod_bastion_abc_label" {
|
||
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=master"
|
||
namespace = "eg"
|
||
stage = "prod"
|
||
name = "bastion"
|
||
attributes = ["abc"]
|
||
delimiter = "-"
|
||
|
||
tags = {
|
||
"BusinessUnit" = "XYZ",
|
||
"Snapshot" = "true"
|
||
}
|
||
}
|
||
|
||
resource "aws_security_group" "eg_prod_bastion_abc" {
|
||
name = module.eg_prod_bastion_abc_label.id
|
||
tags = module.eg_prod_bastion_abc_label.tags
|
||
ingress {
|
||
from_port = 22
|
||
to_port = 22
|
||
protocol = "tcp"
|
||
cidr_blocks = ["0.0.0.0/0"]
|
||
}
|
||
}
|
||
|
||
resource "aws_instance" "eg_prod_bastion_abc" {
|
||
instance_type = "t1.micro"
|
||
tags = module.eg_prod_bastion_abc_label.tags
|
||
vpc_security_group_ids = [aws_security_group.eg_prod_bastion_abc.id]
|
||
}
|
||
|
||
module "eg_prod_bastion_xyz_label" {
|
||
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=master"
|
||
namespace = "eg"
|
||
stage = "prod"
|
||
name = "bastion"
|
||
attributes = ["xyz"]
|
||
delimiter = "-"
|
||
|
||
tags = {
|
||
"BusinessUnit" = "XYZ",
|
||
"Snapshot" = "true"
|
||
}
|
||
}
|
||
|
||
resource "aws_security_group" "eg_prod_bastion_xyz" {
|
||
name = module.eg_prod_bastion_xyz_label.id
|
||
tags = module.eg_prod_bastion_xyz_label.tags
|
||
ingress {
|
||
from_port = 22
|
||
to_port = 22
|
||
protocol = "tcp"
|
||
cidr_blocks = ["0.0.0.0/0"]
|
||
}
|
||
}
|
||
|
||
resource "aws_instance" "eg_prod_bastion_xyz" {
|
||
instance_type = "t1.micro"
|
||
tags = module.eg_prod_bastion_xyz_label.tags
|
||
vpc_security_group_ids = [aws_security_group.eg_prod_bastion_xyz.id]
|
||
}
|
||
```
|
||
|
||
</details>
|
||
|
||
### 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:
|
||
|
||
<details><summary>Click to show</summary>
|
||
|
||
```hcl
|
||
tags = [
|
||
{
|
||
key = Name,
|
||
propagate_at_launch = 1,
|
||
value = namespace-stage-name
|
||
},
|
||
{
|
||
key = Namespace,
|
||
propagate_at_launch = 1,
|
||
value = namespace
|
||
},
|
||
{
|
||
key = Stage,
|
||
propagate_at_launch = 1,
|
||
value = stage
|
||
}
|
||
]
|
||
```
|
||
|
||
Autoscaling group using propagating tagging below (full example: [autoscalinggroup](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
|
||
}
|
||
```
|
||
|
||
</details>
|
||
|
||
### Advanced Example 3
|
||
|
||
See [complete example](./examples/complete) for even more examples.
|
||
|
||
This example shows how you can pass the `context` output of one label module to the next label_module,
|
||
allowing you to create one label that has the base set of values, and then creating every extra label
|
||
as a derivative of that.
|
||
|
||
<details><summary>Click to show</summary>
|
||
|
||
```hcl
|
||
module "label1" {
|
||
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=master"
|
||
namespace = "CloudPosse"
|
||
environment = "UAT"
|
||
stage = "build"
|
||
name = "Winston Churchroom"
|
||
attributes = ["fire", "water", "earth", "air"]
|
||
delimiter = "-"
|
||
|
||
label_order = ["name", "environment", "stage", "attributes"]
|
||
|
||
tags = {
|
||
"City" = "Dublin"
|
||
"Environment" = "Private"
|
||
}
|
||
}
|
||
|
||
module "label2" {
|
||
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=master"
|
||
context = module.label1.context
|
||
name = "Charlie"
|
||
stage = "test"
|
||
delimiter = "+"
|
||
|
||
tags = {
|
||
"City" = "London"
|
||
"Environment" = "Public"
|
||
}
|
||
}
|
||
|
||
module "label3" {
|
||
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=master"
|
||
name = "Starfish"
|
||
stage = "release"
|
||
context = module.label1.context
|
||
delimiter = "."
|
||
|
||
tags = {
|
||
"Eat" = "Carrot"
|
||
"Animal" = "Rabbit"
|
||
}
|
||
}
|
||
```
|
||
|
||
This creates label outputs like this:
|
||
|
||
```hcl
|
||
label1 = {
|
||
"attributes" = [
|
||
"fire",
|
||
"water",
|
||
"earth",
|
||
"air",
|
||
]
|
||
"delimiter" = "-"
|
||
"id" = "winstonchurchroom-uat-build-fire-water-earth-air"
|
||
"name" = "winstonchurchroom"
|
||
"namespace" = "cloudposse"
|
||
"stage" = "build"
|
||
}
|
||
label1_context = {
|
||
"additional_tag_map" = {}
|
||
"attributes" = [
|
||
"fire",
|
||
"water",
|
||
"earth",
|
||
"air",
|
||
]
|
||
"delimiter" = "-"
|
||
"enabled" = true
|
||
"environment" = "UAT"
|
||
"label_order" = [
|
||
"name",
|
||
"environment",
|
||
"stage",
|
||
"attributes",
|
||
]
|
||
"name" = "Winston Churchroom"
|
||
"namespace" = "CloudPosse"
|
||
"stage" = "build"
|
||
"tags" = {
|
||
"City" = "Dublin"
|
||
"Environment" = "Private"
|
||
}
|
||
}
|
||
label1_normalized_context = {
|
||
"additional_tag_map" = {}
|
||
"attributes" = [
|
||
"fire",
|
||
"water",
|
||
"earth",
|
||
"air",
|
||
]
|
||
"delimiter" = "-"
|
||
"enabled" = true
|
||
"environment" = "uat"
|
||
"id_length_limit" = 0
|
||
"label_order" = [
|
||
"name",
|
||
"environment",
|
||
"stage",
|
||
"attributes",
|
||
]
|
||
"name" = "winstonchurchroom"
|
||
"namespace" = "cloudposse"
|
||
"regex_replace_chars" = "/[^-a-zA-Z0-9]/"
|
||
"stage" = "build"
|
||
"tags" = {
|
||
"Attributes" = "fire-water-earth-air"
|
||
"City" = "Dublin"
|
||
"Environment" = "Private"
|
||
"Name" = "winstonchurchroom-uat-build-fire-water-earth-air"
|
||
"Namespace" = "cloudposse"
|
||
"Stage" = "build"
|
||
}
|
||
}
|
||
label1_tags = {
|
||
"Attributes" = "fire-water-earth-air"
|
||
"City" = "Dublin"
|
||
"Environment" = "Private"
|
||
"Name" = "winstonchurchroom-uat-build-fire-water-earth-air"
|
||
"Namespace" = "cloudposse"
|
||
"Stage" = "build"
|
||
}
|
||
label2 = {
|
||
"attributes" = [
|
||
"fire",
|
||
"water",
|
||
"earth",
|
||
"air",
|
||
]
|
||
"delimiter" = "+"
|
||
"id" = "charlie+uat+test+fire+water+earth+air"
|
||
"name" = "charlie"
|
||
"namespace" = "cloudposse"
|
||
"stage" = "test"
|
||
}
|
||
label2_context = {
|
||
"additional_tag_map" = {
|
||
"additional_tag" = "yes"
|
||
"propagate_at_launch" = "true"
|
||
}
|
||
"attributes" = [
|
||
"fire",
|
||
"water",
|
||
"earth",
|
||
"air",
|
||
]
|
||
"delimiter" = "+"
|
||
"enabled" = true
|
||
"environment" = "UAT"
|
||
"label_order" = [
|
||
"name",
|
||
"environment",
|
||
"stage",
|
||
"attributes",
|
||
]
|
||
"name" = "Charlie"
|
||
"namespace" = "CloudPosse"
|
||
"regex_replace_chars" = "/[^a-zA-Z0-9-+]/"
|
||
"stage" = "test"
|
||
"tags" = {
|
||
"City" = "London"
|
||
"Environment" = "Public"
|
||
}
|
||
}
|
||
label2_tags = {
|
||
"Attributes" = "fire+water+earth+air"
|
||
"City" = "London"
|
||
"Environment" = "Public"
|
||
"Name" = "charlie+uat+test+fire+water+earth+air"
|
||
"Namespace" = "cloudposse"
|
||
"Stage" = "test"
|
||
}
|
||
label2_tags_as_list_of_maps = [
|
||
{
|
||
"additional_tag" = "yes"
|
||
"key" = "Attributes"
|
||
"propagate_at_launch" = "true"
|
||
"value" = "fire+water+earth+air"
|
||
},
|
||
{
|
||
"additional_tag" = "yes"
|
||
"key" = "City"
|
||
"propagate_at_launch" = "true"
|
||
"value" = "London"
|
||
},
|
||
{
|
||
"additional_tag" = "yes"
|
||
"key" = "Environment"
|
||
"propagate_at_launch" = "true"
|
||
"value" = "Public"
|
||
},
|
||
{
|
||
"additional_tag" = "yes"
|
||
"key" = "Name"
|
||
"propagate_at_launch" = "true"
|
||
"value" = "charlie+uat+test+fire+water+earth+air"
|
||
},
|
||
{
|
||
"additional_tag" = "yes"
|
||
"key" = "Namespace"
|
||
"propagate_at_launch" = "true"
|
||
"value" = "cloudposse"
|
||
},
|
||
{
|
||
"additional_tag" = "yes"
|
||
"key" = "Stage"
|
||
"propagate_at_launch" = "true"
|
||
"value" = "test"
|
||
},
|
||
]
|
||
label3 = {
|
||
"attributes" = [
|
||
"fire",
|
||
"water",
|
||
"earth",
|
||
"air",
|
||
]
|
||
"delimiter" = "."
|
||
"id" = "starfish.uat.release.fire.water.earth.air"
|
||
"name" = "starfish"
|
||
"namespace" = "cloudposse"
|
||
"stage" = "release"
|
||
}
|
||
label3_context = {
|
||
"additional_tag_map" = {}
|
||
"attributes" = [
|
||
"fire",
|
||
"water",
|
||
"earth",
|
||
"air",
|
||
]
|
||
"delimiter" = "."
|
||
"enabled" = true
|
||
"environment" = "UAT"
|
||
"label_order" = [
|
||
"name",
|
||
"environment",
|
||
"stage",
|
||
"attributes",
|
||
]
|
||
"name" = "Starfish"
|
||
"namespace" = "CloudPosse"
|
||
"regex_replace_chars" = "/[^-a-zA-Z0-9.]/"
|
||
"stage" = "release"
|
||
"tags" = {
|
||
"Animal" = "Rabbit"
|
||
"City" = "Dublin"
|
||
"Eat" = "Carrot"
|
||
"Environment" = "Private"
|
||
}
|
||
}
|
||
label3_normalized_context = {
|
||
"additional_tag_map" = {}
|
||
"attributes" = [
|
||
"fire",
|
||
"water",
|
||
"earth",
|
||
"air",
|
||
]
|
||
"delimiter" = "."
|
||
"enabled" = true
|
||
"environment" = "uat"
|
||
"id_length_limit" = 0
|
||
"label_order" = [
|
||
"name",
|
||
"environment",
|
||
"stage",
|
||
"attributes",
|
||
]
|
||
"name" = "starfish"
|
||
"namespace" = "cloudposse"
|
||
"regex_replace_chars" = "/[^-a-zA-Z0-9.]/"
|
||
"stage" = "release"
|
||
"tags" = {
|
||
"Animal" = "Rabbit"
|
||
"Attributes" = "fire.water.earth.air"
|
||
"City" = "Dublin"
|
||
"Eat" = "Carrot"
|
||
"Environment" = "Private"
|
||
"Name" = "starfish.uat.release.fire.water.earth.air"
|
||
"Namespace" = "cloudposse"
|
||
"Stage" = "release"
|
||
}
|
||
}
|
||
label3_tags = {
|
||
"Animal" = "Rabbit"
|
||
"Attributes" = "fire.water.earth.air"
|
||
"City" = "Dublin"
|
||
"Eat" = "Carrot"
|
||
"Environment" = "Private"
|
||
"Name" = "starfish.uat.release.fire.water.earth.air"
|
||
"Namespace" = "cloudposse"
|
||
"Stage" = "release"
|
||
}
|
||
|
||
```
|
||
|
||
</details>
|
||
|
||
include:
|
||
- docs/targets.md
|
||
- docs/terraform.md
|
||
contributors:
|
||
- name: Erik Osterman
|
||
github: osterman
|
||
- name: Andriy Knysh
|
||
github: aknysh
|
||
- name: Igor Rodionov
|
||
github: goruha
|
||
- name: Sergey Vasilyev
|
||
github: s2504s
|
||
- name: Michael Pereira
|
||
github: MichaelPereira
|
||
- name: Jamie Nelson
|
||
github: Jamie-BitFlight
|
||
- name: Vladimir
|
||
github: SweetOps
|
||
- name: Daren Desjardins
|
||
github: darend
|
||
- name: Maarten van der Hoef
|
||
github: maartenvanderhoef
|
||
- name: Adam Tibbing
|
||
github: tibbing
|