11 KiB
11 KiB
Configuration Validation Guide
Overview
The new configuration system includes comprehensive schema validation to catch errors early and ensure configuration correctness.
Schema Validation Features
1. Required Fields Validation
Ensures all required fields are present:
# Schema definition
[required]
fields = ["name", "version", "enabled"]
# Valid config
name = "my-service"
version = "1.0.0"
enabled = true
# Invalid - missing 'enabled'
name = "my-service"
version = "1.0.0"
# Error: Required field missing: enabled
2. Type Validation
Validates field types:
# Schema
[fields.port]
type = "int"
[fields.name]
type = "string"
[fields.enabled]
type = "bool"
# Valid
port = 8080
name = "orchestrator"
enabled = true
# Invalid - wrong type
port = "8080" # Error: Expected int, got string
3. Enum Validation
Restricts values to predefined set:
# Schema
[fields.environment]
type = "string"
enum = ["dev", "staging", "prod"]
# Valid
environment = "prod"
# Invalid
environment = "production" # Error: Must be one of: dev, staging, prod
4. Range Validation
Validates numeric ranges:
# Schema
[fields.port]
type = "int"
min = 1024
max = 65535
# Valid
port = 8080
# Invalid - below minimum
port = 80 # Error: Must be >= 1024
# Invalid - above maximum
port = 70000 # Error: Must be <= 65535
5. Pattern Validation
Validates string patterns using regex:
# Schema
[fields.email]
type = "string"
pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
# Valid
email = "admin@example.com"
# Invalid
email = "not-an-email" # Error: Does not match pattern
6. Deprecated Fields
Warns about deprecated configuration:
# Schema
[deprecated]
fields = ["old_field"]
[deprecated_replacements]
old_field = "new_field"
# Config using deprecated field
old_field = "value" # Warning: old_field is deprecated. Use new_field instead.
Using Schema Validator
Command Line
# Validate workspace config
provisioning workspace config validate
# Validate provider config
provisioning provider validate aws
# Validate platform service config
provisioning platform validate orchestrator
# Validate with detailed output
provisioning workspace config validate --verbose
Programmatic Usage
use provisioning/core/nulib/lib_provisioning/config/schema_validator.nu *
# Load config
let config = (open ~/workspaces/my-project/config/provisioning.yaml | from yaml)
# Validate against schema
let result = (validate-workspace-config $config)
# Check results
if $result.valid {
print "✅ Configuration is valid"
} else {
print "❌ Configuration has errors:"
for error in $result.errors {
print $" • ($error.message)"
}
}
# Display warnings
if ($result.warnings | length) > 0 {
print "⚠️ Warnings:"
for warning in $result.warnings {
print $" • ($warning.message)"
}
}
Pretty Print Results
# Validate and print formatted results
let result = (validate-workspace-config $config)
print-validation-results $result
Schema Examples
Workspace Schema
File: /Users/Akasha/project-provisioning/provisioning/config/workspace.schema.toml
[required]
fields = ["workspace", "paths"]
[fields.workspace]
type = "record"
[fields.workspace.name]
type = "string"
pattern = "^[a-z][a-z0-9-]*$"
[fields.workspace.version]
type = "string"
pattern = "^\\d+\\.\\d+\\.\\d+$"
[fields.paths]
type = "record"
[fields.paths.base]
type = "string"
[fields.paths.infra]
type = "string"
[fields.debug]
type = "record"
[fields.debug.enabled]
type = "bool"
[fields.debug.log_level]
type = "string"
enum = ["debug", "info", "warn", "error"]
Provider Schema (AWS)
File: /Users/Akasha/project-provisioning/provisioning/extensions/providers/aws/config.schema.toml
[required]
fields = ["provider", "credentials"]
[fields.provider]
type = "record"
[fields.provider.name]
type = "string"
enum = ["aws"]
[fields.provider.region]
type = "string"
pattern = "^[a-z]{2}-[a-z]+-\\d+$"
[fields.provider.enabled]
type = "bool"
[fields.credentials]
type = "record"
[fields.credentials.type]
type = "string"
enum = ["environment", "file", "iam_role"]
[fields.compute]
type = "record"
[fields.compute.default_instance_type]
type = "string"
[fields.compute.default_ami]
type = "string"
pattern = "^ami-[a-f0-9]{8,17}$"
[fields.network]
type = "record"
[fields.network.vpc_id]
type = "string"
pattern = "^vpc-[a-f0-9]{8,17}$"
[fields.network.subnet_id]
type = "string"
pattern = "^subnet-[a-f0-9]{8,17}$"
[deprecated]
fields = ["old_region_field"]
[deprecated_replacements]
old_region_field = "provider.region"
Platform Service Schema (Orchestrator)
File: /Users/Akasha/project-provisioning/provisioning/platform/orchestrator/config.schema.toml
[required]
fields = ["service", "server"]
[fields.service]
type = "record"
[fields.service.name]
type = "string"
enum = ["orchestrator"]
[fields.service.enabled]
type = "bool"
[fields.server]
type = "record"
[fields.server.host]
type = "string"
[fields.server.port]
type = "int"
min = 1024
max = 65535
[fields.workers]
type = "int"
min = 1
max = 32
[fields.queue]
type = "record"
[fields.queue.max_size]
type = "int"
min = 100
max = 10000
[fields.queue.storage_path]
type = "string"
KMS Service Schema
File: /Users/Akasha/project-provisioning/provisioning/core/services/kms/config.schema.toml
[required]
fields = ["kms", "encryption"]
[fields.kms]
type = "record"
[fields.kms.enabled]
type = "bool"
[fields.kms.provider]
type = "string"
enum = ["aws_kms", "gcp_kms", "azure_kv", "vault", "local"]
[fields.encryption]
type = "record"
[fields.encryption.algorithm]
type = "string"
enum = ["AES-256-GCM", "ChaCha20-Poly1305"]
[fields.encryption.key_rotation_days]
type = "int"
min = 30
max = 365
[fields.vault]
type = "record"
[fields.vault.address]
type = "string"
pattern = "^https?://.*$"
[fields.vault.token_path]
type = "string"
[deprecated]
fields = ["old_kms_type"]
[deprecated_replacements]
old_kms_type = "kms.provider"
Validation Workflow
1. Development
# Create new config
vim ~/workspaces/dev/config/provisioning.yaml
# Validate immediately
provisioning workspace config validate
# Fix errors and revalidate
vim ~/workspaces/dev/config/provisioning.yaml
provisioning workspace config validate
2. CI/CD Pipeline
# GitLab CI
validate-config:
stage: validate
script:
- provisioning workspace config validate
- provisioning provider validate aws
- provisioning provider validate upcloud
- provisioning platform validate orchestrator
only:
changes:
- "*/config/**/*"
3. Pre-Deployment
# Validate all configurations before deployment
provisioning workspace config validate --verbose
provisioning provider validate --all
provisioning platform validate --all
# If valid, proceed with deployment
if [[ $? -eq 0 ]]; then
provisioning deploy --workspace production
fi
Error Messages
Clear Error Format
❌ Validation failed
Errors:
• Required field missing: workspace.name
• Field port type mismatch: expected int, got string
• Field environment must be one of: dev, staging, prod
• Field port must be >= 1024
• Field email does not match pattern: ^[a-zA-Z0-9._%+-]+@.*$
⚠️ Warnings:
• Field old_field is deprecated. Use new_field instead.
Error Details
Each error includes:
- field: Which field has the error
- type: Error type (missing_required, type_mismatch, invalid_enum, etc.)
- message: Human-readable description
- Additional context: Expected values, patterns, ranges
Common Validation Patterns
Pattern 1: Hostname Validation
[fields.hostname]
type = "string"
pattern = "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"
Pattern 2: Email Validation
[fields.email]
type = "string"
pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
Pattern 3: Semantic Version
[fields.version]
type = "string"
pattern = "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9]+)?$"
Pattern 4: URL Validation
[fields.url]
type = "string"
pattern = "^https?://[a-zA-Z0-9.-]+(:[0-9]+)?(/.*)?$"
Pattern 5: IPv4 Address
[fields.ip_address]
type = "string"
pattern = "^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$"
Pattern 6: AWS Resource ID
[fields.instance_id]
type = "string"
pattern = "^i-[a-f0-9]{8,17}$"
[fields.ami_id]
type = "string"
pattern = "^ami-[a-f0-9]{8,17}$"
[fields.vpc_id]
type = "string"
pattern = "^vpc-[a-f0-9]{8,17}$"
Testing Validation
Unit Tests
# Run validation test suite
nu provisioning/tests/config_validation_tests.nu
Integration Tests
# Test with real configs
provisioning test validate --workspace dev
provisioning test validate --workspace staging
provisioning test validate --workspace prod
Custom Validation
# Create custom validation function
def validate-custom-config [config: record] {
let result = (validate-workspace-config $config)
# Add custom business logic validation
if ($config.workspace.name | str starts-with "prod") {
if not $config.debug.enabled == false {
$result.errors = ($result.errors | append {
field: "debug.enabled"
type: "custom"
message: "Debug must be disabled in production"
})
}
}
$result
}
Best Practices
1. Validate Early
# Validate during development
provisioning workspace config validate
# Don't wait for deployment
2. Use Strict Schemas
# Be explicit about types and constraints
[fields.port]
type = "int"
min = 1024
max = 65535
# Don't leave fields unvalidated
3. Document Patterns
# Include examples in schema
[fields.email]
type = "string"
pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
# Example: user@example.com
4. Handle Deprecation
# Always provide replacement guidance
[deprecated_replacements]
old_field = "new_field" # Clear migration path
5. Test Schemas
# Include test cases in comments
# Valid: "admin@example.com"
# Invalid: "not-an-email"
Troubleshooting
Schema File Not Found
# Error: Schema file not found: /path/to/schema.toml
# Solution: Ensure schema exists
ls -la /Users/Akasha/project-provisioning/provisioning/config/*.schema.toml
Pattern Not Matching
# Error: Field hostname does not match pattern
# Debug: Test pattern separately
echo "my-hostname" | grep -E "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"
Type Mismatch
# Error: Expected int, got string
# Check config
cat ~/workspaces/dev/config/provisioning.yaml | yq '.server.port'
# Output: "8080" (string)
# Fix: Remove quotes
vim ~/workspaces/dev/config/provisioning.yaml
# Change: port: "8080"
# To: port: 8080