Skip to content

Commit 2831cb7

Browse files
committed
feat: add skip annotation for cilium kube-proxy validator
1 parent 8940a33 commit 2831cb7

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

api/v1alpha1/constants.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,8 @@ const (
5858
// PreflightChecksSkipAllAnnotationValue is the value used in the cluster's annotations to indicate
5959
// that all checks are skipped.
6060
PreflightChecksSkipAllAnnotationValue = "all"
61+
62+
// SkipCiliumKubeProxyReplacementValidation is the key of the annotation on the Cluster
63+
// used to skip Cilium kube-proxy replacement validation.
64+
SkipCiliumKubeProxyReplacementValidation = APIGroup + "/skip-cilium-kube-proxy-replacement-validation"
6165
)

pkg/webhook/cluster/cilium_configuration_validator.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ func (a *advancedCiliumConfigurationValidator) validate(
5656
return admission.Allowed("")
5757
}
5858

59+
// Skip validation if the skip annotation is present
60+
if hasSkipAnnotation(cluster) {
61+
return admission.Allowed("")
62+
}
63+
5964
clusterConfig, err := variables.UnmarshalClusterConfigVariable(cluster.Spec.Topology.Variables)
6065
if err != nil {
6166
return admission.Denied(
@@ -100,6 +105,14 @@ func (a *advancedCiliumConfigurationValidator) validate(
100105
return admission.Allowed("")
101106
}
102107

108+
func hasSkipAnnotation(cluster *clusterv1.Cluster) bool {
109+
if cluster.Annotations == nil {
110+
return false
111+
}
112+
val, ok := cluster.Annotations[v1alpha1.SkipCiliumKubeProxyReplacementValidation]
113+
return ok && val == "true"
114+
}
115+
103116
type ciliumValues struct {
104117
KubeProxyReplacement bool `json:"kubeProxyReplacement"`
105118
}

pkg/webhook/cluster/cilium_configuration_validator_test.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,131 @@ var _ = Describe("AdvancedCiliumConfigurationValidator", func() {
7676
})
7777
})
7878

79+
Context("when skip annotation is present", func() {
80+
It("should skip validation when annotation is true", func() {
81+
cni := &v1alpha1.CNI{
82+
Provider: v1alpha1.CNIProviderCilium,
83+
AddonConfig: v1alpha1.AddonConfig{
84+
Values: &v1alpha1.AddonValues{
85+
SourceRef: &v1alpha1.ValuesReference{
86+
Kind: "ConfigMap",
87+
Name: "cilium-values",
88+
},
89+
},
90+
},
91+
}
92+
cluster := createTestCluster("test-cluster", "test-namespace", v1alpha1.KubeProxyModeDisabled, cni)
93+
94+
// Add skip annotation
95+
cluster.Annotations = map[string]string{
96+
v1alpha1.SkipCiliumKubeProxyReplacementValidation: "true",
97+
}
98+
99+
req := createAdmissionRequest(cluster)
100+
101+
// Create ConfigMap with kubeProxyReplacement set to false - should still allow due to annotation
102+
configMap := &corev1.ConfigMap{
103+
ObjectMeta: metav1.ObjectMeta{
104+
Name: "cilium-values",
105+
Namespace: "test-namespace",
106+
},
107+
Data: map[string]string{
108+
"values.yaml": `
109+
ipam:
110+
mode: kubernetes
111+
kubeProxyReplacement: false
112+
`,
113+
},
114+
}
115+
116+
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(configMap).Build()
117+
validator = NewAdvancedCiliumConfigurationValidator(client, decoder)
118+
119+
resp := validator.validate(context.Background(), req)
120+
Expect(resp.Allowed).To(BeTrue())
121+
})
122+
123+
It("should not skip validation when annotation is false", func() {
124+
cni := &v1alpha1.CNI{
125+
Provider: v1alpha1.CNIProviderCilium,
126+
AddonConfig: v1alpha1.AddonConfig{
127+
Values: &v1alpha1.AddonValues{
128+
SourceRef: &v1alpha1.ValuesReference{
129+
Kind: "ConfigMap",
130+
Name: "cilium-values",
131+
},
132+
},
133+
},
134+
}
135+
cluster := createTestCluster("test-cluster", "test-namespace", v1alpha1.KubeProxyModeDisabled, cni)
136+
137+
// Add skip annotation with false value
138+
cluster.Annotations = map[string]string{
139+
v1alpha1.SkipCiliumKubeProxyReplacementValidation: "false",
140+
}
141+
142+
req := createAdmissionRequest(cluster)
143+
144+
// Create ConfigMap with kubeProxyReplacement set to false - should deny
145+
configMap := &corev1.ConfigMap{
146+
ObjectMeta: metav1.ObjectMeta{
147+
Name: "cilium-values",
148+
Namespace: "test-namespace",
149+
},
150+
Data: map[string]string{
151+
"values.yaml": `
152+
ipam:
153+
mode: kubernetes
154+
kubeProxyReplacement: false
155+
`,
156+
},
157+
}
158+
159+
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(configMap).Build()
160+
validator = NewAdvancedCiliumConfigurationValidator(client, decoder)
161+
162+
resp := validator.validate(context.Background(), req)
163+
Expect(resp.Allowed).To(BeFalse())
164+
})
165+
166+
It("should not skip validation when annotation is missing", func() {
167+
cni := &v1alpha1.CNI{
168+
Provider: v1alpha1.CNIProviderCilium,
169+
AddonConfig: v1alpha1.AddonConfig{
170+
Values: &v1alpha1.AddonValues{
171+
SourceRef: &v1alpha1.ValuesReference{
172+
Kind: "ConfigMap",
173+
Name: "cilium-values",
174+
},
175+
},
176+
},
177+
}
178+
cluster := createTestCluster("test-cluster", "test-namespace", v1alpha1.KubeProxyModeDisabled, cni)
179+
req := createAdmissionRequest(cluster)
180+
181+
// Create ConfigMap with kubeProxyReplacement set to false - should deny
182+
configMap := &corev1.ConfigMap{
183+
ObjectMeta: metav1.ObjectMeta{
184+
Name: "cilium-values",
185+
Namespace: "test-namespace",
186+
},
187+
Data: map[string]string{
188+
"values.yaml": `
189+
ipam:
190+
mode: kubernetes
191+
kubeProxyReplacement: false
192+
`,
193+
},
194+
}
195+
196+
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(configMap).Build()
197+
validator = NewAdvancedCiliumConfigurationValidator(client, decoder)
198+
199+
resp := validator.validate(context.Background(), req)
200+
Expect(resp.Allowed).To(BeFalse())
201+
})
202+
})
203+
79204
Context("when kube-proxy is not disabled", func() {
80205
It("should allow the cluster", func() {
81206
cluster := createTestCluster("test-cluster", "test-namespace", v1alpha1.KubeProxyModeIPTables, nil)

0 commit comments

Comments
 (0)