diff --git a/.github/auto-release.yml b/.github/auto-release.yml
index 39a7f1e..b45efb7 100644
--- a/.github/auto-release.yml
+++ b/.github/auto-release.yml
@@ -17,6 +17,7 @@ version-resolver:
- 'bugfix'
- 'bug'
- 'hotfix'
+ - 'no-release'
default: 'minor'
categories:
@@ -46,7 +47,7 @@ template: |
replacers:
# Remove irrelevant information from Renovate bot
-- search: '/(?<=---\s+)+^#.*(Renovate configuration|Configuration)(?:.|\n)*?This PR has been generated .*/gm'
+- search: '/(?<=---\s)\s*^#.*(Renovate configuration|Configuration)(?:.|\n)*?This PR has been generated .*/gm'
replace: ''
# Remove Renovate bot banner image
- search: '/\[!\[[^\]]*Renovate\][^\]]*\](\([^)]*\))?\s*\n+/gm'
diff --git a/.github/renovate.json b/.github/renovate.json
index ae4f0aa..a780298 100644
--- a/.github/renovate.json
+++ b/.github/renovate.json
@@ -4,9 +4,9 @@
":preserveSemverRanges"
],
"labels": ["auto-update"],
+ "dependencyDashboardAutoclose": true,
"enabledManagers": ["terraform"],
"terraform": {
"ignorePaths": ["**/context.tf", "examples/**"]
}
}
-
diff --git a/.github/workflows/auto-context.yml b/.github/workflows/auto-context.yml
index ab979e0..665833a 100644
--- a/.github/workflows/auto-context.yml
+++ b/.github/workflows/auto-context.yml
@@ -35,7 +35,7 @@ jobs:
- name: Create Pull Request
if: steps.update.outputs.create_pull_request == 'true'
- uses: cloudposse/actions/github/create-pull-request@0.22.0
+ uses: cloudposse/actions/github/create-pull-request@0.30.0
with:
token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}
committer: 'cloudpossebot <11232728+cloudpossebot@users.noreply.github.com>'
diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml
index 375d0fd..c600d60 100644
--- a/.github/workflows/auto-format.yml
+++ b/.github/workflows/auto-format.yml
@@ -62,7 +62,7 @@ jobs:
fi
- name: Auto Test
- uses: cloudposse/actions/github/repository-dispatch@0.22.0
+ uses: cloudposse/actions/github/repository-dispatch@0.30.0
# match users by ID because logins (user names) are inconsistent,
# for example in the REST API Renovate Bot is `renovate[bot]` but
# in GraphQL it is just `renovate`, plus there is a non-bot
diff --git a/.github/workflows/auto-readme.yml b/.github/workflows/auto-readme.yml
new file mode 100644
index 0000000..6f25b8d
--- /dev/null
+++ b/.github/workflows/auto-readme.yml
@@ -0,0 +1,71 @@
+name: "auto-readme"
+on:
+ workflow_dispatch:
+
+ schedule:
+ # Example of job definition:
+ # .---------------- minute (0 - 59)
+ # | .------------- hour (0 - 23)
+ # | | .---------- day of month (1 - 31)
+ # | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
+ # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
+ # | | | | |
+ # * * * * * user-name command to be executed
+
+ # Update README.md nightly at 4am UTC
+ - cron: '0 4 * * *'
+
+jobs:
+ update:
+ if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Find default branch name
+ id: defaultBranch
+ shell: bash
+ env:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ run: |
+ default_branch=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name)
+ printf "::set-output name=defaultBranch::%s\n" "${default_branch}"
+ printf "defaultBranchRef.name=%s\n" "${default_branch}"
+
+ - name: Update readme
+ shell: bash
+ id: update
+ env:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ DEF: "${{ steps.defaultBranch.outputs.defaultBranch }}"
+ run: |
+ make init
+ make readme/build
+ # Ignore changes if they are only whitespace
+ if ! git diff --quiet README.md && git diff --ignore-all-space --ignore-blank-lines --quiet README.md; then
+ git restore README.md
+ echo Ignoring whitespace-only changes in README
+ fi
+
+ - name: Create Pull Request
+ # This action will not create or change a pull request if there are no changes to make.
+ # If a PR of the auto-update/readme branch is open, this action will just update it, not create a new PR.
+ uses: cloudposse/actions/github/create-pull-request@0.30.0
+ with:
+ token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}
+ commit-message: Update README.md and docs
+ title: Update README.md and docs
+ body: |-
+ ## what
+ This is an auto-generated PR that updates the README.md and docs
+
+ ## why
+ To have most recent changes of README.md and doc from origin templates
+
+ branch: auto-update/readme
+ base: ${{ steps.defaultBranch.outputs.defaultBranch }}
+ delete-branch: true
+ labels: |
+ auto-update
+ no-release
+ readme
diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml
index 1d06d9b..3a38fae 100644
--- a/.github/workflows/auto-release.yml
+++ b/.github/workflows/auto-release.yml
@@ -18,9 +18,8 @@ jobs:
github_token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}
# Drafts your next Release notes as Pull Requests are merged into "main"
- uses: release-drafter/release-drafter@v5
- if: "!contains(steps.get-merged-pull-request.outputs.labels, 'no-release')"
with:
- publish: true
+ publish: ${{ !contains(steps.get-merged-pull-request.outputs.labels, 'no-release') }}
prerelease: false
config-name: auto-release.yml
env:
diff --git a/.github/workflows/chatops.yml b/.github/workflows/chatops.yml
index 4ddc067..23f96d8 100644
--- a/.github/workflows/chatops.yml
+++ b/.github/workflows/chatops.yml
@@ -9,7 +9,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: "Handle common commands"
- uses: cloudposse/actions/github/slash-command-dispatch@0.22.0
+ uses: cloudposse/actions/github/slash-command-dispatch@0.30.0
with:
token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}
reaction-token: ${{ secrets.GITHUB_TOKEN }}
@@ -24,7 +24,7 @@ jobs:
- name: "Checkout commit"
uses: actions/checkout@v2
- name: "Run tests"
- uses: cloudposse/actions/github/slash-command-dispatch@0.22.0
+ uses: cloudposse/actions/github/slash-command-dispatch@0.30.0
with:
token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}
reaction-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/validate-codeowners.yml b/.github/workflows/validate-codeowners.yml
index c5193b6..70f829e 100644
--- a/.github/workflows/validate-codeowners.yml
+++ b/.github/workflows/validate-codeowners.yml
@@ -10,7 +10,7 @@ jobs:
steps:
- name: "Checkout source code at current commit"
uses: actions/checkout@v2
- - uses: mszostok/codeowners-validator@v0.5.0
+ - uses: mszostok/codeowners-validator@v0.7.1
if: github.event.pull_request.head.repo.full_name == github.repository
name: "Full check of CODEOWNERS"
with:
@@ -18,10 +18,12 @@ jobs:
# files so we can use the same CODEOWNERS file for Terraform and non-Terraform repos
# checks: "files,syntax,owners,duppatterns"
checks: "syntax,owners,duppatterns"
+ owner_checker_allow_unowned_patterns: "false"
# GitHub access token is required only if the `owners` check is enabled
github_access_token: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}"
- - uses: mszostok/codeowners-validator@v0.5.0
+ - uses: mszostok/codeowners-validator@v0.7.1
if: github.event.pull_request.head.repo.full_name != github.repository
name: "Syntax check of CODEOWNERS"
with:
checks: "syntax,duppatterns"
+ owner_checker_allow_unowned_patterns: "false"
diff --git a/README.md b/README.md
index af4641f..97f8c15 100644
--- a/README.md
+++ b/README.md
@@ -160,27 +160,7 @@ For a complete example, see [examples/complete](examples/complete)
cluster_name = var.cluster_name
cluster_endpoint = var.cluster_endpoint
cluster_certificate_authority_data = var.cluster_certificate_authority_data
-
- security_group_rules = [
- {
- type = "egress"
- from_port = 0
- to_port = 65535
- protocol = "-1"
- cidr_blocks = ["0.0.0.0/0"]
- source_security_group_id = null
- description = "Allow all outbound traffic"
- },
- {
- type = "ingress"
- from_port = 0
- to_port = 65535
- protocol = "-1"
- cidr_blocks = []
- source_security_group_id = "sg-XXXXXXXXX"
- description = "Allow all inbound traffic from Security Group ID of the EKS cluster"
- }
- ]
+ cluster_security_group_id = var.cluster_security_group_id
# Auto-scaling policies and CloudWatch metric alarms
autoscaling_policies_enabled = var.autoscaling_policies_enabled
@@ -226,10 +206,9 @@ Available targets:
| Name | Source | Version |
|------|--------|---------|
-| [autoscale\_group](#module\_autoscale\_group) | cloudposse/ec2-autoscale-group/aws | 0.27.0 |
-| [label](#module\_label) | cloudposse/label/null | 0.25.0 |
-| [security\_group](#module\_security\_group) | cloudposse/security-group/aws | 0.3.3 |
-| [this](#module\_this) | cloudposse/label/null | 0.25.0 |
+| [autoscale\_group](#module\_autoscale\_group) | cloudposse/ec2-autoscale-group/aws | 0.25.0 |
+| [label](#module\_label) | cloudposse/label/null | 0.24.1 |
+| [this](#module\_this) | cloudposse/label/null | 0.24.1 |
## Resources
@@ -241,6 +220,12 @@ Available targets:
| [aws_iam_role_policy_attachment.amazon_eks_cni_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.amazon_eks_worker_node_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.existing_policies_attach_to_eks_workers_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
+| [aws_security_group.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
+| [aws_security_group_rule.egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
+| [aws_security_group_rule.ingress_cidr_blocks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
+| [aws_security_group_rule.ingress_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
+| [aws_security_group_rule.ingress_security_groups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
+| [aws_security_group_rule.ingress_self](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_ami.eks_worker](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source |
| [aws_iam_instance_profile.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_instance_profile) | data source |
| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
@@ -250,10 +235,13 @@ Available targets:
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
-| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no |
+| [additional\_security\_group\_ids](#input\_additional\_security\_group\_ids) | Additional list of security groups that will be attached to the autoscaling group | `list(string)` | `[]` | no |
+| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no |
| [after\_cluster\_joining\_userdata](#input\_after\_cluster\_joining\_userdata) | Additional commands to execute on each worker node after joining the EKS cluster (after executing the `bootstrap.sh` script). For mot info, see https://kubedex.com/90-days-of-aws-eks-in-production | `string` | `""` | no |
+| [allowed\_cidr\_blocks](#input\_allowed\_cidr\_blocks) | List of CIDR blocks to be allowed to connect to the worker nodes | `list(string)` | `[]` | no |
+| [allowed\_security\_groups](#input\_allowed\_security\_groups) | List of Security Group IDs to be allowed to connect to the worker nodes | `list(string)` | `[]` | no |
| [associate\_public\_ip\_address](#input\_associate\_public\_ip\_address) | Associate a public IP address with an instance in a VPC | `bool` | `false` | no |
-| [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no |
+| [attributes](#input\_attributes) | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no |
| [autoscaling\_group\_tags](#input\_autoscaling\_group\_tags) | Additional tags only for the autoscaling group, e.g. "k8s.io/cluster-autoscaler/node-template/taint/dedicated" = "ci-cd:NoSchedule". | `map(string)` | `{}` | no |
| [autoscaling\_policies\_enabled](#input\_autoscaling\_policies\_enabled) | Whether to create `aws_autoscaling_policy` and `aws_cloudwatch_metric_alarm` resources to control Auto Scaling | `bool` | `true` | no |
| [aws\_iam\_instance\_profile\_name](#input\_aws\_iam\_instance\_profile\_name) | The name of the existing instance profile that will be used in autoscaling group for EKS workers. If empty will create a new instance profile. | `string` | `""` | no |
@@ -263,7 +251,9 @@ Available targets:
| [cluster\_certificate\_authority\_data](#input\_cluster\_certificate\_authority\_data) | The base64 encoded certificate data required to communicate with the cluster | `string` | n/a | yes |
| [cluster\_endpoint](#input\_cluster\_endpoint) | EKS cluster endpoint | `string` | n/a | yes |
| [cluster\_name](#input\_cluster\_name) | The name of the EKS cluster | `string` | n/a | yes |
-| [context](#input\_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. | `any` |
{| no | +| [cluster\_security\_group\_id](#input\_cluster\_security\_group\_id) | Security Group ID of the EKS cluster | `string` | n/a | yes | +| [cluster\_security\_group\_ingress\_enabled](#input\_cluster\_security\_group\_ingress\_enabled) | Whether to enable the EKS cluster Security Group as ingress to workers Security Group | `bool` | `true` | no | +| [context](#input\_context) | Single object for setting entire context at once.
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
{| no | | [cpu\_utilization\_high\_evaluation\_periods](#input\_cpu\_utilization\_high\_evaluation\_periods) | The number of periods over which data is compared to the specified threshold | `number` | `2` | no | | [cpu\_utilization\_high\_period\_seconds](#input\_cpu\_utilization\_high\_period\_seconds) | The period in seconds over which the specified statistic is applied | `number` | `300` | no | | [cpu\_utilization\_high\_statistic](#input\_cpu\_utilization\_high\_statistic) | The statistic to apply to the alarm's associated metric. Either of the following is supported: `SampleCount`, `Average`, `Sum`, `Minimum`, `Maximum` | `string` | `"Average"` | no | @@ -274,8 +264,7 @@ Available targets: | [cpu\_utilization\_low\_threshold\_percent](#input\_cpu\_utilization\_low\_threshold\_percent) | The value against which the specified statistic is compared | `number` | `10` | no | | [credit\_specification](#input\_credit\_specification) | Customize the credit specification of the instances |
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
object({| `null` | no | | [default\_cooldown](#input\_default\_cooldown) | The amount of time, in seconds, after a scaling activity completes before another scaling activity can start | `number` | `300` | no | -| [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
cpu_credits = string
})
[| no | -| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| [environment](#input\_environment) | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | | [force\_delete](#input\_force\_delete) | Allows deleting the autoscaling group without waiting for all instances in the pool to terminate. You can force an autoscaling group to delete even if it's in the process of scaling a resource. Normally, Terraform drains all the instances before deleting the group. This bypasses that behavior and potentially leaves resources dangling | `bool` | `false` | no | | [health\_check\_grace\_period](#input\_health\_check\_grace\_period) | Time (in seconds) after instance comes into service before checking health | `number` | `300` | no | | [health\_check\_type](#input\_health\_check\_type) | Controls how health checking is done. Valid values are `EC2` or `ELB` | `string` | `"EC2"` | no | -| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
"GroupMinSize",
"GroupMaxSize",
"GroupDesiredCapacity",
"GroupInServiceInstances",
"GroupPendingInstances",
"GroupStandbyInstances",
"GroupTerminatingInstances",
"GroupTotalInstances"
]
object({| `null` | no | | [instance\_type](#input\_instance\_type) | Instance type to launch | `string` | n/a | yes | | [key\_name](#input\_key\_name) | SSH key name that should be used for the instance | `string` | `""` | no | | [kubelet\_extra\_args](#input\_kubelet\_extra\_args) | Extra arguments to pass to kubelet, like "--register-with-taints=dedicated=ci-cd:NoSchedule --node-labels=purpose=ci-worker" | `string` | `""` | no | -| [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
market_type = string
spot_options = object({
block_duration_minutes = number
instance_interruption_behavior = string
max_price = number
spot_instance_type = string
valid_until = string
})
})
[| no | +| [label\_key\_case](#input\_label\_key\_case) | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
"default"
]
object({| `null` | no | -| [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
instances_distribution = object({
on_demand_allocation_strategy = string
on_demand_base_capacity = number
on_demand_percentage_above_base_capacity = number
spot_allocation_strategy = string
spot_instance_pools = number
spot_max_price = string
})
override = list(object({
instance_type = string
weighted_capacity = number
}))
})
object({| `null` | no | | [placement\_group](#input\_placement\_group) | The name of the placement group into which you'll launch your instances, if any | `string` | `""` | no | | [protect\_from\_scale\_in](#input\_protect\_from\_scale\_in) | Allows setting instance protection. The autoscaling group will not select instances with this setting for terminination during scale in events | `bool` | `false` | no | -| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
affinity = string
availability_zone = string
group_name = string
host_id = string
tenancy = string
})
[| no | -| [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Whether to create a default Security Group with unique name beginning with the normalized prefix. | `bool` | `false` | no | -| [security\_groups](#input\_security\_groups) | A list of Security Group IDs to associate with EKS worker nodes. | `list(string)` | `[]` | no | | [service\_linked\_role\_arn](#input\_service\_linked\_role\_arn) | The ARN of the service-linked role that the ASG will use to call other AWS services | `string` | `""` | no | -| [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | +| [stage](#input\_stage) | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs to launch resources in | `list(string)` | n/a | yes | | [suspended\_processes](#input\_suspended\_processes) | A list of processes to suspend for the AutoScaling Group. The allowed values are `Launch`, `Terminate`, `HealthCheck`, `ReplaceUnhealthy`, `AZRebalance`, `AlarmNotification`, `ScheduledActions`, `AddToLoadBalancer`. Note that if you suspend either the `Launch` or `Terminate` process types, it can prevent your autoscaling group from functioning properly. | `list(string)` | `[]` | no | -| [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
{
"cidr_blocks": [
"0.0.0.0/0"
],
"description": "Allow all outbound traffic",
"from_port": 0,
"protocol": "-1",
"to_port": 65535,
"type": "egress"
}
]
[| no | | [use\_custom\_image\_id](#input\_use\_custom\_image\_id) | If set to `true`, will use variable `image_id` for the EKS workers inside autoscaling group | `bool` | `false` | no | | [use\_existing\_aws\_iam\_instance\_profile](#input\_use\_existing\_aws\_iam\_instance\_profile) | If set to `true`, will use variable `aws_iam_instance_profile_name` to run EKS workers using an existing AWS instance profile that was created outside of this module, workaround for error like `count cannot be computed` | `bool` | `false` | no | +| [use\_existing\_security\_group](#input\_use\_existing\_security\_group) | If set to `true`, will use variable `workers_security_group_id` to run EKS workers using an existing security group that was created outside of this module, workaround for errors like `count cannot be computed` | `bool` | `false` | no | | [vpc\_id](#input\_vpc\_id) | VPC ID for the EKS cluster | `string` | n/a | yes | | [wait\_for\_capacity\_timeout](#input\_wait\_for\_capacity\_timeout) | A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. Setting this to '0' causes Terraform to skip all Capacity Waiting behavior | `string` | `"10m"` | no | | [wait\_for\_elb\_capacity](#input\_wait\_for\_elb\_capacity) | Setting this will cause Terraform to wait for exactly this number of healthy instances in all attached load balancers on both create and update operations. Takes precedence over `min_elb_capacity` behavior | `number` | `0` | no | | [workers\_role\_policy\_arns](#input\_workers\_role\_policy\_arns) | List of policy ARNs that will be attached to the workers default role on creation | `list(string)` | `[]` | no | | [workers\_role\_policy\_arns\_count](#input\_workers\_role\_policy\_arns\_count) | Count of policy ARNs that will be attached to the workers default role on creation. Needed to prevent Terraform error `count can't be computed` | `number` | `0` | no | +| [workers\_security\_group\_id](#input\_workers\_security\_group\_id) | The name of the existing security group that will be used in autoscaling group for EKS workers. If empty, a new security group will be created | `string` | `""` | no | ## Outputs @@ -520,8 +503,8 @@ Check out [our other projects][github], [follow us on twitter][twitter], [apply ### Contributors -| [![Erik Osterman][osterman_avatar]][osterman_homepage]
"Default"
]
{| no | +| [cluster\_security\_group\_id](#input\_cluster\_security\_group\_id) | Security Group ID of the EKS cluster | `string` | n/a | yes | +| [cluster\_security\_group\_ingress\_enabled](#input\_cluster\_security\_group\_ingress\_enabled) | Whether to enable the EKS cluster Security Group as ingress to workers Security Group | `bool` | `true` | no | +| [context](#input\_context) | Single object for setting entire context at once.
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
{| no | | [cpu\_utilization\_high\_evaluation\_periods](#input\_cpu\_utilization\_high\_evaluation\_periods) | The number of periods over which data is compared to the specified threshold | `number` | `2` | no | | [cpu\_utilization\_high\_period\_seconds](#input\_cpu\_utilization\_high\_period\_seconds) | The period in seconds over which the specified statistic is applied | `number` | `300` | no | | [cpu\_utilization\_high\_statistic](#input\_cpu\_utilization\_high\_statistic) | The statistic to apply to the alarm's associated metric. Either of the following is supported: `SampleCount`, `Average`, `Sum`, `Minimum`, `Maximum` | `string` | `"Average"` | no | @@ -66,8 +76,7 @@ | [cpu\_utilization\_low\_threshold\_percent](#input\_cpu\_utilization\_low\_threshold\_percent) | The value against which the specified statistic is compared | `number` | `10` | no | | [credit\_specification](#input\_credit\_specification) | Customize the credit specification of the instances |
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
object({| `null` | no | | [default\_cooldown](#input\_default\_cooldown) | The amount of time, in seconds, after a scaling activity completes before another scaling activity can start | `number` | `300` | no | -| [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
cpu_credits = string
})
[| no | -| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| [environment](#input\_environment) | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | | [force\_delete](#input\_force\_delete) | Allows deleting the autoscaling group without waiting for all instances in the pool to terminate. You can force an autoscaling group to delete even if it's in the process of scaling a resource. Normally, Terraform drains all the instances before deleting the group. This bypasses that behavior and potentially leaves resources dangling | `bool` | `false` | no | | [health\_check\_grace\_period](#input\_health\_check\_grace\_period) | Time (in seconds) after instance comes into service before checking health | `number` | `300` | no | | [health\_check\_type](#input\_health\_check\_type) | Controls how health checking is done. Valid values are `EC2` or `ELB` | `string` | `"EC2"` | no | -| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
"GroupMinSize",
"GroupMaxSize",
"GroupDesiredCapacity",
"GroupInServiceInstances",
"GroupPendingInstances",
"GroupStandbyInstances",
"GroupTerminatingInstances",
"GroupTotalInstances"
]
object({| `null` | no | | [instance\_type](#input\_instance\_type) | Instance type to launch | `string` | n/a | yes | | [key\_name](#input\_key\_name) | SSH key name that should be used for the instance | `string` | `""` | no | | [kubelet\_extra\_args](#input\_kubelet\_extra\_args) | Extra arguments to pass to kubelet, like "--register-with-taints=dedicated=ci-cd:NoSchedule --node-labels=purpose=ci-worker" | `string` | `""` | no | -| [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
market_type = string
spot_options = object({
block_duration_minutes = number
instance_interruption_behavior = string
max_price = number
spot_instance_type = string
valid_until = string
})
})
[| no | +| [label\_key\_case](#input\_label\_key\_case) | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
"default"
]
object({| `null` | no | -| [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
instances_distribution = object({
on_demand_allocation_strategy = string
on_demand_base_capacity = number
on_demand_percentage_above_base_capacity = number
spot_allocation_strategy = string
spot_instance_pools = number
spot_max_price = string
})
override = list(object({
instance_type = string
weighted_capacity = number
}))
})
object({| `null` | no | | [placement\_group](#input\_placement\_group) | The name of the placement group into which you'll launch your instances, if any | `string` | `""` | no | | [protect\_from\_scale\_in](#input\_protect\_from\_scale\_in) | Allows setting instance protection. The autoscaling group will not select instances with this setting for terminination during scale in events | `bool` | `false` | no | -| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
affinity = string
availability_zone = string
group_name = string
host_id = string
tenancy = string
})
[| no | -| [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Whether to create a default Security Group with unique name beginning with the normalized prefix. | `bool` | `false` | no | -| [security\_groups](#input\_security\_groups) | A list of Security Group IDs to associate with EKS worker nodes. | `list(string)` | `[]` | no | | [service\_linked\_role\_arn](#input\_service\_linked\_role\_arn) | The ARN of the service-linked role that the ASG will use to call other AWS services | `string` | `""` | no | -| [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | +| [stage](#input\_stage) | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs to launch resources in | `list(string)` | n/a | yes | | [suspended\_processes](#input\_suspended\_processes) | A list of processes to suspend for the AutoScaling Group. The allowed values are `Launch`, `Terminate`, `HealthCheck`, `ReplaceUnhealthy`, `AZRebalance`, `AlarmNotification`, `ScheduledActions`, `AddToLoadBalancer`. Note that if you suspend either the `Launch` or `Terminate` process types, it can prevent your autoscaling group from functioning properly. | `list(string)` | `[]` | no | -| [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
{
"cidr_blocks": [
"0.0.0.0/0"
],
"description": "Allow all outbound traffic",
"from_port": 0,
"protocol": "-1",
"to_port": 65535,
"type": "egress"
}
]
[| no | | [use\_custom\_image\_id](#input\_use\_custom\_image\_id) | If set to `true`, will use variable `image_id` for the EKS workers inside autoscaling group | `bool` | `false` | no | | [use\_existing\_aws\_iam\_instance\_profile](#input\_use\_existing\_aws\_iam\_instance\_profile) | If set to `true`, will use variable `aws_iam_instance_profile_name` to run EKS workers using an existing AWS instance profile that was created outside of this module, workaround for error like `count cannot be computed` | `bool` | `false` | no | +| [use\_existing\_security\_group](#input\_use\_existing\_security\_group) | If set to `true`, will use variable `workers_security_group_id` to run EKS workers using an existing security group that was created outside of this module, workaround for errors like `count cannot be computed` | `bool` | `false` | no | | [vpc\_id](#input\_vpc\_id) | VPC ID for the EKS cluster | `string` | n/a | yes | | [wait\_for\_capacity\_timeout](#input\_wait\_for\_capacity\_timeout) | A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. Setting this to '0' causes Terraform to skip all Capacity Waiting behavior | `string` | `"10m"` | no | | [wait\_for\_elb\_capacity](#input\_wait\_for\_elb\_capacity) | Setting this will cause Terraform to wait for exactly this number of healthy instances in all attached load balancers on both create and update operations. Takes precedence over `min_elb_capacity` behavior | `number` | `0` | no | | [workers\_role\_policy\_arns](#input\_workers\_role\_policy\_arns) | List of policy ARNs that will be attached to the workers default role on creation | `list(string)` | `[]` | no | | [workers\_role\_policy\_arns\_count](#input\_workers\_role\_policy\_arns\_count) | Count of policy ARNs that will be attached to the workers default role on creation. Needed to prevent Terraform error `count can't be computed` | `number` | `0` | no | +| [workers\_security\_group\_id](#input\_workers\_security\_group\_id) | The name of the existing security group that will be used in autoscaling group for EKS workers. If empty, a new security group will be created | `string` | `""` | no | ## Outputs diff --git a/examples/complete/context.tf b/examples/complete/context.tf index 5e0ef88..81f99b4 100644 --- a/examples/complete/context.tf +++ b/examples/complete/context.tf @@ -8,8 +8,6 @@ # Cloud Posse's standard configuration inputs suitable for passing # to Cloud Posse modules. # -# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf -# # 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`, @@ -22,11 +20,10 @@ module "this" { source = "cloudposse/label/null" - version = "0.25.0" # requires Terraform >= 0.13.0 + version = "0.24.1" # requires Terraform >= 0.13.0 enabled = var.enabled namespace = var.namespace - tenant = var.tenant environment = var.environment stage = var.stage name = var.name @@ -39,8 +36,6 @@ module "this" { id_length_limit = var.id_length_limit label_key_case = var.label_key_case label_value_case = var.label_value_case - descriptor_formats = var.descriptor_formats - labels_as_tags = var.labels_as_tags context = var.context } @@ -52,7 +47,6 @@ variable "context" { default = { enabled = true namespace = null - tenant = null environment = null stage = null name = null @@ -65,15 +59,6 @@ variable "context" { id_length_limit = null label_key_case = null label_value_case = null - descriptor_formats = {} - # Note: we have to use [] instead of null for unset lists due to - # https://github.com/hashicorp/terraform/issues/28137 - # which was not fixed until Terraform 1.0.0, - # but we want the default to be all the labels in `label_order` - # and we want users to be able to prevent all tag generation - # by setting `labels_as_tags` to `[]`, so we need - # a different sentinel to indicate "default" - labels_as_tags = ["unset"] } description = <<-EOT Single object for setting entire context at once. @@ -103,42 +88,32 @@ variable "enabled" { variable "namespace" { type = string default = null - description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" -} - -variable "tenant" { - type = string - default = null - description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" + description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" } variable "environment" { type = string default = null - description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" + description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'" } variable "stage" { type = string default = null - description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" + description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" } variable "name" { type = string default = null - description = <<-EOT - ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. - This is the only ID element not also included as a `tag`. - The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. - EOT + description = "Solution name, e.g. 'app' or 'jenkins'" } variable "delimiter" { type = string default = null description = <<-EOT - Delimiter to be used between ID elements. + Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`. Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. EOT } @@ -146,64 +121,36 @@ variable "delimiter" { variable "attributes" { type = list(string) default = [] - description = <<-EOT - ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, - in the order they appear in the list. New attributes are appended to the - end of the list. The elements of the list are joined by the `delimiter` - and treated as a single ID element. - EOT -} - -variable "labels_as_tags" { - type = set(string) - default = ["default"] - description = <<-EOT - Set of labels (ID elements) to include as tags in the `tags` output. - Default is to include all labels. - Tags with empty values will not be included in the `tags` output. - Set to `[]` to suppress all generated tags. - **Notes:** - The value of the `name` tag, if included, will be the `id`, not the `name`. - Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be - changed in later chained modules. Attempts to change it will be silently ignored. - EOT + description = "Additional attributes (e.g. `1`)" } variable "tags" { type = map(string) default = {} - description = <<-EOT - Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). - Neither the tag keys nor the tag values will be modified by this module. - EOT + description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`" } variable "additional_tag_map" { type = map(string) default = {} - description = <<-EOT - Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. - This is for some rare cases where resources want additional configuration of tags - and therefore take a list of maps with tag key, value, and additional configuration. - EOT + 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 order in which the labels (ID elements) appear in the `id`. + The naming order of the id output and Name tag. Defaults to ["namespace", "environment", "stage", "name", "attributes"]. - You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. - EOT + 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 - Terraform regular expression (regex) string. - Characters matching the regex will be removed from the ID elements. + 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 } @@ -214,7 +161,7 @@ variable "id_length_limit" { description = <<-EOT Limit `id` to this many characters (minimum 6). Set to `0` for unlimited length. - Set to `null` for keep the existing setting, which defaults to `0`. + Set to `null` for default, which is `0`. Does not affect `id_full`. EOT validation { @@ -227,8 +174,7 @@ variable "label_key_case" { type = string default = null description = <<-EOT - Controls the letter case of the `tags` keys (label names) for tags generated by this module. - Does not affect keys of tags passed in via the `tags` input. + The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`. Possible values: `lower`, `title`, `upper`. Default value: `title`. EOT @@ -243,11 +189,8 @@ variable "label_value_case" { type = string default = null description = <<-EOT - Controls the letter case of ID elements (labels) as included in `id`, - set as tag values, and output by this module individually. - Does not affect values of tags passed in via the `tags` input. + The letter case of output label values (also used in `tags` and `id`). Possible values: `lower`, `title`, `upper` and `none` (no transformation). - Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. Default value: `lower`. EOT @@ -256,24 +199,4 @@ variable "label_value_case" { error_message = "Allowed values: `lower`, `title`, `upper`, `none`." } } - -variable "descriptor_formats" { - type = any - default = {} - description = <<-EOT - Describe additional descriptors to be output in the `descriptors` output map. - Map of maps. Keys are names of descriptors. Values are maps of the form - `{ - format = string - labels = list(string) - }` - (Type is `any` so the map values can later be enhanced to provide additional options.) - `format` is a Terraform format string to be passed to the `format()` function. - `labels` is a list of labels, in order, to pass to `format()` function. - Label values will be normalized before being passed to `format()` so they will be - identical to how they appear in `id`. - Default is `{}` (`descriptors` output will be empty). - EOT -} - #### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars index 5782ed3..1f7c49e 100644 --- a/examples/complete/fixtures.us-east-2.tfvars +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -28,4 +28,6 @@ cluster_name = "eg-test-eks-workers-cluster" cluster_endpoint = "" -cluster_certificate_authority_data = "" \ No newline at end of file +cluster_certificate_authority_data = "" + +cluster_security_group_ingress_enabled = false diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 1ce97cf..7b8c8d8 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -37,39 +37,20 @@ module "subnets" { module "eks_workers" { source = "../../" - instance_type = var.instance_type - vpc_id = module.vpc.vpc_id - subnet_ids = module.subnets.public_subnet_ids - health_check_type = var.health_check_type - min_size = var.min_size - max_size = var.max_size - wait_for_capacity_timeout = var.wait_for_capacity_timeout - cluster_name = var.cluster_name - cluster_endpoint = var.cluster_endpoint - cluster_certificate_authority_data = var.cluster_certificate_authority_data - bootstrap_extra_args = "--use-max-pods false" - kubelet_extra_args = "--node-labels=purpose=ci-worker" - - security_group_rules = [ - { - type = "egress" - from_port = 0 - to_port = 65535 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - source_security_group_id = null - description = "Allow all outbound traffic" - }, - { - type = "ingress" - from_port = 0 - to_port = 65535 - protocol = "-1" - cidr_blocks = [] - source_security_group_id = module.vpc.vpc_default_security_group_id - description = "Allow all inbound traffic from trusted Security Groups" - }, - ] + instance_type = var.instance_type + vpc_id = module.vpc.vpc_id + subnet_ids = module.subnets.public_subnet_ids + health_check_type = var.health_check_type + min_size = var.min_size + max_size = var.max_size + wait_for_capacity_timeout = var.wait_for_capacity_timeout + cluster_name = var.cluster_name + cluster_endpoint = var.cluster_endpoint + cluster_certificate_authority_data = var.cluster_certificate_authority_data + cluster_security_group_id = var.cluster_security_group_id + cluster_security_group_ingress_enabled = var.cluster_security_group_ingress_enabled + bootstrap_extra_args = "--use-max-pods false" + kubelet_extra_args = "--node-labels=purpose=ci-worker" # Auto-scaling policies and CloudWatch metric alarms autoscaling_policies_enabled = var.autoscaling_policies_enabled diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index df9bd0e..d379991 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -24,6 +24,17 @@ variable "cluster_certificate_authority_data" { description = "The base64 encoded certificate data required to communicate with the cluster" } +variable "cluster_security_group_ingress_enabled" { + type = bool + description = "Whether to enable the EKS cluster Security Group as ingress to workers Security Group" +} + +variable "cluster_security_group_id" { + type = string + description = "Security Group ID of the EKS cluster" + default = "" +} + variable "instance_type" { type = string description = "Instance type to launch" diff --git a/main.tf b/main.tf index ce6c09d..ce118bf 100644 --- a/main.tf +++ b/main.tf @@ -4,14 +4,13 @@ locals { "kubernetes.io/cluster/${var.cluster_name}" = "owned" } - workers_role_arn = var.use_existing_aws_iam_instance_profile ? join("", data.aws_iam_instance_profile.default.*.role_arn) : join("", aws_iam_role.default.*.arn) - workers_role_name = var.use_existing_aws_iam_instance_profile ? join("", data.aws_iam_instance_profile.default.*.role_name) : join("", aws_iam_role.default.*.name) - security_group_enabled = module.this.enabled && var.security_group_enabled + workers_role_arn = var.use_existing_aws_iam_instance_profile ? join("", data.aws_iam_instance_profile.default.*.role_arn) : join("", aws_iam_role.default.*.arn) + workers_role_name = var.use_existing_aws_iam_instance_profile ? join("", data.aws_iam_instance_profile.default.*.role_name) : join("", aws_iam_role.default.*.name) } module "label" { source = "cloudposse/label/null" - version = "0.25.0" + version = "0.24.1" attributes = ["workers"] tags = local.tags @@ -34,11 +33,10 @@ data "aws_iam_policy_document" "assume_role" { } resource "aws_iam_role" "default" { - count = local.enabled && var.use_existing_aws_iam_instance_profile == false ? 1 : 0 - name = module.label.id - assume_role_policy = join("", data.aws_iam_policy_document.assume_role.*.json) - tags = module.label.tags - permissions_boundary = var.permissions_boundary + count = local.enabled && var.use_existing_aws_iam_instance_profile == false ? 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_worker_node_policy" { @@ -71,17 +69,67 @@ resource "aws_iam_instance_profile" "default" { role = join("", aws_iam_role.default.*.name) } -module "security_group" { - source = "cloudposse/security-group/aws" - version = "0.3.3" +resource "aws_security_group" "default" { + count = local.enabled && var.use_existing_security_group == false ? 1 : 0 + name = module.label.id + description = "Security Group for EKS worker nodes" + vpc_id = var.vpc_id + tags = module.label.tags +} + +resource "aws_security_group_rule" "egress" { + count = local.enabled && var.use_existing_security_group == false ? 1 : 0 + description = "Allow all egress traffic" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + security_group_id = join("", aws_security_group.default.*.id) + type = "egress" +} + +resource "aws_security_group_rule" "ingress_self" { + count = local.enabled && var.use_existing_security_group == false ? 1 : 0 + description = "Allow nodes to communicate with each other" + from_port = 0 + to_port = 65535 + protocol = "-1" + security_group_id = join("", aws_security_group.default.*.id) + source_security_group_id = join("", aws_security_group.default.*.id) + type = "ingress" +} - use_name_prefix = var.security_group_use_name_prefix - rules = var.security_group_rules - description = var.security_group_description - vpc_id = var.vpc_id +resource "aws_security_group_rule" "ingress_cluster" { + count = local.enabled && var.cluster_security_group_ingress_enabled && var.use_existing_security_group == false ? 1 : 0 + description = "Allow worker kubelets and pods to receive communication from the cluster control plane" + from_port = 0 + to_port = 65535 + protocol = "-1" + security_group_id = join("", aws_security_group.default.*.id) + source_security_group_id = var.cluster_security_group_id + type = "ingress" +} - enabled = local.security_group_enabled - context = module.label.context +resource "aws_security_group_rule" "ingress_security_groups" { + count = local.enabled && var.use_existing_security_group == false ? length(var.allowed_security_groups) : 0 + description = "Allow inbound traffic from existing Security Groups" + from_port = 0 + to_port = 65535 + protocol = "-1" + source_security_group_id = var.allowed_security_groups[count.index] + security_group_id = join("", aws_security_group.default.*.id) + type = "ingress" +} + +resource "aws_security_group_rule" "ingress_cidr_blocks" { + count = local.enabled && length(var.allowed_cidr_blocks) > 0 && var.use_existing_security_group == false ? 1 : 0 + description = "Allow inbound traffic from CIDR blocks" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = var.allowed_cidr_blocks + security_group_id = join("", aws_security_group.default.*.id) + type = "ingress" } data "aws_ami" "eks_worker" { @@ -120,7 +168,7 @@ data "aws_iam_instance_profile" "default" { module "autoscale_group" { source = "cloudposse/ec2-autoscale-group/aws" - version = "0.27.0" + version = "0.25.0" enabled = local.enabled tags = merge(local.tags, var.autoscaling_group_tags) @@ -128,7 +176,14 @@ module "autoscale_group" { image_id = var.use_custom_image_id ? var.image_id : join("", data.aws_ami.eks_worker.*.id) iam_instance_profile_name = var.use_existing_aws_iam_instance_profile == false ? join("", aws_iam_instance_profile.default.*.name) : var.aws_iam_instance_profile_name - security_group_ids = compact(concat(module.security_group.*.id, var.security_groups)) + security_group_ids = compact( + concat( + [ + var.use_existing_security_group == false ? join("", aws_security_group.default.*.id) : var.workers_security_group_id + ], + var.additional_security_group_ids + ) + ) user_data_base64 = base64encode(join("", data.template_file.userdata.*.rendered)) diff --git a/outputs.tf b/outputs.tf index c5e5543..35d52ae 100644 --- a/outputs.tf +++ b/outputs.tf @@ -60,17 +60,17 @@ output "autoscaling_group_health_check_type" { output "security_group_id" { description = "ID of the worker nodes Security Group" - value = module.security_group.id + value = join("", aws_security_group.default.*.id) } output "security_group_arn" { description = "ARN of the worker nodes Security Group" - value = module.security_group.arn + value = join("", aws_security_group.default.*.arn) } output "security_group_name" { description = "Name of the worker nodes Security Group" - value = module.security_group.name + value = join("", aws_security_group.default.*.name) } output "workers_role_arn" { diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go index 9f3354b..1f76e27 100644 --- a/test/src/examples_complete_test.go +++ b/test/src/examples_complete_test.go @@ -60,16 +60,16 @@ func TestExamplesComplete(t *testing.T) { // autoscaling_group_name = eg-test-suite-20210416185727403200000006 autoscalingGroupName := terraform.Output(t, terraformOptions, "autoscaling_group_name") // Verify we're getting back the outputs we expect - assert.Regexp(t, regexp.MustCompile(`^`+expectedPrefix+`-\d+$`), autoscalingGroupName, "Autoscaling Group name should be our expected prefix plus a random suffix") + assert.Regexp(t, regexp.MustCompile(`^` + expectedPrefix + `-\d+$`) , autoscalingGroupName, "Autoscaling Group name should be our expected prefix plus a random suffix") // Run `terraform output` to get the value of an output variable var tags []TerraformMapString terraform.OutputStruct(t, terraformOptions, "autoscaling_group_tags", &tags) expectedTag := TerraformMapString{ - "key": "Name", - "value": expectedPrefix, - "propagate_at_launch": "true", + "key": "Name", + "value": expectedPrefix, + "propagate_at_launch": "true", } assert.Contains(t, tags, expectedTag, `Tag "Name" should match eks-workers module ID`) @@ -88,25 +88,15 @@ func TestExamplesComplete(t *testing.T) { launchTemplateId := terraform.Output(t, terraformOptions, "launch_template_id") // Verify we're getting back the outputs we expect // arn:aws:ec2:us-east-2:126450723953:launch-template/ - assert.Equal(t, "arn:aws:ec2:us-east-2:126450723953:launch-template/"+launchTemplateId, launchTemplateArn) + assert.Equal(t, "arn:aws:ec2:us-east-2:126450723953:launch-template/" + launchTemplateId, launchTemplateArn) // Run `terraform output` to get the value of an output variable securityGroupName := terraform.Output(t, terraformOptions, "security_group_name") // Verify we're getting back the outputs we expect - assert.Equal(t, expectedPrefix+"-workers", securityGroupName) - - // Run `terraform output` to get the value of an output variable - securityGroupID := terraform.Output(t, terraformOptions, "security_group_id") - // Verify we're getting back the outputs we expect - assert.Contains(t, securityGroupID, "sg-", "SG ID should contains substring 'sg-'") - - // Run `terraform output` to get the value of an output variable - securityGroupARN := terraform.Output(t, terraformOptions, "security_group_arn") - // Verify we're getting back the outputs we expect - assert.Contains(t, securityGroupARN, "arn:aws:ec2", "SG ID should contains substring 'arn:aws:ec2'") + assert.Equal(t, expectedPrefix + "-workers", securityGroupName) // Run `terraform output` to get the value of an output variable workerRoleName := terraform.Output(t, terraformOptions, "workers_role_name") // Verify we're getting back the outputs we expect - assert.Equal(t, expectedPrefix+"-workers", workerRoleName) + assert.Equal(t, expectedPrefix + "-workers", workerRoleName) } diff --git a/variables.tf b/variables.tf index 089629e..8af6178 100644 --- a/variables.tf +++ b/variables.tf @@ -13,52 +13,32 @@ variable "cluster_certificate_authority_data" { description = "The base64 encoded certificate data required to communicate with the cluster" } -variable "vpc_id" { - type = string - description = "VPC ID for the EKS cluster" -} - -variable "security_group_enabled" { +variable "cluster_security_group_ingress_enabled" { type = bool - description = "Whether to create default Security Group for EKS worker nodes." + description = "Whether to enable the EKS cluster Security Group as ingress to workers Security Group" default = true } -variable "security_group_description" { +variable "cluster_security_group_id" { type = string - default = "Security Group for EKS worker nodes" - description = "The Security Group description." + description = "Security Group ID of the EKS cluster" } -variable "security_group_use_name_prefix" { - type = bool - default = false - description = "Whether to create a default Security Group with unique name beginning with the normalized prefix." +variable "vpc_id" { + type = string + description = "VPC ID for the EKS cluster" } -variable "security_group_rules" { - type = list(any) - default = [ - { - type = "egress" - from_port = 0 - to_port = 65535 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - description = "Allow all outbound traffic" - } - ] - description = <<-EOT - A list of maps of Security Group rules. - The values of map is fully complated with `aws_security_group_rule` resource. - To get more info see https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule . - EOT +variable "allowed_security_groups" { + type = list(string) + default = [] + description = "List of Security Group IDs to be allowed to connect to the worker nodes" } -variable "security_groups" { +variable "allowed_cidr_blocks" { type = list(string) default = [] - description = "A list of Security Group IDs to associate with EKS worker nodes." + description = "List of CIDR blocks to be allowed to connect to the worker nodes" } variable "metadata_http_endpoint_enabled" { @@ -407,16 +387,28 @@ variable "aws_iam_instance_profile_name" { description = "The name of the existing instance profile that will be used in autoscaling group for EKS workers. If empty will create a new instance profile." } -variable "use_existing_aws_iam_instance_profile" { +variable "workers_security_group_id" { + type = string + default = "" + description = "The name of the existing security group that will be used in autoscaling group for EKS workers. If empty, a new security group will be created" +} + +variable "use_existing_security_group" { type = bool - description = "If set to `true`, will use variable `aws_iam_instance_profile_name` to run EKS workers using an existing AWS instance profile that was created outside of this module, workaround for error like `count cannot be computed`" + description = "If set to `true`, will use variable `workers_security_group_id` to run EKS workers using an existing security group that was created outside of this module, workaround for errors like `count cannot be computed`" default = false } -variable "permissions_boundary" { - type = string - description = "Provide an existing permissions boundary to attach to the default role" - default = null +variable "additional_security_group_ids" { + type = list(string) + default = [] + description = "Additional list of security groups that will be attached to the autoscaling group" +} + +variable "use_existing_aws_iam_instance_profile" { + type = bool + description = "If set to `true`, will use variable `aws_iam_instance_profile_name` to run EKS workers using an existing AWS instance profile that was created outside of this module, workaround for error like `count cannot be computed`" + default = false } variable "workers_role_policy_arns" {
"Default"
]