crossplane-renderer
Renders and validates Crossplane compositions with security and policy checks. Automatically activates when testing compositions, rendering examples, or validating resources with Polaris, kube-linter, and Datree. Works standalone or as part of complete KCL validation workflow.
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
Crossplane Renderer & Validator
When This Skill Activates
This skill automatically activates when:
- Rendering Crossplane compositions for testing
- Validating composition security and policies
- Previewing resources before deployment
- User mentions "render", "crossplane", "polaris", "validate", "security"
- Testing composition changes during development
- Debugging composition issues
Relationship with KCL Validator
Standalone Use: Quick composition testing and security validation during development
Integrated Use: Part of the complete validation workflow with kcl-composition-validator skill
- Stage 1: KCL Formatting (
kcl fmt) - Stage 2: KCL Syntax Validation (
kcl run) - Stage 3: Composition Rendering (this skill)
- Stage 4: Security/Policy Validation (this skill)
For complete pre-commit validation, use kcl-composition-validator which runs all stages.
Core Rendering Workflow
Basic Rendering
Purpose: Test that composition renders successfully and preview resources
Command Pattern:
cd infrastructure/base/crossplane/configuration
crossplane render \
examples/<claim-file>.yaml \
<composition-file>.yaml \
functions.yaml \
--extra-resources examples/environmentconfig.yaml \
> /tmp/rendered.yaml
Available Compositions:
-
App Composition (
app-composition.yaml)- Examples:
app-basic.yaml,app-complete.yaml - Progressive complexity: minimal to production-ready
- Features: deployment, database, cache, storage, autoscaling, HA
- Examples:
-
SQLInstance Composition (
sql-instance-composition.yaml)- Examples:
sqlinstance-basic.yaml,sqlinstance-complete.yaml - PostgreSQL via CloudNativePG
- Features: backup, HA, migrations
- Examples:
-
EKS Pod Identity (
epi-composition.yaml)- Example:
epi.yaml - IAM roles for service accounts
- Example:
Rendering Examples
Test basic App configuration:
cd infrastructure/base/crossplane/configuration
crossplane render \
examples/app-basic.yaml \
app-composition.yaml \
functions.yaml \
--extra-resources examples/environmentconfig.yaml \
> /tmp/app-basic-rendered.yaml
Test complete App configuration:
crossplane render \
examples/app-complete.yaml \
app-composition.yaml \
functions.yaml \
--extra-resources examples/environmentconfig.yaml \
> /tmp/app-complete-rendered.yaml
Test SQLInstance:
crossplane render \
examples/sqlinstance-complete.yaml \
sql-instance-composition.yaml \
functions.yaml \
--extra-resources examples/environmentconfig.yaml \
> /tmp/sqlinstance-rendered.yaml
Security & Policy Validation
CRITICAL: Every composition change must pass security and policy validation before committing.
Validation Targets
- Polaris: Security & best practices - Target score: 85+
- kube-linter: Kubernetes best practices - Target: No errors
- Datree: Policy enforcement - Target: No violations (warnings acceptable if documented)
Step-by-Step Validation
Step 1: Render the Composition
cd infrastructure/base/crossplane/configuration
crossplane render examples/app-complete.yaml app-composition.yaml functions.yaml \
--extra-resources examples/environmentconfig.yaml > /tmp/rendered.yaml
Step 2: Polaris Security Audit
polaris audit --audit-path /tmp/rendered.yaml --format=pretty
Expected output:
- Overall score: 85+ (Green/Yellow acceptable)
- No critical security issues
- Resource limits defined
- Health checks configured
Common Polaris Issues:
- Missing resource limits → Add requests/limits in composition
- No health checks → Add liveness/readiness probes
- Running as root → Add securityContext with non-root user
- Privileged containers → Remove privileged: true unless required
Step 3: kube-linter Validation
kube-linter lint /tmp/rendered.yaml
Expected: Clean output with no errors
Common kube-linter Issues:
- Missing liveness/readiness probes
- No resource limits
- Incorrect label schemas
- Deprecated API versions
Step 4: Datree Policy Check
datree test /tmp/rendered.yaml --ignore-missing-schemas
Expected: No policy violations (warnings acceptable if documented)
Common Datree Issues:
- Missing labels (app.kubernetes.io/*)
- Incorrect image tags (using 'latest')
- Missing owner references
- Network policy gaps
Security Validation Checklist
Before committing composition changes:
- Composition renders successfully without errors
- Polaris score is 85+ with no critical issues
- kube-linter passes with no errors
- Datree policy check passes (or warnings documented)
- Resource limits are defined for all containers
- Health checks (liveness/readiness) are configured
- Security contexts are properly set
- No privileged containers (unless justified)
- Images use specific tags (not 'latest')
- Network policies are defined (where applicable)
Rendered Output Analysis
Inspect Resources
Count resources by kind:
grep "^kind:" /tmp/rendered.yaml | sort | uniq -c
Extract specific resource:
# Get Deployment
yq 'select(.kind == "Deployment")' /tmp/rendered.yaml
# Get Service
yq 'select(.kind == "Service")' /tmp/rendered.yaml
# Get HTTPRoute
yq 'select(.kind == "HTTPRoute")' /tmp/rendered.yaml
Check readiness annotations:
# Find resources marked as ready
grep -B 5 'krm.kcl.dev/ready: "True"' /tmp/rendered.yaml
Verify Resource Correctness
Deployment checks:
# Check replicas
yq 'select(.kind == "Deployment") | .spec.replicas' /tmp/rendered.yaml
# Check image
yq 'select(.kind == "Deployment") | .spec.template.spec.containers[0].image' /tmp/rendered.yaml
# Check resource limits
yq 'select(.kind == "Deployment") | .spec.template.spec.containers[0].resources' /tmp/rendered.yaml
Service checks:
# Check service type
yq 'select(.kind == "Service") | .spec.type' /tmp/rendered.yaml
# Check ports
yq 'select(.kind == "Service") | .spec.ports' /tmp/rendered.yaml
HTTPRoute checks:
# Check hostnames
yq 'select(.kind == "HTTPRoute") | .spec.hostnames' /tmp/rendered.yaml
# Check backend refs
yq 'select(.kind == "HTTPRoute") | .spec.rules[0].backendRefs' /tmp/rendered.yaml
Detecting Duplicate Resources
Issue: KCL mutation patterns can cause duplicate resources (see kcl-composition-validator skill)
Detection:
# Count Deployments (should match expected count)
grep -c "kind: Deployment" /tmp/rendered.yaml
# Count Services
grep -c "kind: Service" /tmp/rendered.yaml
# Find duplicate resource names
grep "name:" /tmp/rendered.yaml | sort | uniq -d
If duplicates found:
- Check KCL code for mutation patterns
- Use
kcl-composition-validatorskill for detailed guidance - Refactor to use inline conditionals
- Re-render and verify
Development Workflow
Quick Iteration Cycle
When developing new composition features:
# 1. Make changes to KCL composition
vim infrastructure/base/crossplane/configuration/kcl/app/main.k
# 2. Quick render test
cd infrastructure/base/crossplane/configuration
crossplane render examples/app-complete.yaml app-composition.yaml functions.yaml \
--extra-resources examples/environmentconfig.yaml > /tmp/test.yaml
# 3. Check output
less /tmp/test.yaml
# 4. Iterate until correct
When changes look good:
# 5. Run security validation
polaris audit --audit-path /tmp/test.yaml --format=pretty
kube-linter lint /tmp/test.yaml
datree test /tmp/test.yaml --ignore-missing-schemas
# 6. Run complete validation (includes KCL formatting/syntax)
./scripts/validate-kcl-compositions.sh
Testing Different Scenarios
Test with minimal configuration:
crossplane render examples/app-basic.yaml app-composition.yaml functions.yaml \
--extra-resources examples/environmentconfig.yaml > /tmp/minimal.yaml
Test with complete configuration:
crossplane render examples/app-complete.yaml app-composition.yaml functions.yaml \
--extra-resources examples/environmentconfig.yaml > /tmp/complete.yaml
Compare outputs:
diff -u /tmp/minimal.yaml /tmp/complete.yaml | less
Creating Custom Test Examples
Create a custom claim for testing:
# /tmp/my-test-app.yaml
apiVersion: cloud.ogenki.io/v1alpha1
kind: App
metadata:
name: test-app
namespace: apps
spec:
image: nginx:1.25
replicas: 3
database:
enabled: true
size: small
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 5
Render custom claim:
cd infrastructure/base/crossplane/configuration
crossplane render /tmp/my-test-app.yaml app-composition.yaml functions.yaml \
--extra-resources examples/environmentconfig.yaml > /tmp/my-test-rendered.yaml
Troubleshooting Rendering Issues
Issue: Composition Not Found
Symptom: Error: composition not found
Fix:
- Ensure you're in
infrastructure/base/crossplane/configuration/directory - Verify composition file exists and path is correct
- Check composition file syntax with
yqorkubectl
Issue: Function Not Found
Symptom: Error: function not found or unknown function
Fix:
- Verify
functions.yamlexists in the same directory - Check function images are accessible
- Ensure Docker is running (required for
crossplane render)
Issue: EnvironmentConfig Missing
Symptom: References to environment config fail
Fix:
- Always include
--extra-resources examples/environmentconfig.yaml - Verify the EnvironmentConfig file exists
- Check the EnvironmentConfig spec matches composition expectations
Issue: Render Succeeds but Resources Are Wrong
Symptom: Render completes but output doesn't match expectations
Debug steps:
- Check the claim file matches the composition schema
- Verify EnvironmentConfig has required fields
- Review KCL code in
infrastructure/base/crossplane/configuration/kcl/<module>/ - Check for conditional logic that might affect output
- Use
kcl-composition-validatorskill to validate KCL syntax
Issue: Docker Not Available
Symptom: Error: cannot connect to Docker daemon
Fix:
# Start Docker
sudo systemctl start docker
# Or use podman with docker alias
alias docker=podman
Integration with Complete Validation
For pre-commit validation, use the comprehensive script:
./scripts/validate-kcl-compositions.sh
This runs:
- KCL formatting (
kcl fmt) - KCL syntax validation (
kcl run) - Crossplane rendering (this skill)
For security validation (additional step):
# After rendering
polaris audit --audit-path /tmp/rendered.yaml --format=pretty
kube-linter lint /tmp/rendered.yaml
datree test /tmp/rendered.yaml --ignore-missing-schemas
Common Validation Scenarios
Scenario 1: Testing New Feature in Composition
# 1. Modify composition KCL
vim infrastructure/base/crossplane/configuration/kcl/app/main.k
# 2. Render with feature enabled
cd infrastructure/base/crossplane/configuration
crossplane render examples/app-complete.yaml app-composition.yaml functions.yaml \
--extra-resources examples/environmentconfig.yaml > /tmp/test.yaml
# 3. Verify feature resources exist
grep "kind:" /tmp/test.yaml | sort | uniq -c
# 4. Security validation
polaris audit --audit-path /tmp/test.yaml --format=pretty
Scenario 2: Validating Database Integration
# Render SQLInstance
crossplane render examples/sqlinstance-complete.yaml sql-instance-composition.yaml functions.yaml \
--extra-resources examples/environmentconfig.yaml > /tmp/db.yaml
# Check generated resources
yq 'select(.kind == "Cluster")' /tmp/db.yaml # CloudNativePG Cluster
yq 'select(.kind == "ScheduledBackup")' /tmp/db.yaml # Backup config
yq 'select(.kind == "AtlasMigration")' /tmp/db.yaml # Migrations
# Validate security
polaris audit --audit-path /tmp/db.yaml --format=pretty
Scenario 3: Testing Environment-Specific Configuration
# Create test EnvironmentConfig
cat > /tmp/test-env.yaml <<EOF
apiVersion: cloud.ogenki.io/v1alpha1
kind: EnvironmentConfig
metadata:
name: test-env
data:
environment: prod
region: us-west-2
EOF
# Render with custom environment
crossplane render examples/app-complete.yaml app-composition.yaml functions.yaml \
--extra-resources /tmp/test-env.yaml > /tmp/prod-app.yaml
# Verify environment-specific settings
yq 'select(.kind == "Deployment") | .spec.replicas' /tmp/prod-app.yaml
Performance Optimization
Faster Rendering
Render specific composition only (skip others):
# Instead of running full validation script
crossplane render examples/app-basic.yaml app-composition.yaml functions.yaml \
--extra-resources examples/environmentconfig.yaml
Use local function images (if available):
# Pull function images once
docker pull xpkg.upbound.io/crossplane-contrib/function-kcl:latest
# Subsequent renders will use cached image
Selective Validation
During development, validate only what changed:
# Skip Polaris/kube-linter/Datree during rapid iteration
# Only run these before commit
Before commit, run all validations:
# Complete validation
./scripts/validate-kcl-compositions.sh
# Security validation
polaris audit --audit-path /tmp/rendered.yaml --format=pretty
kube-linter lint /tmp/rendered.yaml
datree test /tmp/rendered.yaml --ignore-missing-schemas
Additional Resources
- Security validation details: See
security-validation.mdin this skill folder - Rendering examples and scenarios: See
examples.mdin this skill folder - Quick command reference: See
quick-reference.mdin this skill folder - KCL-specific validation: Use
kcl-composition-validatorskill
Success Criteria
Validation is successful when:
- ✅ Composition renders without errors
- ✅ No duplicate resources in output
- ✅ Polaris score is 85+ with no critical issues
- ✅ kube-linter reports no errors
- ✅ Datree policy check passes (or warnings documented)
- ✅ Resources match expected count and structure
- ✅ All required fields are populated correctly
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-03-03
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!