1091 lines
41 KiB
HTML
1091 lines
41 KiB
HTML
|
|
<!DOCTYPE HTML>
|
|||
|
|
<html lang="en" class="ayu sidebar-visible" dir="ltr">
|
|||
|
|
<head>
|
|||
|
|
<!-- Book generated using mdBook -->
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<title>Configuration Guide - Provisioning Platform Documentation</title>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<!-- Custom HTML head -->
|
|||
|
|
|
|||
|
|
<meta name="description" content="Complete documentation for the Provisioning Platform - Infrastructure automation with Nushell, KCL, and Rust">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|||
|
|
<meta name="theme-color" content="#ffffff">
|
|||
|
|
|
|||
|
|
<link rel="icon" href="../favicon.svg">
|
|||
|
|
<link rel="shortcut icon" href="../favicon.png">
|
|||
|
|
<link rel="stylesheet" href="../css/variables.css">
|
|||
|
|
<link rel="stylesheet" href="../css/general.css">
|
|||
|
|
<link rel="stylesheet" href="../css/chrome.css">
|
|||
|
|
<link rel="stylesheet" href="../css/print.css" media="print">
|
|||
|
|
|
|||
|
|
<!-- Fonts -->
|
|||
|
|
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
|
|||
|
|
<link rel="stylesheet" href="../fonts/fonts.css">
|
|||
|
|
|
|||
|
|
<!-- Highlight.js Stylesheets -->
|
|||
|
|
<link rel="stylesheet" id="highlight-css" href="../highlight.css">
|
|||
|
|
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
|
|||
|
|
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
|
|||
|
|
|
|||
|
|
<!-- Custom theme stylesheets -->
|
|||
|
|
|
|||
|
|
|
|||
|
|
<!-- Provide site root and default themes to javascript -->
|
|||
|
|
<script>
|
|||
|
|
const path_to_root = "../";
|
|||
|
|
const default_light_theme = "ayu";
|
|||
|
|
const default_dark_theme = "navy";
|
|||
|
|
</script>
|
|||
|
|
<!-- Start loading toc.js asap -->
|
|||
|
|
<script src="../toc.js"></script>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div id="mdbook-help-container">
|
|||
|
|
<div id="mdbook-help-popup">
|
|||
|
|
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
|
|||
|
|
<div>
|
|||
|
|
<p>Press <kbd>←</kbd> or <kbd>→</kbd> to navigate between chapters</p>
|
|||
|
|
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
|
|||
|
|
<p>Press <kbd>?</kbd> to show this help</p>
|
|||
|
|
<p>Press <kbd>Esc</kbd> to hide this help</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div id="body-container">
|
|||
|
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
|||
|
|
<script>
|
|||
|
|
try {
|
|||
|
|
let theme = localStorage.getItem('mdbook-theme');
|
|||
|
|
let sidebar = localStorage.getItem('mdbook-sidebar');
|
|||
|
|
|
|||
|
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
|||
|
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
|||
|
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
|||
|
|
}
|
|||
|
|
} catch (e) { }
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
|||
|
|
<script>
|
|||
|
|
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
|
|||
|
|
let theme;
|
|||
|
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
|||
|
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
|||
|
|
const html = document.documentElement;
|
|||
|
|
html.classList.remove('ayu')
|
|||
|
|
html.classList.add(theme);
|
|||
|
|
html.classList.add("js");
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
|||
|
|
|
|||
|
|
<!-- Hide / unhide sidebar before it is displayed -->
|
|||
|
|
<script>
|
|||
|
|
let sidebar = null;
|
|||
|
|
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
|||
|
|
if (document.body.clientWidth >= 1080) {
|
|||
|
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
|||
|
|
sidebar = sidebar || 'visible';
|
|||
|
|
} else {
|
|||
|
|
sidebar = 'hidden';
|
|||
|
|
}
|
|||
|
|
sidebar_toggle.checked = sidebar === 'visible';
|
|||
|
|
html.classList.remove('sidebar-visible');
|
|||
|
|
html.classList.add("sidebar-" + sidebar);
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
|||
|
|
<!-- populated by js -->
|
|||
|
|
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
|||
|
|
<noscript>
|
|||
|
|
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
|||
|
|
</noscript>
|
|||
|
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
|||
|
|
<div class="sidebar-resize-indicator"></div>
|
|||
|
|
</div>
|
|||
|
|
</nav>
|
|||
|
|
|
|||
|
|
<div id="page-wrapper" class="page-wrapper">
|
|||
|
|
|
|||
|
|
<div class="page">
|
|||
|
|
<div id="menu-bar-hover-placeholder"></div>
|
|||
|
|
<div id="menu-bar" class="menu-bar sticky">
|
|||
|
|
<div class="left-buttons">
|
|||
|
|
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
|||
|
|
<i class="fa fa-bars"></i>
|
|||
|
|
</label>
|
|||
|
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
|||
|
|
<i class="fa fa-paint-brush"></i>
|
|||
|
|
</button>
|
|||
|
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
|||
|
|
<li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
|
|||
|
|
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
|||
|
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
|||
|
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
|||
|
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
|||
|
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
|||
|
|
</ul>
|
|||
|
|
<button id="search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="searchbar">
|
|||
|
|
<i class="fa fa-search"></i>
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<h1 class="menu-title">Provisioning Platform Documentation</h1>
|
|||
|
|
|
|||
|
|
<div class="right-buttons">
|
|||
|
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
|||
|
|
<i id="print-button" class="fa fa-print"></i>
|
|||
|
|
</a>
|
|||
|
|
<a href="https://github.com/provisioning/provisioning-platform" title="Git repository" aria-label="Git repository">
|
|||
|
|
<i id="git-repository-button" class="fa fa-github"></i>
|
|||
|
|
</a>
|
|||
|
|
<a href="https://github.com/provisioning/provisioning-platform/edit/main/provisioning/docs/src/development/configuration.md" title="Suggest an edit" aria-label="Suggest an edit">
|
|||
|
|
<i id="git-edit-button" class="fa fa-edit"></i>
|
|||
|
|
</a>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div id="search-wrapper" class="hidden">
|
|||
|
|
<form id="searchbar-outer" class="searchbar-outer">
|
|||
|
|
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
|||
|
|
</form>
|
|||
|
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
|||
|
|
<div id="searchresults-header" class="searchresults-header"></div>
|
|||
|
|
<ul id="searchresults">
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
|||
|
|
<script>
|
|||
|
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
|||
|
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
|||
|
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
|||
|
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<div id="content" class="content">
|
|||
|
|
<main>
|
|||
|
|
<h1 id="configuration-management"><a class="header" href="#configuration-management">Configuration Management</a></h1>
|
|||
|
|
<p>This document provides comprehensive guidance on provisioning’s configuration architecture, environment-specific configurations, validation, error handling, and migration strategies.</p>
|
|||
|
|
<h2 id="table-of-contents"><a class="header" href="#table-of-contents">Table of Contents</a></h2>
|
|||
|
|
<ol>
|
|||
|
|
<li><a href="#overview">Overview</a></li>
|
|||
|
|
<li><a href="#configuration-architecture">Configuration Architecture</a></li>
|
|||
|
|
<li><a href="#configuration-files">Configuration Files</a></li>
|
|||
|
|
<li><a href="#environment-specific-configuration">Environment-Specific Configuration</a></li>
|
|||
|
|
<li><a href="#user-overrides-and-customization">User Overrides and Customization</a></li>
|
|||
|
|
<li><a href="#validation-and-error-handling">Validation and Error Handling</a></li>
|
|||
|
|
<li><a href="#interpolation-and-dynamic-values">Interpolation and Dynamic Values</a></li>
|
|||
|
|
<li><a href="#migration-strategies">Migration Strategies</a></li>
|
|||
|
|
<li><a href="#troubleshooting">Troubleshooting</a></li>
|
|||
|
|
</ol>
|
|||
|
|
<h2 id="overview"><a class="header" href="#overview">Overview</a></h2>
|
|||
|
|
<p>Provisioning implements a sophisticated configuration management system that has migrated from environment variable-based configuration to a hierarchical TOML configuration system with comprehensive validation and interpolation support.</p>
|
|||
|
|
<p><strong>Key Features</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><strong>Hierarchical Configuration</strong>: Multi-layer configuration with clear precedence</li>
|
|||
|
|
<li><strong>Environment-Specific</strong>: Dedicated configurations for dev, test, and production</li>
|
|||
|
|
<li><strong>Dynamic Interpolation</strong>: Template-based value resolution</li>
|
|||
|
|
<li><strong>Type Safety</strong>: Comprehensive validation and error handling</li>
|
|||
|
|
<li><strong>Migration Support</strong>: Backward compatibility with existing ENV variables</li>
|
|||
|
|
<li><strong>Workspace Integration</strong>: Seamless integration with development workspaces</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Migration Status</strong>: ✅ <strong>Complete</strong> (2025-09-23)</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><strong>65+ files migrated</strong> across entire codebase</li>
|
|||
|
|
<li><strong>200+ ENV variables replaced</strong> with 476 config accessors</li>
|
|||
|
|
<li><strong>16 token-efficient agents</strong> used for systematic migration</li>
|
|||
|
|
<li><strong>92% token efficiency</strong> achieved vs monolithic approach</li>
|
|||
|
|
</ul>
|
|||
|
|
<h2 id="configuration-architecture"><a class="header" href="#configuration-architecture">Configuration Architecture</a></h2>
|
|||
|
|
<h3 id="hierarchical-loading-order"><a class="header" href="#hierarchical-loading-order">Hierarchical Loading Order</a></h3>
|
|||
|
|
<p>The configuration system implements a clear precedence hierarchy (lowest to highest precedence):</p>
|
|||
|
|
<pre><code>Configuration Hierarchy (Low → High Precedence)
|
|||
|
|
┌─────────────────────────────────────────────────┐
|
|||
|
|
│ 1. config.defaults.toml │ ← System defaults
|
|||
|
|
│ (System-wide default values) │
|
|||
|
|
├─────────────────────────────────────────────────┤
|
|||
|
|
│ 2. ~/.config/provisioning/config.toml │ ← User configuration
|
|||
|
|
│ (User-specific preferences) │
|
|||
|
|
├─────────────────────────────────────────────────┤
|
|||
|
|
│ 3. ./provisioning.toml │ ← Project configuration
|
|||
|
|
│ (Project-specific settings) │
|
|||
|
|
├─────────────────────────────────────────────────┤
|
|||
|
|
│ 4. ./.provisioning.toml │ ← Infrastructure config
|
|||
|
|
│ (Infrastructure-specific settings) │
|
|||
|
|
├─────────────────────────────────────────────────┤
|
|||
|
|
│ 5. Environment-specific configs │ ← Environment overrides
|
|||
|
|
│ (config.{dev,test,prod}.toml) │
|
|||
|
|
├─────────────────────────────────────────────────┤
|
|||
|
|
│ 6. Runtime environment variables │ ← Runtime overrides
|
|||
|
|
│ (PROVISIONING_* variables) │
|
|||
|
|
└─────────────────────────────────────────────────┘
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="configuration-access-patterns"><a class="header" href="#configuration-access-patterns">Configuration Access Patterns</a></h3>
|
|||
|
|
<p><strong>Configuration Accessor Functions</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Core configuration access
|
|||
|
|
use core/nulib/lib_provisioning/config/accessor.nu
|
|||
|
|
|
|||
|
|
# Get configuration value with fallback
|
|||
|
|
let api_url = (get-config-value "providers.upcloud.api_url" "https://api.upcloud.com")
|
|||
|
|
|
|||
|
|
# Get required configuration (errors if missing)
|
|||
|
|
let api_key = (get-config-required "providers.upcloud.api_key")
|
|||
|
|
|
|||
|
|
# Get nested configuration
|
|||
|
|
let server_defaults = (get-config-section "defaults.servers")
|
|||
|
|
|
|||
|
|
# Environment-aware configuration
|
|||
|
|
let log_level = (get-config-env "logging.level" "info")
|
|||
|
|
|
|||
|
|
# Interpolated configuration
|
|||
|
|
let data_path = (get-config-interpolated "paths.data") # Resolves {{paths.base}}/data
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="migration-from-env-variables"><a class="header" href="#migration-from-env-variables">Migration from ENV Variables</a></h3>
|
|||
|
|
<p><strong>Before (ENV-based)</strong>:</p>
|
|||
|
|
<pre><code class="language-bash">export PROVISIONING_UPCLOUD_API_KEY="your-key"
|
|||
|
|
export PROVISIONING_UPCLOUD_API_URL="https://api.upcloud.com"
|
|||
|
|
export PROVISIONING_LOG_LEVEL="debug"
|
|||
|
|
export PROVISIONING_BASE_PATH="/usr/local/provisioning"
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>After (Config-based)</strong>:</p>
|
|||
|
|
<pre><code class="language-toml"># config.user.toml
|
|||
|
|
[providers.upcloud]
|
|||
|
|
api_key = "your-key"
|
|||
|
|
api_url = "https://api.upcloud.com"
|
|||
|
|
|
|||
|
|
[logging]
|
|||
|
|
level = "debug"
|
|||
|
|
|
|||
|
|
[paths]
|
|||
|
|
base = "/usr/local/provisioning"
|
|||
|
|
</code></pre>
|
|||
|
|
<h2 id="configuration-files"><a class="header" href="#configuration-files">Configuration Files</a></h2>
|
|||
|
|
<h3 id="system-defaults-configdefaultstoml"><a class="header" href="#system-defaults-configdefaultstoml">System Defaults (<code>config.defaults.toml</code>)</a></h3>
|
|||
|
|
<p><strong>Purpose</strong>: Provides sensible defaults for all system components
|
|||
|
|
<strong>Location</strong>: Root of the repository
|
|||
|
|
<strong>Modification</strong>: Should only be modified by system maintainers</p>
|
|||
|
|
<pre><code class="language-toml"># System-wide defaults - DO NOT MODIFY in production
|
|||
|
|
# Copy values to config.user.toml for customization
|
|||
|
|
|
|||
|
|
[core]
|
|||
|
|
version = "1.0.0"
|
|||
|
|
name = "provisioning-system"
|
|||
|
|
|
|||
|
|
[paths]
|
|||
|
|
# Base path - all other paths derived from this
|
|||
|
|
base = "/usr/local/provisioning"
|
|||
|
|
config = "{{paths.base}}/config"
|
|||
|
|
data = "{{paths.base}}/data"
|
|||
|
|
logs = "{{paths.base}}/logs"
|
|||
|
|
cache = "{{paths.base}}/cache"
|
|||
|
|
runtime = "{{paths.base}}/runtime"
|
|||
|
|
|
|||
|
|
[logging]
|
|||
|
|
level = "info"
|
|||
|
|
file = "{{paths.logs}}/provisioning.log"
|
|||
|
|
rotation = true
|
|||
|
|
max_size = "100MB"
|
|||
|
|
max_files = 5
|
|||
|
|
|
|||
|
|
[http]
|
|||
|
|
timeout = 30
|
|||
|
|
retries = 3
|
|||
|
|
user_agent = "provisioning-system/{{core.version}}"
|
|||
|
|
use_curl = false
|
|||
|
|
|
|||
|
|
[providers]
|
|||
|
|
default = "local"
|
|||
|
|
|
|||
|
|
[providers.upcloud]
|
|||
|
|
api_url = "https://api.upcloud.com/1.3"
|
|||
|
|
timeout = 30
|
|||
|
|
max_retries = 3
|
|||
|
|
|
|||
|
|
[providers.aws]
|
|||
|
|
region = "us-east-1"
|
|||
|
|
timeout = 30
|
|||
|
|
|
|||
|
|
[providers.local]
|
|||
|
|
enabled = true
|
|||
|
|
base_path = "{{paths.data}}/local"
|
|||
|
|
|
|||
|
|
[defaults]
|
|||
|
|
[defaults.servers]
|
|||
|
|
plan = "1xCPU-2GB"
|
|||
|
|
zone = "auto"
|
|||
|
|
template = "ubuntu-22.04"
|
|||
|
|
|
|||
|
|
[cache]
|
|||
|
|
enabled = true
|
|||
|
|
ttl = 3600
|
|||
|
|
path = "{{paths.cache}}"
|
|||
|
|
|
|||
|
|
[orchestrator]
|
|||
|
|
enabled = false
|
|||
|
|
port = 8080
|
|||
|
|
bind = "127.0.0.1"
|
|||
|
|
data_path = "{{paths.data}}/orchestrator"
|
|||
|
|
|
|||
|
|
[workflow]
|
|||
|
|
storage_backend = "filesystem"
|
|||
|
|
parallel_limit = 5
|
|||
|
|
rollback_enabled = true
|
|||
|
|
|
|||
|
|
[telemetry]
|
|||
|
|
enabled = false
|
|||
|
|
endpoint = ""
|
|||
|
|
sample_rate = 0.1
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="user-configuration-configprovisioningconfigtoml"><a class="header" href="#user-configuration-configprovisioningconfigtoml">User Configuration (<code>~/.config/provisioning/config.toml</code>)</a></h3>
|
|||
|
|
<p><strong>Purpose</strong>: User-specific customizations and preferences
|
|||
|
|
<strong>Location</strong>: User’s configuration directory
|
|||
|
|
<strong>Modification</strong>: Users should customize this file for their needs</p>
|
|||
|
|
<pre><code class="language-toml"># User configuration - customizations and personal preferences
|
|||
|
|
# This file overrides system defaults
|
|||
|
|
|
|||
|
|
[core]
|
|||
|
|
name = "provisioning-{{env.USER}}"
|
|||
|
|
|
|||
|
|
[paths]
|
|||
|
|
# Personal installation path
|
|||
|
|
base = "{{env.HOME}}/.local/share/provisioning"
|
|||
|
|
|
|||
|
|
[logging]
|
|||
|
|
level = "debug"
|
|||
|
|
file = "{{paths.logs}}/provisioning-{{env.USER}}.log"
|
|||
|
|
|
|||
|
|
[providers]
|
|||
|
|
default = "upcloud"
|
|||
|
|
|
|||
|
|
[providers.upcloud]
|
|||
|
|
api_key = "your-personal-api-key"
|
|||
|
|
api_secret = "your-personal-api-secret"
|
|||
|
|
|
|||
|
|
[defaults.servers]
|
|||
|
|
plan = "2xCPU-4GB"
|
|||
|
|
zone = "us-nyc1"
|
|||
|
|
|
|||
|
|
[development]
|
|||
|
|
auto_reload = true
|
|||
|
|
hot_reload_templates = true
|
|||
|
|
verbose_errors = true
|
|||
|
|
|
|||
|
|
[notifications]
|
|||
|
|
slack_webhook = "https://hooks.slack.com/your-webhook"
|
|||
|
|
email = "your-email@domain.com"
|
|||
|
|
|
|||
|
|
[git]
|
|||
|
|
auto_commit = true
|
|||
|
|
commit_prefix = "[{{env.USER}}]"
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="project-configuration-provisioningtoml"><a class="header" href="#project-configuration-provisioningtoml">Project Configuration (<code>./provisioning.toml</code>)</a></h3>
|
|||
|
|
<p><strong>Purpose</strong>: Project-specific settings shared across team
|
|||
|
|
<strong>Location</strong>: Project root directory
|
|||
|
|
<strong>Version Control</strong>: Should be committed to version control</p>
|
|||
|
|
<pre><code class="language-toml"># Project-specific configuration
|
|||
|
|
# Shared settings for this project/repository
|
|||
|
|
|
|||
|
|
[core]
|
|||
|
|
name = "my-project-provisioning"
|
|||
|
|
version = "1.2.0"
|
|||
|
|
|
|||
|
|
[infra]
|
|||
|
|
default = "staging"
|
|||
|
|
environments = ["dev", "staging", "production"]
|
|||
|
|
|
|||
|
|
[providers]
|
|||
|
|
default = "upcloud"
|
|||
|
|
allowed = ["upcloud", "aws", "local"]
|
|||
|
|
|
|||
|
|
[providers.upcloud]
|
|||
|
|
# Project-specific UpCloud settings
|
|||
|
|
default_zone = "us-nyc1"
|
|||
|
|
template = "ubuntu-22.04-lts"
|
|||
|
|
|
|||
|
|
[defaults.servers]
|
|||
|
|
plan = "2xCPU-4GB"
|
|||
|
|
storage = 50
|
|||
|
|
firewall_enabled = true
|
|||
|
|
|
|||
|
|
[security]
|
|||
|
|
enforce_https = true
|
|||
|
|
require_mfa = true
|
|||
|
|
allowed_cidr = ["10.0.0.0/8", "172.16.0.0/12"]
|
|||
|
|
|
|||
|
|
[compliance]
|
|||
|
|
data_region = "us-east"
|
|||
|
|
encryption_at_rest = true
|
|||
|
|
audit_logging = true
|
|||
|
|
|
|||
|
|
[team]
|
|||
|
|
admins = ["alice@company.com", "bob@company.com"]
|
|||
|
|
developers = ["dev-team@company.com"]
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="infrastructure-configuration-provisioningtoml"><a class="header" href="#infrastructure-configuration-provisioningtoml">Infrastructure Configuration (<code>./.provisioning.toml</code>)</a></h3>
|
|||
|
|
<p><strong>Purpose</strong>: Infrastructure-specific overrides
|
|||
|
|
<strong>Location</strong>: Infrastructure directory
|
|||
|
|
<strong>Usage</strong>: Overrides for specific infrastructure deployments</p>
|
|||
|
|
<pre><code class="language-toml"># Infrastructure-specific configuration
|
|||
|
|
# Overrides for this specific infrastructure deployment
|
|||
|
|
|
|||
|
|
[core]
|
|||
|
|
name = "production-east-provisioning"
|
|||
|
|
|
|||
|
|
[infra]
|
|||
|
|
name = "production-east"
|
|||
|
|
environment = "production"
|
|||
|
|
region = "us-east-1"
|
|||
|
|
|
|||
|
|
[providers.upcloud]
|
|||
|
|
zone = "us-nyc1"
|
|||
|
|
private_network = true
|
|||
|
|
|
|||
|
|
[providers.aws]
|
|||
|
|
region = "us-east-1"
|
|||
|
|
availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"]
|
|||
|
|
|
|||
|
|
[defaults.servers]
|
|||
|
|
plan = "4xCPU-8GB"
|
|||
|
|
storage = 100
|
|||
|
|
backup_enabled = true
|
|||
|
|
monitoring_enabled = true
|
|||
|
|
|
|||
|
|
[security]
|
|||
|
|
firewall_strict_mode = true
|
|||
|
|
encryption_required = true
|
|||
|
|
audit_all_actions = true
|
|||
|
|
|
|||
|
|
[monitoring]
|
|||
|
|
prometheus_enabled = true
|
|||
|
|
grafana_enabled = true
|
|||
|
|
alertmanager_enabled = true
|
|||
|
|
|
|||
|
|
[backup]
|
|||
|
|
enabled = true
|
|||
|
|
schedule = "0 2 * * *" # Daily at 2 AM
|
|||
|
|
retention_days = 30
|
|||
|
|
</code></pre>
|
|||
|
|
<h2 id="environment-specific-configuration"><a class="header" href="#environment-specific-configuration">Environment-Specific Configuration</a></h2>
|
|||
|
|
<h3 id="development-environment-configdevtoml"><a class="header" href="#development-environment-configdevtoml">Development Environment (<code>config.dev.toml</code>)</a></h3>
|
|||
|
|
<p><strong>Purpose</strong>: Development-optimized settings
|
|||
|
|
<strong>Features</strong>: Enhanced debugging, local providers, relaxed validation</p>
|
|||
|
|
<pre><code class="language-toml"># Development environment configuration
|
|||
|
|
# Optimized for local development and testing
|
|||
|
|
|
|||
|
|
[core]
|
|||
|
|
name = "provisioning-dev"
|
|||
|
|
version = "dev-{{git.branch}}"
|
|||
|
|
|
|||
|
|
[paths]
|
|||
|
|
base = "{{env.PWD}}/dev-environment"
|
|||
|
|
|
|||
|
|
[logging]
|
|||
|
|
level = "debug"
|
|||
|
|
console_output = true
|
|||
|
|
structured_logging = true
|
|||
|
|
debug_http = true
|
|||
|
|
|
|||
|
|
[providers]
|
|||
|
|
default = "local"
|
|||
|
|
|
|||
|
|
[providers.local]
|
|||
|
|
enabled = true
|
|||
|
|
fast_mode = true
|
|||
|
|
mock_delays = false
|
|||
|
|
|
|||
|
|
[http]
|
|||
|
|
timeout = 10
|
|||
|
|
retries = 1
|
|||
|
|
debug_requests = true
|
|||
|
|
|
|||
|
|
[cache]
|
|||
|
|
enabled = true
|
|||
|
|
ttl = 60 # Short TTL for development
|
|||
|
|
debug_cache = true
|
|||
|
|
|
|||
|
|
[development]
|
|||
|
|
auto_reload = true
|
|||
|
|
hot_reload_templates = true
|
|||
|
|
validate_strict = false
|
|||
|
|
experimental_features = true
|
|||
|
|
debug_mode = true
|
|||
|
|
|
|||
|
|
[orchestrator]
|
|||
|
|
enabled = true
|
|||
|
|
port = 8080
|
|||
|
|
debug = true
|
|||
|
|
file_watcher = true
|
|||
|
|
|
|||
|
|
[testing]
|
|||
|
|
parallel_tests = true
|
|||
|
|
cleanup_after_tests = true
|
|||
|
|
mock_external_apis = true
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="testing-environment-configtesttoml"><a class="header" href="#testing-environment-configtesttoml">Testing Environment (<code>config.test.toml</code>)</a></h3>
|
|||
|
|
<p><strong>Purpose</strong>: Testing-specific configuration
|
|||
|
|
<strong>Features</strong>: Mock services, isolated environments, comprehensive logging</p>
|
|||
|
|
<pre><code class="language-toml"># Testing environment configuration
|
|||
|
|
# Optimized for automated testing and CI/CD
|
|||
|
|
|
|||
|
|
[core]
|
|||
|
|
name = "provisioning-test"
|
|||
|
|
version = "test-{{build.timestamp}}"
|
|||
|
|
|
|||
|
|
[logging]
|
|||
|
|
level = "info"
|
|||
|
|
test_output = true
|
|||
|
|
capture_stderr = true
|
|||
|
|
|
|||
|
|
[providers]
|
|||
|
|
default = "local"
|
|||
|
|
|
|||
|
|
[providers.local]
|
|||
|
|
enabled = true
|
|||
|
|
mock_mode = true
|
|||
|
|
deterministic = true
|
|||
|
|
|
|||
|
|
[http]
|
|||
|
|
timeout = 5
|
|||
|
|
retries = 0
|
|||
|
|
mock_responses = true
|
|||
|
|
|
|||
|
|
[cache]
|
|||
|
|
enabled = false
|
|||
|
|
|
|||
|
|
[testing]
|
|||
|
|
isolated_environments = true
|
|||
|
|
cleanup_after_each_test = true
|
|||
|
|
parallel_execution = true
|
|||
|
|
mock_all_external_calls = true
|
|||
|
|
deterministic_ids = true
|
|||
|
|
|
|||
|
|
[orchestrator]
|
|||
|
|
enabled = false
|
|||
|
|
|
|||
|
|
[validation]
|
|||
|
|
strict_mode = true
|
|||
|
|
fail_fast = true
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="production-environment-configprodtoml"><a class="header" href="#production-environment-configprodtoml">Production Environment (<code>config.prod.toml</code>)</a></h3>
|
|||
|
|
<p><strong>Purpose</strong>: Production-optimized settings
|
|||
|
|
<strong>Features</strong>: Performance optimization, security hardening, comprehensive monitoring</p>
|
|||
|
|
<pre><code class="language-toml"># Production environment configuration
|
|||
|
|
# Optimized for performance, reliability, and security
|
|||
|
|
|
|||
|
|
[core]
|
|||
|
|
name = "provisioning-production"
|
|||
|
|
version = "{{release.version}}"
|
|||
|
|
|
|||
|
|
[logging]
|
|||
|
|
level = "warn"
|
|||
|
|
structured_logging = true
|
|||
|
|
sensitive_data_filtering = true
|
|||
|
|
audit_logging = true
|
|||
|
|
|
|||
|
|
[providers]
|
|||
|
|
default = "upcloud"
|
|||
|
|
|
|||
|
|
[http]
|
|||
|
|
timeout = 60
|
|||
|
|
retries = 5
|
|||
|
|
connection_pool = 20
|
|||
|
|
keep_alive = true
|
|||
|
|
|
|||
|
|
[cache]
|
|||
|
|
enabled = true
|
|||
|
|
ttl = 3600
|
|||
|
|
size_limit = "500MB"
|
|||
|
|
persistence = true
|
|||
|
|
|
|||
|
|
[security]
|
|||
|
|
strict_mode = true
|
|||
|
|
encrypt_at_rest = true
|
|||
|
|
encrypt_in_transit = true
|
|||
|
|
audit_all_actions = true
|
|||
|
|
|
|||
|
|
[monitoring]
|
|||
|
|
metrics_enabled = true
|
|||
|
|
tracing_enabled = true
|
|||
|
|
health_checks = true
|
|||
|
|
alerting = true
|
|||
|
|
|
|||
|
|
[orchestrator]
|
|||
|
|
enabled = true
|
|||
|
|
port = 8080
|
|||
|
|
bind = "0.0.0.0"
|
|||
|
|
workers = 4
|
|||
|
|
max_connections = 100
|
|||
|
|
|
|||
|
|
[performance]
|
|||
|
|
parallel_operations = true
|
|||
|
|
batch_operations = true
|
|||
|
|
connection_pooling = true
|
|||
|
|
</code></pre>
|
|||
|
|
<h2 id="user-overrides-and-customization"><a class="header" href="#user-overrides-and-customization">User Overrides and Customization</a></h2>
|
|||
|
|
<h3 id="personal-development-setup"><a class="header" href="#personal-development-setup">Personal Development Setup</a></h3>
|
|||
|
|
<p><strong>Creating User Configuration</strong>:</p>
|
|||
|
|
<pre><code class="language-bash"># Create user config directory
|
|||
|
|
mkdir -p ~/.config/provisioning
|
|||
|
|
|
|||
|
|
# Copy template
|
|||
|
|
cp src/provisioning/config-examples/config.user.toml ~/.config/provisioning/config.toml
|
|||
|
|
|
|||
|
|
# Customize for your environment
|
|||
|
|
$EDITOR ~/.config/provisioning/config.toml
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Common User Customizations</strong>:</p>
|
|||
|
|
<pre><code class="language-toml"># Personal configuration customizations
|
|||
|
|
|
|||
|
|
[paths]
|
|||
|
|
base = "{{env.HOME}}/dev/provisioning"
|
|||
|
|
|
|||
|
|
[development]
|
|||
|
|
editor = "code"
|
|||
|
|
auto_backup = true
|
|||
|
|
backup_interval = "1h"
|
|||
|
|
|
|||
|
|
[git]
|
|||
|
|
auto_commit = false
|
|||
|
|
commit_template = "[{{env.USER}}] {{change.type}}: {{change.description}}"
|
|||
|
|
|
|||
|
|
[providers.upcloud]
|
|||
|
|
api_key = "{{env.UPCLOUD_API_KEY}}"
|
|||
|
|
api_secret = "{{env.UPCLOUD_API_SECRET}}"
|
|||
|
|
default_zone = "de-fra1"
|
|||
|
|
|
|||
|
|
[shortcuts]
|
|||
|
|
# Custom command aliases
|
|||
|
|
quick_server = "server create {{name}} 2xCPU-4GB --zone us-nyc1"
|
|||
|
|
dev_cluster = "cluster create development --infra {{env.USER}}-dev"
|
|||
|
|
|
|||
|
|
[notifications]
|
|||
|
|
desktop_notifications = true
|
|||
|
|
sound_notifications = false
|
|||
|
|
slack_webhook = "{{env.SLACK_WEBHOOK_URL}}"
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="workspace-specific-configuration"><a class="header" href="#workspace-specific-configuration">Workspace-Specific Configuration</a></h3>
|
|||
|
|
<p><strong>Workspace Integration</strong>:</p>
|
|||
|
|
<pre><code class="language-toml"># Workspace-aware configuration
|
|||
|
|
# workspace/config/developer.toml
|
|||
|
|
|
|||
|
|
[workspace]
|
|||
|
|
user = "developer"
|
|||
|
|
type = "development"
|
|||
|
|
|
|||
|
|
[paths]
|
|||
|
|
base = "{{workspace.root}}"
|
|||
|
|
extensions = "{{workspace.root}}/extensions"
|
|||
|
|
runtime = "{{workspace.root}}/runtime/{{workspace.user}}"
|
|||
|
|
|
|||
|
|
[development]
|
|||
|
|
workspace_isolation = true
|
|||
|
|
per_user_cache = true
|
|||
|
|
shared_extensions = false
|
|||
|
|
|
|||
|
|
[infra]
|
|||
|
|
current = "{{workspace.user}}-development"
|
|||
|
|
auto_create = true
|
|||
|
|
</code></pre>
|
|||
|
|
<h2 id="validation-and-error-handling"><a class="header" href="#validation-and-error-handling">Validation and Error Handling</a></h2>
|
|||
|
|
<h3 id="configuration-validation"><a class="header" href="#configuration-validation">Configuration Validation</a></h3>
|
|||
|
|
<p><strong>Built-in Validation</strong>:</p>
|
|||
|
|
<pre><code class="language-bash"># Validate current configuration
|
|||
|
|
provisioning validate config
|
|||
|
|
|
|||
|
|
# Validate specific configuration file
|
|||
|
|
provisioning validate config --file config.dev.toml
|
|||
|
|
|
|||
|
|
# Show configuration with validation
|
|||
|
|
provisioning config show --validate
|
|||
|
|
|
|||
|
|
# Debug configuration loading
|
|||
|
|
provisioning config debug
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Validation Rules</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Configuration validation in Nushell
|
|||
|
|
def validate_configuration [config: record] -> record {
|
|||
|
|
let errors = []
|
|||
|
|
|
|||
|
|
# Validate required fields
|
|||
|
|
if not ("paths" in $config and "base" in $config.paths) {
|
|||
|
|
$errors = ($errors | append "paths.base is required")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Validate provider configuration
|
|||
|
|
if "providers" in $config {
|
|||
|
|
for provider in ($config.providers | columns) {
|
|||
|
|
if $provider == "upcloud" {
|
|||
|
|
if not ("api_key" in $config.providers.upcloud) {
|
|||
|
|
$errors = ($errors | append "providers.upcloud.api_key is required")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Validate numeric values
|
|||
|
|
if "http" in $config and "timeout" in $config.http {
|
|||
|
|
if $config.http.timeout <= 0 {
|
|||
|
|
$errors = ($errors | append "http.timeout must be positive")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
valid: ($errors | length) == 0,
|
|||
|
|
errors: $errors
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="error-handling"><a class="header" href="#error-handling">Error Handling</a></h3>
|
|||
|
|
<p><strong>Configuration-Driven Error Handling</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Never patch with hardcoded fallbacks - use configuration
|
|||
|
|
def get_api_endpoint [provider: string] -> string {
|
|||
|
|
# Good: Configuration-driven with clear error
|
|||
|
|
let config_key = $"providers.($provider).api_url"
|
|||
|
|
let endpoint = try {
|
|||
|
|
get-config-required $config_key
|
|||
|
|
} catch {
|
|||
|
|
error make {
|
|||
|
|
msg: $"API endpoint not configured for provider ($provider)",
|
|||
|
|
help: $"Add '($config_key)' to your configuration file"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$endpoint
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Bad: Hardcoded fallback defeats IaC purpose
|
|||
|
|
def get_api_endpoint_bad [provider: string] -> string {
|
|||
|
|
try {
|
|||
|
|
get-config-required $"providers.($provider).api_url"
|
|||
|
|
} catch {
|
|||
|
|
# DON'T DO THIS - defeats configuration-driven architecture
|
|||
|
|
"https://default-api.com"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Comprehensive Error Context</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell">def load_provider_config [provider: string] -> record {
|
|||
|
|
let config_section = $"providers.($provider)"
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
get-config-section $config_section
|
|||
|
|
} catch { |e|
|
|||
|
|
error make {
|
|||
|
|
msg: $"Failed to load configuration for provider ($provider): ($e.msg)",
|
|||
|
|
label: {
|
|||
|
|
text: "configuration missing",
|
|||
|
|
span: (metadata $provider).span
|
|||
|
|
},
|
|||
|
|
help: [
|
|||
|
|
$"Add [$config_section] section to your configuration",
|
|||
|
|
"Example configuration files available in config-examples/",
|
|||
|
|
"Run 'provisioning config show' to see current configuration"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<h2 id="interpolation-and-dynamic-values"><a class="header" href="#interpolation-and-dynamic-values">Interpolation and Dynamic Values</a></h2>
|
|||
|
|
<h3 id="interpolation-syntax"><a class="header" href="#interpolation-syntax">Interpolation Syntax</a></h3>
|
|||
|
|
<p><strong>Supported Interpolation Variables</strong>:</p>
|
|||
|
|
<pre><code class="language-toml"># Environment variables
|
|||
|
|
base_path = "{{env.HOME}}/provisioning"
|
|||
|
|
user_name = "{{env.USER}}"
|
|||
|
|
|
|||
|
|
# Configuration references
|
|||
|
|
data_path = "{{paths.base}}/data"
|
|||
|
|
log_file = "{{paths.logs}}/{{core.name}}.log"
|
|||
|
|
|
|||
|
|
# Date/time values
|
|||
|
|
backup_name = "backup-{{now.date}}-{{now.time}}"
|
|||
|
|
version = "{{core.version}}-{{now.timestamp}}"
|
|||
|
|
|
|||
|
|
# Git information
|
|||
|
|
branch_name = "{{git.branch}}"
|
|||
|
|
commit_hash = "{{git.commit}}"
|
|||
|
|
version_with_git = "{{core.version}}-{{git.commit}}"
|
|||
|
|
|
|||
|
|
# System information
|
|||
|
|
hostname = "{{system.hostname}}"
|
|||
|
|
platform = "{{system.platform}}"
|
|||
|
|
architecture = "{{system.arch}}"
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="complex-interpolation-examples"><a class="header" href="#complex-interpolation-examples">Complex Interpolation Examples</a></h3>
|
|||
|
|
<p><strong>Dynamic Path Resolution</strong>:</p>
|
|||
|
|
<pre><code class="language-toml">[paths]
|
|||
|
|
base = "{{env.HOME}}/.local/share/provisioning"
|
|||
|
|
config = "{{paths.base}}/config"
|
|||
|
|
data = "{{paths.base}}/data/{{system.hostname}}"
|
|||
|
|
logs = "{{paths.base}}/logs/{{env.USER}}/{{now.date}}"
|
|||
|
|
runtime = "{{paths.base}}/runtime/{{git.branch}}"
|
|||
|
|
|
|||
|
|
[providers.upcloud]
|
|||
|
|
cache_path = "{{paths.cache}}/providers/upcloud/{{env.USER}}"
|
|||
|
|
log_file = "{{paths.logs}}/upcloud-{{now.date}}.log"
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Environment-Aware Configuration</strong>:</p>
|
|||
|
|
<pre><code class="language-toml">[core]
|
|||
|
|
name = "provisioning-{{system.hostname}}-{{env.USER}}"
|
|||
|
|
version = "{{release.version}}+{{git.commit}}.{{now.timestamp}}"
|
|||
|
|
|
|||
|
|
[database]
|
|||
|
|
name = "provisioning_{{env.USER}}_{{git.branch}}"
|
|||
|
|
backup_prefix = "{{core.name}}-backup-{{now.date}}"
|
|||
|
|
|
|||
|
|
[monitoring]
|
|||
|
|
instance_id = "{{system.hostname}}-{{core.version}}"
|
|||
|
|
tags = {
|
|||
|
|
environment = "{{infra.environment}}",
|
|||
|
|
user = "{{env.USER}}",
|
|||
|
|
version = "{{core.version}}",
|
|||
|
|
deployment_time = "{{now.iso8601}}"
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="interpolation-functions"><a class="header" href="#interpolation-functions">Interpolation Functions</a></h3>
|
|||
|
|
<p><strong>Custom Interpolation Logic</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Interpolation resolver
|
|||
|
|
def resolve_interpolation [template: string, context: record] -> string {
|
|||
|
|
let interpolations = ($template | parse --regex '\{\{([^}]+)\}\}')
|
|||
|
|
|
|||
|
|
mut result = $template
|
|||
|
|
|
|||
|
|
for interpolation in $interpolations {
|
|||
|
|
let key_path = ($interpolation.capture0 | str trim)
|
|||
|
|
let value = resolve_interpolation_key $key_path $context
|
|||
|
|
|
|||
|
|
$result = ($result | str replace $"{{($interpolation.capture0)}}" $value)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$result
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def resolve_interpolation_key [key_path: string, context: record] -> string {
|
|||
|
|
match ($key_path | split row ".") {
|
|||
|
|
["env", $var] => ($env | get $var | default ""),
|
|||
|
|
["paths", $path] => (resolve_path_key $path $context),
|
|||
|
|
["now", $format] => (resolve_time_format $format),
|
|||
|
|
["git", $info] => (resolve_git_info $info),
|
|||
|
|
["system", $info] => (resolve_system_info $info),
|
|||
|
|
$path => (get_nested_config_value $path $context)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<h2 id="migration-strategies"><a class="header" href="#migration-strategies">Migration Strategies</a></h2>
|
|||
|
|
<h3 id="env-to-config-migration"><a class="header" href="#env-to-config-migration">ENV to Config Migration</a></h3>
|
|||
|
|
<p><strong>Migration Status</strong>: The system has successfully migrated from ENV-based to config-driven architecture:</p>
|
|||
|
|
<p><strong>Migration Statistics</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><strong>Files Migrated</strong>: 65+ files across entire codebase</li>
|
|||
|
|
<li><strong>Variables Replaced</strong>: 200+ ENV variables → 476 config accessors</li>
|
|||
|
|
<li><strong>Agent-Based Development</strong>: 16 token-efficient agents used</li>
|
|||
|
|
<li><strong>Efficiency Gained</strong>: 92% token efficiency vs monolithic approach</li>
|
|||
|
|
</ul>
|
|||
|
|
<h3 id="legacy-support"><a class="header" href="#legacy-support">Legacy Support</a></h3>
|
|||
|
|
<p><strong>Backward Compatibility</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Configuration accessor with ENV fallback
|
|||
|
|
def get-config-with-env-fallback [
|
|||
|
|
config_key: string,
|
|||
|
|
env_var: string,
|
|||
|
|
default: string = ""
|
|||
|
|
] -> string {
|
|||
|
|
# Try configuration first
|
|||
|
|
let config_value = try {
|
|||
|
|
get-config-value $config_key
|
|||
|
|
} catch { null }
|
|||
|
|
|
|||
|
|
if $config_value != null {
|
|||
|
|
return $config_value
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Fall back to environment variable
|
|||
|
|
let env_value = ($env | get $env_var | default null)
|
|||
|
|
if $env_value != null {
|
|||
|
|
return $env_value
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Use default if provided
|
|||
|
|
if $default != "" {
|
|||
|
|
return $default
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Error if no value found
|
|||
|
|
error make {
|
|||
|
|
msg: $"Configuration value not found: ($config_key)",
|
|||
|
|
help: $"Set ($config_key) in configuration or ($env_var) environment variable"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="migration-tools"><a class="header" href="#migration-tools">Migration Tools</a></h3>
|
|||
|
|
<p><strong>Available Migration Scripts</strong>:</p>
|
|||
|
|
<pre><code class="language-bash"># Migrate existing ENV-based setup to configuration
|
|||
|
|
nu src/tools/migration/env-to-config.nu --scan-environment --create-config
|
|||
|
|
|
|||
|
|
# Validate migration completeness
|
|||
|
|
nu src/tools/migration/validate-migration.nu --check-env-usage
|
|||
|
|
|
|||
|
|
# Generate configuration from current environment
|
|||
|
|
nu src/tools/migration/generate-config.nu --output-file config.migrated.toml
|
|||
|
|
</code></pre>
|
|||
|
|
<h2 id="troubleshooting"><a class="header" href="#troubleshooting">Troubleshooting</a></h2>
|
|||
|
|
<h3 id="common-configuration-issues"><a class="header" href="#common-configuration-issues">Common Configuration Issues</a></h3>
|
|||
|
|
<h4 id="configuration-not-found"><a class="header" href="#configuration-not-found">Configuration Not Found</a></h4>
|
|||
|
|
<p><strong>Error</strong>: <code>Configuration file not found</code></p>
|
|||
|
|
<pre><code class="language-bash"># Solution: Check configuration file paths
|
|||
|
|
provisioning config paths
|
|||
|
|
|
|||
|
|
# Create default configuration
|
|||
|
|
provisioning config init --template user
|
|||
|
|
|
|||
|
|
# Verify configuration loading order
|
|||
|
|
provisioning config debug
|
|||
|
|
</code></pre>
|
|||
|
|
<h4 id="invalid-configuration-syntax"><a class="header" href="#invalid-configuration-syntax">Invalid Configuration Syntax</a></h4>
|
|||
|
|
<p><strong>Error</strong>: <code>Invalid TOML syntax in configuration file</code></p>
|
|||
|
|
<pre><code class="language-bash"># Solution: Validate TOML syntax
|
|||
|
|
nu -c "open config.user.toml | from toml"
|
|||
|
|
|
|||
|
|
# Use configuration validation
|
|||
|
|
provisioning validate config --file config.user.toml
|
|||
|
|
|
|||
|
|
# Show parsing errors
|
|||
|
|
provisioning config check --verbose
|
|||
|
|
</code></pre>
|
|||
|
|
<h4 id="interpolation-errors"><a class="header" href="#interpolation-errors">Interpolation Errors</a></h4>
|
|||
|
|
<p><strong>Error</strong>: <code>Failed to resolve interpolation: {{env.MISSING_VAR}}</code></p>
|
|||
|
|
<pre><code class="language-bash"># Solution: Check available interpolation variables
|
|||
|
|
provisioning config interpolation --list-variables
|
|||
|
|
|
|||
|
|
# Debug specific interpolation
|
|||
|
|
provisioning config interpolation --test "{{env.USER}}"
|
|||
|
|
|
|||
|
|
# Show interpolation context
|
|||
|
|
provisioning config debug --show-interpolation
|
|||
|
|
</code></pre>
|
|||
|
|
<h4 id="provider-configuration-issues"><a class="header" href="#provider-configuration-issues">Provider Configuration Issues</a></h4>
|
|||
|
|
<p><strong>Error</strong>: <code>Provider 'upcloud' configuration invalid</code></p>
|
|||
|
|
<pre><code class="language-bash"># Solution: Validate provider configuration
|
|||
|
|
provisioning validate config --section providers.upcloud
|
|||
|
|
|
|||
|
|
# Show required provider fields
|
|||
|
|
provisioning providers upcloud config --show-schema
|
|||
|
|
|
|||
|
|
# Test provider configuration
|
|||
|
|
provisioning providers upcloud test --dry-run
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="debug-commands"><a class="header" href="#debug-commands">Debug Commands</a></h3>
|
|||
|
|
<p><strong>Configuration Debugging</strong>:</p>
|
|||
|
|
<pre><code class="language-bash"># Show complete resolved configuration
|
|||
|
|
provisioning config show --resolved
|
|||
|
|
|
|||
|
|
# Show configuration loading order
|
|||
|
|
provisioning config debug --show-hierarchy
|
|||
|
|
|
|||
|
|
# Show configuration sources
|
|||
|
|
provisioning config sources
|
|||
|
|
|
|||
|
|
# Test specific configuration keys
|
|||
|
|
provisioning config get paths.base --trace
|
|||
|
|
|
|||
|
|
# Show interpolation resolution
|
|||
|
|
provisioning config interpolation --debug "{{paths.data}}/{{env.USER}}"
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="performance-optimization"><a class="header" href="#performance-optimization">Performance Optimization</a></h3>
|
|||
|
|
<p><strong>Configuration Caching</strong>:</p>
|
|||
|
|
<pre><code class="language-bash"># Enable configuration caching
|
|||
|
|
export PROVISIONING_CONFIG_CACHE=true
|
|||
|
|
|
|||
|
|
# Clear configuration cache
|
|||
|
|
provisioning config cache --clear
|
|||
|
|
|
|||
|
|
# Show cache statistics
|
|||
|
|
provisioning config cache --stats
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Startup Optimization</strong>:</p>
|
|||
|
|
<pre><code class="language-toml"># Optimize configuration loading
|
|||
|
|
[performance]
|
|||
|
|
lazy_loading = true
|
|||
|
|
cache_compiled_config = true
|
|||
|
|
skip_unused_sections = true
|
|||
|
|
|
|||
|
|
[cache]
|
|||
|
|
config_cache_ttl = 3600
|
|||
|
|
interpolation_cache = true
|
|||
|
|
</code></pre>
|
|||
|
|
<p>This configuration management system provides a robust, flexible foundation that supports development workflows while maintaining production reliability and security requirements.</p>
|
|||
|
|
|
|||
|
|
</main>
|
|||
|
|
|
|||
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|||
|
|
<!-- Mobile navigation buttons -->
|
|||
|
|
<a rel="prev" href="../development/COMMAND_HANDLER_GUIDE.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|||
|
|
<i class="fa fa-angle-left"></i>
|
|||
|
|
</a>
|
|||
|
|
|
|||
|
|
<a rel="next prefetch" href="../development/workspace-management.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|||
|
|
<i class="fa fa-angle-right"></i>
|
|||
|
|
</a>
|
|||
|
|
|
|||
|
|
<div style="clear: both"></div>
|
|||
|
|
</nav>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
|||
|
|
<a rel="prev" href="../development/COMMAND_HANDLER_GUIDE.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|||
|
|
<i class="fa fa-angle-left"></i>
|
|||
|
|
</a>
|
|||
|
|
|
|||
|
|
<a rel="next prefetch" href="../development/workspace-management.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|||
|
|
<i class="fa fa-angle-right"></i>
|
|||
|
|
</a>
|
|||
|
|
</nav>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- Livereload script (if served using the cli tool) -->
|
|||
|
|
<script>
|
|||
|
|
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|||
|
|
const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
|
|||
|
|
const socket = new WebSocket(wsAddress);
|
|||
|
|
socket.onmessage = function (event) {
|
|||
|
|
if (event.data === "reload") {
|
|||
|
|
socket.close();
|
|||
|
|
location.reload();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
window.onbeforeunload = function() {
|
|||
|
|
socket.close();
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
window.playground_copyable = true;
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<script src="../elasticlunr.min.js"></script>
|
|||
|
|
<script src="../mark.min.js"></script>
|
|||
|
|
<script src="../searcher.js"></script>
|
|||
|
|
|
|||
|
|
<script src="../clipboard.min.js"></script>
|
|||
|
|
<script src="../highlight.js"></script>
|
|||
|
|
<script src="../book.js"></script>
|
|||
|
|
|
|||
|
|
<!-- Custom JS scripts -->
|
|||
|
|
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
</body>
|
|||
|
|
</html>
|