prvng_kcl/examples/README.md
2025-10-07 11:17:54 +01:00

6.7 KiB

KCL Package Examples

This directory contains practical examples demonstrating how to use the provisioning KCL package schemas.

Example Files

📄 basic_server.k

Simple server configurations for different use cases

  • Web server with nginx and monitoring
  • Database server with PostgreSQL
  • Development server with Docker
# Validate and run
kcl run basic_server.k

# Export to JSON
kcl run basic_server.k --format json

📄 simple_workflow.k

Basic workflow example with sequential operations

  • Database server creation
  • Web server deployment
  • Application configuration with dependencies

Demonstrates:

  • Sequential dependencies
  • Retry policies
  • Basic monitoring
  • Filesystem storage

📄 kubernetes_deployment.k

Complete Kubernetes deployment examples

  • Web application with resources and affinity
  • PostgreSQL with persistent storage
  • Prometheus monitoring stack

Features:

  • Resource limits and requests
  • Persistent volumes
  • Services and networking
  • ConfigMaps and secrets
  • Anti-affinity rules

📄 mixed_provider_workflow.k

Advanced multi-cloud deployment

  • UpCloud compute infrastructure
  • AWS managed services (RDS, ElastiCache)
  • Kubernetes cluster setup
  • Cross-cloud connectivity

Advanced features:

  • Multiple providers in single workflow
  • Complex dependency chains
  • Production-grade monitoring
  • Encrypted state storage
  • Comprehensive retry and rollback strategies

Running Examples

Basic Validation

# Check syntax and validate schemas
kcl fmt examples/*.k
kcl run examples/basic_server.k

JSON Output for Integration

# Generate JSON for Nushell/Rust integration
kcl run examples/simple_workflow.k --format json > workflow.json

# Use with Nushell
let workflow = (open workflow.json)
echo $"Workflow: ($workflow.name)"
echo $"Operations: ($workflow.operations | length)"

Validation with Different Configurations

# Test with custom values
kcl run examples/basic_server.k -D hostname="my-server" -D user="ubuntu"

# Override workflow settings
kcl run examples/simple_workflow.k -D max_parallel_operations=5

Integration Patterns

With Nushell Scripts

# Load and submit workflow
def submit-workflow [file: string] {
    let workflow = (kcl run $file --format json | from json)
    $workflow | to json | http post http://localhost:8080/workflows/batch/submit
}

# Monitor workflow progress
def monitor-workflow [workflow_id: string] {
    while true {
        let status = (http get $"http://localhost:8080/workflows/batch/($workflow_id)")
        print $"Status: ($status.status)"
        if $status.status in ["completed", "failed"] { break }
        sleep 10sec
    }
}

With Rust Orchestrator

use serde_json;
use std::process::Command;

// Generate workflow from KCL
let output = Command::new("kcl")
    .args(&["run", "examples/simple_workflow.k", "--format", "json"])
    .output()?;

// Parse and execute
let workflow: BatchWorkflow = serde_json::from_slice(&output.stdout)?;
let executor = BatchExecutor::new(workflow);
executor.execute().await?;

Customization Examples

Server Configuration Variants

import ..main

# High-performance server
performance_server: main.Server = main.Server {
    hostname: "perf-01"
    title: "High Performance Server"
    labels: "env: prod, tier: compute, performance: high"
    user: "performance"

    # Override defaults for high-performance needs
    running_timeout: 300

    taskservs: [
        main.TaskServDef {
            name: "tuned"
            install_mode: "server"
            profile: "performance"
        }
    ]
}

Workflow Customization

import ..main

# Custom retry policy for network operations
network_retry_policy: main.RetryPolicy = main.RetryPolicy {
    max_attempts: 5
    initial_delay: 10
    max_delay: 120
    backoff_multiplier: 1.5
    retry_on_errors: ["connection_error", "dns_error", "timeout"]
}

# Workflow with custom settings
custom_workflow: main.BatchWorkflow = main.BatchWorkflow {
    workflow_id: "custom_001"
    name: "Custom Network Deployment"

    # Use custom retry policy for all operations
    default_retry_policy: network_retry_policy

    operations: [
        # ... your operations
    ]
}

Best Practices Demonstrated

1. Dependency Management

  • Use sequential dependencies for ordered operations
  • Use conditional dependencies for health checks
  • Set appropriate timeouts for each dependency

2. Resource Configuration

  • Always set resource limits for Kubernetes deployments
  • Use appropriate server plans based on workload
  • Configure persistent storage for stateful services

3. Monitoring & Observability

  • Enable monitoring for production workflows
  • Configure appropriate log levels
  • Set up notifications for critical operations

4. Error Handling

  • Configure retry policies based on operation type
  • Use rollback strategies for critical deployments
  • Set appropriate timeouts for different operations

5. Security

  • Use encrypted storage for sensitive workflows
  • Configure proper network isolation
  • Use secrets management for credentials

Troubleshooting

Common Issues

Schema Validation Errors

# Check for typos in schema names
kcl run examples/basic_server.k --debug

# Validate against specific schema
kcl vet examples/basic_server.k --schema main.Server

Missing Required Fields

# Error: attribute 'labels' of Server is required
# Solution: Always provide required fields
server: main.Server = main.Server {
    hostname: "web-01"
    title: "Web Server"
    labels: "env: prod"  # ✅ Required field
    user: "admin"        # ✅ Required field
}

Import Errors

# Use relative imports within the package
import ..main  # ✅ Correct

# Not absolute imports
import provisioning.main  # ❌ May not work in examples

Testing Examples

# Run all examples to verify they work
for file in examples/*.k; do
    echo "Testing $file"
    kcl run "$file" > /dev/null && echo "✅ PASS" || echo "❌ FAIL"
done

# Test JSON serialization
kcl run examples/simple_workflow.k --format json | jq '.workflow_id'

Contributing Examples

When adding new examples:

  1. Follow naming convention: {purpose}_{type}.k
  2. Include comprehensive comments
  3. Demonstrate specific features
  4. Test before committing
  5. Update this README

Example template:

# {Purpose} Example
# Demonstrates {specific features}

import ..main

# Clear, descriptive variable names
example_resource: main.ResourceType = main.ResourceType {
    # Well-commented configuration
    required_field: "value"

    # Explain non-obvious settings
    optional_field: "explained_value"  # Why this value
}