provisioning/docs/CONFIG_VALIDATION.md

631 lines
11 KiB
Markdown
Raw Normal View History

2025-10-07 11:12:02 +01:00
# 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:
```toml
# 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:
```toml
# 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:
```toml
# 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:
```toml
# 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:
```toml
# 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:
```toml
# 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
```bash
# 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
```nushell
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
```nushell
# 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`
```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`
```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`
```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`
```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
```bash
# 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
```yaml
# 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
```bash
# 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
```toml
[fields.hostname]
type = "string"
pattern = "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"
```
### Pattern 2: Email Validation
```toml
[fields.email]
type = "string"
pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
```
### Pattern 3: Semantic Version
```toml
[fields.version]
type = "string"
pattern = "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9]+)?$"
```
### Pattern 4: URL Validation
```toml
[fields.url]
type = "string"
pattern = "^https?://[a-zA-Z0-9.-]+(:[0-9]+)?(/.*)?$"
```
### Pattern 5: IPv4 Address
```toml
[fields.ip_address]
type = "string"
pattern = "^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$"
```
### Pattern 6: AWS Resource ID
```toml
[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
```nushell
# Run validation test suite
nu provisioning/tests/config_validation_tests.nu
```
### Integration Tests
```bash
# Test with real configs
provisioning test validate --workspace dev
provisioning test validate --workspace staging
provisioning test validate --workspace prod
```
### Custom Validation
```nushell
# 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
```bash
# Validate during development
provisioning workspace config validate
# Don't wait for deployment
```
### 2. Use Strict Schemas
```toml
# Be explicit about types and constraints
[fields.port]
type = "int"
min = 1024
max = 65535
# Don't leave fields unvalidated
```
### 3. Document Patterns
```toml
# 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
```toml
# Always provide replacement guidance
[deprecated_replacements]
old_field = "new_field" # Clear migration path
```
### 5. Test Schemas
```nushell
# Include test cases in comments
# Valid: "admin@example.com"
# Invalid: "not-an-email"
```
## Troubleshooting
### Schema File Not Found
```bash
# 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
```bash
# 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
```bash
# 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
```
## Additional Resources
- [Migration Guide](./MIGRATION_GUIDE.md)
- [Workspace Guide](./WORKSPACE_GUIDE.md)
- [Schema Files](../config/*.schema.toml)
- [Validation Tests](../tests/config_validation_tests.nu)