@@ -22,6 +22,11 @@ import (
22
22
23
23
"k8s.io/api/core/v1"
24
24
"k8s.io/apimachinery/pkg/api/resource"
25
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26
+ v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
27
+ "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodename"
28
+ "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeports"
29
+ "k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources"
25
30
schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"
26
31
)
27
32
@@ -110,3 +115,147 @@ func makeTestNode(allocatable v1.ResourceList) *v1.Node {
110
115
},
111
116
}
112
117
}
118
+
119
+ var (
120
+ extendedResourceA = v1 .ResourceName ("example.com/aaa" )
121
+ hugePageResourceA = v1helper .HugePageResourceName (resource .MustParse ("2Mi" ))
122
+ )
123
+
124
+ func makeResources (milliCPU , memory , pods , extendedA , storage , hugePageA int64 ) v1.NodeResources {
125
+ return v1.NodeResources {
126
+ Capacity : v1.ResourceList {
127
+ v1 .ResourceCPU : * resource .NewMilliQuantity (milliCPU , resource .DecimalSI ),
128
+ v1 .ResourceMemory : * resource .NewQuantity (memory , resource .BinarySI ),
129
+ v1 .ResourcePods : * resource .NewQuantity (pods , resource .DecimalSI ),
130
+ extendedResourceA : * resource .NewQuantity (extendedA , resource .DecimalSI ),
131
+ v1 .ResourceEphemeralStorage : * resource .NewQuantity (storage , resource .BinarySI ),
132
+ hugePageResourceA : * resource .NewQuantity (hugePageA , resource .BinarySI ),
133
+ },
134
+ }
135
+ }
136
+
137
+ func makeAllocatableResources (milliCPU , memory , pods , extendedA , storage , hugePageA int64 ) v1.ResourceList {
138
+ return v1.ResourceList {
139
+ v1 .ResourceCPU : * resource .NewMilliQuantity (milliCPU , resource .DecimalSI ),
140
+ v1 .ResourceMemory : * resource .NewQuantity (memory , resource .BinarySI ),
141
+ v1 .ResourcePods : * resource .NewQuantity (pods , resource .DecimalSI ),
142
+ extendedResourceA : * resource .NewQuantity (extendedA , resource .DecimalSI ),
143
+ v1 .ResourceEphemeralStorage : * resource .NewQuantity (storage , resource .BinarySI ),
144
+ hugePageResourceA : * resource .NewQuantity (hugePageA , resource .BinarySI ),
145
+ }
146
+ }
147
+
148
+ func newResourcePod (usage ... schedulernodeinfo.Resource ) * v1.Pod {
149
+ containers := []v1.Container {}
150
+ for _ , req := range usage {
151
+ containers = append (containers , v1.Container {
152
+ Resources : v1.ResourceRequirements {Requests : req .ResourceList ()},
153
+ })
154
+ }
155
+ return & v1.Pod {
156
+ Spec : v1.PodSpec {
157
+ Containers : containers ,
158
+ },
159
+ }
160
+ }
161
+
162
+ func newPodWithPort (hostPorts ... int ) * v1.Pod {
163
+ networkPorts := []v1.ContainerPort {}
164
+ for _ , port := range hostPorts {
165
+ networkPorts = append (networkPorts , v1.ContainerPort {HostPort : int32 (port )})
166
+ }
167
+ return & v1.Pod {
168
+ Spec : v1.PodSpec {
169
+ Containers : []v1.Container {
170
+ {
171
+ Ports : networkPorts ,
172
+ },
173
+ },
174
+ },
175
+ }
176
+ }
177
+
178
+ func TestGeneralPredicates (t * testing.T ) {
179
+ resourceTests := []struct {
180
+ pod * v1.Pod
181
+ nodeInfo * schedulernodeinfo.NodeInfo
182
+ node * v1.Node
183
+ fits bool
184
+ name string
185
+ wErr error
186
+ reasons []PredicateFailureReason
187
+ }{
188
+ {
189
+ pod : & v1.Pod {},
190
+ nodeInfo : schedulernodeinfo .NewNodeInfo (
191
+ newResourcePod (schedulernodeinfo.Resource {MilliCPU : 9 , Memory : 19 })),
192
+ node : & v1.Node {
193
+ ObjectMeta : metav1.ObjectMeta {Name : "machine1" },
194
+ Status : v1.NodeStatus {Capacity : makeResources (10 , 20 , 32 , 0 , 0 , 0 ).Capacity , Allocatable : makeAllocatableResources (10 , 20 , 32 , 0 , 0 , 0 )},
195
+ },
196
+ fits : true ,
197
+ wErr : nil ,
198
+ name : "no resources/port/host requested always fits" ,
199
+ },
200
+ {
201
+ pod : newResourcePod (schedulernodeinfo.Resource {MilliCPU : 8 , Memory : 10 }),
202
+ nodeInfo : schedulernodeinfo .NewNodeInfo (
203
+ newResourcePod (schedulernodeinfo.Resource {MilliCPU : 5 , Memory : 19 })),
204
+ node : & v1.Node {
205
+ ObjectMeta : metav1.ObjectMeta {Name : "machine1" },
206
+ Status : v1.NodeStatus {Capacity : makeResources (10 , 20 , 32 , 0 , 0 , 0 ).Capacity , Allocatable : makeAllocatableResources (10 , 20 , 32 , 0 , 0 , 0 )},
207
+ },
208
+ fits : false ,
209
+ wErr : nil ,
210
+ reasons : []PredicateFailureReason {
211
+ & InsufficientResourceError {InsufficientResource : noderesources.InsufficientResource {ResourceName : v1 .ResourceCPU , Requested : 8 , Used : 5 , Capacity : 10 }},
212
+ & InsufficientResourceError {InsufficientResource : noderesources.InsufficientResource {ResourceName : v1 .ResourceMemory , Requested : 10 , Used : 19 , Capacity : 20 }},
213
+ },
214
+ name : "not enough cpu and memory resource" ,
215
+ },
216
+ {
217
+ pod : & v1.Pod {
218
+ Spec : v1.PodSpec {
219
+ NodeName : "machine2" ,
220
+ },
221
+ },
222
+ nodeInfo : schedulernodeinfo .NewNodeInfo (),
223
+ node : & v1.Node {
224
+ ObjectMeta : metav1.ObjectMeta {Name : "machine1" },
225
+ Status : v1.NodeStatus {Capacity : makeResources (10 , 20 , 32 , 0 , 0 , 0 ).Capacity , Allocatable : makeAllocatableResources (10 , 20 , 32 , 0 , 0 , 0 )},
226
+ },
227
+ fits : false ,
228
+ wErr : nil ,
229
+ reasons : []PredicateFailureReason {& PredicateFailureError {nodename .Name , nodename .ErrReason }},
230
+ name : "host not match" ,
231
+ },
232
+ {
233
+ pod : newPodWithPort (123 ),
234
+ nodeInfo : schedulernodeinfo .NewNodeInfo (newPodWithPort (123 )),
235
+ node : & v1.Node {
236
+ ObjectMeta : metav1.ObjectMeta {Name : "machine1" },
237
+ Status : v1.NodeStatus {Capacity : makeResources (10 , 20 , 32 , 0 , 0 , 0 ).Capacity , Allocatable : makeAllocatableResources (10 , 20 , 32 , 0 , 0 , 0 )},
238
+ },
239
+ fits : false ,
240
+ wErr : nil ,
241
+ reasons : []PredicateFailureReason {& PredicateFailureError {nodeports .Name , nodeports .ErrReason }},
242
+ name : "hostport conflict" ,
243
+ },
244
+ }
245
+ for _ , test := range resourceTests {
246
+ t .Run (test .name , func (t * testing.T ) {
247
+ test .nodeInfo .SetNode (test .node )
248
+ reasons , err := GeneralPredicates (test .pod , test .nodeInfo )
249
+ fits := len (reasons ) == 0 && err == nil
250
+ if err != nil {
251
+ t .Errorf ("unexpected error: %v" , err )
252
+ }
253
+ if ! fits && ! reflect .DeepEqual (reasons , test .reasons ) {
254
+ t .Errorf ("unexpected failure reasons: %v, want: %v" , reasons , test .reasons )
255
+ }
256
+ if fits != test .fits {
257
+ t .Errorf ("expected: %v got %v" , test .fits , fits )
258
+ }
259
+ })
260
+ }
261
+ }
0 commit comments