# KCL Packaging and Extension Development Guide This guide covers how to package the core KCL modules and develop custom extensions for the provisioning system. ## Table of Contents 1. [Core KCL Package Management](#core-kcl-package-management) 2. [Extension Development](#extension-development) 3. [Infrastructure-Specific Extensions](#infrastructure-specific-extensions) 4. [Publishing and Distribution](#publishing-and-distribution) 5. [Best Practices](#best-practices) ## Core KCL Package Management ### Building the Core Package The core provisioning package contains fundamental schemas and should be built and distributed independently from extensions. ```bash # Navigate to provisioning directory cd /Users/Akasha/project-provisioning/provisioning # Build core package ./tools/kcl-packager.nu build --version 1.0.0 --output dist # Build with documentation ./tools/kcl-packager.nu build --version 1.0.0 --include-docs --output dist # Build different formats ./tools/kcl-packager.nu build --version 1.0.0 --format zip ./tools/kcl-packager.nu build --version 1.0.0 --format tar.gz ``` ### Installing Core Package ```bash # Install locally built package ./tools/kcl-packager.nu install dist/provisioning-1.0.0.tar.gz # Install to custom location ./tools/kcl-packager.nu install dist/provisioning-1.0.0.tar.gz --target ~/.local/kcl/packages # Verify installation kcl list packages | grep provisioning ``` ### Core Package Structure ``` provisioning-1.0.0/ ├── kcl.mod # Package metadata ├── settings.k # System settings schemas ├── server.k # Server definition schemas ├── defaults.k # Default configuration schemas ├── lib.k # Common library schemas ├── dependencies.k # Dependency management schemas ├── cluster.k # Cluster schemas ├── batch.k # Batch workflow schemas ├── README.md # Package documentation └── docs/ # Additional documentation ``` ### Version Management ```bash # Check current version ./tools/kcl-packager.nu version # Build with semantic versioning ./tools/kcl-packager.nu build --version 1.2.0 ./tools/kcl-packager.nu build --version 1.2.0-beta.1 ./tools/kcl-packager.nu build --version 1.2.0-rc.1 # Clean build artifacts ./tools/kcl-packager.nu clean ``` ## Extension Development ### Types of Extensions The system supports three types of extensions: 1. **Taskservs**: Infrastructure services (kubernetes, redis, postgres, etc.) 2. **Providers**: Cloud providers (upcloud, aws, local, etc.) 3. **Clusters**: Complete configurations (buildkit, web, monitoring, etc.) ### Creating a New Taskserv Extension #### 1. Basic Structure ```bash # Create taskserv directory structure mkdir -p extensions/taskservs/my-service/kcl cd extensions/taskservs/my-service/kcl # Initialize KCL module kcl mod init my-service ``` #### 2. Configure Dependencies Edit `kcl.mod`: ```toml [package] name = "my-service" edition = "v0.11.2" version = "0.0.1" [dependencies] provisioning = { path = "~/.kcl/packages/provisioning", version = "0.0.1" } taskservs = { path = "../..", version = "0.0.1" } ``` #### 3. Create Main Schema Create `my-service.k`: ```kcl """ My Service Taskserv Schema Custom service for specific infrastructure needs """ import provisioning.lib as lib import provisioning.dependencies as deps # Service configuration schema schema MyServiceConfig: """Configuration for My Service""" # Service-specific settings enabled: bool = True port: int = 8080 replicas: int = 1 # Resource requirements cpu_request: str = "100m" memory_request: str = "128Mi" cpu_limit: str = "500m" memory_limit: str = "512Mi" # Storage configuration storage_size: str = "10Gi" storage_class?: str # Network configuration service_type: "ClusterIP" | "NodePort" | "LoadBalancer" = "ClusterIP" # Additional configuration environment_vars?: {str: str} config_map_data?: {str: str} check: port > 0 and port < 65536, "Port must be between 1 and 65535" replicas > 0, "Replicas must be greater than 0" len(cpu_request) > 0, "CPU request cannot be empty" len(memory_request) > 0, "Memory request cannot be empty" # Taskserv definition using the common lib pattern schema MyServiceTaskserv(lib.TaskServDef): """My Service Taskserv Definition""" name: str = "my-service" config: MyServiceConfig # Installation profiles profiles?: {str: MyServiceProfile} # Service profiles for different environments schema MyServiceProfile: """Profile-specific configuration for My Service""" config_overrides?: MyServiceConfig installation_mode?: "standalone" | "cluster" | "replicated" = "standalone" # Dependencies definition my_service_dependencies: deps.TaskservDependencies = { name = "my-service" # Dependencies requires = ["kubernetes"] # Requires Kubernetes conflicts = ["old-my-service"] # Cannot coexist with old version optional = ["monitoring", "logging"] # Works better with these provides = ["my-service-api", "my-service-ui"] # Services it provides # Resource requirements resources = { cpu = "100m" memory = "128Mi" disk = "1Gi" network = True privileged = False } # Health checks health_checks = [{ command = "curl -f http://localhost:8080/health" interval = 30 timeout = 10 retries = 3 }] # Installation phases phases = [ { name = "pre-install" order = 1 parallel = False required = True }, { name = "install" order = 2 parallel = True required = True }, { name = "post-install" order = 3 parallel = False required = False } ] # Compatibility os_support = ["linux"] arch_support = ["amd64", "arm64"] k8s_versions = ["1.25+", "1.26+", "1.27+"] } # Default configuration my_service_default: MyServiceTaskserv = { name = "my-service" config = { enabled = True port = 8080 replicas = 1 cpu_request = "100m" memory_request = "128Mi" cpu_limit = "500m" memory_limit = "512Mi" storage_size = "10Gi" service_type = "ClusterIP" } profiles = { "default": { installation_mode = "standalone" }, "production": { config_overrides = { replicas = 3 cpu_request = "200m" memory_request = "256Mi" cpu_limit = "1" memory_limit = "1Gi" storage_size = "50Gi" service_type = "LoadBalancer" } installation_mode = "replicated" }, "development": { config_overrides = { replicas = 1 cpu_request = "50m" memory_request = "64Mi" storage_size = "5Gi" } installation_mode = "standalone" } } } # Export for use by provisioning system { config: my_service_default, dependencies: my_service_dependencies, schema: MyServiceTaskserv } ``` #### 4. Create Version Information Create `version.k`: ```kcl """ Version information for My Service taskserv """ version_info = { name = "my-service" version = "0.0.1" description = "Custom service for specific infrastructure needs" author = "Your Name" license = "MIT" repository = "https://github.com/your-org/my-service-taskserv" # Supported versions min_provisioning_version = "0.0.1" max_provisioning_version = "1.0.0" # Changelog changelog = { "0.0.1" = "Initial release with basic functionality" } } version_info ``` #### 5. Create Dependencies File Create `dependencies.k`: ```kcl """ Dependencies for My Service taskserv """ import provisioning.dependencies as deps # Import the main dependencies from my-service.k import .my-service as ms # Re-export dependencies for discovery system ms.my_service_dependencies ``` ### Creating a Provider Extension #### 1. Provider Structure ```bash # Create provider directory mkdir -p extensions/providers/my-cloud/kcl cd extensions/providers/my-cloud/kcl # Initialize kcl mod init my-cloud ``` #### 2. Provider Schema Create `provision_my-cloud.k`: ```kcl """ My Cloud Provider Schema """ import provisioning.defaults as defaults import provisioning.server as server # Provider-specific configuration schema MyCloudConfig: """My Cloud provider configuration""" api_endpoint: str api_key: str region: str = "us-east-1" project_id?: str # Network settings vpc_id?: str subnet_id?: str security_group_id?: str check: len(api_endpoint) > 0, "API endpoint cannot be empty" len(api_key) > 0, "API key cannot be empty" len(region) > 0, "Region cannot be empty" # Server configuration for this provider schema MyCloudServer(server.Server): """Server configuration for My Cloud""" # Provider-specific server settings instance_type: str = "standard-1vcpu-1gb" availability_zone?: str # Storage configuration root_disk_size: int = 25 additional_disks?: [MyCloudDisk] # Network configuration public_ip: bool = True private_networking: bool = False check: len(instance_type) > 0, "Instance type cannot be empty" root_disk_size >= 10, "Root disk must be at least 10GB" schema MyCloudDisk: """Additional disk configuration""" size: int type: "ssd" | "hdd" = "ssd" mount_point?: str check: size > 0, "Disk size must be positive" # Provider defaults my_cloud_defaults: defaults.ServerDefaults = { lock = False time_zone = "UTC" running_wait = 15 running_timeout = 300 # OS configuration storage_os_find = "name: ubuntu-20.04 | arch: x86_64" # Network settings network_utility_ipv4 = True network_public_ipv4 = True # User settings user = "ubuntu" user_ssh_port = 22 fix_local_hosts = True labels = "provider: my-cloud" } # Export provider configuration { config: MyCloudConfig, server: MyCloudServer, defaults: my_cloud_defaults } ``` ### Creating a Cluster Extension #### 1. Cluster Structure ```bash # Create cluster directory mkdir -p extensions/clusters/my-stack/kcl cd extensions/clusters/my-stack/kcl # Initialize kcl mod init my-stack ``` #### 2. Cluster Schema Create `my-stack.k`: ```kcl """ My Stack Cluster Configuration Complete infrastructure stack with multiple services """ import provisioning.cluster as cluster import provisioning.server as server # Cluster configuration schema MyStackCluster(cluster.ClusterDef): """My Stack cluster definition""" name: str = "my-stack" # Component configuration components: MyStackComponents # Infrastructure settings node_count: int = 3 load_balancer: bool = True monitoring: bool = True logging: bool = True schema MyStackComponents: """Components in My Stack""" # Web tier web_servers: int = 2 web_instance_type: str = "standard-2vcpu-4gb" # Application tier app_servers: int = 3 app_instance_type: str = "standard-4vcpu-8gb" # Database tier db_servers: int = 1 db_instance_type: str = "standard-8vcpu-16gb" db_storage_size: int = 100 # Cache tier cache_enabled: bool = True cache_instance_type: str = "standard-2vcpu-4gb" # Generate server configurations for the cluster my_stack_servers: [server.Server] = [ # Web servers { hostname = "web-01" title = "Web Server 01" # ... web server configuration taskservs = [ { name = "nginx", profile = "web" }, { name = "ssl-cert", profile = "default" } ] }, { hostname = "web-02" title = "Web Server 02" # ... web server configuration taskservs = [ { name = "nginx", profile = "web" }, { name = "ssl-cert", profile = "default" } ] }, # Application servers { hostname = "app-01" title = "Application Server 01" # ... app server configuration taskservs = [ { name = "kubernetes", profile = "worker" }, { name = "containerd", profile = "default" } ] }, # Database server { hostname = "db-01" title = "Database Server 01" # ... database configuration taskservs = [ { name = "postgres", profile = "production" }, { name = "backup-agent", profile = "default" } ] } ] # Export cluster definition { cluster: MyStackCluster, servers: my_stack_servers } ``` ## Infrastructure-Specific Extensions ### Creating Extensions for Specific Infrastructure When you need extensions tailored to specific infrastructure or business requirements: #### 1. Organization Structure ```bash # Create organization-specific extension directory mkdir -p extensions/taskservs/org-specific/my-company-app/kcl cd extensions/taskservs/org-specific/my-company-app/kcl ``` #### 2. Company-Specific Taskserv Create `my-company-app.k`: ```kcl """ My Company Application Taskserv Company-specific application with custom requirements """ import provisioning.lib as lib import provisioning.dependencies as deps schema MyCompanyAppConfig: """Configuration for company-specific application""" # Application settings app_version: str = "latest" environment: "development" | "staging" | "production" = "production" # Company-specific settings company_domain: str internal_api_endpoint: str # Integration settings ldap_server?: str sso_provider?: str monitoring_endpoint?: str # Compliance settings encryption_enabled: bool = True audit_logging: bool = True data_retention_days: int = 90 # Resource settings based on environment resources: MyCompanyAppResources check: len(company_domain) > 0, "Company domain required" len(internal_api_endpoint) > 0, "Internal API endpoint required" data_retention_days > 0, "Data retention must be positive" schema MyCompanyAppResources: """Resource configuration based on environment""" cpu_request: str memory_request: str cpu_limit: str memory_limit: str storage_size: str replicas: int # Environment-specific resource profiles my_company_app_resources = { "development": { cpu_request = "100m" memory_request = "256Mi" cpu_limit = "500m" memory_limit = "512Mi" storage_size = "5Gi" replicas = 1 }, "staging": { cpu_request = "200m" memory_request = "512Mi" cpu_limit = "1" memory_limit = "1Gi" storage_size = "20Gi" replicas = 2 }, "production": { cpu_request = "500m" memory_request = "1Gi" cpu_limit = "2" memory_limit = "4Gi" storage_size = "100Gi" replicas = 5 } } # Taskserv definition schema MyCompanyAppTaskserv(lib.TaskServDef): """My Company App Taskserv Definition""" name: str = "my-company-app" config: MyCompanyAppConfig # Dependencies for company app my_company_app_dependencies: deps.TaskservDependencies = { name = "my-company-app" # Required infrastructure requires = ["kubernetes", "postgres", "redis"] # Integrations optional = ["monitoring", "logging", "backup"] # What this app provides provides = ["company-api", "company-ui", "company-reports"] # Company-specific requirements resources = { cpu = "500m" memory = "1Gi" disk = "10Gi" network = True privileged = False } # Compliance health checks health_checks = [ { command = "curl -f https://app.company.com/health" interval = 30 timeout = 10 retries = 3 }, { command = "check-compliance-status" interval = 300 # Every 5 minutes timeout = 30 retries = 1 } ] # Installation phases phases = [ { name = "pre-install" order = 1 parallel = False required = True }, { name = "install" order = 2 parallel = True required = True }, { name = "configure-integrations" order = 3 parallel = False required = True }, { name = "compliance-check" order = 4 parallel = False required = True } ] # Compatibility os_support = ["linux"] arch_support = ["amd64"] k8s_versions = ["1.25+"] } # Export company app configuration { config: MyCompanyAppTaskserv, dependencies: my_company_app_dependencies } ``` ### Multi-Environment Extensions #### Environment-Specific Configurations Create `environments/production.k`: ```kcl """ Production environment configuration for My Company App """ import ..my-company-app as app production_config: app.MyCompanyAppConfig = { app_version = "v2.1.0" environment = "production" company_domain = "company.com" internal_api_endpoint = "https://api.internal.company.com" # Production integrations ldap_server = "ldap.company.com" sso_provider = "https://sso.company.com" monitoring_endpoint = "https://metrics.company.com" # Production compliance encryption_enabled = True audit_logging = True data_retention_days = 365 # Production resources resources = { cpu_request = "1" memory_request = "2Gi" cpu_limit = "4" memory_limit = "8Gi" storage_size = "500Gi" replicas = 10 } } production_config ``` ## Publishing and Distribution ### Local Development ```bash # Develop and test locally cd extensions/taskservs/my-service module-loader discover taskservs | grep my-service # Load into test workspace cd /tmp/test-workspace module-loader load taskservs . [my-service] ``` ### Version Control ```bash # Create git repository for extension cd extensions/taskservs/my-service git init git add . git commit -m "Initial my-service taskserv" # Tag versions git tag v0.0.1 git push origin v0.0.1 ``` ### Package Distribution #### Creating Extension Packages ```bash # Create extension package tar -czf my-service-taskserv-v0.0.1.tar.gz -C extensions/taskservs my-service # Create bundle with multiple extensions tar -czf company-extensions-v1.0.0.tar.gz \ -C extensions/taskservs my-company-app \ -C extensions/providers my-cloud \ -C extensions/clusters my-stack ``` #### Distribution Methods 1. **Git Repository** ```bash # Users can clone and load git clone https://github.com/company/provisioning-extensions module-loader load taskservs . [my-company-app] ``` 2. **Package Registry** (Future) ```bash # Publish to registry kcl publish extensions/taskservs/my-service # Users install from registry module-loader install taskserv my-service@0.0.1 ``` 3. **Internal Distribution** ```bash # Internal package server curl -O https://packages.company.com/my-service-v0.0.1.tar.gz tar -xzf my-service-v0.0.1.tar.gz -C extensions/taskservs/ ``` ## Best Practices ### Extension Development 1. **Follow Naming Conventions** - Use kebab-case for extension names - Prefix company-specific extensions with organization name - Use semantic versioning 2. **Schema Design** - Include comprehensive validation - Provide sensible defaults - Support multiple profiles/environments - Document all fields 3. **Dependencies** - Declare all dependencies explicitly - Use optional dependencies for enhanced features - Specify compatibility versions 4. **Testing** ```bash # Test extension loading module-loader discover taskservs | grep my-service # Test in isolated workspace mkdir test-workspace cd test-workspace workspace-init.nu . init module-loader load taskservs . [my-service] # Validate KCL compilation kcl check taskservs.k ``` ### Security Considerations 1. **Secrets Management** - Never hardcode secrets in schemas - Use provisioning system's secrets management - Support external secret providers 2. **Input Validation** - Validate all user inputs - Use KCL check constraints - Sanitize external data 3. **Resource Limits** - Set reasonable resource defaults - Provide resource limit options - Include resource monitoring ### Documentation 1. **Extension Documentation** - Include README.md in each extension - Document configuration options - Provide usage examples - Include troubleshooting guide 2. **Version Documentation** - Maintain changelog - Document breaking changes - Include migration guides ### Example Directory Structure ``` extensions/ ├── taskservs/ │ ├── my-service/ │ │ ├── kcl/ │ │ │ ├── kcl.mod │ │ │ ├── my-service.k │ │ │ ├── version.k │ │ │ └── dependencies.k │ │ ├── templates/ │ │ │ ├── deployment.yaml.j2 │ │ │ └── service.yaml.j2 │ │ ├── scripts/ │ │ │ ├── install.nu │ │ │ └── health-check.nu │ │ └── README.md │ └── org-specific/ │ └── my-company-app/ │ ├── kcl/ │ │ ├── kcl.mod │ │ ├── my-company-app.k │ │ ├── version.k │ │ └── environments/ │ │ ├── development.k │ │ ├── staging.k │ │ └── production.k │ └── README.md ├── providers/ │ └── my-cloud/ │ ├── kcl/ │ │ ├── kcl.mod │ │ ├── provision_my-cloud.k │ │ ├── server_my-cloud.k │ │ └── defaults_my-cloud.k │ └── README.md └── clusters/ └── my-stack/ ├── kcl/ │ ├── kcl.mod │ └── my-stack.k └── README.md ``` This guide provides comprehensive coverage of KCL packaging and extension development for both general-purpose and infrastructure-specific use cases.