Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2ae27e3
go(init): scaffolding the project using kubebuilder
mgrzybek Jul 7, 2026
7489512
feat(openstack): Epic 1 — authentification OpenStack (TDD)
mgrzybek Jul 7, 2026
537c115
feat(openstack): Epic 2 — Floating IP cleanup (TDD)
mgrzybek Jul 7, 2026
5c6bd74
feat(openstack): Epic 3 — Load Balancer cleanup (TDD)
mgrzybek Jul 7, 2026
c887846
feat(openstack): Epic 4 — Security Group cleanup (TDD)
mgrzybek Jul 7, 2026
80a77f2
Epic 4 — Security Groups (US4.1 / US4.2):
mgrzybek Jul 8, 2026
0035f75
feat(openstack): Epic 6 — Cinder Snapshot cleanup (TDD)
mgrzybek Jul 8, 2026
692654a
feat(openstack): Epic 7 — Application Credential cleanup (TDD)
mgrzybek Jul 8, 2026
51b934c
feat(controller): Epic 8 — Kubernetes lifecycle (TDD)
mgrzybek Jul 8, 2026
9f62675
feat(controller): Epic 9 — Configuration via env vars (TDD)
mgrzybek Jul 8, 2026
9ed6c53
feat(packaging): Epic 10 — OCI image, Helm chart and SBOM via Nix (TDD)
mgrzybek Jul 8, 2026
cfccd2e
feat(controller): Epic 11 — Observability (Prometheus metrics + Kuber…
mgrzybek Jul 8, 2026
8661e97
feat(openstack): Epic 12 — Robustness: HTTP timeout and Cinder alias …
mgrzybek Jul 8, 2026
ca839be
feat(migration): add the roadmap
mgrzybek Jul 8, 2026
8adac16
feat(doc): translate everything in English
mgrzybek Jul 8, 2026
5c6d915
feat(doc): update README
mgrzybek Jul 8, 2026
3b5a96f
chores: remove Python code
mgrzybek Jul 8, 2026
58996d9
fix(chart): fix packaging tests and update Helm snapshot
mgrzybek Jul 8, 2026
352eb64
feat(ci): start from scratch using nix
mgrzybek Jul 8, 2026
a681ba7
feat: allow userpass cred login, wider prefix selector
Banh-Canh Jul 10, 2026
10e0da1
fix: wait for deletion (retry)
Banh-Canh Jul 10, 2026
c3d2f4b
chore(build): gofmt imports, pin Nix vendorHash, document CI test target
mgrzybek Jul 10, 2026
925b7d4
fix: correct waitForDeletion regressions from the retry refactor
mgrzybek Jul 10, 2026
de5091c
chores(build): add pre-commit and ignore archives
mgrzybek Jul 10, 2026
eab8f8c
chores(ci): run azimuth tests only if the behaviour might change
mgrzybek Jul 10, 2026
159e9d4
chore(build): drop the Dockerfile in favour of Nix, fix dependabot ec…
mgrzybek Jul 10, 2026
2da1191
chores(build): exclude sbom.cdx.json
mgrzybek Jul 10, 2026
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
34 changes: 34 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "Kubebuilder DevContainer",
"image": "golang:1.26",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"moby": false,
"dockerDefaultAddressPool": "base=172.30.0.0/16,size=24"
},
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/common-utils:2": {
"upgradePackages": true
}
},

"runArgs": ["--privileged", "--init"],

"customizations": {
"vscode": {
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"extensions": [
"ms-kubernetes-tools.vscode-kubernetes-tools",
"ms-azuretools.vscode-docker"
]
}
},

"remoteEnv": {
"GO111MODULE": "on"
},

"onCreateCommand": "bash .devcontainer/post-install.sh"
}
153 changes: 153 additions & 0 deletions .devcontainer/post-install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#!/bin/bash
set -euo pipefail

echo "===================================="
echo "Kubebuilder DevContainer Setup"
echo "===================================="

# Verify running as root (required for installing to /usr/local/bin and /etc)
if [ "$(id -u)" -ne 0 ]; then
echo "ERROR: This script must be run as root"
exit 1
fi

echo ""
echo "Detecting system architecture..."
# Detect architecture using uname
MACHINE=$(uname -m)
case "${MACHINE}" in
x86_64)
ARCH="amd64"
;;
aarch64|arm64)
ARCH="arm64"
;;
*)
echo "WARNING: Unsupported architecture ${MACHINE}, defaulting to amd64"
ARCH="amd64"
;;
esac
echo "Architecture: ${ARCH}"

