Runtime Override System

This directory contains documentation for Blueberry IDP's runtime override system and Helm values processing.

Overview

The runtime override system processes Helm values with sophisticated logic to ensure safe, consistent, and dynamic configuration while maintaining platform security and operational requirements.

Override Categories

Required Overrides

Fields that are always overridden at runtime, regardless of user input:

"required": [
    "environment.name",           # Environment identifier
    "environment.namespace",      # Kubernetes namespace
    "environment.ttl",           # Environment time-to-live
    "domain",                    # Based on dev/prod environment
    "backend.image.tag",         # Container image tags
    "backend.gitCommitSha",      # Git commit SHA
    "frontend1.image.tag",       # Frontend image tags
    "frontend1.gitCommitSha",    # Git commit SHA
    "frontend2.image.tag",       # Second frontend image tags
    "frontend2.gitCommitSha",    # Git commit SHA
    "mysql.auth.rootPassword",   # Generated at runtime
]

Computed Values

Fields that are dynamically calculated based on other configuration values:

"computed": {
    "frontend1.env.VITE_BACKEND_PUBLIC_URL": lambda values: f"https://{values.get('environment', {}).get('name', '')}-backend.{values.get('domain', '')}",
    "frontend2.env.VITE_BACKEND_PUBLIC_URL": lambda values: f"https://{values.get('environment', {}).get('name', '')}-backend.{values.get('domain', '')}",
    "backend.env.DATABASE_URL": lambda values: f"mysql://root:{values.get('mysql', {}).get('auth', {}).get('rootPassword', 'generated-password')}@ephemeral-env-{values.get('environment', {}).get('name', '').replace('ephemeral-', '')}-mysql:3306/{values.get('mysql', {}).get('auth', {}).get('database', 'ephemeral_db')}",
    "backend.ingress.host": lambda values: f"{values.get('environment', {}).get('name', '')}-backend.{values.get('domain', '')}",
    "frontend1.ingress.host": lambda values: f"{values.get('environment', {}).get('name', '')}-{values.get('frontend1', {}).get('name', 'frontend1')}.{values.get('domain', '')}",
    "frontend2.ingress.host": lambda values: f"{values.get('environment', {}).get('name', '')}-{values.get('frontend2', {}).get('name', 'frontend2')}.{values.get('domain', '')}",
}

Non-Overridable Fields

Fields that are system-managed and cannot be overridden by users:

"non_overridable": [
    "backend.env.DATABASE_URL",      # Always computed from MySQL settings
    "backend.env.REDIS_HOST",        # Always set to service name
    "backend.env.REDIS_PORT",        # Always 6379
    "frontend1.env.VITE_BACKEND_PUBLIC_URL",  # Always computed
    "frontend2.env.VITE_BACKEND_PUBLIC_URL",  # Always computed
    "backend.image.repository",      # Fixed by repository configuration
    "frontend1.image.repository",    # Fixed by repository configuration
    "frontend2.image.repository",    # Fixed by repository configuration
    # Resource specifications - GKE Autopilot manages these
    "backend.resources",
    "frontend1.resources",
    "frontend2.resources",
    "mysql.primary.resources",
    "redis.master.resources",
    "resources",
]

Extendable Fields

Fields that can be modified after creation:

"extendable": [
    "environment.ttl",  # Can be extended via TTL extension
]

Processing Pipeline

1. Input Collection

def apply_runtime_overrides(values: dict, overrides: dict) -> dict:
    """Apply runtime overrides to Helm values."""
    result = copy.deepcopy(values)

    # Filter out non-overridable keys from user overrides
    filtered_overrides = {}
    non_overridable_keys = set(RUNTIME_OVERRIDES.get("non_overridable", []))

2. Override Filtering

The system filters out non-overridable fields and logs warnings:

for key, value in overrides.items():
    if key in non_overridable_keys:
        logger.warning(
            "Ignoring non-overridable field override",
            field=key,
            value=value,
            metadata={"non_overridable": True}
        )
    else:
        filtered_overrides[key] = value

3. Direct Override Application

Apply user-provided overrides that passed validation:

for key, value in filtered_overrides.items():
    parts = key.split(".")
    current = result
    for part in parts[:-1]:
        if part not in current:
            current[part] = {}
        current = current[part]
    current[parts[-1]] = value

4. Computed Value Generation

Calculate dynamic values based on the current configuration:

for key, compute_func in RUNTIME_OVERRIDES["computed"].items():
    parts = key.split(".")
    current = result
    for part in parts[:-1]:
        if part not in current:
            current[part] = {}
        current = current[part]

    # Check if parent object is enabled
    parent_parts = parts[:-2]
    if parent_parts:
        parent = result
        for part in parent_parts:
            parent = parent.get(part, {})
        if not parent.get("enabled", True):
            continue

    current[parts[-1]] = compute_func(result)

Computed Value Examples

Backend Database URL

# Input values
mysql:
  auth:
    rootPassword: "secure-generated-password"
    database: "ephemeral_db"
environment:
  name: "pr-123"

