Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ catalog-update: ## Update catalog configuration with current bundle image

.PHONY: build-caib
build-caib: ## Build the caib tool
go build -tags containers_image_openpgp -ldflags "-X main.version=$(VERSION)" -o bin/caib cmd/caib/main.go
go build -tags containers_image_openpgp -ldflags "-X main.version=$(VERSION)" -o bin/caib ./cmd/caib

.PHONY: build-api-server
build-api-server: ## Build the api server
Expand Down
186 changes: 128 additions & 58 deletions cmd/caib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ export CAIB_SERVER=https://your-build-api.example
Build a bootc container and push it to a registry:

```bash
bin/caib build manifest.aib.yml \
bin/caib image build manifest.aib.yml \
--arch arm64 \
--push quay.io/myorg/automotive-os:latest \
--follow
--push quay.io/myorg/automotive-os:latest
```

Systems running bootc can then switch to this image:
Expand All @@ -42,36 +41,36 @@ bootc switch quay.io/myorg/automotive-os:latest
Build a bootc container and also create a disk image from it:

```bash
bin/caib build manifest.aib.yml \
bin/caib image build manifest.aib.yml \
--arch arm64 \
--push quay.io/myorg/automotive-os:latest \
--disk \
--push-disk quay.io/myorg/automotive-disk:latest \
-o ./output/disk.qcow2 \
--follow
-o ./output/disk.qcow2
```

### Build a Development (Non-Bootc) Image

Build an ostree-based or package-based disk image for development:

```bash
bin/caib build-dev manifest.aib.yml \
bin/caib image build-dev manifest.aib.yml \
--arch arm64 \
--mode image \
--format qcow2 \
-o ./output/disk.qcow2 \
--follow
-o ./output/disk.qcow2
```

## Commands

### build
All image workflow commands live under `caib image`.

### image build

Builds a bootc container image with optional disk image creation. This is the recommended approach for production.

```bash
bin/caib build <manifest.aib.yml> [flags]
bin/caib image build <manifest.aib.yml> [flags]
```

**Required flags:**
Expand Down Expand Up @@ -108,56 +107,50 @@ bin/caib build <manifest.aib.yml> [flags]

```bash
# Build and push bootc container only
bin/caib build my-manifest.aib.yml \
bin/caib image build my-manifest.aib.yml \
--arch arm64 \
--push quay.io/myorg/automotive:v1.0 \
--follow
--push quay.io/myorg/automotive:v1.0

# Build bootc container + qcow2 disk image, download locally
bin/caib build my-manifest.aib.yml \
bin/caib image build my-manifest.aib.yml \
--arch arm64 \
--push quay.io/myorg/automotive:v1.0 \
--disk \
--format qcow2 \
--push-disk quay.io/myorg/automotive-disk:v1.0 \
-o ./my-image.qcow2 \
--follow
-o ./my-image.qcow2

# Push to OpenShift internal registry (no credentials required)
bin/caib build my-manifest.aib.yml \
bin/caib image build my-manifest.aib.yml \
--arch arm64 \
--internal-registry \
--follow
--internal-registry

# Internal registry with custom image name and tag
bin/caib build my-manifest.aib.yml \
bin/caib image build my-manifest.aib.yml \
--arch arm64 \
--internal-registry \
--image-name my-automotive-os \
--image-tag v1.0 \
--follow
--image-tag v1.0

# Internal registry with disk image
bin/caib build my-manifest.aib.yml \
bin/caib image build my-manifest.aib.yml \
--arch arm64 \
--internal-registry \
--disk \
--follow
--disk

# Use custom builder image
bin/caib build my-manifest.aib.yml \
bin/caib image build my-manifest.aib.yml \
--arch amd64 \
--builder-image quay.io/myorg/my-aib-build:latest \
--push quay.io/myorg/result:latest \
--follow
--push quay.io/myorg/result:latest
```

### disk
### image disk

Creates a disk image from an existing bootc container in a registry.

```bash
bin/caib disk <container-ref> [flags]
bin/caib image disk <container-ref> [flags]
```

**Optional flags:**
Expand All @@ -183,23 +176,21 @@ bin/caib disk <container-ref> [flags]

```bash
# Create disk image from container, download locally
bin/caib disk quay.io/myorg/my-os:v1 \
bin/caib image disk quay.io/myorg/my-os:v1 \
-o ./disk.qcow2 \
--format qcow2 \
--wait
--format qcow2

# Push disk as OCI artifact instead of downloading
bin/caib disk quay.io/myorg/my-os:v1 \
--push quay.io/myorg/my-disk:v1 \
--follow
bin/caib image disk quay.io/myorg/my-os:v1 \
--push quay.io/myorg/my-disk:v1
```