echo ""
echo "------------------------------------"
echo "Setting up bash completion..."
echo "------------------------------------"

BASH_COMPLETIONS_DIR="/usr/share/bash-completion/completions"

# Enable bash-completion in root's .bashrc (devcontainer runs as root)
if ! grep -q "source /usr/share/bash-completion/bash_completion" ~/.bashrc 2>/dev/null; then
echo 'source /usr/share/bash-completion/bash_completion' >> ~/.bashrc
echo "Added bash-completion to .bashrc"
fi

echo ""
echo "------------------------------------"
echo "Installing development tools..."
echo "------------------------------------"

# Install kind
if ! command -v kind &> /dev/null; then
echo "Installing kind..."
curl -Lo /usr/local/bin/kind "https://kind.sigs.k8s.io/dl/latest/kind-linux-${ARCH}"
chmod +x /usr/local/bin/kind
echo "kind installed successfully"
fi

# Generate kind bash completion
if command -v kind &> /dev/null; then
if kind completion bash > "${BASH_COMPLETIONS_DIR}/kind" 2>/dev/null; then
echo "kind completion installed"
else
echo "WARNING: Failed to generate kind completion"
fi
fi

# Install kubebuilder
if ! command -v kubebuilder &> /dev/null; then
echo "Installing kubebuilder..."
curl -Lo /usr/local/bin/kubebuilder "https://go.kubebuilder.io/dl/latest/linux/${ARCH}"
chmod +x /usr/local/bin/kubebuilder
echo "kubebuilder installed successfully"
fi

# Generate kubebuilder bash completion
if command -v kubebuilder &> /dev/null; then
if kubebuilder completion bash > "${BASH_COMPLETIONS_DIR}/kubebuilder" 2>/dev/null; then
echo "kubebuilder completion installed"
else
echo "WARNING: Failed to generate kubebuilder completion"
fi
fi

