Skip to content

feat(chart): integrate operator-managed migrations - #348

Closed
Siddhant-K-code wants to merge 25 commits into
siddhant-k-code-authored-operator-chartfrom
siddhant-k-code-authored-openfga-integration
Closed

Siddhant-K-code wants to merge 25 commits into
siddhant-k-code-authored-operator-chartfrom
siddhant-k-code-authored-openfga-integration

Conversation

@Siddhant-K-code

@Siddhant-K-code Siddhant-K-code commented Aug 24, 2026 •

Copy link
Copy Markdown
Member

Summary

Integrates the migration operator into the OpenFGA chart while preserving existing migration behavior when operator mode is disabled.

  • Wires openfga-operator as an optional subchart controlled by operator.enabled.
  • Switches PostgreSQL and MySQL migrations to operator-managed Jobs when operator mode is enabled.
  • Starts new database-backed operator deployments at zero replicas, preserves live replicas during upgrades, and keeps memory-backed deployments at one replica.
  • Adds the migration ServiceAccount and least-privilege RBAC required by operator-created Jobs.
  • Preserves external-secret pre-hooks, in-release post-hooks, ServiceAccount cleanup, and annotation overrides from fix(chart): harden external migration hooks #345.
  • Adds operator-mode values, documentation, and Helm unit coverage.

Stack

Native stack 351. Open #345 to view the GitHub stack map. Review bottom to top:

  1. fix(chart): harden external migration hooks #345: External migration hooks, base main
  2. feat(operator): add migration orchestration controller #346: Migration controller, base fix(chart): harden external migration hooks #345
  3. feat(operator-chart): package the migration operator #347: Operator Helm chart, base feat(operator): add migration orchestration controller #346
  4. feat(chart): integrate operator-managed migrations #348: OpenFGA chart integration (this PR), base feat(operator-chart): package the migration operator #347
  5. ci(operator): add build and upgrade coverage #349: Operator CI and upgrade E2E, base feat(chart): integrate operator-managed migrations #348
  6. docs(operator): document migration architecture decisions #350: Migration architecture ADRs, base ci(operator): add build and upgrade coverage #349

Replaces closed #339 and carries the OpenFGA chart integration portion of source #331. CI and upgrade E2E remain in the next layer.

Attribution

  • The 14 original integration commits are replayed with Ed Milic (@emilic) as their actual Git author, preserving author dates, messages, and commit boundaries.
  • The two original branch-integration commits are preserved as tree-identical, two-parent merge commits authored by Anurag Bandyopadhyay (@SoulPancake).
  • GitHub links both contributors to their replayed commits. Source PR feat: operator migration #331 contains no co-author trailers.

Validation

  • Full OpenFGA Helm suite: 9 suites and 53 tests
  • Focused operator and migration suites: 6 suites and 36 tests
  • Helm lint and template for default, operator PostgreSQL, operator memory, and external-hook modes
  • Nested operator values and unknown-key schema rejection
  • Focused ct lint
  • Exact 16-path reviewed scope
  • git diff --check

emilic and others added 15 commits August 24, 2026 19:11
Replace Helm hook-based migrations with a lightweight Kubernetes
operator that watches OpenFGA Deployments, detects version changes,
and runs migrations as regular Jobs.

- Go operator using controller-runtime (no CRDs)
- Helm subchart with opt-in via operator.enabled (default false)
- Dedicated migration ServiceAccount (separate from runtime)
- Auto-recovery on database failure (delete/retry cycle)
- GitHub Actions workflow for multi-arch image builds
- Integration test values for local Kubernetes clusters

