Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions policy/overlays/nerc-ocp-prod/validate-class-example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ spec:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces: ["rhods-notebooks"]
labelSelector:
matchLabels:
nerc.mghpcc.org/class: fake_class
namespaces: ["ope-rhods-testing-1fef2f"]
# Removed labelSelector to match all pods, but we can add it back if needed for specific classes
# labelSelector:
# matchLabels:
# nerc.mghpcc.org/class: example_class
parameters:
image: "image-registry.openshift-image-registry.svc:5000/redhat-ods-applications/ucsls-f24:latest"
image_name: "ucsls-F24"
cpuLimit: "2"
memLimit: "8Gi"
cpuRequest: "1"
memRequest: "8Gi"
allowed_images:
- image: "image-registry.openshift-image-registry.svc:5000/redhat-ods-applications/base-ope-image:latest"
name: "Base OPE Image"
resource_size: "X Small"
gpu_count: 0
- image: "image-registry.openshift-image-registry.svc:5000/redhat-ods-applications/ucsls-f24:latest"
name: "ucsls-F24"
resource_size: "Small"
gpu_count: 1
Original file line number Diff line number Diff line change
Expand Up @@ -10,90 +10,117 @@ spec:
validation:
openAPIV3Schema:
properties:
image:
type: string
image_name:
type: string
cpuLimit:
type: string
memLimit:
type: string
cpuRequest:
type: string
memRequest:
type: string
allowed_images:
type: array
items:
type: object
properties:
image:
type: string
name:
type: string
resource_size:
type: string
enum: ["X Small", "Small", "Medium", "Large", "X Large"]
gpu_count:
type: integer
required: ["image", "name", "resource_size", "gpu_count"]
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package K8sRequiredOPEPod

# Function to determine the resource size
resource_size(cpuLimit, memLimit, cpuRequest, memRequest) = size {
cpuLimit == "1"
memLimit == "4Gi"
cpuRequest == "100m"
memRequest == "1Gi"
size := "X Small"
} else = size {
cpuLimit == "2"
memLimit == "8Gi"
cpuRequest == "1"
memRequest == "8Gi"
size := "Small"
} else = size {
cpuLimit == "6"
memLimit == "24Gi"
cpuRequest == "3"
memRequest == "24Gi"
size := "Medium"
} else = size {
cpuLimit == "14"
memLimit == "56Gi"
cpuRequest == "7"
memRequest == "56Gi"
size := "Large"
} else = size {
cpuLimit == "30"
memLimit == "120Gi"
cpuRequest == "15"
memRequest == "120Gi"
size := "X Large"
# Function to get resource values based on size (string)
get_resource_values(size) = values {
size == "X Small"
values := {
"cpuLimit": "1",
"memLimit": "4Gi",
"cpuRequest": "100m",
"memRequest": "1Gi"
}
} else = values {
size == "Small"
values := {
"cpuLimit": "2",
"memLimit": "8Gi",
"cpuRequest": "1",
"memRequest": "8Gi"
}
} else = values {
size == "Medium"
values := {
"cpuLimit": "6",
"memLimit": "24Gi",
"cpuRequest": "3",
"memRequest": "24Gi"
}
} else = values {
size == "Large"
values := {
"cpuLimit": "14",
"memLimit": "56Gi",
"cpuRequest": "7",
"memRequest": "56Gi"
}
} else = values {
size == "X Large"
values := {
"cpuLimit": "30",
"memLimit": "120Gi",
"cpuRequest": "15",
"memRequest": "120Gi"
}
}

# Find the image configuration for the provided image
find_image_config(provided) = config {
config := input.parameters.allowed_images[_]
provided == config.image
}

# Verify class image
# Verify container image
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
container := input.review.object.spec.containers[0]
env_var := container.env[_]
env_var.name == "JUPYTER_IMAGE"
provided := env_var.value
required := input.parameters.image
provided != required
not find_image_config(provided)

size := resource_size(input.parameters.cpuLimit, input.parameters.memLimit, input.parameters.cpuRequest, input.parameters.memRequest)
msg := sprintf("Must use %s image with %s resource size", [input.parameters.image_name, size])
allowed_names := concat(", ", [sprintf("%s (%s resource size, %d GPUs)", [img.name, img.resource_size, img.gpu_count]) | img := input.parameters.allowed_images[_]])
msg := sprintf("Must use one of these images: [%s]", [allowed_names])
}

# Verify resource size
# Validate resources
violation[{"msg": msg}] {
requiredCpuLimit := input.parameters.cpuLimit
requiredMemoryLimit := input.parameters.memLimit
requiredCpuRequest := input.parameters.cpuRequest
requiredMemoryRequest := input.parameters.memRequest

container := input.review.object.spec.containers[0]
env_var := container.env[_]
env_var.name == "JUPYTER_IMAGE"
provided := env_var.value

image_config := find_image_config(provided)
resource_values := get_resource_values(image_config.resource_size)
gpu_count := image_config.gpu_count

# Get actual resource values from container
cpuLimit := container.resources.limits.cpu
memLimit := container.resources.limits.memory
cpuRequest := container.resources.requests.cpu
memRequest := container.resources.requests.memory
actual_gpu_request := object.get(container.resources.requests, "nvidia.com/gpu", "0")
actual_gpu_limit := object.get(container.resources.limits, "nvidia.com/gpu", "0")

requiredCpuLimit != cpuLimit
requiredMemoryLimit != memLimit
requiredCpuRequest != cpuRequest
requiredMemoryRequest != memRequest
# Violation if any resource doesn't match the required values
any([
cpuLimit != resource_values.cpuLimit,
memLimit != resource_values.memLimit,
cpuRequest != resource_values.cpuRequest,
memRequest != resource_values.memRequest,
actual_gpu_request != sprintf("%d", [gpu_count]),
actual_gpu_limit != sprintf("%d", [gpu_count])
])

size := resource_size(input.parameters.cpuLimit, input.parameters.memLimit, input.parameters.cpuRequest, input.parameters.memRequest)
msg := sprintf("Must use %s image with %s resource size", [input.parameters.image_name, size])
# Generate error message
allowed_names := concat(", ", [sprintf("%s (%s resource size, %d GPUs)", [img.name, img.resource_size, img.gpu_count]) | img := input.parameters.allowed_images[_]])
msg := sprintf("Must use one of these images: [%s]", [allowed_names])
}