Architecture¶
openvox-code is built around five core components that work together in a two-phase workflow.
Core Components¶
Resolver¶
The Resolver reads the configuration file and determines which modules, at which versions, need to be placed into which environments. It handles:
- Parsing
openvox-code.yaml(with Kubernetes-style envelope support) and optional lockfiles - Resolving branch names and tags to concrete Git SHAs
- Computing the full module list for each environment from module sets, inline modules, and per-branch module files
- Detecting conflicts (e.g., duplicate module names from different sources)
- Expanding branch discovery after fetching: listing branches from the cache, filtering through
branchSelectorpatterns, and reading per-branch module files from the control repo
Cache Manager¶
The Cache Manager maintains a directory of bare Git clones, providing a shared cache that avoids redundant network transfers. It handles:
- Creating and updating bare mirror clones for each unique Git URL
- Per-host credential resolution: selecting the right SSH key or credential helper based on the Git URL's host
- Retry with exponential backoff for transient network failures (up to 3 attempts with 1s, 2s, 4s backoff)
- Resolving refs (branches, tags, SHAs) to concrete commit SHAs within cached repositories
- Listing branches in cached repositories for branch discovery
- Checking out files from cached repos into target directories using
git archive
Fetcher¶
The Fetcher orchestrates parallel Git fetch operations using the Cache Manager. It:
- Collects all unique Git URLs from the resolved environments
- Fetches repositories concurrently using a semaphore to limit parallelism
- Delegates actual clone/fetch operations to the Cache Manager
Deployer¶
The Deployer takes the resolved environment list and materializes it on disk. It:
- Checks out the control repo and modules from the bare clone cache into environment directories
- Reads per-branch module files from the checked-out control repo to discover additional modules
- Performs atomic deploys using temporary directories and renames
- Cleans up stale environments that no longer exist in the config or branches
- Can be run independently via
openvox-code deploy(offline, from cache)
Builder (OCI)¶
The Builder packages deployed environments into OCI container images for use with openvox-operator or any OCI-compatible runtime.
- Produces standard OCI images with Puppet code as the filesystem layer
- Supports tagging and pushing to container registries
- Supports multi-architecture image builds
- Run via
openvox-code buildandopenvox-code push
Two-Phase Workflow¶
openvox-code separates network operations (fetching) from local operations (deploying). This separation enables offline deployments and makes the tool more reliable in air-gapped or restricted environments.
Phase 1: Mirror¶
Fetch all Git repositories into the local bare clone cache. This is the only phase that requires network access.
openvox-code mirror --config openvox-code.yaml
Phase 2: Deploy¶
Read from the local cache and write environments to disk. No network access required. This phase includes:
- Checking out the control repo for each environment
- Reading per-branch module files from the control repo checkout
- Resolving
follow_branchmodules to the environment's branch (with fallback) - Checking out all modules into the environment directory
openvox-code deploy --config openvox-code.yaml
Combined¶
The sync command runs both phases in sequence:
openvox-code sync --config openvox-code.yaml
Flow Diagram¶
graph LR
A[openvox-code.yaml] --> B[Resolver]
B --> C[Fetcher]
C -->|parallel git fetch| D[Cache Manager]
D -->|bare clones| E[Deployer]
E -->|control repo checkout| F[Per-Branch Module Files]
F --> E
E -->|atomic write| G[Environment Directories]
G --> H[Builder]
H --> I[OCI Image]
style A fill:#ff9800,color:#000
style D fill:#ff9800,color:#000
style G fill:#ff9800,color:#000
style I fill:#ff9800,color:#000
The path from Environment Directories to Builder is optional -- OCI image output is only used when deploying to Kubernetes via openvox-operator.
Directory Layout¶
After a successful sync, the on-disk layout looks like:
/etc/puppetlabs/code/environments/
├── production/
│ ├── manifests/
│ ├── modules/
│ │ ├── stdlib/
│ │ ├── apache/
│ │ └── ...
│ ├── site/ # custom target_dir modules
│ │ ├── role/
│ │ └── profile/
│ └── environment.conf
├── staging/
│ ├── manifests/
│ ├── modules/
│ └── environment.conf
└── development/
├── manifests/
├── modules/
└── environment.conf
/var/cache/openvox-code/
├── git/
│ ├── github.com-puppetlabs-puppetlabs-stdlib.git/
│ ├── github.com-puppetlabs-puppetlabs-apache.git/
│ └── ...
└── locks/