github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/caas/kubernetes/provider/specs/admissionregistration_test.go (about) 1 // Copyright 2021 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package specs_test 5 6 import ( 7 "encoding/base64" 8 "strings" 9 10 jc "github.com/juju/testing/checkers" 11 gc "gopkg.in/check.v1" 12 admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1" 13 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 14 "k8s.io/utils/pointer" 15 16 k8sspecs "github.com/juju/juju/caas/kubernetes/provider/specs" 17 "github.com/juju/juju/testing" 18 ) 19 20 type webhooksSuite struct { 21 testing.BaseSuite 22 } 23 24 var _ = gc.Suite(&webhooksSuite{}) 25 26 func (s *webhooksSuite) TestK8sMutatingWebhookV1Beta1(c *gc.C) { 27 specV1Beta1 := ` 28 name: example-mutatingwebhookconfiguration 29 labels: 30 foo: bar 31 annotations: 32 juju.io/disable-name-prefix: "true" 33 webhooks: 34 - name: "example.mutatingwebhookconfiguration.com" 35 failurePolicy: Ignore 36 clientConfig: 37 service: 38 name: apple-service 39 namespace: apples 40 path: /apple 41 caBundle: "YXBwbGVz" 42 namespaceSelector: 43 matchExpressions: 44 - key: production 45 operator: DoesNotExist 46 rules: 47 - apiGroups: 48 - "" 49 apiVersions: 50 - v1 51 operations: 52 - CREATE 53 - UPDATE 54 resources: 55 - pods 56 ` 57 var obj k8sspecs.K8sMutatingWebhook 58 err := k8sspecs.NewStrictYAMLOrJSONDecoder(strings.NewReader(specV1Beta1), len(specV1Beta1)).Decode(&obj) 59 c.Assert(err, jc.ErrorIsNil) 60 61 webhookFailurePolicy1 := admissionregistrationv1beta1.Ignore 62 CABundle, err := base64.StdEncoding.DecodeString("YXBwbGVz") 63 c.Assert(err, jc.ErrorIsNil) 64 c.Assert(obj, gc.DeepEquals, k8sspecs.K8sMutatingWebhook{ 65 Meta: k8sspecs.Meta{ 66 Name: "example-mutatingwebhookconfiguration", 67 Labels: map[string]string{"foo": "bar"}, 68 Annotations: map[string]string{"juju.io/disable-name-prefix": "true"}, 69 }, 70 Webhooks: []k8sspecs.K8sMutatingWebhookSpec{ 71 { 72 Version: k8sspecs.K8sWebhookV1Beta1, 73 SpecV1Beta1: admissionregistrationv1beta1.MutatingWebhook{ 74 Name: "example.mutatingwebhookconfiguration.com", 75 FailurePolicy: &webhookFailurePolicy1, 76 ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{ 77 Service: &admissionregistrationv1beta1.ServiceReference{ 78 Name: "apple-service", 79 Namespace: "apples", 80 Path: pointer.StringPtr("/apple"), 81 }, 82 CABundle: CABundle, 83 }, 84 NamespaceSelector: &metav1.LabelSelector{ 85 MatchExpressions: []metav1.LabelSelectorRequirement{ 86 {Key: "production", Operator: metav1.LabelSelectorOpDoesNotExist}, 87 }, 88 }, 89 Rules: []admissionregistrationv1beta1.RuleWithOperations{ 90 { 91 Operations: []admissionregistrationv1beta1.OperationType{ 92 admissionregistrationv1beta1.Create, 93 admissionregistrationv1beta1.Update, 94 }, 95 Rule: admissionregistrationv1beta1.Rule{ 96 APIGroups: []string{""}, 97 APIVersions: []string{"v1"}, 98 Resources: []string{"pods"}, 99 }, 100 }, 101 }, 102 }, 103 }, 104 }, 105 }) 106 } 107 108 func (s *webhooksSuite) TestK8sMutatingWebhookV1(c *gc.C) { 109 specV1 := ` 110 name: example-mutatingwebhookconfiguration 111 labels: 112 foo: bar 113 annotations: 114 juju.io/disable-name-prefix: "true" 115 webhooks: 116 - name: "example.mutatingwebhookconfiguration.com" 117 failurePolicy: Ignore 118 clientConfig: 119 service: 120 name: apple-service 121 namespace: apples 122 path: /apple 123 caBundle: "YXBwbGVz" 124 namespaceSelector: 125 matchExpressions: 126 - key: production 127 operator: DoesNotExist 128 rules: 129 - apiGroups: 130 - "" 131 apiVersions: 132 - v1 133 operations: 134 - CREATE 135 - UPDATE 136 resources: 137 - pods 138 ` 139 var obj k8sspecs.K8sMutatingWebhook 140 err := k8sspecs.NewStrictYAMLOrJSONDecoder(strings.NewReader(specV1), len(specV1)).Decode(&obj) 141 c.Assert(err, jc.ErrorIsNil) 142 143 webhookFailurePolicy1 := admissionregistrationv1beta1.Ignore 144 CABundle, err := base64.StdEncoding.DecodeString("YXBwbGVz") 145 c.Assert(err, jc.ErrorIsNil) 146 c.Assert(obj, gc.DeepEquals, k8sspecs.K8sMutatingWebhook{ 147 Meta: k8sspecs.Meta{ 148 Name: "example-mutatingwebhookconfiguration", 149 Labels: map[string]string{"foo": "bar"}, 150 Annotations: map[string]string{"juju.io/disable-name-prefix": "true"}, 151 }, 152 Webhooks: []k8sspecs.K8sMutatingWebhookSpec{ 153 { 154 Version: k8sspecs.K8sWebhookV1Beta1, 155 SpecV1Beta1: admissionregistrationv1beta1.MutatingWebhook{ 156 Name: "example.mutatingwebhookconfiguration.com", 157 FailurePolicy: &webhookFailurePolicy1, 158 ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{ 159 Service: &admissionregistrationv1beta1.ServiceReference{ 160 Name: "apple-service", 161 Namespace: "apples", 162 Path: pointer.StringPtr("/apple"), 163 }, 164 CABundle: CABundle, 165 }, 166 NamespaceSelector: &metav1.LabelSelector{ 167 MatchExpressions: []metav1.LabelSelectorRequirement{ 168 {Key: "production", Operator: metav1.LabelSelectorOpDoesNotExist}, 169 }, 170 }, 171 Rules: []admissionregistrationv1beta1.RuleWithOperations{ 172 { 173 Operations: []admissionregistrationv1beta1.OperationType{ 174 admissionregistrationv1beta1.Create, 175 admissionregistrationv1beta1.Update, 176 }, 177 Rule: admissionregistrationv1beta1.Rule{ 178 APIGroups: []string{""}, 179 APIVersions: []string{"v1"}, 180 Resources: []string{"pods"}, 181 }, 182 }, 183 }, 184 }, 185 }, 186 }, 187 }) 188 } 189 190 func (s *webhooksSuite) TestK8sMutatingWebhookInvalid(c *gc.C) { 191 spec := ` 192 name: example-mutatingwebhookconfiguration 193 labels: 194 foo: bar 195 annotations: 196 juju.io/disable-name-prefix: "true" 197 ` 198 var obj k8sspecs.K8sMutatingWebhook 199 err := k8sspecs.NewStrictYAMLOrJSONDecoder(strings.NewReader(spec), len(spec)).Decode(&obj) 200 c.Assert(err, jc.ErrorIsNil) 201 c.Assert(obj.Validate(), gc.ErrorMatches, `empty webhooks "example-mutatingwebhookconfiguration" not valid`) 202 } 203 204 func (s *webhooksSuite) TestK8sValidatingWebhookV1Beta1(c *gc.C) { 205 206 specV1Beta1 := ` 207 name: pod-policy.example.com 208 labels: 209 foo: bar 210 annotations: 211 juju.io/disable-name-prefix: "true" 212 webhooks: 213 - name: "pod-policy.example.com" 214 rules: 215 - apiGroups: [""] 216 apiVersions: ["v1"] 217 operations: ["CREATE"] 218 resources: ["pods"] 219 scope: "Namespaced" 220 clientConfig: 221 service: 222 namespace: "example-namespace" 223 name: "example-service" 224 caBundle: "YXBwbGVz" 225 admissionReviewVersions: ["v1", "v1beta1"] 226 sideEffects: None 227 timeoutSeconds: 5 228 ` 229 var obj k8sspecs.K8sValidatingWebhook 230 err := k8sspecs.NewStrictYAMLOrJSONDecoder(strings.NewReader(specV1Beta1), len(specV1Beta1)).Decode(&obj) 231 c.Assert(err, jc.ErrorIsNil) 232 233 CABundle, err := base64.StdEncoding.DecodeString("YXBwbGVz") 234 c.Assert(err, jc.ErrorIsNil) 235 scope := admissionregistrationv1beta1.NamespacedScope 236 sideEffects := admissionregistrationv1beta1.SideEffectClassNone 237 c.Assert(obj, gc.DeepEquals, k8sspecs.K8sValidatingWebhook{ 238 Meta: k8sspecs.Meta{ 239 Name: "pod-policy.example.com", 240 Labels: map[string]string{"foo": "bar"}, 241 Annotations: map[string]string{"juju.io/disable-name-prefix": "true"}, 242 }, 243 Webhooks: []k8sspecs.K8sValidatingWebhookSpec{ 244 { 245 Version: k8sspecs.K8sWebhookV1Beta1, 246 SpecV1Beta1: admissionregistrationv1beta1.ValidatingWebhook{ 247 Name: "pod-policy.example.com", 248 Rules: []admissionregistrationv1beta1.RuleWithOperations{ 249 { 250 Operations: []admissionregistrationv1beta1.OperationType{ 251 admissionregistrationv1beta1.Create, 252 }, 253 Rule: admissionregistrationv1beta1.Rule{ 254 APIGroups: []string{""}, 255 APIVersions: []string{"v1"}, 256 Resources: []string{"pods"}, 257 Scope: &scope, 258 }, 259 }, 260 }, 261 ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{ 262 Service: &admissionregistrationv1beta1.ServiceReference{ 263 Name: "example-service", 264 Namespace: "example-namespace", 265 }, 266 CABundle: CABundle, 267 }, 268 AdmissionReviewVersions: []string{"v1", "v1beta1"}, 269 SideEffects: &sideEffects, 270 TimeoutSeconds: pointer.Int32Ptr(5), 271 }, 272 }, 273 }, 274 }) 275 } 276 277 func (s *webhooksSuite) TestK8sValidatingWebhookV1(c *gc.C) { 278 279 specV1 := ` 280 name: pod-policy.example.com 281 labels: 282 foo: bar 283 annotations: 284 juju.io/disable-name-prefix: "true" 285 webhooks: 286 - name: "pod-policy.example.com" 287 rules: 288 - apiGroups: [""] 289 apiVersions: ["v1"] 290 operations: ["CREATE"] 291 resources: ["pods"] 292 scope: "Namespaced" 293 clientConfig: 294 service: 295 namespace: "example-namespace" 296 name: "example-service" 297 caBundle: "YXBwbGVz" 298 admissionReviewVersions: ["v1", "v1beta1"] 299 sideEffects: None 300 timeoutSeconds: 5 301 ` 302 var obj k8sspecs.K8sValidatingWebhook 303 err := k8sspecs.NewStrictYAMLOrJSONDecoder(strings.NewReader(specV1), len(specV1)).Decode(&obj) 304 c.Assert(err, jc.ErrorIsNil) 305 306 CABundle, err := base64.StdEncoding.DecodeString("YXBwbGVz") 307 c.Assert(err, jc.ErrorIsNil) 308 scope := admissionregistrationv1beta1.NamespacedScope 309 sideEffects := admissionregistrationv1beta1.SideEffectClassNone 310 c.Assert(obj, gc.DeepEquals, k8sspecs.K8sValidatingWebhook{ 311 Meta: k8sspecs.Meta{ 312 Name: "pod-policy.example.com", 313 Labels: map[string]string{"foo": "bar"}, 314 Annotations: map[string]string{"juju.io/disable-name-prefix": "true"}, 315 }, 316 Webhooks: []k8sspecs.K8sValidatingWebhookSpec{ 317 { 318 Version: k8sspecs.K8sWebhookV1Beta1, 319 SpecV1Beta1: admissionregistrationv1beta1.ValidatingWebhook{ 320 Name: "pod-policy.example.com", 321 Rules: []admissionregistrationv1beta1.RuleWithOperations{ 322 { 323 Operations: []admissionregistrationv1beta1.OperationType{ 324 admissionregistrationv1beta1.Create, 325 }, 326 Rule: admissionregistrationv1beta1.Rule{ 327 APIGroups: []string{""}, 328 APIVersions: []string{"v1"}, 329 Resources: []string{"pods"}, 330 Scope: &scope, 331 }, 332 }, 333 }, 334 ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{ 335 Service: &admissionregistrationv1beta1.ServiceReference{ 336 Name: "example-service", 337 Namespace: "example-namespace", 338 }, 339 CABundle: CABundle, 340 }, 341 AdmissionReviewVersions: []string{"v1", "v1beta1"}, 342 SideEffects: &sideEffects, 343 TimeoutSeconds: pointer.Int32Ptr(5), 344 }, 345 }, 346 }, 347 }) 348 } 349 350 func (s *webhooksSuite) TestK8sValidatingWebhookInvalid(c *gc.C) { 351 352 spec := ` 353 name: pod-policy.example.com 354 labels: 355 foo: bar 356 annotations: 357 juju.io/disable-name-prefix: "true" 358 ` 359 var obj k8sspecs.K8sValidatingWebhook 360 err := k8sspecs.NewStrictYAMLOrJSONDecoder(strings.NewReader(spec), len(spec)).Decode(&obj) 361 c.Assert(err, jc.ErrorIsNil) 362 c.Assert(obj.Validate(), gc.ErrorMatches, `empty webhooks "pod-policy.example.com" not valid`) 363 }