@@ -2,31 +2,103 @@ package webhooks
2
2
3
3
import (
4
4
"context"
5
- "encoding/json"
6
- "testing"
7
5
8
- admissionv1 "k8s.io/api/admission/v1 "
9
- "k8s.io/client-go/kubernetes/scheme "
10
- "sigs.k8s.io/controller-runtime/pkg/client/fake "
11
- "sigs. k8s.io/controller-runtime/pkg/webhook/admission "
12
-
13
- "github.com/stretchr/testify/assert "
6
+ "github.com/miyunari/model-validation-controller/api/v1alpha1 "
7
+ . "github.com/onsi/ginkgo/v2 "
8
+ . "github.com/onsi/gomega "
9
+ corev1 " k8s.io/api/core/v1 "
10
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11
+ "k8s.io/apimachinery/pkg/types "
14
12
)
15
13
16
- func Test_PodInterceptor_Handle ( t * testing. T ) {
17
- const req = `{"kind":"AdmissionReview","apiVersion":"admission.k8s.io/v1","request":{"uid":"c33e1334-1a38-4684-aff8-e8c366ea89b9","kind":{"group":"","version":"v1","kind":"Pod"},"resource":{"group":"","version":"v1","resource":"pods"},"requestKind":{"group":"","version":"v1","kind":"Pod"},"requestResource":{"group":"","version":"v1","resource":"pods"},"name":"ollama","namespace":"model-validation-controller","operation":"CREATE","userInfo":{"username":"admin","groups":["system:masters","system:authenticated"],"extra":{"authentication.kubernetes.io/credential-id":["X509SHA256=acb312b9049f7fbeb8788001d7e61e145f10df1e4a752d1ef2caa3097d233246"]}},"object":{"kind":"Pod","apiVersion":"v1","metadata":{"name":"ollama","namespace":"model-validation-controller","creationTimestamp":null,"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{\"validation.rhtas.redhat.com/ml\":\"true\"},\"name\":\"ollama\",\"namespace\":\"model-validation-controller\"},\"spec\":{\"containers\":[{\"image\":\"ollama/ollama\",\"name\":\"ollama\",\"ports\":[{\"containerPort\":11434}]}]}}\n","validation.rhtas.redhat.com/ml":"true"},"managedFields":[{"manager":"kubectl-client-side-apply","operation":"Update","apiVersion":"v1","time":"2025-01-18T20:43:09Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:kubectl.kubernetes.io/last-applied-configuration":{},"f:validation.rhtas.redhat.com/ml":{}}},"f:spec":{"f:containers":{"k:{\"name\":\"ollama\"}":{".":{},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":11434,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:enableServiceLinks":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}}]},"spec":{"volumes":[{"name":"kube-api-access-v9hhf","projected":{"sources":[{"serviceAccountToken":{"expirationSeconds":3607,"path":"token"}},{"configMap":{"name":"kube-root-ca.crt","items":[{"key":"ca.crt","path":"ca.crt"}]}},{"downwardAPI":{"items":[{"path":"namespace","fieldRef":{"apiVersion":"v1","fieldPath":"metadata.namespace"}}]}}],"defaultMode":420}}],"containers":[{"name":"ollama","image":"ollama/ollama","ports":[{"containerPort":11434,"protocol":"TCP"}],"resources":{},"volumeMounts":[{"name":"kube-api-access-v9hhf","readOnly":true,"mountPath":"/var/run/secrets/kubernetes.io/serviceaccount"}],"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"Always"}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","serviceAccountName":"default","serviceAccount":"default","securityContext":{},"schedulerName":"default-scheduler","tolerations":[{"key":"node.kubernetes.io/not-ready","operator":"Exists","effect":"NoExecute","tolerationSeconds":300},{"key":"node.kubernetes.io/unreachable","operator":"Exists","effect":"NoExecute","tolerationSeconds":300}],"priority":0,"enableServiceLinks":true,"preemptionPolicy":"PreemptLowerPriority"},"status":{}},"oldObject":null,"dryRun":false,"options":{"kind":"CreateOptions","apiVersion":"meta.k8s.io/v1","fieldManager":"kubectl-client-side-apply"}}}`
14
+ var _ = Describe ( "Pod webhook" , func ( ) {
15
+ Context ("Pod webhook test" , func () {
18
16
19
- var review admissionv1.AdmissionReview
20
- err := json .Unmarshal ([]byte (req ), & review )
21
- assert .NoError (t , err )
17
+ const (
18
+ Name = "test"
19
+ Namespace = "default"
20
+ )
22
21
23
- decoder := admission .NewDecoder (scheme .Scheme )
24
- handler := NewPodInterceptor (fake .NewClientBuilder ().Build (), decoder )
22
+ ctx := context .Background ()
25
23
26
- resp := handler .Handle (context .Background (), admission.Request {
27
- AdmissionRequest : * review .Request ,
28
- })
24
+ namespace := & corev1.Namespace {
25
+ ObjectMeta : metav1.ObjectMeta {
26
+ Name : Name ,
27
+ Namespace : Namespace ,
28
+ },
29
+ }
30
+
31
+ typeNamespaceName := types.NamespacedName {Name : Name , Namespace : Namespace }
32
+
33
+ BeforeEach (func () {
34
+ By ("Creating the Namespace to perform the tests" )
35
+ err := k8sClient .Create (ctx , namespace )
36
+ Expect (err ).To (Not (HaveOccurred ()))
37
+
38
+ By ("Create ModelValidation resource" )
39
+ err = k8sClient .Create (ctx , & v1alpha1.ModelValidation {
40
+ ObjectMeta : metav1.ObjectMeta {
41
+ Name : Name ,
42
+ Namespace : Namespace ,
43
+ },
44
+ Spec : v1alpha1.ModelValidationSpec {
45
+ Model : v1alpha1.Model {
46
+ Path : "test" ,
47
+ SignaturePath : "test" ,
48
+ },
49
+ Config : v1alpha1.ValidationConfig {
50
+ SigstoreConfig : nil ,
51
+ PkiConfig : nil ,
52
+ PrivateKeyConfig : nil ,
53
+ },
54
+ },
55
+ })
56
+ Expect (err ).To (Not (HaveOccurred ()))
57
+ })
29
58
30
- assert .NotNil (t , resp )
31
- assert .True (t , resp .Allowed )
32
- }
59
+ AfterEach (func () {
60
+ // TODO(user): Attention if you improve this code by adding other context test you MUST
61
+ // be aware of the current delete namespace limitations.
62
+ // More info: https://book.kubebuilder.io/reference/envtest.html#testing-considerations
63
+ By ("Deleting the Namespace to perform the tests" )
64
+ _ = k8sClient .Delete (ctx , namespace )
65
+ })
66
+
67
+ It ("Should create sidecar container" , func () {
68
+ By ("create labeled pod" )
69
+ instance := & corev1.Pod {
70
+ ObjectMeta : metav1.ObjectMeta {
71
+ Name : Name ,
72
+ Namespace : Namespace ,
73
+ Labels : map [string ]string {"validation.rhtas.redhat.com/ml" : "true" },
74
+ },
75
+ Spec : corev1.PodSpec {
76
+ Containers : []corev1.Container {
77
+ {
78
+ Name : "test" ,
79
+ Image : "test" ,
80
+ },
81
+ },
82
+ },
83
+ }
84
+ err := k8sClient .Create (ctx , instance )
85
+ Expect (err ).To (Not (HaveOccurred ()))
86
+
87
+ By ("Checking that validation sidecar was created" )
88
+ found := & corev1.Pod {}
89
+ Eventually (func () error {
90
+ return k8sClient .Get (ctx , typeNamespaceName , found )
91
+ }).Should (Succeed ())
92
+
93
+ Eventually (
94
+ func (g Gomega ) []corev1.Container {
95
+ Expect (k8sClient .Get (ctx , typeNamespaceName , found )).To (Succeed ())
96
+ return found .Spec .InitContainers
97
+ },
98
+ ).Should (And (
99
+ WithTransform (func (containers []corev1.Container ) int { return len (containers ) }, Equal (1 )),
100
+ WithTransform (func (containers []corev1.Container ) string { return containers [0 ].Image }, Equal ("ghcr.io/sigstore/model-transparency-cli:v1.0.1" )),
101
+ ))
102
+ })
103
+ })
104
+ })
0 commit comments