From df8b991bef53fcab8f01c542cd1c3ccc6242b61c Mon Sep 17 00:00:00 2001 From: Nuru Date: Fri, 28 Aug 2020 01:17:00 -0700 Subject: [PATCH] Convert to context.tf, allow AWS 3.0 provider (#75) * Convert to context.tf, allow AWS 3.0 provider * Executed 'terraform fmt' * Updated README.md * Put "cluster" after user-provided attributes * Restore incorrectly deleted parameter Co-authored-by: actions-bot <58130806+actions-bot@users.noreply.github.com> --- .github/CODEOWNERS | 3 + .github/auto-release.yml | 40 +++++++ .github/workflows/auto-release.yml | 19 ++++ .github/workflows/chatops.yml | 8 +- README.md | 23 ++-- auth.tf | 10 +- context.tf | 167 +++++++++++++++++++++++++++++ docs/terraform.md | 23 ++-- examples/complete/context.tf | 167 +++++++++++++++++++++++++++++ examples/complete/main.tf | 50 ++++----- examples/complete/variables.tf | 33 ------ examples/complete/versions.tf | 4 +- iam.tf | 12 +-- main.tf | 34 +++--- sg.tf | 10 +- variables.tf | 48 --------- versions.tf | 2 +- 17 files changed, 488 insertions(+), 165 deletions(-) create mode 100644 .github/auto-release.yml create mode 100644 .github/workflows/auto-release.yml create mode 100644 context.tf create mode 100644 examples/complete/context.tf diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bed3c967..07b38d2c 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 diff --git a/.github/auto-release.yml b/.github/auto-release.yml new file mode 100644 index 00000000..2836185f --- /dev/null +++ b/.github/auto-release.yml @@ -0,0 +1,40 @@ +name-template: 'v$RESOLVED_VERSION' +tag-template: '$RESOLVED_VERSION' +version-template: '$MAJOR.$MINOR.$PATCH' +version-resolver: + major: + labels: + - 'major' + minor: + labels: + - 'minor' + - 'enhancement' + patch: + labels: + - 'patch' + - 'fix' + - 'bugfix' + - 'bug' + - 'hotfix' + default: 'minor' + +categories: + - title: '🚀 Enhancements' + labels: + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - 'hotfix' + +change-template: | +
+ $TITLE @$AUTHOR (#$NUMBER) + + $BODY +
+ +template: | + $CHANGES diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml new file mode 100644 index 00000000..e21fbfe4 --- /dev/null +++ b/.github/workflows/auto-release.yml @@ -0,0 +1,19 @@ +name: auto-release + +on: + push: + branches: + - master + +jobs: + semver: + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v5 + with: + publish: true + prerelease: false + config-name: auto-release.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/chatops.yml b/.github/workflows/chatops.yml index a6bb11b4..0d943109 100644 --- a/.github/workflows/chatops.yml +++ b/.github/workflows/chatops.yml @@ -9,13 +9,13 @@ jobs: steps: - uses: actions/checkout@v2 - name: "Handle common commands" - uses: cloudposse/actions/github/slash-command-dispatch@0.15.0 + uses: cloudposse/actions/github/slash-command-dispatch@0.16.0 with: token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} reaction-token: ${{ secrets.GITHUB_TOKEN }} repository: cloudposse/actions commands: rebuild-readme, terraform-fmt - permission: none + permission: triage issue-type: pull-request test: @@ -24,13 +24,13 @@ jobs: - name: "Checkout commit" uses: actions/checkout@v2 - name: "Run tests" - uses: cloudposse/actions/github/slash-command-dispatch@0.15.0 + uses: cloudposse/actions/github/slash-command-dispatch@0.16.0 with: token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} reaction-token: ${{ secrets.GITHUB_TOKEN }} repository: cloudposse/actions commands: test - permission: none + permission: triage issue-type: pull-request reactions: false diff --git a/README.md b/README.md index 7bc25b44..7f8e9534 100644 --- a/README.md +++ b/README.md @@ -285,12 +285,13 @@ Available targets: ``` + ## Requirements | Name | Version | |------|---------| | terraform | >= 0.12.0, < 0.14.0 | -| aws | ~> 2.0 | +| aws | >= 2.0, < 4.0 | | kubernetes | ~> 1.11 | | local | ~> 1.3 | | null | ~> 2.0 | @@ -300,7 +301,7 @@ Available targets: | Name | Version | |------|---------| -| aws | ~> 2.0 | +| aws | >= 2.0, < 4.0 | | kubernetes | ~> 1.11 | | null | ~> 2.0 | @@ -308,6 +309,7 @@ Available targets: | 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 | | allowed\_cidr\_blocks | List of CIDR blocks to be allowed to connect to the EKS cluster | `list(string)` | `[]` | no | | allowed\_security\_groups | List of Security Group IDs to be allowed to connect to the EKS cluster | `list(string)` | `[]` | no | | apply\_config\_map\_aws\_auth | Whether to apply the ConfigMap to allow worker nodes to join the EKS cluster and allow additional users, accounts and roles to acces the cluster | `bool` | `true` | no | @@ -319,24 +321,28 @@ Available targets: | cluster\_encryption\_config\_kms\_key\_policy | Cluster Encryption Config KMS Key Resource argument - key policy | `string` | `null` | no | | cluster\_encryption\_config\_resources | Cluster Encryption Config Resources to encrypt, e.g. ['secrets'] | `list` |
[
"secrets"
]
| no | | cluster\_log\_retention\_period | Number of days to retain cluster logs. Requires `enabled_cluster_log_types` to be set. See https://docs.aws.amazon.com/en_us/eks/latest/userguide/control-plane-logs.html. | `number` | `0` | no | -| delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes` | `string` | `"-"` | no | -| enabled | Set to false to prevent the module from creating any resources | `bool` | `true` | no | +| 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 | | enabled\_cluster\_log\_types | A list of the desired control plane logging to enable. For more information, see https://docs.aws.amazon.com/en_us/eks/latest/userguide/control-plane-logs.html. Possible values [`api`, `audit`, `authenticator`, `controllerManager`, `scheduler`] | `list(string)` | `[]` | no | | endpoint\_private\_access | Indicates whether or not the Amazon EKS private API server endpoint is enabled. Default to AWS EKS resource and it is false | `bool` | `false` | no | | endpoint\_public\_access | Indicates whether or not the Amazon EKS public API server endpoint is enabled. Default to AWS EKS resource and it is true | `bool` | `true` | no | -| environment | Environment, e.g. 'prod', 'staging', 'dev', 'pre-prod', 'UAT' | `string` | `""` | 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 | | kubernetes\_config\_map\_ignore\_role\_changes | Set to `true` to ignore IAM role changes in the Kubernetes Auth ConfigMap | `bool` | `true` | no | | kubernetes\_version | Desired Kubernetes master version. If you do not specify a value, the latest available version is used | `string` | `"1.15"` | 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 | | local\_exec\_interpreter | shell to use for local\_exec | `list(string)` |
[
"/bin/sh",
"-c"
]
| no | | map\_additional\_aws\_accounts | Additional AWS account numbers to add to `config-map-aws-auth` ConfigMap | `list(string)` | `[]` | no | | map\_additional\_iam\_roles | Additional IAM roles to add to `config-map-aws-auth` ConfigMap |
list(object({
rolearn = string
username = string
groups = list(string)
}))
| `[]` | no | | map\_additional\_iam\_users | Additional IAM users to add to `config-map-aws-auth` ConfigMap |
list(object({
userarn = string
username = string
groups = list(string)
}))
| `[]` | no | -| name | Solution name, e.g. 'app' or 'jenkins' | `string` | `""` | no | -| namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `""` | 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 | | oidc\_provider\_enabled | Create an IAM OIDC identity provider for the cluster, then you can create IAM roles to associate with a service account in the cluster, instead of using kiam or kube2iam. For more information, see https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html | `bool` | `false` | no | | public\_access\_cidrs | Indicates which CIDR blocks can access the Amazon EKS public API server endpoint when enabled. EKS defaults this to a list with 0.0.0.0/0. | `list(string)` |
[
"0.0.0.0/0"
]
| 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 | | region | AWS Region | `string` | n/a | yes | -| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `""` | no | +| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | subnet\_ids | A list of subnet IDs to launch the cluster in | `list(string)` | n/a | yes | | tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | | vpc\_id | VPC ID for the EKS cluster | `string` | n/a | yes | @@ -366,6 +372,7 @@ Available targets: | security\_group\_id | ID of the EKS cluster Security Group | | security\_group\_name | Name of the EKS cluster Security Group | + diff --git a/auth.tf b/auth.tf index 8e6aac4f..7abffc9f 100644 --- a/auth.tf +++ b/auth.tf @@ -47,7 +47,7 @@ locals { } resource "null_resource" "wait_for_cluster" { - count = var.enabled && var.apply_config_map_aws_auth ? 1 : 0 + count = local.enabled && var.apply_config_map_aws_auth ? 1 : 0 depends_on = [aws_eks_cluster.default[0]] provisioner "local-exec" { @@ -60,7 +60,7 @@ resource "null_resource" "wait_for_cluster" { } data "aws_eks_cluster" "eks" { - count = var.enabled && var.apply_config_map_aws_auth ? 1 : 0 + count = local.enabled && var.apply_config_map_aws_auth ? 1 : 0 name = join("", aws_eks_cluster.default.*.id) } @@ -70,7 +70,7 @@ data "aws_eks_cluster" "eks" { # If the AWS provider assumes an IAM role, `aws_eks_cluster_auth` will use the same IAM role to get the auth token. # https://www.terraform.io/docs/providers/aws/d/eks_cluster_auth.html data "aws_eks_cluster_auth" "eks" { - count = var.enabled && var.apply_config_map_aws_auth ? 1 : 0 + count = local.enabled && var.apply_config_map_aws_auth ? 1 : 0 name = join("", aws_eks_cluster.default.*.id) } @@ -82,7 +82,7 @@ provider "kubernetes" { } resource "kubernetes_config_map" "aws_auth_ignore_changes" { - count = var.enabled && var.apply_config_map_aws_auth && var.kubernetes_config_map_ignore_role_changes ? 1 : 0 + count = local.enabled && var.apply_config_map_aws_auth && var.kubernetes_config_map_ignore_role_changes ? 1 : 0 depends_on = [null_resource.wait_for_cluster[0]] metadata { @@ -102,7 +102,7 @@ resource "kubernetes_config_map" "aws_auth_ignore_changes" { } resource "kubernetes_config_map" "aws_auth" { - count = var.enabled && var.apply_config_map_aws_auth && var.kubernetes_config_map_ignore_role_changes == false ? 1 : 0 + count = local.enabled && var.apply_config_map_aws_auth && var.kubernetes_config_map_ignore_role_changes == false ? 1 : 0 depends_on = [null_resource.wait_for_cluster[0]] metadata { diff --git a/context.tf b/context.tf new file mode 100644 index 00000000..bae0cf1d --- /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 1d771f07..fe73ac2a 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -1,9 +1,10 @@ + ## Requirements | Name | Version | |------|---------| | terraform | >= 0.12.0, < 0.14.0 | -| aws | ~> 2.0 | +| aws | >= 2.0, < 4.0 | | kubernetes | ~> 1.11 | | local | ~> 1.3 | | null | ~> 2.0 | @@ -13,7 +14,7 @@ | Name | Version | |------|---------| -| aws | ~> 2.0 | +| aws | >= 2.0, < 4.0 | | kubernetes | ~> 1.11 | | null | ~> 2.0 | @@ -21,6 +22,7 @@ | 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 | | allowed\_cidr\_blocks | List of CIDR blocks to be allowed to connect to the EKS cluster | `list(string)` | `[]` | no | | allowed\_security\_groups | List of Security Group IDs to be allowed to connect to the EKS cluster | `list(string)` | `[]` | no | | apply\_config\_map\_aws\_auth | Whether to apply the ConfigMap to allow worker nodes to join the EKS cluster and allow additional users, accounts and roles to acces the cluster | `bool` | `true` | no | @@ -32,24 +34,28 @@ | cluster\_encryption\_config\_kms\_key\_policy | Cluster Encryption Config KMS Key Resource argument - key policy | `string` | `null` | no | | cluster\_encryption\_config\_resources | Cluster Encryption Config Resources to encrypt, e.g. ['secrets'] | `list` |
[
"secrets"
]
| no | | cluster\_log\_retention\_period | Number of days to retain cluster logs. Requires `enabled_cluster_log_types` to be set. See https://docs.aws.amazon.com/en_us/eks/latest/userguide/control-plane-logs.html. | `number` | `0` | no | -| delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes` | `string` | `"-"` | no | -| enabled | Set to false to prevent the module from creating any resources | `bool` | `true` | no | +| 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 | | enabled\_cluster\_log\_types | A list of the desired control plane logging to enable. For more information, see https://docs.aws.amazon.com/en_us/eks/latest/userguide/control-plane-logs.html. Possible values [`api`, `audit`, `authenticator`, `controllerManager`, `scheduler`] | `list(string)` | `[]` | no | | endpoint\_private\_access | Indicates whether or not the Amazon EKS private API server endpoint is enabled. Default to AWS EKS resource and it is false | `bool` | `false` | no | | endpoint\_public\_access | Indicates whether or not the Amazon EKS public API server endpoint is enabled. Default to AWS EKS resource and it is true | `bool` | `true` | no | -| environment | Environment, e.g. 'prod', 'staging', 'dev', 'pre-prod', 'UAT' | `string` | `""` | 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 | | kubernetes\_config\_map\_ignore\_role\_changes | Set to `true` to ignore IAM role changes in the Kubernetes Auth ConfigMap | `bool` | `true` | no | | kubernetes\_version | Desired Kubernetes master version. If you do not specify a value, the latest available version is used | `string` | `"1.15"` | 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 | | local\_exec\_interpreter | shell to use for local\_exec | `list(string)` |
[
"/bin/sh",
"-c"
]
| no | | map\_additional\_aws\_accounts | Additional AWS account numbers to add to `config-map-aws-auth` ConfigMap | `list(string)` | `[]` | no | | map\_additional\_iam\_roles | Additional IAM roles to add to `config-map-aws-auth` ConfigMap |
list(object({
rolearn = string
username = string
groups = list(string)
}))
| `[]` | no | | map\_additional\_iam\_users | Additional IAM users to add to `config-map-aws-auth` ConfigMap |
list(object({
userarn = string
username = string
groups = list(string)
}))
| `[]` | no | -| name | Solution name, e.g. 'app' or 'jenkins' | `string` | `""` | no | -| namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `""` | 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 | | oidc\_provider\_enabled | Create an IAM OIDC identity provider for the cluster, then you can create IAM roles to associate with a service account in the cluster, instead of using kiam or kube2iam. For more information, see https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html | `bool` | `false` | no | | public\_access\_cidrs | Indicates which CIDR blocks can access the Amazon EKS public API server endpoint when enabled. EKS defaults this to a list with 0.0.0.0/0. | `list(string)` |
[
"0.0.0.0/0"
]
| 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 | | region | AWS Region | `string` | n/a | yes | -| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `""` | no | +| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | subnet\_ids | A list of subnet IDs to launch the cluster in | `list(string)` | n/a | yes | | tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | | vpc\_id | VPC ID for the EKS cluster | `string` | n/a | yes | @@ -79,3 +85,4 @@ | security\_group\_id | ID of the EKS cluster Security Group | | security\_group\_name | Name of the EKS cluster Security Group | + diff --git a/examples/complete/context.tf b/examples/complete/context.tf new file mode 100644 index 00000000..bae0cf1d --- /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 8ec46cbf..fe27ed04 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -3,13 +3,10 @@ provider "aws" { } module "label" { - source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.17.0" - namespace = var.namespace - name = var.name - stage = var.stage - delimiter = var.delimiter - attributes = compact(concat(var.attributes, list("cluster"))) - tags = var.tags + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.19.2" + attributes = ["cluster"] + + context = module.this.context } locals { @@ -36,22 +33,18 @@ locals { } module "vpc" { - source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.16.1" - namespace = var.namespace - stage = var.stage - name = var.name - attributes = var.attributes + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.17.0" + cidr_block = "172.16.0.0/16" tags = local.tags + + context = module.this.context } module "subnets" { - source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.27.0" + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.28.0" + availability_zones = var.availability_zones - namespace = var.namespace - stage = var.stage - name = var.name - attributes = var.attributes vpc_id = module.vpc.vpc_id igw_id = module.vpc.igw_id cidr_block = module.vpc.vpc_cidr_block @@ -60,15 +53,14 @@ module "subnets" { tags = local.tags public_subnets_additional_tags = local.public_subnets_additional_tags private_subnets_additional_tags = local.private_subnets_additional_tags + + context = module.this.context } + module "eks_cluster" { - source = "../../" - namespace = var.namespace - stage = var.stage - name = var.name - attributes = var.attributes - tags = var.tags + source = "../../" + region = var.region vpc_id = module.vpc.vpc_id subnet_ids = concat(module.subnets.private_subnet_ids, module.subnets.public_subnet_ids) @@ -77,6 +69,8 @@ module "eks_cluster" { oidc_provider_enabled = var.oidc_provider_enabled enabled_cluster_log_types = var.enabled_cluster_log_types cluster_log_retention_period = var.cluster_log_retention_period + + context = module.this.context } # Ensure ordering of resource creation to eliminate the race conditions when applying the Kubernetes Auth ConfigMap. @@ -92,12 +86,8 @@ data "null_data_source" "wait_for_cluster_and_kubernetes_configmap" { } module "eks_node_group" { - source = "git::https://github.com/cloudposse/terraform-aws-eks-node-group.git?ref=tags/0.7.1" - namespace = var.namespace - stage = var.stage - name = var.name - attributes = var.attributes - tags = var.tags + source = "git::https://github.com/cloudposse/terraform-aws-eks-node-group.git?ref=tags/0.8.0" + subnet_ids = module.subnets.private_subnet_ids cluster_name = data.null_data_source.wait_for_cluster_and_kubernetes_configmap.outputs["cluster_name"] instance_types = var.instance_types @@ -106,4 +96,6 @@ module "eks_node_group" { max_size = var.max_size kubernetes_labels = var.kubernetes_labels disk_size = var.disk_size + + context = module.this.context } diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index abaf2453..f07a7b1d 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -8,39 +8,6 @@ variable "availability_zones" { description = "List of availability zones" } -variable "namespace" { - type = string - description = "Namespace, which could be your organization name, e.g. 'eg' or 'cp'" -} - -variable "stage" { - type = string - description = "Stage, e.g. 'prod', 'staging', 'dev' or 'testing'" -} - -variable "name" { - type = string - description = "Solution name, e.g. 'app' or 'cluster'" -} - -variable "delimiter" { - type = string - default = "-" - description = "Delimiter to be used between `name`, `namespace`, `stage`, etc." -} - -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 "kubernetes_version" { type = string default = "1.17" diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf index ce2b5be8..62f1dd45 100644 --- a/examples/complete/versions.tf +++ b/examples/complete/versions.tf @@ -1,8 +1,8 @@ terraform { - required_version = ">= 0.12.0" + required_version = ">= 0.12.0, < 0.14.0" required_providers { - aws = "~> 2.0" + aws = ">= 2.0, < 4.0" template = "~> 2.0" null = "~> 2.0" local = "~> 1.3" diff --git a/iam.tf b/iam.tf index f0785f8b..f6886ea0 100644 --- a/iam.tf +++ b/iam.tf @@ -1,5 +1,5 @@ data "aws_iam_policy_document" "assume_role" { - count = var.enabled ? 1 : 0 + count = local.enabled ? 1 : 0 statement { effect = "Allow" @@ -13,20 +13,20 @@ data "aws_iam_policy_document" "assume_role" { } resource "aws_iam_role" "default" { - count = var.enabled ? 1 : 0 + count = local.enabled ? 1 : 0 name = module.label.id assume_role_policy = join("", data.aws_iam_policy_document.assume_role.*.json) tags = module.label.tags } resource "aws_iam_role_policy_attachment" "amazon_eks_cluster_policy" { - count = var.enabled ? 1 : 0 + count = local.enabled ? 1 : 0 policy_arn = format("arn:%s:iam::aws:policy/AmazonEKSClusterPolicy", join("", data.aws_partition.current.*.partition)) role = join("", aws_iam_role.default.*.name) } resource "aws_iam_role_policy_attachment" "amazon_eks_service_policy" { - count = var.enabled ? 1 : 0 + count = local.enabled ? 1 : 0 policy_arn = format("arn:%s:iam::aws:policy/AmazonEKSServicePolicy", join("", data.aws_partition.current.*.partition)) role = join("", aws_iam_role.default.*.name) } @@ -36,7 +36,7 @@ resource "aws_iam_role_policy_attachment" "amazon_eks_service_policy" { # Because of that, on a new AWS account (where load balancers have not been provisioned yet, `nginx-ingress` fails to provision a load balancer data "aws_iam_policy_document" "cluster_elb_service_role" { - count = var.enabled ? 1 : 0 + count = local.enabled ? 1 : 0 statement { effect = "Allow" @@ -52,7 +52,7 @@ data "aws_iam_policy_document" "cluster_elb_service_role" { } resource "aws_iam_role_policy" "cluster_elb_service_role" { - count = var.enabled ? 1 : 0 + count = local.enabled ? 1 : 0 name = module.label.id role = join("", aws_iam_role.default.*.name) policy = join("", data.aws_iam_policy_document.cluster_elb_service_role.*.json) diff --git a/main.tf b/main.tf index d9bc3d70..ad1dbc73 100644 --- a/main.tf +++ b/main.tf @@ -1,35 +1,37 @@ locals { + enabled = module.this.enabled + cluster_encryption_config = { resources = var.cluster_encryption_config_resources - provider_key_arn = var.enabled && var.cluster_encryption_config_enabled && var.cluster_encryption_config_kms_key_id == "" ? join("", aws_kms_key.cluster.*.arn) : var.cluster_encryption_config_kms_key_id + provider_key_arn = local.enabled && var.cluster_encryption_config_enabled && var.cluster_encryption_config_kms_key_id == "" ? join("", aws_kms_key.cluster.*.arn) : var.cluster_encryption_config_kms_key_id } } module "label" { - source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.17.0" - namespace = var.namespace - stage = var.stage - environment = var.environment - name = var.name - delimiter = var.delimiter - attributes = compact(concat(var.attributes, ["cluster"])) - tags = var.tags - enabled = var.enabled + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.19.2" + + # Using attributes = ["cluster"] would put "cluster" before any user-specified attributes. + # While that might be preferable (adding an attribute "blue" would create + # ...name-cluster-blue instead of ...name-blue-cluster), historically we forced "cluster" + # to the end of the attribute list, so we do it again here to maintain compatibility. + attributes = compact(concat(module.this.attributes, ["cluster"])) + + context = module.this.context } data "aws_partition" "current" { - count = var.enabled ? 1 : 0 + count = local.enabled ? 1 : 0 } resource "aws_cloudwatch_log_group" "default" { - count = var.enabled && length(var.enabled_cluster_log_types) > 0 ? 1 : 0 + count = local.enabled && length(var.enabled_cluster_log_types) > 0 ? 1 : 0 name = "/aws/eks/${module.label.id}/cluster" retention_in_days = var.cluster_log_retention_period tags = module.label.tags } resource "aws_kms_key" "cluster" { - count = var.enabled && var.cluster_encryption_config_enabled && var.cluster_encryption_config_kms_key_id == "" ? 1 : 0 + count = local.enabled && var.cluster_encryption_config_enabled && var.cluster_encryption_config_kms_key_id == "" ? 1 : 0 description = "EKS Cluster ${module.label.id} Encryption Config KMS Key" enable_key_rotation = var.cluster_encryption_config_kms_key_enable_key_rotation deletion_window_in_days = var.cluster_encryption_config_kms_key_deletion_window_in_days @@ -38,13 +40,13 @@ resource "aws_kms_key" "cluster" { } resource "aws_kms_alias" "cluster" { - count = var.enabled && var.cluster_encryption_config_enabled && var.cluster_encryption_config_kms_key_id == "" ? 1 : 0 + count = local.enabled && var.cluster_encryption_config_enabled && var.cluster_encryption_config_kms_key_id == "" ? 1 : 0 name = format("alias/%v", module.label.id) target_key_id = join("", aws_kms_key.cluster.*.key_id) } resource "aws_eks_cluster" "default" { - count = var.enabled ? 1 : 0 + count = local.enabled ? 1 : 0 name = module.label.id tags = module.label.tags role_arn = join("", aws_iam_role.default.*.arn) @@ -86,7 +88,7 @@ resource "aws_eks_cluster" "default" { # https://medium.com/@marcincuber/amazon-eks-with-oidc-provider-iam-roles-for-kubernetes-services-accounts-59015d15cb0c # resource "aws_iam_openid_connect_provider" "default" { - count = (var.enabled && var.oidc_provider_enabled) ? 1 : 0 + count = (local.enabled && var.oidc_provider_enabled) ? 1 : 0 url = join("", aws_eks_cluster.default.*.identity.0.oidc.0.issuer) client_id_list = ["sts.amazonaws.com"] diff --git a/sg.tf b/sg.tf index 6c57d35b..e16e7904 100644 --- a/sg.tf +++ b/sg.tf @@ -1,5 +1,5 @@ resource "aws_security_group" "default" { - count = var.enabled ? 1 : 0 + count = local.enabled ? 1 : 0 name = module.label.id description = "Security Group for EKS cluster" vpc_id = var.vpc_id @@ -7,7 +7,7 @@ resource "aws_security_group" "default" { } resource "aws_security_group_rule" "egress" { - count = var.enabled ? 1 : 0 + count = local.enabled ? 1 : 0 description = "Allow all egress traffic" from_port = 0 to_port = 0 @@ -18,7 +18,7 @@ resource "aws_security_group_rule" "egress" { } resource "aws_security_group_rule" "ingress_workers" { - count = var.enabled ? length(var.workers_security_group_ids) : 0 + count = local.enabled ? length(var.workers_security_group_ids) : 0 description = "Allow the cluster to receive communication from the worker nodes" from_port = 0 to_port = 65535 @@ -29,7 +29,7 @@ resource "aws_security_group_rule" "ingress_workers" { } resource "aws_security_group_rule" "ingress_security_groups" { - count = var.enabled ? length(var.allowed_security_groups) : 0 + count = local.enabled ? length(var.allowed_security_groups) : 0 description = "Allow inbound traffic from existing Security Groups" from_port = 0 to_port = 65535 @@ -40,7 +40,7 @@ resource "aws_security_group_rule" "ingress_security_groups" { } resource "aws_security_group_rule" "ingress_cidr_blocks" { - count = var.enabled && length(var.allowed_cidr_blocks) > 0 ? 1 : 0 + count = local.enabled && length(var.allowed_cidr_blocks) > 0 ? 1 : 0 description = "Allow inbound traffic from CIDR blocks" from_port = 0 to_port = 65535 diff --git a/variables.tf b/variables.tf index a4cb8cc8..b0b94d6d 100644 --- a/variables.tf +++ b/variables.tf @@ -1,51 +1,3 @@ -variable "namespace" { - type = string - default = "" - description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" -} - -variable "environment" { - type = string - default = "" - description = "Environment, e.g. 'prod', 'staging', 'dev', 'pre-prod', 'UAT'" -} - -variable "stage" { - type = string - default = "" - description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" -} - -variable "name" { - type = string - default = "" - description = "Solution name, e.g. 'app' or 'jenkins'" -} - -variable "enabled" { - type = bool - default = true - description = "Set to false to prevent the module from creating any resources" -} - -variable "delimiter" { - type = string - default = "-" - description = "Delimiter to be used between `namespace`, `environment`, `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 "region" { type = string description = "AWS Region" diff --git a/versions.tf b/versions.tf index 1738fd75..62f1dd45 100644 --- a/versions.tf +++ b/versions.tf @@ -2,7 +2,7 @@ terraform { required_version = ">= 0.12.0, < 0.14.0" required_providers { - aws = "~> 2.0" + aws = ">= 2.0, < 4.0" template = "~> 2.0" null = "~> 2.0" local = "~> 1.3"