Skip to content

Commit 9dc2cd4

Browse files
CodeRabbit Generated Unit Tests: Add unit tests for PR changes
1 parent d10367b commit 9dc2cd4

3 files changed

Lines changed: 466 additions & 0 deletions

File tree

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# =============================================================================
2+
# Tests: Worker node autoscaling conditional expression
3+
#
4+
# PR Change (prod/compute.tf, module "k8s_worker_nodes"):
5+
#
6+
# Before:
7+
# enable_autoscaling = var.enable_autoscaling
8+
#
9+
# After:
10+
# enable_autoscaling = var.k8s_worker_instance_group_size > 0 ? var.enable_autoscaling : false
11+
#
12+
# Intent: When the worker MIG target_size is 0 (fully drained), the autoscaler
13+
# must be disabled unconditionally so GCP does not fight the deliberately-empty
14+
# group. The autoscaler_id output is null when no autoscaler is created.
15+
#
16+
# Tests:
17+
# 1. size > 0, enable_autoscaling=true → autoscaler_id is non-null
18+
# 2. size > 0, enable_autoscaling=false → autoscaler_id is null
19+
# 3. size = 0, enable_autoscaling=true → autoscaler_id is null (conditional override)
20+
# 4. size = 0, enable_autoscaling=false → autoscaler_id is null
21+
# 5. size = 1 (boundary), enable_autoscaling=true → autoscaler_id is non-null
22+
# 6. Master nodes: autoscaler_id always null (hardcoded enable_autoscaling=false)
23+
# =============================================================================
24+
25+
mock_provider "google" {}
26+
27+
# ---------------------------------------------------------------------------
28+
# Test 1: Normal operation — workers with size > 0 and autoscaling enabled.
29+
# The conditional passes var.enable_autoscaling through: true → true.
30+
# autoscaler_id should be a non-null string (resource was created).
31+
# ---------------------------------------------------------------------------
32+
run "worker_autoscaling_enabled_when_group_size_positive" {
33+
command = plan
34+
35+
variables {
36+
k8s_worker_instance_group_size = 2
37+
enable_autoscaling = true
38+
autoscaling_min_replicas = 2
39+
autoscaling_max_replicas = 5
40+
41+
service_account_email = "sa@test-project.iam.gserviceaccount.com"
42+
}
43+
44+
# size(2) > 0 and enable_autoscaling=true → conditional evaluates to true → autoscaler created
45+
assert {
46+
condition = module.k8s_worker_nodes.autoscaler_id != null
47+
error_message = "Worker autoscaler must be created when group size > 0 and enable_autoscaling = true."
48+
}
49+
}
50+
51+
# ---------------------------------------------------------------------------
52+
# Test 2: Workers with size > 0 but autoscaling explicitly disabled.
53+
# The conditional passes var.enable_autoscaling through: false → false.
54+
# autoscaler_id should be null.
55+
# ---------------------------------------------------------------------------
56+
run "worker_autoscaling_disabled_when_group_size_positive_but_autoscaling_false" {
57+
command = plan
58+
59+
variables {
60+
k8s_worker_instance_group_size = 2
61+
enable_autoscaling = false
62+
autoscaling_min_replicas = 2
63+
autoscaling_max_replicas = 5
64+
65+
service_account_email = "sa@test-project.iam.gserviceaccount.com"
66+
}
67+
68+
# size(2) > 0 but enable_autoscaling=false → conditional evaluates to false → no autoscaler
69+
assert {
70+
condition = module.k8s_worker_nodes.autoscaler_id == null
71+
error_message = "Worker autoscaler must not be created when enable_autoscaling = false, even with positive group size."
72+
}
73+
}
74+
75+
# ---------------------------------------------------------------------------
76+
# Test 3 (KEY NEW BEHAVIOR): Workers with size = 0 and enable_autoscaling=true.
77+
# The conditional overrides enable_autoscaling to false, preventing the
78+
# autoscaler from conflicting with a deliberately-empty MIG.
79+
# autoscaler_id should be null despite enable_autoscaling=true.
80+
# ---------------------------------------------------------------------------
81+
run "worker_autoscaling_forced_false_when_group_size_is_zero" {
82+
command = plan
83+
84+
variables {
85+
k8s_worker_instance_group_size = 0
86+
enable_autoscaling = true # user flag is true, but group is empty
87+
autoscaling_min_replicas = 2
88+
autoscaling_max_replicas = 5
89+
90+
service_account_email = "sa@test-project.iam.gserviceaccount.com"
91+
}
92+
93+
# size(0) is NOT > 0 → conditional resolves to false → no autoscaler created
94+
assert {
95+
condition = module.k8s_worker_nodes.autoscaler_id == null
96+
error_message = "Worker autoscaler must be suppressed when group size is 0, regardless of enable_autoscaling value."
97+
}
98+
}
99+
100+
# ---------------------------------------------------------------------------
101+
# Test 4: Workers with size = 0 and enable_autoscaling = false.
102+
# Both the explicit value and the conditional produce false; autoscaler_id null.
103+
# ---------------------------------------------------------------------------
104+
run "worker_autoscaling_null_when_group_size_zero_and_autoscaling_false" {
105+
command = plan
106+
107+
variables {
108+
k8s_worker_instance_group_size = 0
109+
enable_autoscaling = false
110+
autoscaling_min_replicas = 2
111+
autoscaling_max_replicas = 5
112+
113+
service_account_email = "sa@test-project.iam.gserviceaccount.com"
114+
}
115+
116+
assert {
117+
condition = module.k8s_worker_nodes.autoscaler_id == null
118+
error_message = "No autoscaler when group size is 0 and enable_autoscaling is false."
119+
}
120+
}
121+
122+
# ---------------------------------------------------------------------------
123+
# Test 5: Boundary — size = 1 is the minimum value for the conditional to
124+
# evaluate to true (size > 0). Autoscaling should be enabled.
125+
# ---------------------------------------------------------------------------
126+
run "worker_autoscaling_enabled_at_minimum_nonzero_boundary" {
127+
command = plan
128+
129+
variables {
130+
k8s_worker_instance_group_size = 1 # boundary: exactly one instance
131+
enable_autoscaling = true
132+
autoscaling_min_replicas = 1
133+
autoscaling_max_replicas = 5
134+
135+
service_account_email = "sa@test-project.iam.gserviceaccount.com"
136+
}
137+
138+
# size(1) > 0 and enable_autoscaling=true → conditional evaluates to true
139+
assert {
140+
condition = module.k8s_worker_nodes.autoscaler_id != null
141+
error_message = "Autoscaler should be created when group size is exactly 1 (minimum non-zero boundary)."
142+
}
143+
}
144+
145+
# ---------------------------------------------------------------------------
146+
# Test 6: Master nodes always have enable_autoscaling = false (hardcoded).
147+
# Regression: The PR did not change the master node autoscaling policy.
148+
# Master autoscaler_id must remain null even when enable_autoscaling=true globally.
149+
# ---------------------------------------------------------------------------
150+
run "master_autoscaling_always_disabled_regardless_of_global_enable_autoscaling" {
151+
command = plan
152+
153+
variables {
154+
k8s_master_instance_group_size = 1
155+
enable_autoscaling = true # global flag is true, but masters ignore it
156+
k8s_worker_instance_group_size = 2
157+
158+
service_account_email = "sa@test-project.iam.gserviceaccount.com"
159+
}
160+
161+
# Master nodes have enable_autoscaling = false hardcoded in compute.tf → no autoscaler
162+
assert {
163+
condition = module.k8s_master_nodes.autoscaler_id == null
164+
error_message = "Master nodes must never have an autoscaler; enable_autoscaling is hardcoded to false in compute.tf."
165+
}
166+
}
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# =============================================================================
2+
# Tests: enable_autoscaling resource creation behavior
3+
#
4+
# PR Change: Worker nodes now use a conditional for enable_autoscaling:
5+
# var.k8s_worker_instance_group_size > 0 ? var.enable_autoscaling : false
6+
#
7+
# The conditional is evaluated in the calling environment (prod/compute.tf)
8+
# before being passed into this module. These module-level tests verify that
9+
# the module correctly creates/omits the autoscaler based on the value it
10+
# receives, validating the downstream behavior of that conditional.
11+
#
12+
# Tests:
13+
# 1. enable_autoscaling=true → google_compute_autoscaler is created (count=1)
14+
# 2. enable_autoscaling=false → google_compute_autoscaler is NOT created (count=0)
15+
# 3. enable_autoscaling=true with cpu_target=0.7 → CPU policy is applied
16+
# 4. Boundary: min_replicas=1 (minimum valid value)
17+
# =============================================================================
18+
19+
mock_provider "google" {}
20+
21+
# ---------------------------------------------------------------------------
22+
# Test 1: enable_autoscaling=true creates exactly one autoscaler resource.
23+
# ---------------------------------------------------------------------------
24+
run "autoscaler_created_when_autoscaling_enabled" {
25+
command = plan
26+
27+
variables {
28+
name_prefix = "test-workers"
29+
network = "projects/test-project/global/networks/test-vpc"
30+
subnetwork = "projects/test-project/regions/asia-northeast3/subnetworks/test-subnet"
31+
create_instance_template = true
32+
create_instance_group = true
33+
instance_group_zone = "asia-northeast3-a"
34+
instance_group_target_size = 2
35+
update_policy_type = "OPPORTUNISTIC"
36+
enable_autoscaling = true
37+
autoscaling_min_replicas = 2
38+
autoscaling_max_replicas = 5
39+
autoscaling_cpu_target = 0.7
40+
}
41+
42+
assert {
43+
condition = length(google_compute_autoscaler.autoscaler) == 1
44+
error_message = "Exactly one autoscaler should be created when enable_autoscaling is true."
45+
}
46+
47+
assert {
48+
condition = google_compute_autoscaler.autoscaler[0].autoscaling_policy[0].min_replicas == 2
49+
error_message = "Autoscaler min_replicas should match autoscaling_min_replicas variable."
50+
}
51+
52+
assert {
53+
condition = google_compute_autoscaler.autoscaler[0].autoscaling_policy[0].max_replicas == 5
54+
error_message = "Autoscaler max_replicas should match autoscaling_max_replicas variable."
55+
}
56+
}
57+
58+
# ---------------------------------------------------------------------------
59+
# Test 2: enable_autoscaling=false creates NO autoscaler.
60+
# This is the value produced when k8s_worker_instance_group_size == 0,
61+
# because the conditional forces enable_autoscaling to false.
62+
# Also mirrors the permanent behavior of k8s_master_nodes.
63+
# ---------------------------------------------------------------------------
64+
run "autoscaler_not_created_when_autoscaling_disabled" {
65+
command = plan
66+
67+
variables {
68+
name_prefix = "test-workers-empty"
69+
network = "projects/test-project/global/networks/test-vpc"
70+
subnetwork = "projects/test-project/regions/asia-northeast3/subnetworks/test-subnet"
71+
create_instance_template = true
72+
create_instance_group = true
73+
instance_group_zone = "asia-northeast3-a"
74+
instance_group_target_size = 0
75+
update_policy_type = "OPPORTUNISTIC"
76+
# The conditional in prod/compute.tf resolves to false when target_size == 0.
77+
# Here we pass false directly to test the module-level behavior.
78+
enable_autoscaling = false
79+
}
80+
81+
assert {
82+
condition = length(google_compute_autoscaler.autoscaler) == 0
83+
error_message = "No autoscaler should be created when enable_autoscaling is false (as when group size is 0)."
84+
}
85+
}
86+
87+
# ---------------------------------------------------------------------------
88+
# Test 3: CPU utilization target of 0.7 is applied when autoscaling is on.
89+
# Worker nodes use autoscaling_cpu_target = 0.7 (hardcoded in compute.tf).
90+
# ---------------------------------------------------------------------------
91+
run "autoscaler_cpu_target_applied_at_0_7" {
92+
command = plan
93+
94+
variables {
95+
name_prefix = "test-workers-cpu"
96+
network = "projects/test-project/global/networks/test-vpc"
97+
subnetwork = "projects/test-project/regions/asia-northeast3/subnetworks/test-subnet"
98+
create_instance_template = true
99+
create_instance_group = true
100+
instance_group_zone = "asia-northeast3-a"
101+
instance_group_target_size = 2
102+
update_policy_type = "OPPORTUNISTIC"
103+
enable_autoscaling = true
104+
autoscaling_min_replicas = 2
105+
autoscaling_max_replicas = 5
106+
autoscaling_cpu_target = 0.7
107+
}
108+
109+
assert {
110+
condition = google_compute_autoscaler.autoscaler[0].autoscaling_policy[0].cpu_utilization[0].target == 0.7
111+
error_message = "CPU utilization target should be 0.7 as configured in compute.tf."
112+
}
113+
}
114+
115+
# ---------------------------------------------------------------------------
116+
# Test 4: Boundary — minimum valid non-zero group size (size=1) with
117+
# autoscaling enabled results in autoscaler being created.
118+
# This corresponds to the boundary of the conditional expression (size > 0).
119+
# ---------------------------------------------------------------------------
120+
run "autoscaler_created_at_minimum_nonzero_group_size" {
121+
command = plan
122+
123+
variables {
124+
name_prefix = "test-workers-single"
125+
network = "projects/test-project/global/networks/test-vpc"
126+
subnetwork = "projects/test-project/regions/asia-northeast3/subnetworks/test-subnet"
127+
create_instance_template = true
128+
create_instance_group = true
129+
instance_group_zone = "asia-northeast3-a"
130+
instance_group_target_size = 1
131+
update_policy_type = "OPPORTUNISTIC"
132+
enable_autoscaling = true
133+
autoscaling_min_replicas = 1
134+
autoscaling_max_replicas = 5
135+
autoscaling_cpu_target = 0.7
136+
}
137+
138+
assert {
139+
condition = length(google_compute_autoscaler.autoscaler) == 1
140+
error_message = "Autoscaler should be created for minimum non-zero group size (size=1)."
141+
}
142+
}
143+
144+
# ---------------------------------------------------------------------------
145+
# Test 5: Master node configuration — autoscaling hardcoded to false,
146+
# update_policy_type = "OPPORTUNISTIC". No autoscaler regardless of group size.
147+
# Regression test: master nodes must never get an autoscaler.
148+
# ---------------------------------------------------------------------------
149+
run "master_nodes_never_have_autoscaler" {
150+
command = plan
151+
152+
variables {
153+
name_prefix = "test-masters"
154+
network = "projects/test-project/global/networks/test-vpc"
155+
subnetwork = "projects/test-project/regions/asia-northeast3/subnetworks/test-subnet"
156+
create_instance_template = true
157+
create_instance_group = true
158+
instance_group_zone = "asia-northeast3-a"
159+
instance_group_target_size = 1
160+
update_policy_type = "OPPORTUNISTIC"
161+
enable_autoscaling = false # Master nodes: always false
162+
}
163+
164+
assert {
165+
condition = length(google_compute_autoscaler.autoscaler) == 0
166+
error_message = "Master nodes must never have an autoscaler (enable_autoscaling is hardcoded to false)."
167+
}
168+
169+
assert {
170+
condition = google_compute_instance_group_manager.instance_group[0].update_policy[0].type == "OPPORTUNISTIC"
171+
error_message = "Master node MIG must use OPPORTUNISTIC update policy."
172+
}
173+
}

0 commit comments

Comments
 (0)