Skip to content

Commit

Permalink
Merge pull request #1855 from openshift-cherrypick-robot/cherry-pick-…
Browse files Browse the repository at this point in the history
…1821-to-release-4.14

[release-4.14] OCPBUGS-27347: UPSTREAM: <carry>: Update management webhook pod admission logic
  • Loading branch information
openshift-merge-bot[bot] committed Feb 21, 2024
2 parents 28ed2d7 + 4c490f2 commit c79e5e2
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 20 deletions.
Expand Up @@ -217,6 +217,13 @@ func (a *managementCPUsOverride) Admit(ctx context.Context, attr admission.Attri
return err
}

if _, found := ns.Annotations[namespaceAllowedAnnotation]; !found && len(workloadType) > 0 {
pod.Annotations[workloadAdmissionWarning] = fmt.Sprintf(
"skipping pod CPUs requests modifications because the %s namespace is not annotated with %s to allow workload partitioning",
ns.GetName(), namespaceAllowedAnnotation)
return nil
}

if !doesNamespaceAllowWorkloadType(ns.Annotations, workloadType) {
return admission.NewForbidden(attr, fmt.Errorf("%s the pod namespace %q does not allow the workload type %s", PluginName, ns.Name, workloadType))
}
Expand Down Expand Up @@ -449,10 +456,13 @@ func podHasBothCPULimitAndRequest(containers []coreapi.Container) bool {
return false
}

// doesNamespaceAllowWorkloadType will return false when a workload type does not match any present ones.
func doesNamespaceAllowWorkloadType(annotations map[string]string, workloadType string) bool {
v, found := annotations[namespaceAllowedAnnotation]
// When a namespace contains no annotation for workloads we infer that to mean all workload types are allowed.
// The mutation hook will strip all workload annotation from pods that contain them in that circumstance.
if !found {
return false
return true
}

for _, t := range strings.Split(v, ",") {
Expand Down
Expand Up @@ -84,12 +84,12 @@ func TestAdmit(t *testing.T) {
}{
{
name: "should return admission error when the pod namespace does not allow the workload type",
pod: testManagedPod("500m", "250m", "500Mi", "250Mi"),
pod: testManagedPodWithWorkloadAnnotation("500m", "250m", "500Mi", "250Mi", "non-existent"),
expectedCpuRequest: resource.MustParse("250m"),
namespace: testNamespace(),
namespace: testManagedNamespace(),
nodes: []*corev1.Node{testNodeWithManagementResource()},
infra: testClusterSNOInfra(),
expectedError: fmt.Errorf("the pod namespace %q does not allow the workload type management", "namespace"),
expectedError: fmt.Errorf("the pod namespace %q does not allow the workload type non-existent", "managed-namespace"),
},
{
name: "should ignore pods that do not have managed annotation",
Expand Down Expand Up @@ -167,6 +167,25 @@ func TestAdmit(t *testing.T) {
expectedError: fmt.Errorf(`failed to get workload annotation effect: the workload annotation value map["test":"test"] does not have "effect" key`),
infra: testClusterSNOInfra(),
},
{
name: "should return admission warning when the pod has workload annotation but the namespace does not",
pod: testManagedPodWithAnnotations(
"500m",
"250m",
"500Mi",
"250Mi",
map[string]string{
fmt.Sprintf("%s%s", podWorkloadTargetAnnotationPrefix, workloadTypeManagement): `{"test": "test"}`,
},
),
expectedCpuRequest: resource.MustParse("250m"),
expectedAnnotations: map[string]string{
workloadAdmissionWarning: "skipping pod CPUs requests modifications because the namespace namespace is not annotated with workload.openshift.io/allowed to allow workload partitioning",
},
namespace: testNamespace(),
nodes: []*corev1.Node{testNodeWithManagementResource()},
infra: testClusterSNOInfra(),
},
{
name: "should delete CPU requests and update workload CPU annotations for the burstable pod with managed annotation",
pod: testManagedPod("", "250m", "500Mi", "250Mi"),
Expand Down Expand Up @@ -437,16 +456,28 @@ func TestValidate(t *testing.T) {
expectedError: fmt.Errorf("the pod without workload annotations can not have containers with workload resources %q", "management.workload.openshift.io/cores"),
},
{
name: "should return invalid error when the pod has workload annotation, but the pod namespace does not have allowed annotation",
pod: testManagedPod(
name: "should return invalid error when the pod has workload annotation, but the pod namespace does not have allowed workload type",
pod: testManagedPodWithWorkloadAnnotation(
"500m",
"250m",
"500Mi",
"250Mi",
"non-existent",
),
namespace: testNamespace(),
namespace: testManagedNamespace(),
nodes: []*corev1.Node{testNodeWithManagementResource()},
expectedError: fmt.Errorf("the pod can not have workload annotation, when the namespace %q does not allow it", "namespace"),
expectedError: fmt.Errorf("the pod can not have workload annotation, when the namespace %q does not allow it", "managed-namespace"),
},
{
name: "should not return any errors when the pod has workload annotation, but the pod namespace has no annotations",
pod: testManagedPod(
"500m",
"250m",
"500Mi",
"250Mi",
),
namespace: testNamespace(),
nodes: []*corev1.Node{testNodeWithManagementResource()},
},
{
name: "should not return any errors when the pod and namespace valid",
Expand Down Expand Up @@ -532,19 +563,12 @@ func testManagedStaticPod(cpuLimit, cpuRequest, memoryLimit, memoryRequest strin
}

func testManagedPod(cpuLimit, cpuRequest, memoryLimit, memoryRequest string) *kapi.Pod {
pod := testPod(cpuLimit, cpuRequest, memoryLimit, memoryRequest)

pod.Annotations = map[string]string{}
for _, c := range pod.Spec.InitContainers {
cpusetAnnotation := fmt.Sprintf("%s%s", containerResourcesAnnotationPrefix, c.Name)
pod.Annotations[cpusetAnnotation] = `{"cpuset": "0-1"}`
}
for _, c := range pod.Spec.Containers {
cpusetAnnotation := fmt.Sprintf("%s%s", containerResourcesAnnotationPrefix, c.Name)
pod.Annotations[cpusetAnnotation] = `{"cpuset": "0-1"}`
}
return testManagedPodWithWorkloadAnnotation(cpuLimit, cpuRequest, memoryLimit, memoryRequest, workloadTypeManagement)
}

managementWorkloadAnnotation := fmt.Sprintf("%s%s", podWorkloadTargetAnnotationPrefix, workloadTypeManagement)
func testManagedPodWithWorkloadAnnotation(cpuLimit, cpuRequest, memoryLimit, memoryRequest string, workloadType string) *kapi.Pod {
pod := testPod(cpuLimit, cpuRequest, memoryLimit, memoryRequest)
managementWorkloadAnnotation := fmt.Sprintf("%s%s", podWorkloadTargetAnnotationPrefix, workloadType)
pod.Annotations = map[string]string{
managementWorkloadAnnotation: fmt.Sprintf(`{"%s":"%s"}`, podWorkloadAnnotationEffect, workloadEffectPreferredDuringScheduling),
}
Expand Down

0 comments on commit c79e5e2

Please sign in to comment.