KCL Composition Validator
When This Skill Activates
This skill automatically activates when:
- •Modifying files in
infrastructure/base/crossplane/configuration/kcl/ - •Working with KCL compositions or Crossplane resources
- •User mentions "kcl", "crossplane", "composition", or "validate"
- •Before committing changes that include
.kfiles - •When running pre-commit validation
Critical: Why This Matters
The CI enforces strict KCL formatting and will fail your commit if validation doesn't pass.
Common issues this skill prevents:
- •Formatting violations that fail CI
- •Syntax errors in KCL code
- •Resource mutation causing duplicate resources (issue #285)
- •Rendering failures in composition pipeline
Three-Stage Validation Process
Stage 1: KCL Formatting (CRITICAL - CI Enforced)
Purpose: Ensure code follows strict formatting standards that CI will check.
What to check:
- •Single-line list comprehensions (NOT multi-line)
- •No trailing blank lines between sections
- •Proper indentation and spacing
How to validate:
cd infrastructure/base/crossplane/configuration/kcl/<module> kcl fmt .
Check for changes:
git diff --quiet . || echo "Files were reformatted - review changes"
If kcl fmt made changes, the formatting was incorrect. Review the diff and commit the formatted version.
Stage 2: KCL Syntax and Logic Validation
Purpose: Test KCL code executes without errors using example settings.
How to validate:
cd infrastructure/base/crossplane/configuration/kcl/<module> kcl run . -Y settings-example.yaml
What this catches:
- •Syntax errors in KCL code
- •Logic errors in conditionals
- •Type mismatches
- •Reference errors
Stage 3: Crossplane Render Validation
Purpose: Test the complete composition pipeline end-to-end.
Comprehensive validation script:
# From repository root ./scripts/validate-kcl-compositions.sh
This script validates ALL compositions through all three stages automatically.
Manual validation (for specific compositions):
cd infrastructure/base/crossplane/configuration # Test basic example crossplane render examples/app-basic.yaml app-composition.yaml functions.yaml \ --extra-resources examples/environmentconfig.yaml > /tmp/rendered.yaml # Test complete example crossplane render examples/app-complete.yaml app-composition.yaml functions.yaml \ --extra-resources examples/environmentconfig.yaml > /tmp/rendered.yaml
Tested compositions:
- •
app: app-basic.yaml, app-complete.yaml - •
cloudnativepg(SQLInstance): sqlinstance-basic.yaml, sqlinstance-complete.yaml - •
eks-pod-identity: epi.yaml
Critical KCL Rules
Rule 1: NEVER MUTATE RESOURCES (Issue #285)
Background: https://github.com/crossplane-contrib/function-kcl/issues/285
Mutating dictionaries/resources after creation causes function-kcl to create duplicate resources. This is a known bug in function-kcl's duplicate detection mechanism.
WRONG - Mutation Pattern:
# ❌ Creating resource then modifying it later
_deployment = {
apiVersion = "apps/v1"
kind = "Deployment"
metadata = {
name = _name
annotations = {
"base-annotation" = "value"
}
}
}
# ❌ MUTATION! This causes duplicates
if _deploymentReady:
_deployment.metadata.annotations["krm.kcl.dev/ready"] = "True"
_items += [_deployment]
CORRECT - Inline Conditional Pattern:
# ✅ Using inline conditionals
_deployment = {
apiVersion = "apps/v1"
kind = "Deployment"
metadata = {
name = _name
annotations = {
"base-annotation" = "value"
if _deploymentReady:
"krm.kcl.dev/ready" = "True" # ✅ Inline conditional
}
}
}
_items += [_deployment]
CORRECT - List Comprehension Pattern:
# ✅ List comprehensions with inline definitions
_items += [{
apiVersion = "apps/v1"
kind = "Deployment"
metadata = {
name = _name + "-" + db.name
annotations = {
"base-annotation" = "value"
if _ready:
"krm.kcl.dev/ready" = "True"
}
}
} for db in databases]
Safe patterns:
- •Inline conditionals within dictionary literals
- •List comprehensions with inline definitions
- •Ternary operators returning complete dictionaries
Unsafe patterns (NEVER use):
- •Post-creation field assignment:
resource.field = value - •Post-creation nested assignment:
resource.metadata.annotations["key"] = "value" - •Any mutation of resource variables after initial creation
Rule 2: Single-Line List Comprehensions
WRONG:
# ❌ Multi-line comprehension (will fail CI)
_ready = any_true([
c.get("type") == "Available" and c.get("status") == "True"
for c in conditions or []
])
CORRECT:
# ✅ Single-line comprehension
_ready = any_true([c.get("type") == "Available" and c.get("status") == "True" for c in conditions or []])
Rule 3: No Trailing Blank Lines
Remove extra blank lines between logical sections. The kcl fmt tool will catch these.
Pre-Commit Workflow
ALWAYS run before committing KCL changes:
# From repository root ./scripts/validate-kcl-compositions.sh
Expected output:
╔════════════════════════════════════════════════════════════════╗ ║ KCL Crossplane Composition Validation ║ ╚════════════════════════════════════════════════════════════════╝ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Validating: app ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📝 [1/3] Checking KCL formatting... ✅ Formatting is correct 🧪 [2/3] Validating KCL syntax and logic... ✅ KCL syntax valid 🎨 [3/3] Testing crossplane render... Testing: app-basic.yaml ✅ app-basic.yaml renders successfully Testing: app-complete.yaml ✅ app-complete.yaml renders successfully ✅ All checks passed for app
Target: Zero errors, minimal warnings.
Common Issues and Fixes
Issue: Code Reformatted by kcl fmt
Symptom: kcl fmt makes changes to your code
Fix:
- •Review the changes with
git diff - •Commit the formatted version
- •The formatting is now correct for CI
Issue: Syntax Errors
Symptom: kcl run fails with syntax error
Fix:
- •Read the error message carefully
- •Check the line number indicated
- •Common causes: missing commas, incorrect indentation, typos
- •Fix the syntax and re-run validation
Issue: Render Failures
Symptom: crossplane render fails
Fix:
- •Check that example files match composition schema
- •Verify
functions.yamlis correctly configured - •Ensure
environmentconfig.yamlexists - •Check function-kcl version compatibility
Issue: Duplicate Resources Created
Symptom: Multiple identical resources in rendered output
Fix:
- •Search for resource mutation patterns in code
- •Look for lines like:
_resource.field = value - •Refactor to use inline conditionals
- •See Rule 1 above for correct patterns
Quick Checklist
Before committing KCL changes, ensure:
- • Run
./scripts/validate-kcl-compositions.shfrom repo root - • All formatting checks pass (Stage 1)
- • All syntax validations pass (Stage 2)
- • All render tests pass (Stage 3)
- • No resource mutation patterns in code
- • List comprehensions are single-line
- • No trailing blank lines
Additional Resources
- •Mutation bug details: See
reference.mdin this skill folder - •Code patterns: See
examples.mdin this skill folder - •Quick reference: See
quick-reference.mdin this skill folder
Validation Targets
Modules validated:
- •
app- Application composition with progressive complexity - •
cloudnativepg- PostgreSQL database instances - •
eks-pod-identity- EKS Pod Identity for IAM roles
Example files tested:
- •Basic examples (minimal configuration)
- •Complete examples (production-ready with all features)
Success Criteria
Validation is successful when:
- •
kcl fmtmakes no changes (formatting correct) - •
kcl runexecutes without errors (syntax valid) - •
crossplane rendersucceeds for all examples (composition valid) - •Zero errors reported by validation script
- •Minimal warnings (Docker availability only)