Skip to content

Commit c22c386

Browse files
committed
🐛 Add tests for ImagePullSecrets handling in CronJob, Deployment, and DaemonSet updates
1 parent f29e212 commit c22c386

5 files changed

Lines changed: 141 additions & 8 deletions

File tree

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright Mondoo, Inc. 2026
2+
// SPDX-License-Identifier: BUSL-1.1
3+
4+
package k8s
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
appsv1 "k8s.io/api/apps/v1"
11+
batchv1 "k8s.io/api/batch/v1"
12+
corev1 "k8s.io/api/core/v1"
13+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14+
)
15+
16+
func TestUpdateCronJobFields_ImagePullSecrets(t *testing.T) {
17+
desired := &batchv1.CronJob{
18+
Spec: batchv1.CronJobSpec{
19+
Schedule: "*/5 * * * *",
20+
JobTemplate: batchv1.JobTemplateSpec{
21+
Spec: batchv1.JobSpec{
22+
Template: corev1.PodTemplateSpec{
23+
Spec: corev1.PodSpec{
24+
Containers: []corev1.Container{{Name: "test", Image: "test:latest"}},
25+
ImagePullSecrets: []corev1.LocalObjectReference{
26+
{Name: "my-secret"},
27+
{Name: "another-secret"},
28+
},
29+
},
30+
},
31+
},
32+
},
33+
},
34+
}
35+
36+
obj := &batchv1.CronJob{}
37+
UpdateCronJobFields(obj, desired)
38+
39+
assert.Equal(t, desired.Spec.Schedule, obj.Spec.Schedule)
40+
assert.Equal(t, desired.Spec.JobTemplate.Spec.Template.Spec.Containers, obj.Spec.JobTemplate.Spec.Template.Spec.Containers)
41+
assert.Equal(t, desired.Spec.JobTemplate.Spec.Template.Spec.ImagePullSecrets, obj.Spec.JobTemplate.Spec.Template.Spec.ImagePullSecrets)
42+
}
43+
44+
func TestUpdateCronJobFields_PreservesUnmanagedFields(t *testing.T) {
45+
obj := &batchv1.CronJob{
46+
Spec: batchv1.CronJobSpec{
47+
JobTemplate: batchv1.JobTemplateSpec{
48+
Spec: batchv1.JobSpec{
49+
Template: corev1.PodTemplateSpec{
50+
Spec: corev1.PodSpec{
51+
DNSPolicy: corev1.DNSClusterFirst,
52+
SchedulerName: "custom-scheduler",
53+
},
54+
},
55+
},
56+
},
57+
},
58+
}
59+
60+
desired := &batchv1.CronJob{
61+
ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"app": "test"}},
62+
Spec: batchv1.CronJobSpec{
63+
Schedule: "*/10 * * * *",
64+
JobTemplate: batchv1.JobTemplateSpec{
65+
Spec: batchv1.JobSpec{
66+
Template: corev1.PodTemplateSpec{
67+
Spec: corev1.PodSpec{
68+
Containers: []corev1.Container{{Name: "test"}},
69+
},
70+
},
71+
},
72+
},
73+
},
74+
}
75+
76+
UpdateCronJobFields(obj, desired)
77+
78+
// Managed fields are updated
79+
assert.Equal(t, "*/10 * * * *", obj.Spec.Schedule)
80+
// Unmanaged fields are preserved
81+
assert.Equal(t, corev1.DNSClusterFirst, obj.Spec.JobTemplate.Spec.Template.Spec.DNSPolicy)
82+
assert.Equal(t, "custom-scheduler", obj.Spec.JobTemplate.Spec.Template.Spec.SchedulerName)
83+
}
84+
85+
func TestUpdateDeploymentFields_ImagePullSecrets(t *testing.T) {
86+
desired := &appsv1.Deployment{
87+
Spec: appsv1.DeploymentSpec{
88+
Template: corev1.PodTemplateSpec{
89+
Spec: corev1.PodSpec{
90+
Containers: []corev1.Container{{Name: "test", Image: "test:latest"}},
91+
ImagePullSecrets: []corev1.LocalObjectReference{
92+
{Name: "my-secret"},
93+
},
94+
},
95+
},
96+
},
97+
}
98+
99+
obj := &appsv1.Deployment{}
100+
UpdateDeploymentFields(obj, desired)
101+
102+
assert.Equal(t, desired.Spec.Template.Spec.ImagePullSecrets, obj.Spec.Template.Spec.ImagePullSecrets)
103+
assert.Equal(t, desired.Spec.Template.Spec.Containers, obj.Spec.Template.Spec.Containers)
104+
}
105+
106+
func TestUpdateDaemonSetFields_ImagePullSecrets(t *testing.T) {
107+
desired := &appsv1.DaemonSet{
108+
Spec: appsv1.DaemonSetSpec{
109+
Template: corev1.PodTemplateSpec{
110+
Spec: corev1.PodSpec{
111+
Containers: []corev1.Container{{Name: "test", Image: "test:latest"}},
112+
ImagePullSecrets: []corev1.LocalObjectReference{
113+
{Name: "my-secret"},
114+
},
115+
},
116+
},
117+
},
118+
}
119+
120+
obj := &appsv1.DaemonSet{}
121+
UpdateDaemonSetFields(obj, desired)
122+
123+
assert.Equal(t, desired.Spec.Template.Spec.ImagePullSecrets, obj.Spec.Template.Spec.ImagePullSecrets)
124+
assert.Equal(t, desired.Spec.Template.Spec.Containers, obj.Spec.Template.Spec.Containers)
125+
}

