Purpose: For all users, documents the exact order in which the CLI resolves configuration values from flags, environment variables, files, and built-in defaults.
General Rule
When the same setting is specified in multiple places, the CLI uses the value from the highest-precedence source:
1. Command-line flags (highest)
2. Environment variables
3. Cluster config file (.<cluster>-config.yaml)
4. CLI config file (~/.config/opencenter/config.yaml)
5. Built-in defaults (lowest)
A higher-numbered source is used only when no higher source provides a value.
Detailed Breakdown
1. Command-Line Flags
Flags always win. Two categories:
Persistent flags (available on every command):
| Flag | Type | Description |
| --- | --- | --- |
| --log-level | string | Log level: debug, info, warn, error |
| --dry-run | bool | Preview without executing |
| --yes | bool | Auto-confirm destructive operations |
| --config-dir | string | Override the openCenter configuration directory |
| --output | string | Output format for supported commands: text, json, yaml |
| --quiet | bool | Suppress nonessential human output |
Command-scoped flags still take precedence over configuration and environment values. For example, lifecycle commands that acquire locks expose their own --break-lock flag.
the set override mechanism overrides individual fields using dot-path notation:
opencenter cluster set my-cluster opencenter.meta.env=staging
Evidence: cmd/root.go — addGlobalFlags(), parseGlobalOptions()
2. Environment Variables
Environment variables override config file values but lose to explicit flags.
Log level example — the code checks whether --log-level is still at its default (warn). If so, it reads OPENCENTER_LOG_LEVEL. If the flag was explicitly set to any value, the env var is ignored:
// Precedence: flag > env var > default ("warn")
if globalFlags.LogLevel == "warn" {
if envLevel := os.Getenv("OPENCENTER_LOG_LEVEL"); envLevel != "" {
globalFlags.LogLevel = envLevel
}
}
Evidence: cmd/root.go lines 165—171
3. Cluster Configuration File
The per-cluster config at <clustersDir>/<organization>/.<cluster>-config.yaml. This is the primary source for cluster-specific settings (provider, networking, services, secrets, gitops).
Loaded by ConfigurationManager.Load() which resolves the path via the PathResolver.
Evidence: internal/config/manager.go — Load()
4. CLI Configuration File
The user-level CLI config at ~/.config/opencenter/config.yaml. Provides defaults that apply across all clusters:
logging:
level: warn
paths:
configDir: ~/.config/opencenter
clustersDir: ~/.config/opencenter/clusters
pluginsDir: ~/.config/opencenter/plugins
defaults:
provider: openstack
region: dfw3
environment: dev
Evidence: internal/config/cli_config.go — DefaultCLIConfig(), NewConfigManager()
5. Built-In Defaults
Hard-coded in the Go source. Applied when no other source provides a value:
| Setting | Default | Source |
| --- | --- | --- |
| logging.level | warn | DefaultCLIConfig() |
| logging.format | text | DefaultCLIConfig() |
| cluster_defaults.provider | openstack | DefaultCLIConfig() |
| cluster_defaults.region | dfw3 | DefaultCLIConfig() |
| cluster_defaults.environment | dev | DefaultCLIConfig() |
| cluster_defaults.gitops_auth_method | token | DefaultCLIConfig() |
| gitops.repository.branch | main | normalize() in loader |
| gitops.flux.interval | 5m | normalize() in loader |
Evidence: internal/config/cli_config.go — DefaultCLIConfig(), internal/config/v2/loader.go — normalize()
Directory Resolution
Directories follow their own precedence chains. Each directory type is resolved independently.
Config Directory
Determines where CLI-level configuration is stored.
1. OPENCENTER_CONFIG_DIR env var
2. Platform default:
- macOS/Linux: ~/.config/opencenter
- Windows: %APPDATA%\opencenter
Evidence: internal/config/persistence/paths.go — DefaultConfigDir()
Clusters Directory
Determines the base path for all organization and cluster directories.
1. OPENCENTER_CLUSTERS_DIR env var
2. CLI config paths.clustersDir (from ~/.config/opencenter/config.yaml)
3. OPENCENTER_CONFIG_DIR + /clusters
4. <DefaultConfigDir>/clusters
OPENCENTER_CLUSTERS_DIR is a runtime override for cluster storage. Without it, the CLI config value takes priority even when OPENCENTER_CONFIG_DIR is set. This allows pointing the config dir at one location while storing clusters elsewhere.
Evidence: internal/config/cli_config_helpers.go — ResolveClustersDir()
State Directory
Stores runtime artifacts: audit logs, bootstrap state, file locks.
1. OPENCENTER_STATE_DIR env var
2. CLI config paths.stateDir
3. XDG_STATE_HOME + /opencenter
4. Platform default:
- macOS/Linux: ~/.local/state/opencenter
- Windows: %LOCALAPPDATA%\opencenter\state
Evidence: internal/config/persistence/paths.go — DefaultStateDir()
Cluster Path Resolution
When a command receives a cluster identifier, the resolver uses two strategies depending on format:
With organization (opencenter-cloud/gizmo):
<clustersDir>/<organization>/infrastructure/clusters/<cluster>/
Uses PathResolver.Resolve() — scoped to the specified organization.
Without organization (gizmo):
Scans all organization directories under clustersDir looking for a matching infrastructure/clusters/<cluster>/ directory. Uses PathResolver.ResolveWithFallback().
Evidence: internal/core/paths/resolver.go — Resolve(), ResolveWithFallback()
Provider Credential Resolution
Cloud provider credentials follow provider-specific precedence. The CLI does not invent its own credential chain — it defers to the provider’s standard mechanism.
OpenStack
1. flags (e.g., secrets.global.openstack_username=...)
2. Cluster config secrets.global.openstack_* fields
3. OS_* environment variables (OS_CLOUD, OS_AUTH_URL, OS_USERNAME, etc.)
4. clouds.yaml (~/.config/openstack/clouds.yaml)
Debugging Precedence
Run any command with --log-level debug to see which sources the CLI is reading:
opencenter cluster use opencenter-cloud/gizmo --log-level debug
The debug output includes:
=== OpenCenter CLI Debug Information ===
Command: opencenter cluster use
Environment Variables:
OPENCENTER_CONFIG_DIR: /custom/path (or "not set")
OPENCENTER_LOG_LEVEL: debug (or "not set")
Configuration Paths:
Clusters Directory: /Users/you/.config/opencenter/clusters
Global Flags:
--log-level: debug========================================
Evidence: cmd/root.go — PersistentPreRunE
Common Pitfalls
Cluster storage vs OPENCENTER_CONFIG_DIR: OPENCENTER_CONFIG_DIR controls CLI-level configuration. To override cluster storage without editing config.yaml, set OPENCENTER_CLUSTERS_DIR. If it is unset, an explicit CLI config paths.clustersDir takes priority over the OPENCENTER_CONFIG_DIR/clusters fallback.
--log-level default masking: The env var OPENCENTER_LOG_LEVEL is only read when the flag is at its default value (warn). If you pass --log-level warn explicitly, the CLI treats it as "flag was set" and the env var is still read (because the value matches the default). This is a Cobra limitation — the CLI checks the value, not whether the flag was explicitly passed.
the config file flag scope: The the config file flag provides an alternative cluster configuration file path. It does not change the CLI config (~/.config/opencenter/config.yaml) or the clusters directory.