Support opaque integer resource accounting.
- Prevents kubelet from overwriting capacity during sync. - Handles opaque integer resources in the scheduler. - Adds scheduler predicate tests for opaque resources. - Validates opaque int resources: - Ensures supplied opaque int quantities in node capacity, node allocatable, pod request and pod limit are integers. - Adds tests for new validation logic (node update and pod spec). - Added e2e tests for opaque integer resources.
This commit is contained in:
@@ -3665,6 +3665,52 @@ func TestValidatePod(t *testing.T) {
|
||||
},
|
||||
Spec: validPodSpec,
|
||||
},
|
||||
{ // valid opaque integer resources for init container
|
||||
ObjectMeta: api.ObjectMeta{Name: "valid-opaque-int", Namespace: "ns"},
|
||||
Spec: api.PodSpec{
|
||||
InitContainers: []api.Container{
|
||||
{
|
||||
Name: "valid-opaque-int",
|
||||
Image: "image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("10"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("20"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||
RestartPolicy: api.RestartPolicyAlways,
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
{ // valid opaque integer resources for regular container
|
||||
ObjectMeta: api.ObjectMeta{Name: "valid-opaque-int", Namespace: "ns"},
|
||||
Spec: api.PodSpec{
|
||||
InitContainers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "valid-opaque-int",
|
||||
Image: "image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("10"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("20"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RestartPolicy: api.RestartPolicyAlways,
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, pod := range successCases {
|
||||
if errs := ValidatePod(&pod); len(errs) != 0 {
|
||||
@@ -4155,6 +4201,112 @@ func TestValidatePod(t *testing.T) {
|
||||
},
|
||||
Spec: validPodSpec,
|
||||
},
|
||||
"invalid opaque integer resource requirement: request must be <= limit": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "invalid",
|
||||
Image: "image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("2"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RestartPolicy: api.RestartPolicyAlways,
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
"invalid fractional opaque integer resource in container request": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "invalid",
|
||||
Image: "image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("500m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RestartPolicy: api.RestartPolicyAlways,
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
"invalid fractional opaque integer resource in init container request": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"},
|
||||
Spec: api.PodSpec{
|
||||
InitContainers: []api.Container{
|
||||
{
|
||||
Name: "invalid",
|
||||
Image: "image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("500m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||
RestartPolicy: api.RestartPolicyAlways,
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
"invalid fractional opaque integer resource in container limit": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "invalid",
|
||||
Image: "image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("2.5"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RestartPolicy: api.RestartPolicyAlways,
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
"invalid fractional opaque integer resource in init container limit": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"},
|
||||
Spec: api.PodSpec{
|
||||
InitContainers: []api.Container{
|
||||
{
|
||||
Name: "invalid",
|
||||
Image: "image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("2.5"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||
RestartPolicy: api.RestartPolicyAlways,
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
}
|
||||
for k, v := range errorCases {
|
||||
if errs := ValidatePod(&v); len(errs) == 0 {
|
||||
@@ -6347,6 +6499,60 @@ func TestValidateNodeUpdate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}, false},
|
||||
{api.Node{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "valid-opaque-int-resources",
|
||||
},
|
||||
}, api.Node{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "valid-opaque-int-resources",
|
||||
},
|
||||
Status: api.NodeStatus{
|
||||
Capacity: api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse("10"),
|
||||
api.ResourceName(api.ResourceMemory): resource.MustParse("10G"),
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
api.OpaqueIntResourceName("B"): resource.MustParse("10"),
|
||||
},
|
||||
},
|
||||
}, true},
|
||||
{api.Node{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "invalid-fractional-opaque-int-capacity",
|
||||
},
|
||||
}, api.Node{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "invalid-fractional-opaque-int-capacity",
|
||||
},
|
||||
Status: api.NodeStatus{
|
||||
Capacity: api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse("10"),
|
||||
api.ResourceName(api.ResourceMemory): resource.MustParse("10G"),
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("500m"),
|
||||
},
|
||||
},
|
||||
}, false},
|
||||
{api.Node{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "invalid-fractional-opaque-int-allocatable",
|
||||
},
|
||||
}, api.Node{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "invalid-fractional-opaque-int-allocatable",
|
||||
},
|
||||
Status: api.NodeStatus{
|
||||
Capacity: api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse("10"),
|
||||
api.ResourceName(api.ResourceMemory): resource.MustParse("10G"),
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
},
|
||||
Allocatable: api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse("10"),
|
||||
api.ResourceName(api.ResourceMemory): resource.MustParse("10G"),
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("4.5"),
|
||||
},
|
||||
},
|
||||
}, false},
|
||||
}
|
||||
for i, test := range tests {
|
||||
test.oldNode.ObjectMeta.ResourceVersion = "1"
|
||||
|
Reference in New Issue
Block a user