From 4061ecd8141276e1896d649a35a9975367bfa315 Mon Sep 17 00:00:00 2001 From: Ameya Sathe Date: Tue, 7 Jul 2026 13:57:12 +0530 Subject: [PATCH] docs(OSAC-2402): sync AGENTS.md with codebase and condense to size limits Signed-off-by: Ameya Sathe Assisted-by: Claude Code Signed-off-by: Ameya Sathe rh-pre-commit.version: 2.4.0 rh-pre-commit.check-secrets: ENABLED --- AGENTS.md | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..84bd265 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,125 @@ +# host-management-openstack + +Kubernetes controller that manages bare metal host power state via OpenStack Ironic. Watches HostLease custom resources (defined in bare-metal-fulfillment-operator) and reconciles desired power state (`spec.poweredOn`) through Ironic APIs. Optionally integrates with AAP for provisioning workflows via osac-operator's shared provisioning lifecycle. + +## Critical Rules + +- **No CRDs in this repo** — HostLease is owned by bare-metal-fulfillment-operator; install it before deploying +- **Always `make manifests`** after modifying RBAC markers in controller code +- **Never edit** `config/rbac/role.yaml` — it is generated by controller-gen +- **Always `go mod tidy`** before committing +- Run `make lint test` before committing + +## Dev Environment + +**Language**: Go (see `go.mod`) | **Framework**: controller-runtime (Kubebuilder v4) | **Build tool**: Make | **Container tool**: Podman (default) | **Test framework**: Ginkgo v2 + Gomega | **Linter**: golangci-lint (see `Makefile`) + +```bash +make build # Build manager binary +make test # Unit tests (uses envtest, excludes e2e) +make test-e2e # E2E tests (auto-creates/tears down Kind cluster host-management-openstack-test-e2e) +make lint # golangci-lint +make lint-fix # golangci-lint run --fix +make fmt && make vet # Format and vet + +make manifests # Generate RBAC, CRD, and webhook manifests via controller-gen (only RBAC output today — no local CRDs or webhooks) +make generate # Generate DeepCopy methods via controller-gen + +make run # Run controller locally (requires HOSTLEASE_NAMESPACE env var) +make deploy IMG=/host-management-openstack:tag +make undeploy # Remove operator from cluster + +make image-build IMG=/host-management-openstack:tag # Build with Podman +make image-push IMG=/host-management-openstack:tag +make docker-buildx PLATFORMS=linux/amd64,linux/arm64 # Multi-arch build +make build-installer IMG=... # Generate dist/install.yaml (consolidated manifest) + +pre-commit run --all-files # Run all pre-commit hooks +``` + +## Repository Structure + +```text +host-management-openstack/ +├── cmd/ +│ ├── main.go # Operator entry point (manager setup, AAP config, namespace filtering) +│ └── main_test.go # Entry point tests +├── internal/ +│ ├── controller/ # HostLease reconciliation (power sync, provisioning lifecycle, finalizers) +│ └── management/ # Power management abstraction (pluggable backend interface, OpenStack impl) +├── config/ +│ ├── default/ # Kustomize default overlay +│ ├── manager/ # Manager deployment manifest +│ ├── rbac/ # Generated RBAC rules +│ ├── prometheus/ # Prometheus monitoring config (commented out by default) +│ ├── network-policy/ # Network policy definitions (commented out by default) +│ └── samples/ # Example HostLease CR +├── test/ +│ ├── e2e/ # End-to-end tests (Kind cluster) +│ └── utils/ # Test utilities +├── Makefile # Build, test, lint, deploy targets +├── go.mod # Go dependencies (see go.mod) +└── .golangci.yml # Linter configuration +``` + +## Resources Managed + +This operator manages no CRDs. It watches **HostLease** CRs (from bare-metal-fulfillment-operator) filtered by `spec.hostClass == "openstack"` and reconciles their power state via Ironic using `spec.externalHostID` as the Ironic node UUID. + +## Architecture + +```text +HostLease CR (spec.poweredOn, spec.externalHostID) + ↓ (reconcile, filtered by hostClass == "openstack") +HostLease Controller (named "openstack-host") + ├── (power sync via) Management Client → OpenStack Ironic + └── (optional provisioning via) osac-operator/pkg/provisioning → AAP +``` + +### Key Subsystems + +| Package | Purpose | +|---------|---------| +| `internal/controller/` | HostLease reconciliation: finalizers, power sync (60s recheck), AAP provisioning (30s poll) | +| `internal/management/` | Power management abstraction with pluggable backend; OpenStack impl via gophercloud v2 | +| `cmd/main.go` | Manager setup, AAP client config (`OSAC_AAP_*` env vars), namespace filtering (`HOSTLEASE_NAMESPACE`) | + +## CI + +GitHub Actions (`.github/workflows/`): +- **build-image.yaml** — runs tests, builds + pushes container image to GHCR +- **pre-commit.yaml** — pre-commit hooks + golangci-lint on PRs + +## Code Quality + +- **golangci-lint** (see `Makefile`) with dupl, errcheck, ginkgolinter, goconst, gocyclo, govet, ineffassign, lll, misspell, prealloc, revive, staticcheck, unconvert, unused; formatters: gofmt, goimports (see `.golangci.yml`) +- **Pre-commit hooks**: trailing-whitespace, check-merge-conflict, end-of-file-fixer, check-added-large-files, check-case-conflict, check-json, check-symlinks, detect-private-key, yamllint --strict (excludes `config/`), golangci-lint run --fix +- **Tests**: Ginkgo v2 + Gomega with envtest for unit tests; Kind cluster for e2e (`test/e2e/`) + +## Container Security + +- **Base images**: Go toolset (builder, see `Containerfile`), gcr.io/distroless/static:nonroot (runtime) +- **Multi-stage build**: CGO_ENABLED=0, runs as non-root user 65532 +- **Default registry**: ghcr.io/osac-project/host-management-openstack:latest + +## Code Generation Flow + +1. Modify RBAC markers in controller code (`internal/controller/`) +2. Run `make manifests` → runs controller-gen for RBAC, CRD, and webhook output; only RBAC is produced today (HostLease CRD is external) +3. Run `make generate` → regenerates DeepCopy methods if API types change + +## Test Structure + +- `internal/controller/hostlease_controller_test.go` — reconciliation scenarios with envtest +- `internal/management/openstack_internal_test.go` — OpenStack client unit tests +- `internal/management/management_test.go` — backend factory tests +- `cmd/main_test.go` — entry point tests +- `test/e2e/` — end-to-end tests with Kind cluster (named `host-management-openstack-test-e2e`) +- `test/utils/` — shared test utilities +- **ENVTEST_K8S_VERSION**: Auto-detected from k8s.io/api version in go.mod + +## Cross-Component Integration + +- **bare-metal-fulfillment-operator** — owns the HostLease CRD; must be installed first +- **osac-operator** — provides `pkg/provisioning` (lifecycle state machine) and `pkg/aap` (AAP client); update with `go get github.com/osac-project/osac-operator@ && go mod tidy` +- **fulfillment-service** — creates HostLease resources during bare metal provisioning