tests/e2e/scripts/deploy-operator-mirroring.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fi
4545
# Generate values override file
4646
# Using a file avoids Helm --set escaping issues with dots in registry mirror keys
4747
VALUES_FILE=$(mktemp /tmp/mondoo-mirror-values-XXXXXX.yaml)
48-
trap "rm -f ${VALUES_FILE}" EXIT
48+
trap 'rm -f "${VALUES_FILE}"' EXIT
4949

5050
cat > "${VALUES_FILE}" <<EOF
5151
operator:

tests/e2e/scripts/verify-mirroring.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ if [[ "${ENABLE_PROXY_TEST}" == "true" && -n "${SQUID_PROXY_IP}" ]]; then
9090
SQUID_INSTANCE="${NAME_PREFIX:-mondoo-e2e}-squid-proxy"
9191

9292
check_warn "Squid proxy shows access log traffic" \
93-
bash -c "gcloud compute ssh '${SQUID_INSTANCE}' --zone='${SQUID_ZONE}' --project='${PROJECT_ID}' --command='sudo tail -20 /var/log/squid/access.log' 2>/dev/null | grep -q ."
93+
bash -c "gcloud compute ssh '${SQUID_INSTANCE}' --zone='${SQUID_ZONE}' --project='${PROJECT_ID}' --tunnel-through-iap --command='sudo tail -20 /var/log/squid/access.log' 2>/dev/null | grep -q ."
9494

9595
info "Squid access log (last 20 lines):"
9696
gcloud compute ssh "${SQUID_INSTANCE}" --zone="${SQUID_ZONE}" --project="${PROJECT_ID}" \
97-
--command="sudo tail -20 /var/log/squid/access.log" 2>/dev/null || warn "Could not retrieve Squid logs"
97+
--tunnel-through-iap --command="sudo tail -20 /var/log/squid/access.log" 2>/dev/null || warn "Could not retrieve Squid logs"
9898
else
9999
info ""
100100
info "--- Proxy checks skipped (enable_proxy_test != true) ---"

tests/e2e/terraform/proxy.tf

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
resource "google_compute_instance" "squid_proxy" {
99
count = var.enable_proxy_test ? 1 : 0
1010

11+
lifecycle {
12+
precondition {
13+
condition = var.enable_mirror_test
14+
error_message = "enable_proxy_test requires enable_mirror_test to also be true."
15+
}
16+
}
17+
1118
name = "${local.name_prefix}-squid-proxy"
1219
project = var.project_id
1320
zone = "${var.region}-a"
@@ -21,7 +28,7 @@ resource "google_compute_instance" "squid_proxy" {
2128

2229
network_interface {
2330
network = "default"
24-
access_config {} # Ephemeral public IP for SSH access
31+
# No access_config — use IAP tunneling for SSH instead of a public IP
2532
}
2633

2734
metadata_startup_script = <<-SCRIPT
@@ -74,10 +81,10 @@ resource "google_compute_firewall" "allow_squid" {
7481
target_tags = ["squid-proxy"]
7582
}
7683

77-
resource "google_compute_firewall" "allow_squid_ssh" {
84+
resource "google_compute_firewall" "allow_squid_iap_ssh" {
7885
count = var.enable_proxy_test ? 1 : 0
7986

80-
name = "${local.name_prefix}-allow-squid-ssh"
87+
name = "${local.name_prefix}-allow-squid-iap-ssh"
8188
project = var.project_id
8289
network = "default"
8390

@@ -86,6 +93,7 @@ resource "google_compute_firewall" "allow_squid_ssh" {
8693
ports = ["22"]
8794
}
8895

89-
source_ranges = ["0.0.0.0/0"]
96+
# IAP's IP range for TCP forwarding
97+
source_ranges = ["35.235.240.0/20"]
9098
target_tags = ["squid-proxy"]
9199
}

tests/e2e/terraform/terraform.example.tfvars

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ autopilot = true
88
# Set to true to provision a mirror AR repo for registry mirroring/imagePullSecrets tests
99
enable_mirror_test = false
1010
# Set to true to also provision a Squid proxy VM for proxy tests (requires enable_mirror_test)
11-
enable_proxy_test = false
11+
enable_proxy_test = false

0 commit comments

Comments
 (0)