Configuration Validation

This directory contains documentation for Blueberry IDP's configuration validation and warning systems.

Overview

The validation system ensures that user-provided configuration overrides are safe, valid, and compatible with the platform's constraints while providing helpful feedback for invalid configurations.

Validation Architecture

Multi-Layer Validation

  1. Schema Validation - Against Helm values schema
  2. Field Classification - Categorize override types
  3. Resource Constraint Checking - GKE Autopilot compliance
  4. Security Policy Enforcement - Platform security rules

Validation Categories

Non-Overridable Fields

System-managed fields that cannot be overridden by users:
- backend.env.DATABASE_URL - Always computed from MySQL settings
- backend.env.REDIS_HOST - Always set to service name
- frontend.env.VITE_BACKEND_PUBLIC_URL - Always computed
- *.image.repository - Fixed by repository configuration
- *.resources - GKE Autopilot manages automatically

Computed Fields

Fields that are dynamically calculated at runtime:
- backend.ingress.host - Based on environment name and domain
- frontend.ingress.host - Based on environment name and service
- backend.env.DATABASE_URL - Computed from MySQL configuration
- frontend.env.VITE_BACKEND_PUBLIC_URL - Computed from backend URL

Required Fields

Fields that are always overridden at runtime:
- environment.name - Environment identifier
- environment.namespace - Kubernetes namespace
- environment.ttl - Environment time-to-live
- *.image.tag - Container image tags
- *.gitCommitSha - Git commit references

Resource Specifications

Resource-related fields blocked for GKE Autopilot:
- resources, requests, limits
- cpu, memory specifications
- storage and volume configurations

Validation Process

Input Processing

def validate_user_overrides(overrides: dict) -> dict:
    """Validate user overrides and return warnings."""
    warnings = []
    filtered_overrides = {}

    # Classification sets
    non_overridable_keys = set(RUNTIME_OVERRIDES.get("non_overridable", []))
    computed_keys = set(RUNTIME_OVERRIDES.get("computed", {}).keys())
    required_keys = set(RUNTIME_OVERRIDES.get("required", []))

Warning Generation

The system generates specific warnings for different violation types:

Non-Overridable Warning

{
  "field": "backend.env.DATABASE_URL",
  "type": "non_overridable",
  "message": "Field 'backend.env.DATABASE_URL' is non-overridable (system managed) and will be ignored"
}

Computed Warning

{
  "field": "frontend1.env.VITE_BACKEND_PUBLIC_URL",
  "type": "computed",
  "message": "Field 'frontend1.env.VITE_BACKEND_PUBLIC_URL' is computed at runtime and will be ignored"
}

Resource Specification Warning

{
  "field": "backend.resources.requests.cpu",
  "type": "resource_spec",
  "message": "Field 'backend.resources.requests.cpu' contains resource specifications which are not allowed in GKE Autopilot and will be ignored"
}

Configuration Constraint Examples

Valid Overrides

# ✅ Valid: Custom environment variables
backend:
  env:
    CUSTOM_API_ENDPOINT: "https://api.example.com"
    FEATURE_FLAG_ENABLED: "true"

# ✅ Valid: Service configuration
backend:
  replicas: 3
  port: 8080

# ✅ Valid: Application settings
mysql:
  auth:
    database: "my_custom_db"

Invalid Overrides

# ❌ Invalid: Non-overridable field
backend:
  env:
    DATABASE_URL: "mysql://custom:pass@host:3306/db"  # System managed

# ❌ Invalid: Computed field
frontend1:
  env:
    VITE_BACKEND_PUBLIC_URL: "https://custom.domain.com"  # Computed at runtime

# ❌ Invalid: Resource specification
backend:
  resources:
    requests:
      cpu: "500m"  # GKE Autopilot manages resources
      memory: "1Gi"

# ❌ Invalid: Required field
environment:
  name: "custom-name"  # Always overridden at runtime

Environment Variable Validation

Allowed Environment Variables

Environment variables under backend.env and frontend.env are generally allowed:

backend:
  env:
    # ✅ Custom application settings
    LOG_LEVEL: "debug"
    API_TIMEOUT: "30s"
    FEATURE_TOGGLES: "feature1,feature2"

    # ✅ Integration endpoints
    EXTERNAL_SERVICE_URL: "https://api.partner.com"
    WEBHOOK_SECRET: "webhook-secret-key"

Blocked Environment Variables

System-managed environment variables are blocked:

backend:
  env:
    # ❌ Database connection (computed)
    DATABASE_URL: "mysql://..."

    # ❌ Redis connection (system managed)
    REDIS_HOST: "custom-redis"
    REDIS_PORT: "6380"

Best Practices

User Configuration

  • Use environment variables for custom application settings
  • Avoid overriding system-managed fields
  • Test configuration changes in development environments
  • Review validation warnings carefully

Platform Development

  • Document all non-overridable fields
  • Provide clear warning messages
  • Implement comprehensive validation rules
  • Monitor validation patterns for improvements

Error Handling

  • Always validate user input
  • Provide actionable error messages
  • Log validation events for monitoring
  • Implement graceful degradation

Implementation Examples

Validation Function

def validate_user_overrides(overrides: dict) -> dict:
    """Validate user overrides and return warnings."""
    warnings = []
    filtered_overrides = {}

    for key, value in overrides.items():
        if key in non_overridable_keys:
            warnings.append({
                "field": key,
                "type": "non_overridable",
                "message": f"Field '{key}' is non-overridable (system managed) and will be ignored"
            })
        elif contains_resource_spec(key, value):
            warnings.append({
                "field": key,
                "type": "resource_spec",
                "message": f"Field '{key}' contains resource specifications which are not allowed in GKE Autopilot and will be ignored"
            })
        else:
            filtered_overrides[key] = value

    return {"warnings": warnings, "filtered_overrides": filtered_overrides}

Resource Detection

def contains_resource_spec(key: str, value: Any) -> bool:
    """Check if a key or its nested values contain resource specifications."""
    resource_related_patterns = ["resources", "requests", "limits", "cpu", "memory"]

    # Check if the key itself indicates resources
    for pattern in resource_related_patterns:
        if pattern in key.lower():
            return True

    # Check nested dictionaries
    if isinstance(value, dict):
        for k, v in value.items():
            if contains_resource_spec(k, v):
                return True

    return False

Troubleshooting

Common Validation Errors

  • "Field is non-overridable": Field is system-managed, use different approach
  • "Contains resource specifications": Remove CPU/memory settings for GKE Autopilot
  • "Field is computed at runtime": Field is automatically calculated, remove override

Debugging Validation

  • Review validation warnings in API responses
  • Check field names against schema documentation
  • Test overrides in development environment
  • Use validation endpoint to test configurations
  • blueberry/models/helm_values.py - Validation implementation
  • charts/environment/values.yaml - Environment Helm schema
  • blueberry/api/config_sets.py - API validation endpoints
  • blueberry/services/environment_creator.py - Runtime validation
Document ID: reference/configuration/validation/README