### build-dev
### image build-dev

Builds a disk image (ostree or package-based) for development workflows. Creates standalone disk images without bootc container integration.

```bash
bin/caib build-dev <manifest.aib.yml> [flags]
bin/caib image build-dev <manifest.aib.yml> [flags]
```

**Required flags:**
Expand Down Expand Up @@ -231,28 +222,101 @@ bin/caib build-dev <manifest.aib.yml> [flags]

```bash
# Build ostree-based image and download
bin/caib build-dev my-manifest.aib.yml \
bin/caib image build-dev my-manifest.aib.yml \
--arch arm64 \
--mode image \
--format qcow2 \
-o ./disk.qcow2 \
--follow
-o ./disk.qcow2

# Build and push to OCI registry (requires REGISTRY_USERNAME/REGISTRY_PASSWORD env vars)
bin/caib build-dev my-manifest.aib.yml \
bin/caib image build-dev my-manifest.aib.yml \
--arch arm64 \
--mode image \
--format qcow2 \
--push quay.io/myorg/disk-image:v1.0 \
--follow
--push quay.io/myorg/disk-image:v1.0
Comment on lines 231 to +236

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid overstating auth requirements in the build-dev push example.

Line 231 says push requires REGISTRY_USERNAME/REGISTRY_PASSWORD, but the same README now documents other supported methods (--registry-auth-file, REGISTRY_AUTH_FILE, discovered auth.json). Please relax wording to avoid user confusion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/caib/README.md` around lines 231 - 236, Update the README example heading
to avoid overstating authentication requirements: replace the phrase that says
push "requires REGISTRY_USERNAME/REGISTRY_PASSWORD" with a neutral sentence that
notes multiple authentication methods are supported (e.g., environment vars
REGISTRY_USERNAME/REGISTRY_PASSWORD, REGISTRY_AUTH_FILE/--registry-auth-file, or
discovered auth.json) and recommends setting an auth method if pushing to a
registry; ensure the example block (the image build/push command) remains
unchanged and briefly list the alternate auth methods in the same sentence for
clarity.

```

### image reseal / prepare-reseal / extract-for-signing / inject-signed

Sealed operations manage TPM-based image sealing for secure boot workflows. All sealed commands share a common set of flags.

**Shared flags:**
| Flag | Default | Description |
|------|---------|-------------|
| `--server` | `$CAIB_SERVER` | Build API server URL |
| `--token` | `$CAIB_TOKEN` | Bearer token |
| `--input` | | Input/source container ref (alternative to positional) |
| `--output` | | Output container ref (alternative to positional) |
| `--aib-image` | `quay.io/.../automotive-image-builder:latest` | AIB container image |
| `--builder-image` | | Builder container image (overrides `--arch` default) |
| `--arch` | (auto-detected) | Target architecture (`amd64`, `arm64`) |
| `--key` | | Path to local PEM key file |
| `--passwd` | | Password for encrypted key file |
| `--key-secret` | | Name of cluster secret containing sealing key |
| `--key-password-secret` | | Name of cluster secret containing key password |
| `--registry-auth-file` | | Path to Docker/Podman auth file for registry authentication |
| `--extra-args` | | Extra arguments to pass to AIB (repeatable) |
| `--timeout` | `120` | Timeout in minutes |
| `-w`, `--wait` | `false` | Wait for completion |
| `-f`, `--follow` | `true` | Stream task logs |

Comment on lines +243 to +262

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add blank lines around new tables to satisfy markdownlint MD058.

Both newly added tables are missing the required blank line before table start.

📝 Suggested markdown fix
 **Shared flags:**
+
 | Flag | Default | Description |
 |------|---------|-------------|
 | `--server` | `$CAIB_SERVER` | Build API server URL |
@@
 | `-w`, `--wait` | `false` | Wait for completion |
 | `-f`, `--follow` | `true` | Stream task logs |
@@
 Additional flag:
+
 | Flag | Description |
 |------|-------------|
 | `--signed` | Signed artifact ref (alternative to positional) |

Also applies to: 320-323

🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 255-255: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/caib/README.md` around lines 254 - 273, The newly added Markdown tables
(including the "**Shared flags:**" table and the other recent table) are missing
the required blank lines before their start; insert a single blank line above
each table and ensure at least one blank line after the preceding paragraph so
the tables comply with markdownlint MD058.

#### reseal

Reseal a bootc container image with a new TPM key. If no key is provided, an ephemeral key is generated.

```bash
bin/caib image reseal <source-container> <output-container> [flags]
```

### download
**Examples:**