# Install kubectl
if ! command -v kubectl &> /dev/null; then
echo "Installing kubectl..."
KUBECTL_VERSION=$(curl -Ls https://dl.k8s.io/release/stable.txt)
curl -Lo /usr/local/bin/kubectl "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${ARCH}/kubectl"
chmod +x /usr/local/bin/kubectl
echo "kubectl installed successfully"
fi

# Generate kubectl bash completion
if command -v kubectl &> /dev/null; then
if kubectl completion bash > "${BASH_COMPLETIONS_DIR}/kubectl" 2>/dev/null; then
echo "kubectl completion installed"
else
echo "WARNING: Failed to generate kubectl completion"
fi
fi

# Generate Docker bash completion
if command -v docker &> /dev/null; then
if docker completion bash > "${BASH_COMPLETIONS_DIR}/docker" 2>/dev/null; then
echo "docker completion installed"
else
echo "WARNING: Failed to generate docker completion"
fi
fi

echo ""
echo "------------------------------------"
echo "Configuring Docker environment..."
echo "------------------------------------"

# Wait for Docker to be ready
echo "Waiting for Docker to be ready..."
for i in {1..30}; do
if docker info >/dev/null 2>&1; then
echo "Docker is ready"
break
fi
if [ "$i" -eq 30 ]; then
echo "WARNING: Docker not ready after 30s"
fi
sleep 1
done

# Create kind network (ignore if already exists)
if ! docker network inspect kind >/dev/null 2>&1; then
if docker network create kind >/dev/null 2>&1; then
echo "Created kind network"
else
echo "WARNING: Failed to create kind network (may already exist)"
fi
fi

echo ""
echo "------------------------------------"
echo "Verifying installations..."
echo "------------------------------------"
kind version
kubebuilder version
kubectl version --client
docker --version
go version

echo ""
echo "===================================="
echo "DevContainer ready!"
echo "===================================="
echo "All development tools installed successfully."
echo "You can now start building Kubernetes operators."
6 changes: 0 additions & 6 deletions .dockerignore

This file was deleted.

17 changes: 8 additions & 9 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
version: 2
updates:
updates:
# Using dependabot for all GHA violates pinning policy
- package-ecosystem: github-actions
Expand All @@ -19,18 +18,18 @@ updates:
- dependency-name: "actions/*"
- dependency-name: "github-actions/*"

# Automatically propose PRs for Python dependencies
- package-ecosystem: pip
# Automatically propose PRs for Go module dependencies
- package-ecosystem: gomod
directory: "/"
schedule:
# Check for new versions daily
interval: daily
# Check for new versions weekly
interval: weekly
groups:
pip-updates:
go-updates:
patterns: ["*"]
labels:
- automation
- pip-update
- go-update
commit-message:
# Prefix all commit messages with "pip: "
prefix: "pip"
# Prefix all commit messages with "go: "
prefix: "go"
79 changes: 59 additions & 20 deletions .github/workflows/build-push-artifacts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ on:

jobs:
build_push_images:
name: Build and push images
name: Build and push images (Nix)
runs-on: ubuntu-latest
permissions:
contents: read
Expand All @@ -36,6 +36,9 @@ jobs:
with:
ref: ${{ inputs.ref }}

- name: Install Nix
uses: DeterminateSystems/nix-installer-action@07ebb8d2749aa2fac2baae7d1cfa011e4acfd8d1 # v5

- name: Login to GitHub Container Registry
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
Expand All @@ -47,27 +50,63 @@ jobs:
id: semver
uses: azimuth-cloud/github-actions/semver@master

- name: Calculate metadata for image
id: image-meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with:
images: ghcr.io/azimuth-cloud/cluster-api-janitor-openstack
# Produce the branch name or tag and the SHA as tags
tags: |
type=ref,event=branch
type=ref,event=tag
type=raw,value=${{ steps.semver.outputs.short-sha }}
- name: Compute image tags
id: tags
run: |
# All final tags for the manifest list (space-separated)
TAGS=""
REF="${{ github.ref }}"
SHA="${{ steps.semver.outputs.short-sha }}"
IMAGE="ghcr.io/azimuth-cloud/cluster-api-janitor-openstack"
if [[ "$REF" == refs/tags/* ]]; then
TAG="${REF#refs/tags/}"
TAGS="$IMAGE:$TAG $IMAGE:$SHA"
elif [[ "$REF" == refs/heads/* ]]; then
BRANCH="${REF#refs/heads/}"
TAGS="$IMAGE:$BRANCH $IMAGE:$SHA"
else
TAGS="$IMAGE:$SHA"
fi
echo "tags=$TAGS" >> "$GITHUB_OUTPUT"
echo "sha_tag=$IMAGE:$SHA" >> "$GITHUB_OUTPUT"
echo "image=$IMAGE" >> "$GITHUB_OUTPUT"

- name: Build amd64 image
run: nix-build nix -A image -o image-amd64.tar.gz

- name: Build arm64 image (cross-compiled)
run: nix-build nix -A image-arm64 -o image-arm64.tar.gz

- name: Push arch-specific images and create manifest list
env:
SHA_TAG: ${{ steps.tags.outputs.sha_tag }}
IMAGE: ${{ steps.tags.outputs.image }}
TAGS: ${{ steps.tags.outputs.tags }}
run: |
# Push each arch image under a unique tag used only to assemble the manifest.
skopeo copy \
docker-archive:image-amd64.tar.gz \
"docker://${SHA_TAG}-amd64"
skopeo copy \
docker-archive:image-arm64.tar.gz \
"docker://${SHA_TAG}-arm64"

# For each final tag, create and push a multi-arch manifest list.
for TAG in $TAGS; do
docker manifest create "$TAG" \
--amend "${SHA_TAG}-amd64" \
--amend "${SHA_TAG}-arm64"
docker manifest push "$TAG"
done

- name: Generate SBOM (CycloneDX)
run: nix-build nix -A sbom -o sbom.cdx.json

- name: Build and push image
uses: azimuth-cloud/github-actions/docker-multiarch-build-push@master
- name: Upload SBOM as artifact
uses: actions/upload-artifact@v4
with:
cache-key: cluster-api-janitor-openstack
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.image-meta.outputs.tags }}
labels: ${{ steps.image-meta.outputs.labels }}
github-token: ${{ secrets.GITHUB_TOKEN }}
name: sbom-${{ steps.semver.outputs.short-sha }}
path: sbom.cdx.json

build_push_chart:
name: Build and push Helm chart
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: CI

on:
push:
pull_request:

permissions: {}

jobs:
nix:
name: fmt + vet + test (Nix)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- uses: DeterminateSystems/nix-installer-action@07ebb8d2749aa2fac2baae7d1cfa011e4acfd8d1 # v5

- name: Run fmt + vet + unit tests
run: nix-build nix -A tests
Loading
Loading