Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions .github/workflows/pr-checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,8 @@ jobs:
- name: kubara init --prep
run: |
set -euo pipefail
cd src
go run main.go --work-dir "${{ env.OUTPUT_GENERATED_DIR }}" init --prep
cd "${{ env.OUTPUT_GENERATED_DIR }}"
go run "${GITHUB_WORKSPACE}/src/main.go" init --prep

- name: Update .env (strict template mode)
run: |
Expand All @@ -304,8 +304,8 @@ jobs:
- name: kubara init
run: |
set -euo pipefail
cd src
go run main.go --work-dir "${{ env.OUTPUT_GENERATED_DIR }}" init
cd "${{ env.OUTPUT_GENERATED_DIR }}"
go run "${GITHUB_WORKSPACE}/src/main.go" init

- name: Update config.yaml (strict mode)
run: |
Expand All @@ -314,8 +314,9 @@ jobs:

- name: Generate kubara artifacts
run: |
cd src
go run main.go --work-dir "${{ env.OUTPUT_GENERATED_DIR }}" generate
set -euo pipefail
cd "${{ env.OUTPUT_GENERATED_DIR }}"
go run "${GITHUB_WORKSPACE}/src/main.go" generate

- name: Upload generated helm and terraform files
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
Expand Down
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ help, h Shows a list of commands or help for one command

```text
--kubeconfig string Path to kubeconfig file (default: "~/.kube/config")
--work-dir string, -w string Working directory (default: ".")
--config-file string, -c string Path to the configuration file (default: "config.yaml")
--env-file string Path to the .env file (default: ".env")
--test-connection Check if Kubernetes cluster can be reached. List namespaces and exit
--base64 Enable base64 encode/decode mode
--encode Base64 encode input
Expand Down
64 changes: 64 additions & 0 deletions docs/content/10_decisions/ADR-0005-multi-hub-improvements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
| status | date | decision-makers | consulted | informed |
|--------------|------------|-----------------|--------------------|--------------------|
| | | | | |

# Directory-Scoped Execution Context for Multi-Hub GitOps Repositories

## Context and Problem Statement

Following feedback and bugreports from our community around the handling and documentation of multi-hub setups,
we decided to improve kubaras support for multi-hub setups.

Previously, `kubara generate` hardcoded its output paths to `./platform-components` and `./platform-configs/<cluster>`
relative to the current working directory, and wiped `./platform-components` before every generate run.
When multiple configuration files coexisted in a repository:
1. Running generation for one config would wipe or overwrite the shared `platform-components` of another config, possibly resulting in the deletion of required files.
2. If different configs referenced different catalog versions or customized services, conflicts occurred.
3. Argo CD Application manifests need accurate repository-relative subpaths to locate charts and values overlays within the Git repository.
4. Relative paths in Terraform templates (e.g. `../../../../platform-components/...`) depend on a consistent relative depth between `platform-configs` and `platform-components`.

Kubara needs an ergonomic, deterministic way to support multiple hub-and-spoke configurations within the same repository without cross-configuration interference.

## Decision Drivers

- Different configurations may use different catalog versions and platform stacks.
- Templating for one configuration must never mutate, wipe or overwrite another configuration's manifests.
- Zero breaking changes to existing single-configuration repositories.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which wouldn't be true if we remove --config-file and/or --env-file

- Keep Terraform relative module paths (`../../../../platform-components/...`) working without requiring modifications to catalog templates.
- Git repository subpaths must be computed automatically to simplify Argo CD GitOps workflows.
- Developer experience must be intuitive: Easily target individual hubs, a set of hubs or run batch generation across all.
- Minimize sources of mixups in execution context around .env file and config.yaml

## Decision Outcome

**One Hub per Config, one Folder per Hub**.

### Folder Layout
Hubs exist in isolated directories, at the root level or nested (e.g. `prod`, `project-a/staging`) containing:
- `config.yaml`
- `.env`
- `platform-components/` (isolated generated Helm charts and Terraform modules)
- `platform-configs/` (cluster-specific overlays)

Because `platform-configs` and `platform-components` remain siblings inside each hub directory, existing Terraform relative source paths (`../../../../platform-components/...`) remain valid.

### Automatic GitOps Path Computation
When executing within a hub folder, `kubara generate` automatically:
1. Traverses up the directory tree to discover the Git repository root (`.git`).
1. Calculates the Git-relative subpath from the Git root to the hub (e.g. `setups/dev-fleet`).
1. Injects computed repository paths into `argocd.repo`:
- `components.path`: `<git-rel-path>/platform-components/helm`
- `configs.path`: `<git-rel-path>/platform-configs`

### CLI Ergonomics
1. **Targeting**: `generate --hub <path>` sets the target hub directory, accepting a list of hubs to generate.
1. **Directory Scoping**: Commands execute within the hub directory or target hubs via `--hub`. Legacy flags (`--work-dir`, `--config-file`, and `--env-file`) are removed in favor of directory-scoped context.
1. **Batch Generation**: `kubara generate --all` (alias `-A`) discovers all configurations in the current directory and generates each hub in its own isolated context.
1. **Removal of old Flags**: `--work-dir`, `--config-file` and `--env-file` have been removed and are replaced by `--hub`
Comment on lines +55 to +57

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be discussed and duplication


## Consequences

- **Good**, because multiple hub-and-spoke setups can live in the same Git repository without file collisions.
- **Good**, because setups can independently upgrade catalog versions and dependencies.
- **Good**, because Argo CD path calculation requires zero manual configuration.
- **Good**, because single-config repositories at root remain completely unaffected (zero breaking changes).
31 changes: 15 additions & 16 deletions docs/content/1_getting_started/bootstrapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This guide provides a step-by-step process for bootstrapping your platform running on Kubernetes, including the necessary [prerequisites](prerequisites.md), architecture setup, and deployment instructions. Try to follow the instructions first. If you have any questions or issues, please reach out directly via Teams. If you're interested in the setup details, explore the Wiki pages.

If you intend to manage multiple hubs with kubara, take a look at [Multi-Hub Environments](../4_building_your_platform/multi-hub.md)
---

## 1. Getting Started
Expand Down Expand Up @@ -105,13 +106,13 @@ kubara init
```

