@@ -38,6 +38,7 @@ import (
38
38
node "k8s.io/kubernetes/pkg/apis/node"
39
39
nodev1beta1 "k8s.io/kubernetes/pkg/apis/node/v1beta1"
40
40
"k8s.io/kubernetes/pkg/features"
41
+ "k8s.io/kubernetes/pkg/util/tolerations"
41
42
)
42
43
43
44
// PluginName indicates name of admission plugin.
@@ -81,6 +82,9 @@ func (r *RuntimeClass) ValidateInitialization() error {
81
82
82
83
// Admit makes an admission decision based on the request attributes
83
84
func (r * RuntimeClass ) Admit (ctx context.Context , attributes admission.Attributes , o admission.ObjectInterfaces ) error {
85
+ if ! utilfeature .DefaultFeatureGate .Enabled (features .RuntimeClass ) {
86
+ return nil
87
+ }
84
88
85
89
// Ignore all calls to subresources or resources other than pods.
86
90
if shouldIgnore (attributes ) {
@@ -92,18 +96,20 @@ func (r *RuntimeClass) Admit(ctx context.Context, attributes admission.Attribute
92
96
return err
93
97
}
94
98
if utilfeature .DefaultFeatureGate .Enabled (features .PodOverhead ) {
95
- err = setOverhead (attributes , pod , runtimeClass )
96
- if err != nil {
99
+ if err := setOverhead (attributes , pod , runtimeClass ); err != nil {
97
100
return err
98
101
}
99
102
}
100
103
104
+ if err := setScheduling (attributes , pod , runtimeClass ); err != nil {
105
+ return err
106
+ }
107
+
101
108
return nil
102
109
}
103
110
104
111
// Validate makes sure that pod adhere's to RuntimeClass's definition
105
112
func (r * RuntimeClass ) Validate (ctx context.Context , attributes admission.Attributes , o admission.ObjectInterfaces ) error {
106
-
107
113
// Ignore all calls to subresources or resources other than pods.
108
114
if shouldIgnore (attributes ) {
109
115
return nil
@@ -114,7 +120,7 @@ func (r *RuntimeClass) Validate(ctx context.Context, attributes admission.Attrib
114
120
return err
115
121
}
116
122
if utilfeature .DefaultFeatureGate .Enabled (features .PodOverhead ) {
117
- if err = validateOverhead (attributes , pod , runtimeClass ); err != nil {
123
+ if err : = validateOverhead (attributes , pod , runtimeClass ); err != nil {
118
124
return err
119
125
}
120
126
}
@@ -131,34 +137,33 @@ func NewRuntimeClass() *RuntimeClass {
131
137
132
138
// prepareObjects returns pod and runtimeClass types from the given admission attributes
133
139
func (r * RuntimeClass ) prepareObjects (attributes admission.Attributes ) (pod * api.Pod , runtimeClass * v1beta1.RuntimeClass , err error ) {
134
-
135
140
pod , ok := attributes .GetObject ().(* api.Pod )
136
141
if ! ok {
137
142
return nil , nil , apierrors .NewBadRequest ("Resource was marked with kind Pod but was unable to be converted" )
138
143
}
139
144
145
+ if pod .Spec .RuntimeClassName == nil {
146
+ return pod , nil , nil
147
+ }
148
+
140
149
// get RuntimeClass object
141
- if pod .Spec .RuntimeClassName != nil {
142
- runtimeClass , err = r .runtimeClassLister .Get (* pod .Spec .RuntimeClassName )
143
- if err != nil {
144
- return pod , nil , err
145
- }
150
+ runtimeClass , err = r .runtimeClassLister .Get (* pod .Spec .RuntimeClassName )
151
+ if apierrors .IsNotFound (err ) {
152
+ return pod , nil , admission .NewForbidden (attributes , fmt .Errorf ("pod rejected: RuntimeClass %q not found" , * pod .Spec .RuntimeClassName ))
146
153
}
147
154
148
- // return the pod and runtimeClass. If no RuntimeClass is specified in PodSpec, runtimeClass will be nil
149
- return pod , runtimeClass , nil
155
+ // return the pod and runtimeClass.
156
+ return pod , runtimeClass , err
150
157
}
151
158
152
159
func setOverhead (a admission.Attributes , pod * api.Pod , runtimeClass * v1beta1.RuntimeClass ) (err error ) {
153
-
154
160
if runtimeClass == nil || runtimeClass .Overhead == nil {
155
161
return nil
156
162
}
157
163
158
164
// convert to internal type and assign to pod's Overhead
159
165
nodeOverhead := & node.Overhead {}
160
- err = nodev1beta1 .Convert_v1beta1_Overhead_To_node_Overhead (runtimeClass .Overhead , nodeOverhead , nil )
161
- if err != nil {
166
+ if err = nodev1beta1 .Convert_v1beta1_Overhead_To_node_Overhead (runtimeClass .Overhead , nodeOverhead , nil ); err != nil {
162
167
return err
163
168
}
164
169
@@ -172,13 +177,43 @@ func setOverhead(a admission.Attributes, pod *api.Pod, runtimeClass *v1beta1.Run
172
177
return nil
173
178
}
174
179
175
- func validateOverhead (a admission.Attributes , pod * api.Pod , runtimeClass * v1beta1.RuntimeClass ) (err error ) {
180
+ func setScheduling (a admission.Attributes , pod * api.Pod , runtimeClass * v1beta1.RuntimeClass ) (err error ) {
181
+ if runtimeClass == nil || runtimeClass .Scheduling == nil {
182
+ return nil
183
+ }
184
+
185
+ // convert to internal type and assign to pod's Scheduling
186
+ nodeScheduling := & node.Scheduling {}
187
+ if err = nodev1beta1 .Convert_v1beta1_Scheduling_To_node_Scheduling (runtimeClass .Scheduling , nodeScheduling , nil ); err != nil {
188
+ return err
189
+ }
190
+
191
+ runtimeNodeSelector := nodeScheduling .NodeSelector
192
+ newNodeSelector := pod .Spec .NodeSelector
193
+ if newNodeSelector == nil {
194
+ newNodeSelector = runtimeNodeSelector
195
+ } else {
196
+ for key , runtimeClassValue := range runtimeNodeSelector {
197
+ if podValue , ok := newNodeSelector [key ]; ok && podValue != runtimeClassValue {
198
+ return admission .NewForbidden (a , fmt .Errorf ("conflict: runtimeClass.scheduling.nodeSelector[%s] = %s; pod.spec.nodeSelector[%s] = %s" , key , runtimeClassValue , key , podValue ))
199
+ }
200
+ newNodeSelector [key ] = runtimeClassValue
201
+ }
202
+ }
203
+
204
+ newTolerations := tolerations .MergeTolerations (pod .Spec .Tolerations , nodeScheduling .Tolerations )
176
205
206
+ pod .Spec .NodeSelector = newNodeSelector
207
+ pod .Spec .Tolerations = newTolerations
208
+
209
+ return nil
210
+ }
211
+
212
+ func validateOverhead (a admission.Attributes , pod * api.Pod , runtimeClass * v1beta1.RuntimeClass ) (err error ) {
177
213
if runtimeClass != nil && runtimeClass .Overhead != nil {
178
214
// If the Overhead set doesn't match what is provided in the RuntimeClass definition, reject the pod
179
215
nodeOverhead := & node.Overhead {}
180
- err := nodev1beta1 .Convert_v1beta1_Overhead_To_node_Overhead (runtimeClass .Overhead , nodeOverhead , nil )
181
- if err != nil {
216
+ if err := nodev1beta1 .Convert_v1beta1_Overhead_To_node_Overhead (runtimeClass .Overhead , nodeOverhead , nil ); err != nil {
182
217
return err
183
218
}
184
219
if ! apiequality .Semantic .DeepEqual (nodeOverhead .PodFixed , pod .Spec .Overhead ) {
0 commit comments