Resolves #211, #107, #120, #100, #126
- Harden pod security (runAsNonRoot, seccompProfile, drop ALL caps)
- Find container by name instead of index to handle sidecars
- Skip migration for memory datastore
- Persist retry-after annotation before Job deletion to survive re-enqueue
- Clear MigrationFailed condition on success
- Propagate imagePullSecrets and securityContext to migration Jobs
- Remove unused RBAC rules (secrets, serviceaccounts)
- Add POD_NAMESPACE downward API for namespace-scoped watch default
- Remove no-op migration values (timeout, backoffLimit, resources)
- Fix migration SA helper to require name when create=false
- Guard operator logic on both operator.enabled and migration.enabled
- Build and load operator image into kind for chart-testing CI
- Add path filters to operator workflow
- Fix ADR inaccuracies (retry strategy, default-enabled wording)
- Pin Dockerfile base image to golang:1.26.2
- Render extraInitContainers in operator mode (previously skipped)
- Add version label to migration Jobs and delete stale Jobs on image change
- Use namespaced Role/RoleBinding when watchAllNamespaces is false
- Replace Status().Update with Status().Patch to avoid write conflicts
- Fix logger.Error(nil, ...) to logger.Info for expected failure state
- Wire desiredVersion param into buildMigrationJob for version tracking
- Update RBAC: deployments/status verb from update to patch
- Don't force replicas: 0 for memory engine in operator mode
- Guard migration SA creation on migration.enabled
- Document both required labels and mutable tag limitation in README
- Add opt-in annotation (openfga.dev/migration-enabled) so the operator
  only manages migrations for explicitly opted-in Deployments
- Propagate volumes, volumeMounts, and envFrom from the Deployment to
  migration Jobs for TLS certs and file-based credentials
- Remove watchAllNamespaces option; operator is now always namespace-scoped
- Update ADR-004 dependency example to match actual file:// reference
- Add test for migration-not-enabled skip behavior
- Wrap deployment annotations in conditional to avoid emitting empty
  annotations: field which produces an invalid manifest
- Store full version in annotation (openfga.dev/desired-version) and
  truncate label to 63 chars to support digest-pinned images
- Align operator image default to ghcr.io/openfga/openfga-operator to
  match CI publishing target
When operator.enabled=true but migration.enabled=false, the legacy
wait-for-migration initContainer could render and hang waiting for a
Job that will never be created. Gate on operator.enabled instead so
the legacy path is fully disabled when the operator is installed.
…essions

The double-quoted annotation values contained inner double quotes (e.g.
"memory") which produced invalid YAML that IDEs flagged as errors. Switch
to single-quote wrappers so the inner Go template strings don't conflict.
20 new tests across 4 files covering the operator-enabled code paths
that previously had no unit test coverage:

- deployment: annotations, replicas=0, autoscaling conflict, initContainers gating
- job: template not rendered when operator enabled
- serviceaccount: migration SA creation, custom names, IRSA annotations
- rbac: legacy Role/RoleBinding not rendered when operator enabled
The operator was scaling Deployments to 0 replicas during every migration,
causing a full outage on every helm upgrade — a regression from the existing
rolling update behavior. OpenFGA already gates readiness on schema version
(MinimumSupportedDatastoreSchemaRevision in sqlcommon.IsReady), so new pods
naturally block until migration completes while old pods keep serving.

Use Helm's lookup function to preserve the live replica count on upgrade
(falling back to replicas: 0 on fresh install where no Deployment exists).
Remove scaleDeploymentToZero from the operator reconcile loop. Update
ADR-002 to document the rationale and the readiness gate dependency.
…ent template

- findOpenFGAContainer now reads the openfga.dev/container-name
  annotation emitted by the chart, and returns an error when the target
  container is missing instead of silently falling back to the first
  container in the pod spec.
- migration_controller surfaces that error to the reconciler instead
  of logging and skipping, so misconfigured Deployments are visible.
- deployment.yaml emits the new container-name annotation, collapses
  the replica-preservation logic to a single branch (both previous
  branches already preserved existing replicas), and uses
  selectorLabels on the pod template to avoid chart-version churn in
  pod labels across upgrades.
- values.yaml documents the openfga-operator subchart values
  passthrough and clarifies migration service account behavior.
I switched the pod template labels from openfga.labels to openfga.selectorLabels, which would have stripped
helm.sh/chart, commonLabels, component, version, managed-by, and
part-of from running pods on upgrade — a breaking change for any
tooling filtering on those labels.

Add a helm-unittest regression guard for both operator on/off modes.
- charts/openfga-operator/ci and charts/openfga/ci values files so
  chart-testing exercises both the standalone operator subchart and
  the parent chart with operator.enabled=true.
- .github/ci/operator-postgres-values.yaml plus a dedicated workflow
  step that installs at v1.9.5 and upgrades to v1.14.1 (crossing the
  v1.10.0 !!REQUIRES MIGRATION!! boundary), asserting the migration
  ConfigMap and ready rollout at each step.