This command creates a `config.yaml` file based on the values from your `.env`.
It also creates a `renovate.json` in the working directory when no supported Renovate configuration exists. The generated custom manager keeps versioned OCI catalog references in this config up to date. Use `--renovate=false` if the repository does not use Renovate:
It also creates a `renovate.json` at the root of your Git repository (or working directory if outside a Git repository) when no supported Renovate configuration exists. The generated custom manager keeps versioned OCI catalog references in this config up to date. Use `--renovate=false` if the repository does not use Renovate:

```bash
kubara init --renovate=false
```

For Renovate to discover the generated file, use the Git repository root as kubara's working directory. The generated file uses Renovate's `config:recommended` preset and enables automatic updates for kubara catalog versions in `config.yaml`. Renovate can also update other supported dependencies it detects in the repository.
When run from a subfolder in a Git repository, `init` automatically writes `renovate.json` to the Git repository root with the correct relative path matcher for your workspace's `config.yaml`. The generated file uses Renovate's `config:recommended` preset and enables automatic updates for kubara catalog versions in `config.yaml`. Renovate can also update other supported dependencies it detects in the repository.

Kubara does not modify an existing Renovate configuration. In that case, `init` logs a warning and you can add the [Renovate settings for catalog updates](../2_concepts/catalog_distribution.md#automatic-catalog-updates-with-renovate) manually.

Expand All @@ -137,7 +138,7 @@ kubara init \
--catalog-overwrite
```

The bootstrap reference is stored in the root `bootstrapCatalog` field, while repeated `--catalog` values are stored on the generated cluster. Local paths are resolved relative to `--work-dir` when kubara loads them.
The bootstrap reference is stored in the root `bootstrapCatalog` field, while repeated `--catalog` values are stored on the generated cluster. Local paths are resolved relative to the workspace directory when kubara loads them.

When using `--overwrite`, only values from `.env` are replaced.
Additional settings in your existing `config.yaml` are preserved and merged.
Expand Down Expand Up @@ -518,38 +519,36 @@ but also other supported possibilities when bootstrapping.

### Bootstrapping Multiple Hub Clusters

You can bootstrap multiple Hub clusters.
You **cannot** reuse the same `config.yaml` file for multiple Hub clusters. Only one hub per config is supported.
You can bootstrap multiple Hub clusters in the same Git repository.
Each Hub cluster has its own directory (workspace) containing its own `config.yaml` and optional `.env`. Only one hub per config is supported.

**Why?**
During the bootstrap process, the `.env` file is used to provide credentials.
If you reuse the same `.env` file, you would have to constantly adjust it for each Hub - which is error-prone.
For a detailed guide on managing multiple hubs, directory layouts, selective generation (`--hub`), and batch generation (`--all`), see [Multi-Hub Environments](../4_building_your_platform/multi-hub.md).

Since version `0.2.0`, this is much easier. You can simply provide a different env file:
To set up an additional Hub cluster, create and switch to its directory:

```bash
kubara init --prep --env-file .another-env
mkdir -p setups/another-hub
cd setups/another-hub
kubara init --prep
```
Fill out `.another-env` with the required values. Generate a new config file from it:
Fill out `.env` with the required values. Generate the config file:

```bash
kubara --config-file another-config.yaml --env-file .another-env init
kubara init
```

This will use the values from `.another-env` to generate `another-config.yaml`.

Render Terraform modules and Helm charts for the new Hub cluster:

```bash
# default: generates both Helm and Terraform
# use --helm or --terraform to generate only one type
./kubara --config-file another-config.yaml generate
kubara generate
```

Finally, bootstrap your additional Hub cluster:

```bash
kubara bootstrap --config-file another-config.yaml --env-file .another-env <cluster name from another-config.yaml>
kubara bootstrap <cluster name from config.yaml>
```

## What's Next?
Expand Down
19 changes: 5 additions & 14 deletions docs/content/1_getting_started/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,14 @@ kubara
[--catalog-overwrite]
[--catalog]=[value]
[--check-update]
[--config-file|-c]=[value]
[--decode]
[--encode]
[--env-file]=[value]
[--file]=[value]
[--help|-h]
[--kubeconfig]=[value]
[--string]=[value]
[--test-connection]
[--version|-v]
[--work-dir|-w]=[value]
```

# DESCRIPTION
Expand All @@ -46,14 +43,10 @@ kubara [command]

**--check-update**: Check online for a newer kubara release

**--config-file, -c**="": Path to the configuration file (default: "config.yaml")

**--decode**: Base64 decode input

**--encode**: Base64 encode input

**--env-file**="": Path to the .env file (default: ".env")

**--file**="": Input file path for base64 operation

**--help, -h**: show help
Expand All @@ -66,8 +59,6 @@ kubara [command]

**--version, -v**: print the version

**--work-dir, -w**="": Working directory (default: ".")


# COMMANDS

Expand Down Expand Up @@ -99,14 +90,18 @@ Shows a list of commands or help for one command

Generate files from catalog templates

>kubara generate [--terraform|--helm] [--catalog PATH_OR_OCI [--catalog-overwrite]] [--dry-run]
>kubara generate [--all|--hubs HUB1,HUB2,...|--hub HUB3] [--terraform|--helm] [--catalog PATH_OR_OCI] [--catalog-overwrite]] [--dry-run]

