Skip to content

Commit 31d26f0

Browse files
authored
feat: add var automatic_channel_upgrade (#281)
* feat: add var automatic_channel_upgrade - AKS clusters can now be automatically upgraded to new patch or minor versions - Added unit tests to covert differnet auto-upgrade settings - Extended startup example to enable automatic patch upgrades (most common use-case) Signed-off-by: Nathanael Liechti <technat@technat.ch>
1 parent b346574 commit 31d26f0

8 files changed

Lines changed: 99 additions & 3 deletions

File tree

.checkov_config.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
block-list-secret-scan: []
2+
branch: master
3+
directory:
4+
- ./
5+
download-external-modules: false
6+
evaluate-variables: true
7+
external-modules-download-path: .external_modules
8+
framework:
9+
- all
10+
quiet: true
11+
secrets-scan-file-type: []
12+
skip-check:
13+
- CKV_GHA_3
14+
- CKV_AZURE_168
15+
- CKV_AZURE_170
16+
skip-framework:
17+
- dockerfile
18+
summary-position: top

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ No modules.
284284
| <a name="input_agents_tags"></a> [agents\_tags](#input\_agents\_tags) | (Optional) A mapping of tags to assign to the Node Pool. | `map(string)` | `{}` | no |
285285
| <a name="input_agents_type"></a> [agents\_type](#input\_agents\_type) | (Optional) The type of Node Pool which should be created. Possible values are AvailabilitySet and VirtualMachineScaleSets. Defaults to VirtualMachineScaleSets. | `string` | `"VirtualMachineScaleSets"` | no |
286286
| <a name="input_api_server_authorized_ip_ranges"></a> [api\_server\_authorized\_ip\_ranges](#input\_api\_server\_authorized\_ip\_ranges) | (Optional) The IP ranges to allow for incoming traffic to the server nodes. | `set(string)` | `null` | no |
287+
| <a name="input_automatic_channel_upgrade"></a> [automatic\_channel\_upgrade](#input\_automatic\_channel\_upgrade) | (Optional) The upgrade channel for this Kubernetes Cluster. Possible values are `patch`, `rapid`, `node-image` and `stable`. By default automatic-upgrades are turned off. Note that you cannot use the `patch` upgrade channel and still specify the patch version using `kubernetes_version`. See [the documentation](https://learn.microsoft.com/en-us/azure/aks/auto-upgrade-cluster) for more information | `string` | `null` | no |
287288
| <a name="input_azure_policy_enabled"></a> [azure\_policy\_enabled](#input\_azure\_policy\_enabled) | Enable Azure Policy Addon. | `bool` | `false` | no |
288289
| <a name="input_client_id"></a> [client\_id](#input\_client\_id) | (Optional) The Client ID (appId) for the Service Principal used for the AKS deployment | `string` | `""` | no |
289290
| <a name="input_client_secret"></a> [client\_secret](#input\_client\_secret) | (Optional) The Client Secret (password) for the Service Principal used for the AKS deployment | `string` | `""` | no |

examples/startup/main.tf

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ module "aks" {
3636

3737
prefix = "prefix-${random_id.prefix.hex}"
3838
resource_group_name = local.resource_group.name
39+
kubernetes_version = "1.24" # don't specify the patch version!
40+
automatic_channel_upgrade = "patch"
3941
agents_availability_zones = ["1", "2"]
4042
agents_count = null
4143
agents_max_count = 2
@@ -87,4 +89,4 @@ module "aks" {
8789
agents_tags = {
8890
"Agent" : "agentTag"
8991
}
90-
}
92+
}

locals.tf

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
11
locals {
2+
# automatic upgrades are either:
3+
# - null
4+
# - patch, but then the kubernetes_version musnt't specify a patch number
5+
# - rapid/stable/node-image, but then the kubernetes_version must be null
6+
automatic_channel_upgrade_check = var.automatic_channel_upgrade == null ? true : (
7+
contains(["patch"], var.automatic_channel_upgrade) &&
8+
can(regex("^[0-9]{1,}\\.[0-9]{1,}$", var.kubernetes_version))
9+
) ? true : (
10+
contains(["rapid", "stable", "node-image"], var.automatic_channel_upgrade) &&
11+
var.kubernetes_version == null
12+
)
213
# Abstract the decision whether to create an Analytics Workspace or not.
314
create_analytics_solution = var.log_analytics_workspace_enabled && var.log_analytics_solution_id == null
415
create_analytics_workspace = var.log_analytics_workspace_enabled && var.log_analytics_workspace == null
@@ -18,4 +29,4 @@ locals {
1829
name = var.log_analytics_workspace.name
1930
}
2031
) : null # Finally, the Log Analytics Workspace should be disabled.
21-
}
32+
}

main.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ resource "azurerm_kubernetes_cluster" "main" {
1919
name = var.cluster_name == null ? "${var.prefix}-aks" : var.cluster_name
2020
resource_group_name = data.azurerm_resource_group.main.name
2121
api_server_authorized_ip_ranges = var.api_server_authorized_ip_ranges
22+
automatic_channel_upgrade = var.automatic_channel_upgrade
2223
azure_policy_enabled = var.azure_policy_enabled
2324
disk_encryption_set_id = var.disk_encryption_set_id
2425
dns_prefix = var.prefix
@@ -238,6 +239,10 @@ resource "azurerm_kubernetes_cluster" "main" {
238239
condition = !(var.load_balancer_profile_enabled && var.load_balancer_sku != "standard")
239240
error_message = "Enabling load_balancer_profile requires that `load_balancer_sku` be set to `standard`"
240241
}
242+
precondition {
243+
condition = local.automatic_channel_upgrade_check
244+
error_message = "Either disable automatic upgrades, only specify up to the minor version when using `automatic_channel_upgrade=patch` or don't specify `kubernetes_version` at all when using `automatic_channel_upgrade=stable|rapid|node-image`."
245+
}
241246
}
242247
}
243248

test/unit/unit_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,51 @@ func TestLogAnalyticsWorkspaceEnabledSolutionProvidedShouldNotCreateSolution(t *
105105
})
106106
}
107107

108+
func TestAutomaticUpgrades(t *testing.T) {
109+
testCases := map[string]struct {
110+
name string
111+
vars map[string]interface{}
112+
}{
113+
"automatic_patches_no_patch_number_specified": {
114+
vars: map[string]interface{}{
115+
"prefix": "foo",
116+
"resource_group_name": "bar",
117+
"automatic_channel_upgrade": "patch",
118+
"kubernetes_version": "1.25",
119+
},
120+
},
121+
"automatic_upgrades_to_newest_version": {
122+
vars: map[string]interface{}{
123+
"prefix": "foo",
124+
"resource_group_name": "bar",
125+
"automatic_channel_upgrade": "rapid",
126+
},
127+
},
128+
"automatic_upgrades_to_stable_version": {
129+
vars: map[string]interface{}{
130+
"prefix": "foo",
131+
"resource_group_name": "bar",
132+
"automatic_channel_upgrade": "stable",
133+
},
134+
},
135+
}
136+
137+
for name, tt := range testCases {
138+
t.Run(name, func(t *testing.T) {
139+
test_helper.RunE2ETest(t, "../../", "unit-test-fixture",
140+
terraform.Options{
141+
Upgrade: false,
142+
Vars: tt.vars,
143+
},
144+
func(t *testing.T, output test_helper.TerraformOutput) {
145+
upgrades, ok := output["automatic_channel_upgrade_check"].(bool)
146+
assert.True(t, ok)
147+
assert.True(t, upgrades)
148+
})
149+
})
150+
}
151+
}
152+
108153
func dummyRequiredVariables() map[string]interface{} {
109154
return map[string]interface{}{
110155
"prefix": "foo",

unit-test-fixture/outputs.tf

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@ output "create_analytics_workspace" {
88

99
output "log_analytics_workspace" {
1010
value = local.log_analytics_workspace
11-
}
11+
}
12+
13+
output "automatic_channel_upgrade_check" {
14+
value = local.automatic_channel_upgrade_check
15+
}

variables.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,16 @@ variable "api_server_authorized_ip_ranges" {
9393
default = null
9494
}
9595

96+
variable "automatic_channel_upgrade" {
97+
type = string
98+
default = null
99+
description = "(Optional) The upgrade channel for this Kubernetes Cluster. Possible values are `patch`, `rapid`, `node-image` and `stable`. By default automatic-upgrades are turned off. Note that you cannot use the `patch` upgrade channel and still specify the patch version using `kubernetes_version`. See [the documentation](https://learn.microsoft.com/en-us/azure/aks/auto-upgrade-cluster) for more information"
100+
validation {
101+
condition = var.automatic_channel_upgrade == null ? true : contains(["patch", "stable", "rapid", "node-image"], var.automatic_channel_upgrade)
102+
error_message = "`automatic_channel_upgrade`'s possible values are `patch`, `stable`, `rapid` or `node-image`."
103+
}
104+
}
105+
96106
variable "azure_policy_enabled" {
97107
type = bool
98108
description = "Enable Azure Policy Addon."

0 commit comments

Comments
 (0)