operator: unify namespace ownership for orca/inventory/machine-ops (follow-up to #529)
- Dominant language
- Go
- Stars
- 28
- Forks
- 11
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 55
Description
### Summary
PR #530 (closing #529) made the unbounded-operator the sole runtime owner of the shared `unbounded-system` Namespace for the operator-managed components (gantry, machina, metalman, net, storage): those components skip `Namespace` objects during reconcile, and every operator-managed template ships the identical canonical label set (`unbounded.SystemNamespaceLabels()`), enforced by the drift guard.
Three deploy flows that also default into `unbounded-system` were deliberately left out of scope (see #529 "Out of scope" and the `operatorManaged: false` rows in `internal/unbounded/namespace_drift_test.go`): **orca**, **inventory**, and **machine-ops**. They are not part of the operator's component registry, so the operator never reconciles them. This issue tracks bringing them under the same single-owner / unified-label posture.
### Current behavior / evidence
All three render a `Namespace` whose name defaults to `unbounded-system`, but with labels that diverge from the canonical set the operator now maintains:
| Component | Template | `app.kubernetes.io/name` |
|---|---|---|
| orca | `deploy/orca/01-namespace.yaml.tmpl` | `orca` |
| inventory | `deploy/inventory/common/01-namespace.yaml.tmpl` | *(none)* |
| machine-ops | `deploy/machine-ops/00-namespace.yaml.tmpl` | *(none)* |
The drift guard currently name-checks these (asserts the default namespace name) but does not assert their labels, because they are not operator-managed.
### Impact
- **Not churn today, but a latent divergence.** The operator's `BootstrapMaintainer` reasserts `SystemNamespaceLabels()` (including `app.kubernetes.io/name: unbounded-cloud`) every interval with `ForceOwnership`. If any of these flows is applied into the same cluster/namespace as the operator, the operator will (correctly) flip `app.kubernetes.io/name` away from `orca`/absent to `unbounded-cloud`.
- **Potential tug-of-war under GitOps.** A one-time `kubectl apply` is harmless (the operator wins on the next tick and it stays). But if orca/inventory/machine-ops are reconciled by a tool that periodically re-applies their Namespace under a stable field manager, the shared `app.kubernetes.io/name` key would ping-pong between that manager and `unbounded-operator` - the same class of problem #529 fixed for the operator-managed set.
- The single-identity goal for `unbounded-system` is only partially realized while these templates carry divergent/absent identity labels.
### Open question
Confirm the intended topology: are orca / inventory / machine-ops ever deployed into the same `unbounded-system` namespace as the operator, or are they control-plane-side / standalone flows that never co-reside with it? The chosen direction below depends on this.
### Proposed direction (pick per component)
1. **If a component should be operator-owned at runtime:** add it to the operator's managed set (or at least route its Namespace through the operator), and rely on the existing central `Namespace` skip.
2. **If a component stays standalone but shares `unbounded-system`:** unify its template's Namespace to the identical `SystemNamespaceLabels()` (canonical name + managed-by + PSA), and flip its row to `operatorManaged: true` in `namespace_drift_test.go` so the drift guard enforces parity. This matches the direct-apply parity contract PR #530 established for the operator-managed components.
3. **If a component must not share `unbounded-system`:** give it its own namespace default (like `deploy/playpen` uses `playpen`) so it never contends for the shared object.
### Acceptance criteria
- [ ] Decision recorded for each of orca, inventory, machine-ops (own the namespace, unify labels, or separate namespace).
- [ ] No divergent/absent identity labels remain on any template that defaults into `unbounded-system`.
- [ ] `namespace_drift_test.go` asserts labels (not just name) for every template that shares `unbounded-system`.
- [ ] `make fmt`, `make lint`, `go test ./internal/operator/... ./internal/unbounded/...` pass.
### References
- #529 / PR #530 - operator now owns `unbounded-system` for the operator-managed components; these three were explicitly out of scope.
- Canonical label source of truth: `internal/unbounded/unbounded.go` (`SystemNamespaceLabels`).
- Drift guard: `internal/unbounded/namespace_drift_test.go` (`operatorManaged` flag).
Contributor guide
Research direction
Start by reviewing #529 and PR #530, then inspect deploy/orca/01-namespace.yaml.tmpl, deploy/inventory/common/01-namespace.yaml.tmpl, deploy/machine-ops/00-namespace.yaml.tmpl, internal/unbounded/unbounded.go, and internal/unbounded/namespace_drift_test.go. Record the namespace decision for each component, update the affected templates and drift assertions, and run make fmt, make lint, and the specified Go tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, kubernetes
- Domain
- devops, infrastructure, testing
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100