**--all, -A**: Discover and target all hubs in the working directory

**--dry-run**: Preview generation without creating files

**--helm**: Only generate Helm files

**--help, -h**: show help

**--hub, --hubs**="": Target a list of comma separated hub directories

**--terraform**: Only generate Terraform files

### help, h
Expand All @@ -127,10 +122,6 @@ Bootstrap Argo CD onto a cluster

**--local**: Provision an isolated local evaluation environment. Local testing only; not for production use.

**--platform-components**="": Path to the platform-components directory (default: "platform-components")

**--platform-configs**="": Path to platform-configs directory (default: "platform-configs")

**--timeout**="": Timeout for kubernetes API calls (e.g. 10s, 1m) (default: 5m0s)

**--with-es-crds**: Deprecated: ignored because CRDs are applied automatically during bootstrap.
Expand Down
2 changes: 2 additions & 0 deletions docs/content/1_getting_started/quick_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ It is intended for **local testing only**, not for production use.

This guide supports Linux, macOS and WSL on Windows.

If you intend to manage multiple hubs with kubara, take a look at [Multi-Hub Environments](../4_building_your_platform/multi-hub.md)

## Prerequisites

Install kubara first via the [installation guide](installation.md), then make sure these tools are available on your host:
Expand Down
2 changes: 1 addition & 1 deletion docs/content/2_concepts/catalog_distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,4 @@ Add the following settings to your `renovate.json` or GitOps repository's Renova
}
```

Adjust `managerFilePatterns` when the kubara config has a different repository-relative path. `kubara init` does this automatically for the configured `--config-file`. The reference matcher supports registries with ports and ignores digest-pinned catalog references.
Adjust `managerFilePatterns` when the kubara config has a different repository-relative path. `kubara init` does this automatically for the current repository. The reference matcher supports registries with ports and ignores digest-pinned catalog references.
13 changes: 12 additions & 1 deletion docs/content/2_concepts/catalog_templating.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ Files without the `.tplt` suffix are copied as-is.

## What data is available in templates?

kubara builds a template context with three top-level objects:
kubara builds a template context with four top-level objects:

- `.cluster`
- `.env`
- `.catalog`
- `.workspace`

### `.cluster`

Expand Down Expand Up @@ -74,6 +75,16 @@ Today this is mainly service metadata such as:

This is useful when template logic needs catalog-level defaults or service metadata.

### `.workspace`

When working in a Git repository, `.workspace` exposes GitOps path context:

- `.workspace.gitRelativePath`: Relative subpath from the Git repository root to the workspace (e.g. `setups/dev-fleet`, or `""` if at repo root).
- `.workspace.platformComponents`: Relative Git path to components (`<gitRelativePath>/platform-components/helm`).
- `.workspace.platformConfigs`: Relative Git path to configs (`<gitRelativePath>/platform-configs`).

Additionally, kubara automatically populates these computed paths into `.cluster.argocd.repo.https.components.path` and `.cluster.argocd.repo.https.configs.path` (or their OCI equivalents) unless explicitly overridden in `config.yaml`. Spoke clusters in `.spokes` receive matching computed paths.

## Cross-templating in practice

The Homer example shows the main idea well: one service template can react to settings from other services and from the cluster itself.
Expand Down
3 changes: 2 additions & 1 deletion docs/content/2_concepts/catalogs.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ kubara generate --catalog oci://ghcr.io/acme/platform-catalogs/my-catalog:1.2.3
- a local catalog directory
- an OCI reference such as `oci://ghcr.io/acme/platform-catalogs/my-catalog:1.2.3`

