Skip to content

Commit 6ccf1a9

Browse files
aknyshNuru
andauthored
Add force_update_version and replace_node_group_on_version_update variables (#151)
* Add `force_update_version` and `include_kubernetes_version_in_keepers` variables * Add `force_update_version` and `include_kubernetes_version_in_keepers` variables * Add `force_update_version` and `include_kubernetes_version_in_keepers` variables * Add `force_update_version` and `include_kubernetes_version_in_keepers` variables * Add `force_update_version` and `replace_node_group_on_version_update` variables * Update variables.tf Co-authored-by: Nuru <[email protected]> * Update variables.tf Co-authored-by: Nuru <[email protected]> * Add `force_update_version` and `replace_node_group_on_version_update` variables --------- Co-authored-by: Nuru <[email protected]>
1 parent 80e8786 commit 6ccf1a9

File tree

9 files changed

+87
-45
lines changed

9 files changed

+87
-45
lines changed

.github/renovate.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
{
22
"extends": [
33
"config:base",
4-
":preserveSemverRanges"
4+
":preserveSemverRanges",
5+
":rebaseStalePrs"
56
],
6-
"baseBranches": ["main", "master", "/^release\\/v\\d{1,2}$/"],
7+
"baseBranches": ["main"],
78
"labels": ["auto-update"],
89
"dependencyDashboardAutoclose": true,
910
"enabledManagers": ["terraform"],
1011
"terraform": {
11-
"ignorePaths": ["**/context.tf", "examples/**"]
12+
"ignorePaths": ["**/context.tf"]
1213
}
1314
}

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
same "printed page" as the copyright notice for easier
187187
identification within third-party archives.
188188

189-
Copyright 2019-2022 Cloud Posse, LLC
189+
Copyright 2019-2023 Cloud Posse, LLC
190190

191191
Licensed under the Apache License, Version 2.0 (the "License");
192192
you may not use this file except in compliance with the License.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ https://docs.aws.amazon.com/eks/latest/userguide/windows-support.html
351351
| <a name="input_enabled"></a> [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no |
352352
| <a name="input_enclave_enabled"></a> [enclave\_enabled](#input\_enclave\_enabled) | Set to `true` to enable Nitro Enclaves on the instance. | `bool` | `false` | no |
353353
| <a name="input_environment"></a> [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no |
354+
| <a name="input_force_update_version"></a> [force\_update\_version](#input\_force\_update\_version) | When updating the Kubernetes version, force Pods to be removed even if PodDisruptionBudget or taint/toleration issues would otherwise prevent them from being removed (and cause the update to fail) | `bool` | `false` | no |
354355
| <a name="input_id_length_limit"></a> [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).<br>Set to `0` for unlimited length.<br>Set to `null` for keep the existing setting, which defaults to `0`.<br>Does not affect `id_full`. | `number` | `null` | no |
355356
| <a name="input_instance_types"></a> [instance\_types](#input\_instance\_types) | Instance types to use for this node group (up to 20). Defaults to ["t3.medium"].<br>Must be empty if the launch template configured by `launch_template_id` specifies an instance type. | `list(string)` | <pre>[<br> "t3.medium"<br>]</pre> | no |
356357
| <a name="input_kubelet_additional_options"></a> [kubelet\_additional\_options](#input\_kubelet\_additional\_options) | Additional flags to pass to kubelet.<br>DO NOT include `--node-labels` or `--node-taints`,<br>use `kubernetes_labels` and `kubernetes_taints` to specify those." | `list(string)` | `[]` | no |
@@ -378,6 +379,7 @@ https://docs.aws.amazon.com/eks/latest/userguide/windows-support.html
378379
| <a name="input_node_role_policy_arns"></a> [node\_role\_policy\_arns](#input\_node\_role\_policy\_arns) | List of policy ARNs to attach to the worker role this module creates in addition to the default ones | `list(string)` | `[]` | no |
379380
| <a name="input_placement"></a> [placement](#input\_placement) | Configuration for the [`placement` Configuration Block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template#placement) of the launch template.<br>Leave list empty for defaults. Pass list with single object with attributes matching the `placement` block to configure it.<br>Note that this configures the launch template only. Some elements will be ignored by the Auto Scaling Group<br>that actually launches instances. Consult AWS documentation for details. | `list(any)` | `[]` | no |
380381
| <a name="input_regex_replace_chars"></a> [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.<br>Characters matching the regex will be removed from the ID elements.<br>If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
382+
| <a name="input_replace_node_group_on_version_update"></a> [replace\_node\_group\_on\_version\_update](#input\_replace\_node\_group\_on\_version\_update) | Force Node Group replacement when updating to a new Kubernetes version. If set to `false` (the default), the Node Groups will be updated in-place | `bool` | `false` | no |
381383
| <a name="input_resources_to_tag"></a> [resources\_to\_tag](#input\_resources\_to\_tag) | List of auto-launched resource types to tag. Valid types are "instance", "volume", "elastic-gpu", "spot-instances-request", "network-interface". | `list(string)` | <pre>[<br> "instance",<br> "volume",<br> "network-interface"<br>]</pre> | no |
382384
| <a name="input_ssh_access_security_group_ids"></a> [ssh\_access\_security\_group\_ids](#input\_ssh\_access\_security\_group\_ids) | Set of EC2 Security Group IDs to allow SSH access (port 22) to the worker nodes. If you specify `ec2_ssh_key`, but do not specify this configuration when you create an EKS Node Group, port 22 on the worker nodes is opened to the Internet (0.0.0.0/0) | `list(string)` | `[]` | no |
383385
| <a name="input_stage"></a> [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |

docs/terraform.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
| <a name="input_enabled"></a> [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no |
7575
| <a name="input_enclave_enabled"></a> [enclave\_enabled](#input\_enclave\_enabled) | Set to `true` to enable Nitro Enclaves on the instance. | `bool` | `false` | no |
7676
| <a name="input_environment"></a> [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no |
77+
| <a name="input_force_update_version"></a> [force\_update\_version](#input\_force\_update\_version) | When updating the Kubernetes version, force Pods to be removed even if PodDisruptionBudget or taint/toleration issues would otherwise prevent them from being removed (and cause the update to fail) | `bool` | `false` | no |
7778
| <a name="input_id_length_limit"></a> [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).<br>Set to `0` for unlimited length.<br>Set to `null` for keep the existing setting, which defaults to `0`.<br>Does not affect `id_full`. | `number` | `null` | no |
7879
| <a name="input_instance_types"></a> [instance\_types](#input\_instance\_types) | Instance types to use for this node group (up to 20). Defaults to ["t3.medium"].<br>Must be empty if the launch template configured by `launch_template_id` specifies an instance type. | `list(string)` | <pre>[<br> "t3.medium"<br>]</pre> | no |
7980
| <a name="input_kubelet_additional_options"></a> [kubelet\_additional\_options](#input\_kubelet\_additional\_options) | Additional flags to pass to kubelet.<br>DO NOT include `--node-labels` or `--node-taints`,<br>use `kubernetes_labels` and `kubernetes_taints` to specify those." | `list(string)` | `[]` | no |
@@ -101,6 +102,7 @@
101102
| <a name="input_node_role_policy_arns"></a> [node\_role\_policy\_arns](#input\_node\_role\_policy\_arns) | List of policy ARNs to attach to the worker role this module creates in addition to the default ones | `list(string)` | `[]` | no |
102103
| <a name="input_placement"></a> [placement](#input\_placement) | Configuration for the [`placement` Configuration Block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template#placement) of the launch template.<br>Leave list empty for defaults. Pass list with single object with attributes matching the `placement` block to configure it.<br>Note that this configures the launch template only. Some elements will be ignored by the Auto Scaling Group<br>that actually launches instances. Consult AWS documentation for details. | `list(any)` | `[]` | no |
103104
| <a name="input_regex_replace_chars"></a> [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.<br>Characters matching the regex will be removed from the ID elements.<br>If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
105+
| <a name="input_replace_node_group_on_version_update"></a> [replace\_node\_group\_on\_version\_update](#input\_replace\_node\_group\_on\_version\_update) | Force Node Group replacement when updating to a new Kubernetes version. If set to `false` (the default), the Node Groups will be updated in-place | `bool` | `false` | no |
104106
| <a name="input_resources_to_tag"></a> [resources\_to\_tag](#input\_resources\_to\_tag) | List of auto-launched resource types to tag. Valid types are "instance", "volume", "elastic-gpu", "spot-instances-request", "network-interface". | `list(string)` | <pre>[<br> "instance",<br> "volume",<br> "network-interface"<br>]</pre> | no |
105107
| <a name="input_ssh_access_security_group_ids"></a> [ssh\_access\_security\_group\_ids](#input\_ssh\_access\_security\_group\_ids) | Set of EC2 Security Group IDs to allow SSH access (port 22) to the worker nodes. If you specify `ec2_ssh_key`, but do not specify this configuration when you create an EKS Node Group, port 22 on the worker nodes is opened to the Internet (0.0.0.0/0) | `list(string)` | `[]` | no |
106108
| <a name="input_stage"></a> [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |

examples/complete/main.tf

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ module "https_sg" {
101101

102102
module "eks_cluster" {
103103
source = "cloudposse/eks-cluster/aws"
104-
version = "2.4.0"
104+
version = "2.9.0"
105105
region = var.region
106106
vpc_id = module.vpc.vpc_id
107107
subnet_ids = module.subnets.public_subnet_ids
@@ -122,7 +122,7 @@ module "eks_node_group" {
122122
source = "../../"
123123

124124
subnet_ids = module.this.enabled ? module.subnets.public_subnet_ids : ["filler_string_for_enabled_is_false"]
125-
cluster_name = module.eks_cluster.eks_cluster_id
125+
cluster_name = module.this.enabled ? module.eks_cluster.eks_cluster_id : "disabled"
126126
instance_types = var.instance_types
127127
desired_size = var.desired_size
128128
min_size = var.min_size
@@ -141,7 +141,6 @@ module "eks_node_group" {
141141
delete_on_termination = true
142142
}]
143143

144-
145144
ec2_ssh_key_name = var.ec2_ssh_key_name
146145
ssh_access_security_group_ids = [module.ssh_source_access.id]
147146
associated_security_group_ids = [module.ssh_source_access.id, module.https_sg.id]
@@ -155,17 +154,20 @@ module "eks_node_group" {
155154

156155
before_cluster_joining_userdata = [var.before_cluster_joining_userdata]
157156

158-
context = module.this.context
159-
160157
# Ensure ordering of resource creation to eliminate the race conditions when applying the Kubernetes Auth ConfigMap.
161158
# Do not create Node Group before the EKS cluster is created and the `aws-auth` Kubernetes ConfigMap is applied.
162159
depends_on = [module.eks_cluster, module.eks_cluster.kubernetes_config_map_id]
163160

164161
create_before_destroy = true
165162

163+
force_update_version = var.force_update_version
164+
replace_node_group_on_version_update = var.replace_node_group_on_version_update
165+
166166
node_group_terraform_timeouts = [{
167167
create = "40m"
168168
update = null
169169
delete = "20m"
170170
}]
171+
172+
context = module.this.context
171173
}

examples/complete/variables.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,15 @@ variable "after_cluster_joining_userdata" {
151151
error_message = "You may not specify more than one `after_cluster_joining_userdata`."
152152
}
153153
}
154+
155+
variable "force_update_version" {
156+
type = bool
157+
default = false
158+
description = "When updating the Kubernetes version, force Pods to be removed even if PodDisruptionBudget or taint/toleration issues would otherwise prevent them from being removed (and cause the update to fail)"
159+
}
160+
161+
variable "replace_node_group_on_version_update" {
162+
type = bool
163+
default = false
164+
description = "Force Node Group replacement when updating to a new Kubernetes version. If set to `false` (the default), the Node Groups will be updated in-place"
165+
}

main.tf

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ locals {
9797
max_size = var.max_size
9898
min_size = var.min_size
9999
}
100+
101+
force_update_version = var.force_update_version
100102
}
101103
}
102104

@@ -106,15 +108,21 @@ resource "random_pet" "cbd" {
106108
separator = module.label.delimiter
107109
length = 1
108110

109-
keepers = {
110-
node_role_arn = local.ng.node_role_arn
111-
subnet_ids = join(",", local.ng.subnet_ids)
112-
instance_types = join(",", local.ng.instance_types)
113-
ami_type = local.ng.ami_type
114-
capacity_type = local.ng.capacity_type
115-
116-
launch_template_id = local.launch_template_id
117-
}
111+
keepers = merge(
112+
{
113+
node_role_arn = local.ng.node_role_arn
114+
subnet_ids = join(",", local.ng.subnet_ids)
115+
instance_types = join(",", local.ng.instance_types)
116+
ami_type = local.ng.ami_type
117+
capacity_type = local.ng.capacity_type
118+
launch_template_id = local.launch_template_id
119+
},
120+
# If `var.replace_node_group_on_version_update` is set to `true`, the Node Groups will be replaced instead of updated in-place
121+
var.replace_node_group_on_version_update && local.ng.version != null ?
122+
{
123+
version = local.ng.version
124+
} : {}
125+
)
118126
}
119127

120128
# Because create_before_destroy is such a dramatic change, we want to make it optional.
@@ -134,14 +142,15 @@ resource "aws_eks_node_group" "default" {
134142
}
135143

136144
# From here to end of resource should be identical in both node groups
137-
cluster_name = local.ng.cluster_name
138-
node_role_arn = local.ng.node_role_arn
139-
subnet_ids = local.ng.subnet_ids
140-
instance_types = local.ng.instance_types
141-
ami_type = local.ng.ami_type
142-
labels = local.ng.labels
143-
release_version = local.ng.release_version
144-
version = local.ng.version
145+
cluster_name = local.ng.cluster_name
146+
node_role_arn = local.ng.node_role_arn
147+
subnet_ids = local.ng.subnet_ids
148+
instance_types = local.ng.instance_types
149+
ami_type = local.ng.ami_type
150+
labels = local.ng.labels
151+
release_version = local.ng.release_version
152+
version = local.ng.version
153+
force_update_version = local.ng.force_update_version
145154

146155
capacity_type = local.ng.capacity_type
147156

@@ -213,14 +222,15 @@ resource "aws_eks_node_group" "cbd" {
213222
}
214223

215224
# From here to end of resource should be identical in both node groups
216-
cluster_name = local.ng.cluster_name
217-
node_role_arn = local.ng.node_role_arn
218-
subnet_ids = local.ng.subnet_ids
219-
instance_types = local.ng.instance_types
220-
ami_type = local.ng.ami_type
221-
labels = local.ng.labels
222-
release_version = local.ng.release_version
223-
version = local.ng.version
225+
cluster_name = local.ng.cluster_name
226+
node_role_arn = local.ng.node_role_arn
227+
subnet_ids = local.ng.subnet_ids
228+
instance_types = local.ng.instance_types
229+
ami_type = local.ng.ami_type
230+
labels = local.ng.labels
231+
release_version = local.ng.release_version
232+
version = local.ng.version
233+
force_update_version = local.ng.force_update_version
224234

225235
capacity_type = local.ng.capacity_type
226236

test/src/examples_complete_test.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import (
44
"encoding/base64"
55
"fmt"
66
"os"
7+
"regexp"
78
"strings"
89
"sync/atomic"
910
"testing"
1011
"time"
1112

1213
"github.com/gruntwork-io/terratest/modules/random"
1314
"github.com/gruntwork-io/terratest/modules/terraform"
14-
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
15+
testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
1516
"github.com/stretchr/testify/assert"
1617

1718
corev1 "k8s.io/api/core/v1"
@@ -59,7 +60,7 @@ func newClientset(cluster *eks.Cluster) (*kubernetes.Clientset, error) {
5960

6061
func cleanup(t *testing.T, terraformOptions *terraform.Options, tempTestFolder string) {
6162
terraform.Destroy(t, terraformOptions)
62-
os.RemoveAll(tempTestFolder)
63+
_ = os.RemoveAll(tempTestFolder)
6364
}
6465

6566
// Test the Terraform module in examples/complete using Terratest.
@@ -72,7 +73,7 @@ func TestExamplesComplete(t *testing.T) {
7273
terraformFolderRelativeToRoot := "examples/complete"
7374
varFiles := []string{"fixtures.us-east-2.tfvars"}
7475

75-
tempTestFolder := test_structure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
76+
tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
7677

7778
terraformOptions := &terraform.Options{
7879
// The path to where our Terraform code is located
@@ -193,7 +194,7 @@ func TestExamplesCompleteDisabled(t *testing.T) {
193194
terraformFolderRelativeToRoot := "examples/complete"
194195
varFiles := []string{"fixtures.us-east-2.tfvars"}
195196

196-
tempTestFolder := test_structure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
197+
tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
197198

198199
terraformOptions := &terraform.Options{
199200
// The path to where our Terraform code is located
@@ -203,19 +204,19 @@ func TestExamplesCompleteDisabled(t *testing.T) {
203204
VarFiles: varFiles,
204205
Vars: map[string]interface{}{
205206
"attributes": attributes,
206-
"enabled": "false",
207+
"enabled": false,
207208
},
208209
}
209210

210211
// At the end of the test, run `terraform destroy` to clean up any resources that were created
211212
defer cleanup(t, terraformOptions, tempTestFolder)
212213

213214
// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
214-
terraform.InitAndApply(t, terraformOptions)
215-
216-
// Get all the output and lookup a field. Pass if the field is missing or empty.
217-
example := terraform.OutputAll(t, terraformOptions)["eks_node_group_arn"]
215+
results := terraform.InitAndApply(t, terraformOptions)
218216

219-
// Verify we're getting back the outputs we expect
220-
assert.Empty(t, example, "When disabled, module should have no outputs.")
217+
// Should complete successfully without creating or changing any resources.
218+
// Extract the "Resources:" section of the output to make the error message more readable.
219+
re := regexp.MustCompile(`Resources: [^.]+\.`)
220+
match := re.FindString(results)
221+
assert.Equal(t, "Resources: 0 added, 0 changed, 0 destroyed.", match, "Re-applying the same configuration should not change any resources")
221222
}

variables.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,3 +450,15 @@ variable "detailed_monitoring_enabled" {
450450
default = false
451451
description = "The launched EC2 instance will have detailed monitoring enabled. Defaults to false"
452452
}
453+
454+
variable "force_update_version" {
455+
type = bool
456+
default = false
457+
description = "When updating the Kubernetes version, force Pods to be removed even if PodDisruptionBudget or taint/toleration issues would otherwise prevent them from being removed (and cause the update to fail)"
458+
}
459+
460+
variable "replace_node_group_on_version_update" {
461+
type = bool
462+
default = false
463+
description = "Force Node Group replacement when updating to a new Kubernetes version. If set to `false` (the default), the Node Groups will be updated in-place"
464+
}

0 commit comments

Comments
 (0)