# Computed result
backend:
  env:
    DATABASE_URL: "mysql://root:secure-generated-password@ephemeral-env-pr-123-mysql:3306/ephemeral_db"

Frontend Backend URL

# Input values
environment:
  name: "pr-456"
domain: "ephemeral.blueberry.florenciacomuzzi.com"

# Computed result
frontend1:
  env:
    VITE_BACKEND_PUBLIC_URL: "https://pr-456-backend.ephemeral.blueberry.florenciacomuzzi.com"

Ingress Hosts

# Input values
environment:
  name: "feature-branch"
domain: "ephemeral.blueberry.florenciacomuzzi.com"
frontend1:
  name: "sample-fe-1"

# Computed results
backend:
  ingress:
    host: "feature-branch-backend.ephemeral.blueberry.florenciacomuzzi.com"

frontend1:
  ingress:
    host: "feature-branch-sample-fe-1.ephemeral.blueberry.florenciacomuzzi.com"

Configuration Examples

Valid Runtime Configuration

# Base values (from charts/environment/values.yaml)
environment:
  name: ""  # Will be overridden
  namespace: ""  # Will be overridden
  ttl: "24h"  # Will be overridden

backend:
  image:
    repository: "us-docker.pkg.dev/development-454916/blueberry/sample-be-1"
    tag: "latest"  # Will be overridden
  port: 8000

# Runtime overrides applied
environment:
  name: "pr-789"
  namespace: "ephemeral-pr-789"
  ttl: "72h"

backend:
  image:
    tag: "sha-abc123"
  gitCommitSha: "abc123def456"

# Final computed values
backend:
  env:
    DATABASE_URL: "mysql://root:generated-password@ephemeral-env-pr-789-mysql:3306/ephemeral_db"
  ingress:
    host: "pr-789-backend.ephemeral.blueberry.florenciacomuzzi.com"

frontend1:
  env:
    VITE_BACKEND_PUBLIC_URL: "https://pr-789-backend.ephemeral.blueberry.florenciacomuzzi.com"
  ingress:
    host: "pr-789-sample-fe-1.ephemeral.blueberry.florenciacomuzzi.com"

Security Considerations

Field Protection

  • Non-overridable fields prevent security bypasses
  • Computed values ensure consistent URL generation
  • Resource specifications blocked for GKE Autopilot compliance

Validation Integration

  • Runtime overrides work with validation system
  • Warnings generated for blocked overrides
  • Audit logging for all override attempts

Dynamic Value Safety

  • Computed functions use safe string operations
  • Input sanitization prevents injection attacks
  • Error handling for malformed configurations

Best Practices

Platform Development

  • Always validate computed value functions
  • Use type hints for override functions
  • Test override combinations thoroughly
  • Document override behavior clearly

Configuration Management

  • Keep override logic simple and predictable
  • Use meaningful names for computed values
  • Implement proper error handling
  • Monitor override performance

Debugging

  • Log override decisions for troubleshooting
  • Provide clear error messages
  • Use structured logging for override events
  • Test override scenarios in development

Implementation Examples

Override Function

def apply_runtime_overrides(values: dict, overrides: dict) -> dict:
    """Apply runtime overrides to Helm values."""
    import copy

    result = copy.deepcopy(values)

    # Filter non-overridable keys
    filtered_overrides = {}
    non_overridable_keys = set(RUNTIME_OVERRIDES.get("non_overridable", []))

    for key, value in overrides.items():
        if key in non_overridable_keys:
            from blueberry.infrastructure.logging import get_logger
            logger = get_logger(__name__)
            logger.warning(
                "Ignoring non-overridable field override",
                field=key,
                value=value,
                metadata={"non_overridable": True}
            )
        else:
            filtered_overrides[key] = value

    # Apply direct overrides
    for key, value in filtered_overrides.items():
        parts = key.split(".")
        current = result
        for part in parts[:-1]:
            if part not in current:
                current[part] = {}
            current = current[part]
        current[parts[-1]] = value

    # Apply computed values
    for key, compute_func in RUNTIME_OVERRIDES["computed"].items():
        parts = key.split(".")
        current = result
        for part in parts[:-1]:
            if part not in current:
                current[part] = {}
            current = current[part]

        # Check if parent object is enabled
        parent_parts = parts[:-2]
        if parent_parts:
            parent = result
            for part in parent_parts:
                parent = parent.get(part, {})
            if not parent.get("enabled", True):
                continue

        current[parts[-1]] = compute_func(result)

    return result

Troubleshooting

Override Not Applied

  • Check if field is in non-overridable list
  • Verify field path syntax is correct
  • Ensure parent objects exist in values
  • Review validation warnings

Computed Value Incorrect

  • Check input values for computation
  • Verify compute function logic
  • Test with different input combinations
  • Review function error handling

Performance Issues

  • Monitor override processing time
  • Check for expensive compute functions
  • Optimize string operations
  • Consider caching computed values
  • blueberry/models/helm_values.py - Override system implementation
  • charts/environment/values.yaml - Base Helm values
  • blueberry/services/environment_creator.py - Runtime processing
  • blueberry/api/config_sets.py - API integration
Document ID: reference/configuration/overrides/README