Local paths are resolved relative to `--work-dir`. OCI-backed catalogs use the local kubara cache and are pulled automatically when the requested reference is not cached. See [Catalog distribution](catalog_distribution.md).
Local paths are resolved relative to the workspace directory. OCI-backed catalogs use the local kubara cache and are pulled automatically when the requested reference is not cached. See [Catalog distribution](catalog_distribution.md).

`init` and `cluster add` persist their `--catalog` references in the new cluster entry. Commands such as `schema`, `generate`, and `bootstrap` use CLI catalogs as temporary additions and do not rewrite `config.yaml`.

Expand Down Expand Up @@ -234,6 +234,7 @@ If a cluster has no Terraform block or uses `terraform.provider: none`, the defa

Shared output paths must also be deterministic across clusters. Identical content is written once; conflicting content for the same final path causes generation to fail before files are changed.


## Schema generation

When `config.yaml` exists, `kubara schema` resolves catalogs per cluster and emits cluster-specific service branches. This keeps editor completion and validation aligned with the services available to each cluster.
Expand Down
2 changes: 1 addition & 1 deletion docs/content/4_building_your_platform/create_catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ clusters:
- oci://ghcr.io/acme/platform-catalogs/security:1.4.0
```

Catalog order is significant. Cluster catalogs are loaded first in the listed order, followed by repeated `--catalog` values. Local references are resolved relative to `--work-dir`.
Catalog order is significant. Cluster catalogs are loaded first in the listed order, followed by repeated `--catalog` values. Local references are resolved relative to the workspace directory.

`kubara schema` automatically discovers cluster catalogs when `config.yaml` exists. Before creating a configuration, pass the catalog explicitly as shown above.

Expand Down
Loading
Loading