Both the operator subchart and the parent chart's operator/migration
blocks were missing additionalProperties: false, so typos like
`migrationjob:` (lowercase), `enbaled: true`, or misplaced fields
were silently ignored at install time. Add the guard to all
well-defined object blocks — free-form blocks (podAnnotations,
resources, securityContext, etc.) stay permissive since they pass
through to pod spec.
When operator.enabled=true the workload starts at 0 replicas and only
scales up after migration. If the operator pod is unhealthy this looks
like a stuck install with no signal. Add NOTES output pointing at the
operator deployment, migration Job, and MigrationFailed condition.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Aug 24, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 991c85e7-beb5-4a06-8c20-f2a84c0464da

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…ator-plus-migration-hooks

# Conflicts:
#	charts/openfga/templates/deployment.yaml
#	charts/openfga/templates/job.yaml

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Integrates the openfga-operator subchart into charts/openfga to support operator-managed migrations while keeping the existing Helm-managed migration behavior when operator mode is disabled.

Changes:

  • Adds operator.enabled + migration.* values (and schema) and wires openfga-operator as a conditional dependency.
  • Gates legacy migration Job/hooks, migration initContainers, and legacy RBAC when operator mode is enabled; adds operator-specific Deployment annotations and optional migration ServiceAccount.
  • Adds Helm unit tests and CI values to cover operator mode rendering and conflicts (e.g., autoscaling).

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
charts/openfga/values.yaml Adds operator mode and migration ServiceAccount configuration values.
charts/openfga/values.schema.json Extends schema to validate operator/migration keys and allow openfga-operator passthrough.
charts/openfga/Chart.yaml Adds openfga-operator as an optional subchart dependency gated by operator.enabled.
charts/openfga/Chart.lock Updates dependency lock for the new local subchart dependency.
charts/openfga/templates/deployment.yaml Adds operator annotations, replica gating logic, autoscaling conflict fail, and migration initContainer gating updates.
charts/openfga/templates/_helpers.tpl Adds migration ServiceAccount name helper; disables pre-install hook logic in operator mode.
charts/openfga/templates/job.yaml Disables legacy Helm migration Job rendering when operator mode is enabled.
charts/openfga/templates/rbac.yaml Disables legacy RBAC rendering when operator mode is enabled.
charts/openfga/templates/serviceaccount.yaml Adds optional migration ServiceAccount rendering for operator mode.
charts/openfga/templates/NOTES.txt Adds operator-mode user guidance and troubleshooting notes.
charts/openfga/README.md Documents operator-managed migrations and behavior differences vs Helm-managed modes.
charts/openfga/ci/operator-mode-values.yaml Adds CT/install values to exercise operator mode (memory datastore) in CI.
charts/openfga/tests/operator_mode_test.yaml Adds unit coverage for operator annotations, replica behavior, initContainer gating, and autoscaling conflict.
charts/openfga/tests/operator_mode_serviceaccount_test.yaml Adds unit coverage for operator migration ServiceAccount rendering rules.
charts/openfga/tests/operator_mode_rbac_test.yaml Adds unit coverage ensuring legacy RBAC is suppressed in operator mode.
charts/openfga/tests/operator_mode_job_test.yaml Adds unit coverage ensuring legacy migration Job is suppressed in operator mode.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread charts/openfga/templates/deployment.yaml Outdated
…k-code-authored-openfga-integration

# Conflicts:
#	charts/openfga/templates/_helpers.tpl
#	charts/openfga/templates/serviceaccount.yaml
@SoulPancake
SoulPancake requested a balanced review from Copilot August 24, 2026 14:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated 3 comments.

Comment thread charts/openfga/templates/job.yaml
Comment thread charts/openfga/Chart.yaml
Comment thread charts/openfga/README.md Outdated
…k-code-authored-openfga-integration

# Conflicts:
#	charts/openfga/Chart.yaml
…k-code-authored-openfga-integration

# Conflicts:
#	charts/openfga/templates/_helpers.tpl
@Siddhant-K-code

Copy link
Copy Markdown
Member Author

Closing this stack for now. We're going to focus first on updating, reviewing, and fixing #309.

@Siddhant-K-code
Siddhant-K-code deleted the siddhant-k-code-authored-openfga-integration branch September 22, 2026 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants