diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bed3c96..30b3a85 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -12,3 +12,6 @@ # Cloud Posse must review any changes to GitHub actions .github/* @cloudposse/engineering + +# Cloud Posse must review any changes to standard context definition +**/context.tf @cloudposse/engineering \ No newline at end of file diff --git a/README.md b/README.md index 1df9e91..2e0130b 100644 --- a/README.md +++ b/README.md @@ -103,31 +103,37 @@ Available targets: | Name | Version | |------|---------| | terraform | >= 0.12.0, < 0.14.0 | -| aws | >= 2.0, < 4.0 | -| null | ~> 2.0 | -| template | ~> 2.0 | +| aws | >= 2.0 | +| null | >= 2.0 | +| template | >= 2.0 | ## Providers | Name | Version | |------|---------| -| aws | >= 2.0, < 4.0 | -| template | ~> 2.0 | +| aws | >= 2.0 | +| template | >= 2.0 | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | | attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | -| delimiter | Delimiter to be used between `namespace`, `stage`, `name` and `attributes` | `string` | `"-"` | no | -| enabled | Set to false to prevent the module from creating or accessing any resources | `bool` | `true` | no | -| environment | Environment, e.g. 'prod', 'staging', 'dev', 'pre-prod', 'UAT' | `string` | `""` | no | -| name | The Name of the application or solution (e.g. `bastion` or `portal`) | `string` | n/a | yes | -| namespace | Namespace (e.g. `eg` or `cp`) | `string` | n/a | yes | +| context | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. |
object({
enabled = bool
namespace = string
environment = string
stage = string
name = string
delimiter = string
attributes = list(string)
tags = map(string)
additional_tag_map = map(string)
regex_replace_chars = string
label_order = list(string)
id_length_limit = number
})
|
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_order": [],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | +| delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| id\_length\_limit | Limit `id` to this many characters.
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | +| label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | +| name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | +| namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | | parent\_zone\_id | ID of the hosted zone to contain this record (or specify `parent_zone_name`) | `string` | `""` | no | | parent\_zone\_name | Name of the hosted zone to contain this record (or specify `parent_zone_id`) | `string` | `""` | no | -| stage | Stage (e.g. `prod`, `dev`, `staging`) | `string` | n/a | yes | -| tags | Additional tags (e.g. map('BusinessUnit','XYZ') | `map(string)` | `{}` | no | +| parent\_zone\_record\_enabled | Whether to create the NS record on the parent zone. Useful for creating a cluster zone across accounts. `var.parent_zone_name` required if set to false. | `bool` | `true` | no | +| regex\_replace\_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | +| tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | | zone\_name | Zone name | `string` | `"$${name}.$${stage}.$${parent_zone_name}"` | no | ## Outputs @@ -139,6 +145,7 @@ Available targets: | parent\_zone\_name | Name of the hosted zone to contain this record | | zone\_id | Route53 DNS Zone ID | | zone\_name | Route53 DNS Zone name | +| zone\_name\_servers | Route53 DNS Zone Name Servers | diff --git a/context.tf b/context.tf new file mode 100644 index 0000000..bae0cf1 --- /dev/null +++ b/context.tf @@ -0,0 +1,167 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.19.2" + + enabled = var.enabled + namespace = var.namespace + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = object({ + enabled = bool + namespace = string + environment = string + stage = string + name = string + delimiter = string + attributes = list(string) + tags = map(string) + additional_tag_map = map(string) + regex_replace_chars = string + label_order = list(string) + id_length_limit = number + }) + default = { + enabled = true + namespace = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" +} + +variable "environment" { + type = string + default = null + description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = "Solution name, e.g. 'app' or 'jenkins'" +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = "Additional attributes (e.g. `1`)" +} + +variable "tags" { + type = map(string) + default = {} + description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`" +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = "Additional tags for appending to tags_as_list_of_maps. Not added to `tags`." +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The naming order of the id output and Name tag. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 5 elements, but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters. + Set to `0` for unlimited length. + Set to `null` for default, which is `0`. + Does not affect `id_full`. + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/docs/terraform.md b/docs/terraform.md index 2ab7730..7eab52b 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -4,31 +4,37 @@ | Name | Version | |------|---------| | terraform | >= 0.12.0, < 0.14.0 | -| aws | >= 2.0, < 4.0 | -| null | ~> 2.0 | -| template | ~> 2.0 | +| aws | >= 2.0 | +| null | >= 2.0 | +| template | >= 2.0 | ## Providers | Name | Version | |------|---------| -| aws | >= 2.0, < 4.0 | -| template | ~> 2.0 | +| aws | >= 2.0 | +| template | >= 2.0 | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | | attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | -| delimiter | Delimiter to be used between `namespace`, `stage`, `name` and `attributes` | `string` | `"-"` | no | -| enabled | Set to false to prevent the module from creating or accessing any resources | `bool` | `true` | no | -| environment | Environment, e.g. 'prod', 'staging', 'dev', 'pre-prod', 'UAT' | `string` | `""` | no | -| name | The Name of the application or solution (e.g. `bastion` or `portal`) | `string` | n/a | yes | -| namespace | Namespace (e.g. `eg` or `cp`) | `string` | n/a | yes | +| context | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. |
object({
enabled = bool
namespace = string
environment = string
stage = string
name = string
delimiter = string
attributes = list(string)
tags = map(string)
additional_tag_map = map(string)
regex_replace_chars = string
label_order = list(string)
id_length_limit = number
})
|
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_order": [],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | +| delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| id\_length\_limit | Limit `id` to this many characters.
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | +| label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | +| name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | +| namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | | parent\_zone\_id | ID of the hosted zone to contain this record (or specify `parent_zone_name`) | `string` | `""` | no | | parent\_zone\_name | Name of the hosted zone to contain this record (or specify `parent_zone_id`) | `string` | `""` | no | -| stage | Stage (e.g. `prod`, `dev`, `staging`) | `string` | n/a | yes | -| tags | Additional tags (e.g. map('BusinessUnit','XYZ') | `map(string)` | `{}` | no | +| parent\_zone\_record\_enabled | Whether to create the NS record on the parent zone. Useful for creating a cluster zone across accounts. `var.parent_zone_name` required if set to false. | `bool` | `true` | no | +| regex\_replace\_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | +| tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | | zone\_name | Zone name | `string` | `"$${name}.$${stage}.$${parent_zone_name}"` | no | ## Outputs @@ -40,5 +46,6 @@ | parent\_zone\_name | Name of the hosted zone to contain this record | | zone\_id | Route53 DNS Zone ID | | zone\_name | Route53 DNS Zone name | +| zone\_name\_servers | Route53 DNS Zone Name Servers | diff --git a/examples/complete/context.tf b/examples/complete/context.tf new file mode 100644 index 0000000..bae0cf1 --- /dev/null +++ b/examples/complete/context.tf @@ -0,0 +1,167 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.19.2" + + enabled = var.enabled + namespace = var.namespace + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = object({ + enabled = bool + namespace = string + environment = string + stage = string + name = string + delimiter = string + attributes = list(string) + tags = map(string) + additional_tag_map = map(string) + regex_replace_chars = string + label_order = list(string) + id_length_limit = number + }) + default = { + enabled = true + namespace = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" +} + +variable "environment" { + type = string + default = null + description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = "Solution name, e.g. 'app' or 'jenkins'" +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = "Additional attributes (e.g. `1`)" +} + +variable "tags" { + type = map(string) + default = {} + description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`" +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = "Additional tags for appending to tags_as_list_of_maps. Not added to `tags`." +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The naming order of the id output and Name tag. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 5 elements, but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters. + Set to `0` for unlimited length. + Set to `null` for default, which is `0`. + Does not affect `id_full`. + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 44c3c40..f3031ec 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -4,9 +4,7 @@ provider "aws" { module "domain" { source = "../../" - namespace = var.namespace - stage = var.stage - name = var.name + context = module.this.context parent_zone_name = var.parent_zone_name zone_name = "$${name}.$${parent_zone_name}" } diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index 6a3d377..024a1e2 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -1,18 +1,3 @@ -variable "name" { - type = string - description = "The Name of the application or solution (e.g. `bastion` or `portal`)" -} - -variable "namespace" { - type = string - description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" -} - -variable "stage" { - type = string - description = "Stage (e.g. `prod`, `dev`, `staging`)" -} - variable "region" { type = string description = "AWS region" diff --git a/main.tf b/main.tf index 60f460b..f2521e7 100644 --- a/main.tf +++ b/main.tf @@ -1,24 +1,12 @@ -module "label" { - source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.19.2" - namespace = var.namespace - stage = var.stage - environment = var.environment - name = var.name - delimiter = var.delimiter - attributes = var.attributes - tags = var.tags - enabled = var.enabled -} - locals { - enabled = var.enabled ? 1 : 0 + enabled = module.this.enabled ? 1 : 0 + parent_zone_record_enabled = var.parent_zone_record_enabled && module.this.enabled ? 1 : 0 } -data "aws_region" "default" { -} +data "aws_region" "default" {} data "aws_route53_zone" "parent_zone" { - count = local.enabled + count = local.parent_zone_record_enabled zone_id = var.parent_zone_id name = var.parent_zone_name } @@ -28,13 +16,13 @@ data "template_file" "zone_name" { template = replace(var.zone_name, "$$", "$") vars = { - namespace = var.namespace - environment = var.environment - name = var.name - stage = var.stage - id = module.label.id - attributes = join(var.delimiter, module.label.attributes) - parent_zone_name = join("", data.aws_route53_zone.parent_zone.*.name) + namespace = module.this.namespace + environment = module.this.environment + name = module.this.name + stage = module.this.stage + id = module.this.id + attributes = join(module.this.delimiter, module.this.attributes) + parent_zone_name = coalesce(join("", data.aws_route53_zone.parent_zone.*.name), var.parent_zone_name) region = data.aws_region.default.name } } @@ -42,11 +30,11 @@ data "template_file" "zone_name" { resource "aws_route53_zone" "default" { count = local.enabled name = join("", data.template_file.zone_name.*.rendered) - tags = module.label.tags + tags = module.this.tags } resource "aws_route53_record" "ns" { - count = local.enabled + count = local.parent_zone_record_enabled zone_id = join("", data.aws_route53_zone.parent_zone.*.zone_id) name = join("", aws_route53_zone.default.*.name) type = "NS" diff --git a/outputs.tf b/outputs.tf index 6fb5811..ecfca33 100644 --- a/outputs.tf +++ b/outputs.tf @@ -18,6 +18,11 @@ output "zone_name" { description = "Route53 DNS Zone name" } +output "zone_name_servers" { + value = try(aws_route53_zone.default[0].name_servers, []) + description = "Route53 DNS Zone Name Servers" +} + output "fqdn" { value = join("", aws_route53_zone.default.*.name) description = "Fully-qualified domain name" diff --git a/variables.tf b/variables.tf index 4e2f080..ce7de2d 100644 --- a/variables.tf +++ b/variables.tf @@ -1,24 +1,3 @@ -variable "name" { - type = string - description = "The Name of the application or solution (e.g. `bastion` or `portal`)" -} - -variable "namespace" { - type = string - description = "Namespace (e.g. `eg` or `cp`)" -} - -variable "environment" { - default = "" - type = string - description = "Environment, e.g. 'prod', 'staging', 'dev', 'pre-prod', 'UAT'" -} - -variable "stage" { - type = string - description = "Stage (e.g. `prod`, `dev`, `staging`)" -} - variable "zone_name" { type = string default = "$$${name}.$$${stage}.$$${parent_zone_name}" @@ -37,26 +16,8 @@ variable "parent_zone_name" { description = "Name of the hosted zone to contain this record (or specify `parent_zone_id`)" } -variable "delimiter" { - type = string - default = "-" - description = "Delimiter to be used between `namespace`, `stage`, `name` and `attributes`" -} - -variable "attributes" { - type = list(string) - default = [] - description = "Additional attributes (e.g. `1`)" -} - -variable "tags" { - type = map(string) - default = {} - description = "Additional tags (e.g. map('BusinessUnit','XYZ')" -} - -variable "enabled" { +variable "parent_zone_record_enabled" { type = bool default = true - description = "Set to false to prevent the module from creating or accessing any resources" + description = "Whether to create the NS record on the parent zone. Useful for creating a cluster zone across accounts. `var.parent_zone_name` required if set to false." } diff --git a/versions.tf b/versions.tf index 8af40e5..3cfaa79 100644 --- a/versions.tf +++ b/versions.tf @@ -2,8 +2,8 @@ terraform { required_version = ">= 0.12.0, < 0.14.0" required_providers { - aws = ">= 2.0, < 4.0" - template = "~> 2.0" - null = "~> 2.0" + aws = ">= 2.0" + template = ">= 2.0" + null = ">= 2.0" } }