A Kubernetes Resource Model (KRM) YAML validator using Common Expression Language (CEL) validation rules.
Prebuilt binaries are available on the Releases page.
Alternatively, you can install via go install
:
go install github.com/RRethy/celery@latest
# Validate a file
celery validate deployment.yaml --expression "object.spec.replicas >= 3"
# Validate from stdin
cat deployment.yaml | celery validate --expression "object.spec.replicas >= 3"
# Single rule file
celery validate deployment.yaml --rule-file validation-rules.yaml
# Multiple rule files
celery validate deployment.yaml --rule-file base-rules.yaml --rule-file prod-rules.yaml
# Using glob patterns (must be quoted)
celery validate deployment.yaml --rule-file "rules/*.yaml"
See the fixtures/
directory for complete working examples including:
- Basic validation policies
- Multi-document policies
- Advanced selectors (labels, annotations, regex)
- Sample Kubernetes resources for testing
Validation rules are defined as Kubernetes Resource Model (KRM) resources using the ValidationRules
kind:
apiVersion: celery.io/v1
kind: ValidationRules
metadata:
name: production-standards
spec:
rules:
- name: minimum-replicas
expression: "object.spec.replicas >= 3"
message: "Deployments must have at least 3 replicas for high availability"
target:
kind: Deployment
- name: required-labels
expression: "has(object.metadata.labels) && has(object.metadata.labels.app)"
message: "Resources must have an 'app' label"
You can define multiple ValidationRules resources in a single file using YAML document separators:
apiVersion: celery.io/v1
kind: ValidationRules
metadata:
name: deployment-standards
spec:
rules:
- name: minimum-replicas
expression: "object.spec.replicas >= 3"
message: "Deployments must have at least 3 replicas"
target:
kind: Deployment
---
apiVersion: celery.io/v1
kind: ValidationRules
metadata:
name: service-standards
spec:
rules:
- name: service-port-check
expression: "object.spec.ports.all(p, p.port > 0 && p.port <= 65535)"
message: "Service ports must be valid"
target:
kind: Service
The target
field uses the same format as Kustomize patches, allowing precise targeting of resources:
target:
group: <optional API group> # e.g., "apps", "batch"
version: <optional version> # e.g., "v1", "v1beta1"
kind: <optional kind> # e.g., "Deployment", "Service"
name: <optional name> # e.g., "my-app"
namespace: <optional namespace> # e.g., "production"
labelSelector: <optional label selector> # e.g., "app=nginx,tier=frontend"
annotationSelector: <optional selector> # e.g., "criticality=high"
# Target all Deployments
target:
kind: Deployment
# Target by API group/version/kind
target:
group: apps
version: v1
kind: Deployment
# Target by label selector
target:
kind: Deployment
labelSelector: "environment=production,tier in (frontend,backend)"
# Target by name
target:
kind: Service
name: "web-service"
# Target specific resource
target:
kind: Deployment
name: "web-app"
# Target by namespace
target:
kind: Deployment
namespace: production
The following variables are available in CEL expressions:
object
: The current Kubernetes resource being validatedallObjects
: List of all resources in the current validation batch (for cross-resource validation)
has()
: Check if a field existssize()
: Get the size of a list or mapmatches()
: Regular expression matchingall()
,exists()
: List predicates- Standard operators:
==
,!=
,>
,>=
,<
,<=
,&&
,||
,!
# Check minimum replicas
--expression "object.spec.replicas >= 3"
# Ensure namespace is set
--expression "has(object.metadata.namespace) && object.metadata.namespace != ''"
# No latest tags in container images
--expression "!object.spec.template.spec.containers.exists(c, c.image.endsWith(':latest'))"
# Check resource limits
--expression "object.spec.template.spec.containers.all(c, has(c.resources.limits.memory))"
# Cross-resource validation: Ensure Deployment has a corresponding Service
--expression "object.kind != 'Deployment' || allObjects.exists(o, o.kind == 'Service' && o.metadata.name == object.metadata.name)"