```bash
# Reseal with ephemeral key
bin/caib image reseal quay.io/myorg/my-os:v1 quay.io/myorg/my-os:resealed

# Reseal with explicit key
bin/caib image reseal quay.io/myorg/my-os:v1 quay.io/myorg/my-os:resealed \
--key ./seal-key.pem

# Using --input/--output flags instead of positionals
bin/caib image reseal --input quay.io/myorg/my-os:v1 --output quay.io/myorg/my-os:resealed
```

#### prepare-reseal

Prepare a bootc container image for resealing (first step in a two-step seal workflow).

```bash
bin/caib image prepare-reseal <source-container> <output-container> [flags]
```

#### extract-for-signing

Extract components from a container image for external signing (e.g. secure boot).

```bash
bin/caib image extract-for-signing <source-container> <output-artifact> [flags]
```

#### inject-signed

Inject externally signed components back into a container image.

```bash
bin/caib image inject-signed <source-container> <signed-artifact> <output-container> [flags]
```

Additional flag:
| Flag | Description |
|------|-------------|
| `--signed` | Signed artifact ref (alternative to positional) |

### image download

Downloads artifacts from a completed build.

```bash
bin/caib download <build-name> [flags]
bin/caib image download <build-name> [flags]
```

| Flag | Default | Description |
Expand All @@ -261,25 +325,25 @@ bin/caib download <build-name> [flags]
| `--token` | `$CAIB_TOKEN` | Bearer token |
| `-o`, `--output` | (required) | Destination file or directory for downloaded artifact |

### list
### image list

Lists existing builds.

```bash
bin/caib list [flags]
bin/caib image list [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--server` | `$CAIB_SERVER` | Build API server URL |
| `--token` | `$CAIB_TOKEN` | Bearer token |

### show
### image show

Shows detailed information for a single build, including current status and resolved build parameters.

```bash
bin/caib show <build-name> [flags]
bin/caib image show <build-name> [flags]
```

| Flag | Default | Description |
Expand All @@ -292,11 +356,11 @@ bin/caib show <build-name> [flags]

```bash
# Human-friendly detail view
bin/caib show my-build
bin/caib image show my-build

# Machine-readable output
bin/caib show my-build -o json
bin/caib show my-build -o yaml
bin/caib image show my-build -o json
bin/caib image show my-build -o yaml
```

## Bootc vs Dev Builds
Expand All @@ -317,10 +381,15 @@ The CLI automatically detects authentication in this order:
3. Bearer token from kubeconfig (OpenShift `oc login`, exec plugins)
4. `oc whoami -t` command (if `oc` is available)

For registry authentication (`--push`, `--push-disk`):
For registry authentication (`--push`, `--push-disk`, sealed operations):

1. `REGISTRY_USERNAME` / `REGISTRY_PASSWORD` environment variables
2. Docker/Podman auth files (`~/.docker/config.json`, `~/.config/containers/auth.json`)
1. `--registry-auth-file` flag — explicit path to a Docker/Podman auth file (highest priority)
2. `REGISTRY_USERNAME` / `REGISTRY_PASSWORD` environment variables
3. Auto-discovery of auth files from standard locations:
- `$REGISTRY_AUTH_FILE` environment variable
- `$XDG_RUNTIME_DIR/containers/auth.json`
- `/run/containers/<uid>/auth.json`
- `~/.config/containers/auth.json`

For the OpenShift internal registry (`--internal-registry`):

Expand Down Expand Up @@ -349,6 +418,7 @@ Supported locations:
| `CAIB_TOKEN` | Bearer token (equivalent to `--token`) |
| `REGISTRY_USERNAME` | Registry username for push operations |
| `REGISTRY_PASSWORD` | Registry password for push operations |
| `REGISTRY_AUTH_FILE` | Path to Docker/Podman auth file (auto-discovery candidate) |

## Timeouts and Retries

Expand All @@ -370,7 +440,7 @@ Supported locations:
| HTTP 503/504 during log follow | Build pod starting | CLI retries automatically |
| Build fails after upload | PVC transition timing | Increase `--timeout`, check operator logs |
| "no bearer token found" | Not logged in | Run `oc login` or set `CAIB_TOKEN` |
| Registry auth failure | Missing credentials | Set `REGISTRY_USERNAME/REGISTRY_PASSWORD` env vars or login via `podman login` |
| Registry auth failure | Missing credentials | Run `podman login`, set `REGISTRY_USERNAME/REGISTRY_PASSWORD` env vars, or use `--registry-auth-file` |

## Version

Expand Down
10 changes: 10 additions & 0 deletions cmd/caib/build_validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

import (
common "github.com/centos-automotive-suite/automotive-dev-operator/cmd/caib/common"
)

// sanitizeBuildName is kept in main package for existing tests.
func sanitizeBuildName(name string) string {
return common.SanitizeBuildName(name)
}
Loading