@@ -11,79 +11,122 @@ import (
11
11
corev1 "k8s.io/api/core/v1"
12
12
schedulev1 "k8s.io/api/scheduling/v1"
13
13
"k8s.io/client-go/tools/record"
14
+ "k8s.io/utils/ptr"
14
15
"sigs.k8s.io/controller-runtime/pkg/client"
15
16
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
16
17
17
- capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2 "
18
+ "github.com/projectcapsule/capsule/pkg/api "
18
19
"github.com/projectcapsule/capsule/pkg/webhook/utils"
19
20
)
20
21
21
22
func mutatePodDefaults (ctx context.Context , req admission.Request , c client.Client , decoder admission.Decoder , recorder record.EventRecorder , namespace string ) * admission.Response {
22
- var err error
23
-
24
- pod := & corev1.Pod {}
25
- if err = decoder .Decode (req , pod ); err != nil {
23
+ var pod corev1.Pod
24
+ if err := decoder .Decode (req , & pod ); err != nil {
26
25
return utils .ErroredResponse (err )
27
26
}
28
27
29
28
pod .SetNamespace (namespace )
30
29
31
- var tnt * capsulev1beta2.Tenant
30
+ tnt , tErr := utils .TenantByStatusNamespace (ctx , c , pod .Namespace )
31
+ if tErr != nil {
32
+ return utils .ErroredResponse (tErr )
33
+ } else if tnt == nil {
34
+ return nil
35
+ }
32
36
33
- tnt , err = utils .TenantByStatusNamespace (ctx , c , pod .Namespace )
34
- if err != nil {
35
- return utils .ErroredResponse (err )
37
+ var err error
38
+
39
+ pcMutated , pcErr := handlePriorityClassDefault (ctx , c , tnt .Spec .PriorityClasses , & pod )
40
+ if pcErr != nil {
41
+ return utils .ErroredResponse (pcErr )
42
+ } else if pcMutated {
43
+ defer func () {
44
+ if err == nil {
45
+ recorder .Eventf (tnt , corev1 .EventTypeNormal , "TenantDefault" , "Assigned Tenant default Priority Class %s to %s/%s" , tnt .Spec .PriorityClasses .Default , pod .Namespace , pod .Name )
46
+ }
47
+ }()
48
+ }
49
+
50
+ rcMutated , rcErr := handleRuntimeClassDefault (tnt .Spec .RuntimeClasses , & pod )
51
+ if rcErr != nil {
52
+ return utils .ErroredResponse (rcErr )
53
+ } else if rcMutated {
54
+ defer func () {
55
+ if err == nil {
56
+ recorder .Eventf (tnt , corev1 .EventTypeNormal , "TenantDefault" , "Assigned Tenant default Runtime Class %s to %s/%s" , tnt .Spec .RuntimeClasses .Default , pod .Namespace , pod .Name )
57
+ }
58
+ }()
36
59
}
37
60
38
- if tnt == nil {
61
+ if ! rcMutated && ! pcMutated {
39
62
return nil
40
63
}
41
64
42
- allowed := tnt . Spec . PriorityClasses
65
+ var marshaled [] byte
43
66
67
+ if marshaled , err = json .Marshal (pod ); err != nil {
68
+ return utils .ErroredResponse (err )
69
+ }
70
+
71
+ return ptr .To (admission .PatchResponseFromRaw (req .Object .Raw , marshaled ))
72
+ }
73
+
74
+ func handleRuntimeClassDefault (allowed * api.DefaultAllowedListSpec , pod * corev1.Pod ) (mutated bool , err error ) {
44
75
if allowed == nil || allowed .Default == "" {
45
- return nil
76
+ return false , nil
46
77
}
47
78
48
- priorityClassPod := pod .Spec .PriorityClassName
79
+ runtimeClass := pod .Spec .RuntimeClassName
49
80
50
- var mutate bool
81
+ if allowed .Default == "" && runtimeClass == nil {
82
+ return false , nil
83
+ }
84
+
85
+ if allowed .Default != "" && runtimeClass != nil && * runtimeClass == allowed .Default {
86
+ return false , nil
87
+ }
88
+
89
+ if allowed .Default != "" && runtimeClass != nil && * runtimeClass != allowed .Default {
90
+ // Should not happen, validation must be happened before
91
+ return false , NewRuntimeClassError (allowed .Default , * runtimeClass )
92
+ }
93
+
94
+ pod .Spec .RuntimeClassName = & allowed .Default
95
+
96
+ return true , nil
97
+ }
98
+
99
+ func handlePriorityClassDefault (ctx context.Context , c client.Client , allowed * api.DefaultAllowedListSpec , pod * corev1.Pod ) (mutated bool , err error ) {
100
+ if allowed == nil || allowed .Default == "" {
101
+ return false , nil
102
+ }
103
+
104
+ priorityClassPod := pod .Spec .PriorityClassName
51
105
52
106
var cpc * schedulev1.PriorityClass
53
107
// PriorityClass name is empty, if no GlobalDefault is set and no PriorityClass was given on pod
54
108
if len (priorityClassPod ) > 0 && priorityClassPod != allowed .Default {
55
109
cpc , err = utils .GetPriorityClassByName (ctx , c , priorityClassPod )
56
110
// Should not happen, since API already checks if PC present
57
111
if err != nil {
58
- response := admission .Denied (NewPriorityClassError (priorityClassPod , err ).Error ())
59
-
60
- return & response
112
+ return false , NewPriorityClassError (priorityClassPod , err )
61
113
}
62
114
} else {
63
- mutate = true
115
+ mutated = true
64
116
}
65
117
66
- if mutate = mutate || (utils .IsDefaultPriorityClass (cpc ) && cpc .GetName () != allowed .Default ); ! mutate {
67
- return nil
118
+ if mutated = mutated || (utils .IsDefaultPriorityClass (cpc ) && cpc .GetName () != allowed .Default ); ! mutated {
119
+ return false , nil
68
120
}
69
121
70
122
pc , err := utils .GetPriorityClassByName (ctx , c , allowed .Default )
71
123
if err != nil {
72
- return utils . ErroredResponse ( fmt .Errorf ("failed to assign tenant default Priority Class: %w" , err ) )
124
+ return false , fmt .Errorf ("failed to assign tenant default Priority Class: %w" , err )
73
125
}
74
126
75
127
pod .Spec .PreemptionPolicy = pc .PreemptionPolicy
76
128
pod .Spec .Priority = & pc .Value
77
129
pod .Spec .PriorityClassName = pc .Name
78
- // Marshal Pod
79
- marshaled , err := json .Marshal (pod )
80
- if err != nil {
81
- return utils .ErroredResponse (err )
82
- }
83
-
84
- recorder .Eventf (tnt , corev1 .EventTypeNormal , "TenantDefault" , "Assigned Tenant default Priority Class %s to %s/%s" , allowed .Default , pod .Namespace , pod .Name )
85
-
86
- response := admission .PatchResponseFromRaw (req .Object .Raw , marshaled )
87
130
88
- return & response
131
+ return true , nil
89
132
}
0 commit comments