Taskserv Developer Guide
Overview
This guide covers how to develop, create, and maintain taskservs in the provisioning system. Taskservs are reusable infrastructure components that can be deployed across different cloud providers and environments.
Architecture Overview
Layered System
The provisioning system uses a 3-layer architecture for taskservs:
- Layer 1 (Core):
provisioning/extensions/taskservs/{category}/{name}- Base taskserv definitions - Layer 2 (Workspace):
provisioning/workspace/templates/taskservs/{category}/{name}.k- Template configurations - Layer 3 (Infrastructure):
workspace/infra/{infra}/task-servs/{name}.k- Infrastructure-specific overrides
Resolution Order
The system resolves taskservs in this priority order:
- Infrastructure layer (highest priority) - specific to your infrastructure
- Workspace layer (medium priority) - templates and patterns
- Core layer (lowest priority) - base extensions
Taskserv Structure
Standard Directory Layout
provisioning/extensions/taskservs/{category}/{name}/
├── kcl/ # KCL configuration
│ ├── kcl.mod # Module definition
│ ├── {name}.k # Main schema
│ ├── version.k # Version information
│ └── dependencies.k # Dependencies (optional)
├── default/ # Default configurations
│ ├── defs.toml # Default values
│ └── install-{name}.sh # Installation script
├── README.md # Documentation
└── info.md # Metadata
Categories
Taskservs are organized into these categories:
- container-runtime: containerd, crio, crun, podman, runc, youki
- databases: postgres, redis
- development: coder, desktop, gitea, nushell, oras, radicle
- infrastructure: kms, os, provisioning, webhook, kubectl, polkadot
- kubernetes: kubernetes (main orchestration)
- networking: cilium, coredns, etcd, ip-aliases, proxy, resolv
- storage: external-nfs, mayastor, oci-reg, rook-ceph
Creating New Taskservs
Method 1: Using the Extension Creation Tool
# Create a new taskserv interactively
nu provisioning/tools/create-extension.nu interactive
# Create directly with parameters
nu provisioning/tools/create-extension.nu taskserv my-service \
--template basic \
--author "Your Name" \
--description "My service description" \
--output provisioning/extensions
Method 2: Manual Creation
- Choose a category and create the directory structure:
mkdir -p provisioning/extensions/taskservs/{category}/{name}/kcl
mkdir -p provisioning/extensions/taskservs/{category}/{name}/default
- Create the KCL module definition (
kcl/kcl.mod):
[package]
name = "my-service"
version = "1.0.0"
description = "Service description"
[dependencies]
k8s = { oci = "oci://ghcr.io/kcl-lang/k8s", tag = "1.30" }
- Create the main KCL schema (
kcl/my-service.k):
# My Service Configuration
schema MyService {
# Service metadata
name: str = "my-service"
version: str = "latest"
namespace: str = "default"
# Service configuration
replicas: int = 1
port: int = 8080
# Resource requirements
cpu: str = "100m"
memory: str = "128Mi"
# Additional configuration
config?: {str: any} = {}
}
# Default configuration
my_service_config: MyService = MyService {
name = "my-service"
version = "latest"
replicas = 1
port = 8080
}
- Create version information (
kcl/version.k):
# Version information for my-service taskserv
schema MyServiceVersion {
current: str = "1.0.0"
compatible: [str] = ["1.0.0"]
deprecated?: [str] = []
}
my_service_version: MyServiceVersion = MyServiceVersion {}
- Create default configuration (
default/defs.toml):
[service]
name = "my-service"
version = "latest"
port = 8080
[deployment]
replicas = 1
strategy = "RollingUpdate"
[resources]
cpu_request = "100m"
cpu_limit = "500m"
memory_request = "128Mi"
memory_limit = "512Mi"
- Create installation script (
default/install-my-service.sh):
#!/bin/bash
set -euo pipefail
# My Service Installation Script
echo "Installing my-service..."
# Configuration
SERVICE_NAME="${SERVICE_NAME:-my-service}"
SERVICE_VERSION="${SERVICE_VERSION:-latest}"
NAMESPACE="${NAMESPACE:-default}"
# Install service
kubectl create namespace "${NAMESPACE}" --dry-run=client -o yaml | kubectl apply -f -
# Apply configuration
envsubst < my-service-deployment.yaml | kubectl apply -f -
echo "✅ my-service installed successfully"
Working with Templates
Creating Workspace Templates
Templates provide reusable configurations that can be customized per infrastructure:
# Create template directory
mkdir -p provisioning/workspace/templates/taskservs/{category}
# Create template file
cat > provisioning/workspace/templates/taskservs/{category}/{name}.k << 'EOF'
# Template for {name} taskserv
import taskservs.{category}.{name}.kcl.{name} as base
# Template configuration extending base
{name}_template: base.{Name} = base.{name}_config {
# Template customizations
version = "stable"
replicas = 2 # Production default
# Environment-specific overrides will be applied at infrastructure layer
}
EOF
Infrastructure Overrides
Create infrastructure-specific configurations:
# Create infrastructure override
mkdir -p workspace/infra/{your-infra}/task-servs
cat > workspace/infra/{your-infra}/task-servs/{name}.k << 'EOF'
# Infrastructure-specific configuration for {name}
import provisioning.workspace.templates.taskservs.{category}.{name} as template
# Infrastructure customizations
{name}_config: template.{name}_template {
# Override for this specific infrastructure
version = "1.2.3" # Pin to specific version
replicas = 3 # Scale for this environment
# Infrastructure-specific settings
resources = {
cpu = "200m"
memory = "256Mi"
}
}
EOF
CLI Commands
Taskserv Management
# Create taskserv (deploy to infrastructure)
provisioning/core/cli/provisioning taskserv create {name} --infra {infra-name} --check
# Generate taskserv configuration
provisioning/core/cli/provisioning taskserv generate {name} --infra {infra-name}
# Delete taskserv
provisioning/core/cli/provisioning taskserv delete {name} --infra {infra-name} --check
# List available taskservs
nu -c "use provisioning/core/nulib/taskservs/discover.nu *; discover-taskservs"
# Check taskserv versions
provisioning/core/cli/provisioning taskserv versions {name}
provisioning/core/cli/provisioning taskserv check-updates {name}
Discovery and Testing
# Test layer resolution for a taskserv
nu -c "use provisioning/workspace/tools/layer-utils.nu *; test_layer_resolution {name} {infra} {provider}"
# Show layer statistics
nu -c "use provisioning/workspace/tools/layer-utils.nu *; show_layer_stats"
# Get taskserv information
nu -c "use provisioning/core/nulib/taskservs/discover.nu *; get-taskserv-info {name}"
# Search taskservs
nu -c "use provisioning/core/nulib/taskservs/discover.nu *; search-taskservs {query}"
Best Practices
1. Naming Conventions
- Use kebab-case for taskserv names:
my-service,data-processor - Use descriptive names that indicate the service purpose
- Avoid generic names like
service,app,tool
2. Configuration Design
- Define sensible defaults in the base schema
- Make configurations parameterizable through variables
- Support multi-environment deployment (dev, test, prod)
- Include resource limits and requests
3. Dependencies
- Declare all dependencies explicitly in
kcl.mod - Use version constraints to ensure compatibility
- Consider dependency order for installation
4. Documentation
- Provide comprehensive README.md with usage examples
- Document all configuration options
- Include troubleshooting sections
- Add version compatibility information
5. Testing
- Test taskservs across different providers (AWS, UpCloud, local)
- Validate with
--checkflag before deployment - Test layer resolution to ensure proper override behavior
- Verify dependency resolution works correctly
Troubleshooting
Common Issues
-
Taskserv not discovered
- Ensure
kcl/kcl.modexists and is valid TOML - Check directory structure matches expected layout
- Verify taskserv is in correct category folder
- Ensure
-
Layer resolution not working
- Use
test_layer_resolutiontool to debug - Check file paths and naming conventions
- Verify import statements in KCL files
- Use
-
Dependency resolution errors
- Check
kcl.moddependencies section - Ensure dependency versions are compatible
- Verify dependency taskservs exist and are discoverable
- Check
-
Configuration validation failures
- Use
kcl checkto validate KCL syntax - Check for missing required fields
- Verify data types match schema definitions
- Use
Debug Commands
# Enable debug mode for taskserv operations
provisioning/core/cli/provisioning taskserv create {name} --debug --check
# Check KCL syntax
kcl check provisioning/extensions/taskservs/{category}/{name}/kcl/{name}.k
# Validate taskserv structure
nu provisioning/tools/create-extension.nu validate provisioning/extensions/taskservs/{category}/{name}
# Show detailed discovery information
nu -c "use provisioning/core/nulib/taskservs/discover.nu *; discover-taskservs | where name == '{name}'"
Contributing
Pull Request Guidelines
- Follow the standard directory structure
- Include comprehensive documentation
- Add tests and validation
- Update category documentation if adding new categories
- Ensure backward compatibility
Review Checklist
- Proper directory structure and naming
- Valid KCL schemas with appropriate types
- Comprehensive README documentation
- Working installation scripts
- Proper dependency declarations
- Template configurations (if applicable)
- Layer resolution testing
Advanced Topics
Custom Categories
To add new taskserv categories:
- Create the category directory structure
- Update the discovery system if needed
- Add category documentation
- Create initial taskservs for the category
- Add category templates if applicable
Cross-Provider Compatibility
Design taskservs to work across multiple providers:
schema MyService {
# Provider-agnostic configuration
name: str
version: str
# Provider-specific sections
aws?: AWSConfig
upcloud?: UpCloudConfig
local?: LocalConfig
}
Advanced Dependencies
Handle complex dependency scenarios:
# Conditional dependencies
schema MyService {
database_type: "postgres" | "mysql" | "redis"
# Dependencies based on configuration
if database_type == "postgres":
postgres_config: PostgresConfig
elif database_type == "redis":
redis_config: RedisConfig
}
This guide provides comprehensive coverage of taskserv development. For specific examples, see the existing taskservs in provisioning/extensions/taskservs/ and their corresponding templates in provisioning/workspace/templates/taskservs/.