This is page 1 of 126. Use http://codebase.md/controlplaneio-fluxcd/flux-operator?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .github
│ ├── actions
│ │ └── runner-cleanup
│ │ └── action.yml
│ ├── copilot-instructions.md
│ ├── dependabot.yaml
│ └── workflows
│ ├── actions-test.yaml
│ ├── e2e-olm.yaml
│ ├── preview.yaml
│ ├── push-manifests.yaml
│ ├── release.yaml
│ └── test.yaml
├── .gitignore
├── .golangci.yml
├── .goreleaser.yml
├── actions
│ └── setup
│ ├── action.yaml
│ └── README.md
├── AGENTS.md
├── api
│ └── v1
│ ├── common_types_test.go
│ ├── common_types.go
│ ├── fluxinstance_types.go
│ ├── fluxreport_types.go
│ ├── groupversion_info.go
│ ├── history_types_test.go
│ ├── history_types.go
│ ├── resourceset_types.go
│ ├── resourcesetinputprovider_types.go
│ ├── schedule_types.go
│ └── zz_generated.deepcopy.go
├── cmd
│ ├── cli
│ │ ├── build_instance.go
│ │ ├── build_resourceset_test.go
│ │ ├── build_resourceset.go
│ │ ├── build.go
│ │ ├── client.go
│ │ ├── completion_bash.go
│ │ ├── completion_fish.go
│ │ ├── completion_powershell.go
│ │ ├── completion_zsh.go
│ │ ├── completion.go
│ │ ├── create_secret_basicauth_test.go
│ │ ├── create_secret_basicauth.go
│ │ ├── create_secret_githubapp.go
│ │ ├── create_secret_proxy_test.go
│ │ ├── create_secret_proxy.go
│ │ ├── create_secret_registry_test.go
│ │ ├── create_secret_registry.go
│ │ ├── create_secret_sops_test.go
│ │ ├── create_secret_sops.go
│ │ ├── create_secret_ssh.go
│ │ ├── create_secret_tls.go
│ │ ├── create_secret.go
│ │ ├── create.go
│ │ ├── debug_web_cookie.go
│ │ ├── debug_web.go
│ │ ├── debug.go
│ │ ├── delete_inputprovider_test.go
│ │ ├── delete_inputprovider.go
│ │ ├── delete_instance_test.go
│ │ ├── delete_instance.go
│ │ ├── delete_resourceset_test.go
│ │ ├── delete_resourceset.go
│ │ ├── delete.go
│ │ ├── distro_decrypt_manifests_test.go
│ │ ├── distro_decrypt_manifests.go
│ │ ├── distro_decrypt_token_test.go
│ │ ├── distro_decrypt_token.go
│ │ ├── distro_decrypt.go
│ │ ├── distro_encrypt_manifests_test.go
│ │ ├── distro_encrypt_manifests.go
│ │ ├── distro_encrypt_token_test.go
│ │ ├── distro_encrypt_token.go
│ │ ├── distro_encrypt.go
│ │ ├── distro_keygen_enc_test.go
│ │ ├── distro_keygen_enc.go
│ │ ├── distro_keygen_sig_test.go
│ │ ├── distro_keygen_sig.go
│ │ ├── distro_keygen.go
│ │ ├── distro_revoke_license_key_test.go
│ │ ├── distro_revoke_license_key.go
│ │ ├── distro_revoke.go
│ │ ├── distro_sign_artifacts_test.go
│ │ ├── distro_sign_artifacts.go
│ │ ├── distro_sign_license_key_test.go
│ │ ├── distro_sign_license_key.go
│ │ ├── distro_sign_manifests_test.go
│ │ ├── distro_sign_manifests.go
│ │ ├── distro_sign.go
│ │ ├── distro_verify_artifacts_test.go
│ │ ├── distro_verify_artifacts.go
│ │ ├── distro_verify_license_key_test.go
│ │ ├── distro_verify_license_key.go
│ │ ├── distro_verify_manifests_test.go
│ │ ├── distro_verify_manifests.go
│ │ ├── distro_verify.go
│ │ ├── distro.go
│ │ ├── Dockerfile
│ │ ├── export_report_test.go
│ │ ├── export_report.go
│ │ ├── export_resource_test.go
│ │ ├── export_resource.go
│ │ ├── export.go
│ │ ├── get_inputprovider_test.go
│ │ ├── get_inputprovider.go
│ │ ├── get_instance.go
│ │ ├── get_resources.go
│ │ ├── get_resourceset_test.go
│ │ ├── get_resourceset.go
│ │ ├── get.go
│ │ ├── install.go
│ │ ├── main.go
│ │ ├── README.md
│ │ ├── reconcile_inputprovider.go
│ │ ├── reconcile_instance.go
│ │ ├── reconcile_resource.go
│ │ ├── reconcile_resources.go
│ │ ├── reconcile_resourceset.go
│ │ ├── reconcile.go
│ │ ├── resume_inputprovider.go
│ │ ├── resume_instance.go
│ │ ├── resume_resource.go
│ │ ├── resume_resourceset.go
│ │ ├── resume.go
│ │ ├── stats.go
│ │ ├── suite_test.go
│ │ ├── suspend_inputprovider.go
│ │ ├── suspend_instance.go
│ │ ├── suspend_resource.go
│ │ ├── suspend_resourceset.go
│ │ ├── suspend.go
│ │ ├── testdata
│ │ │ └── build_resourceset
│ │ │ ├── golden-labeled.yaml
│ │ │ ├── golden-named.yaml
│ │ │ ├── golden-permuted.yaml
│ │ │ ├── golden.yaml
│ │ │ ├── inputs.yaml
│ │ │ ├── rset-standalone.yaml
│ │ │ ├── rset-with-rsip-labeled.yaml
│ │ │ ├── rset-with-rsip-named.yaml
│ │ │ ├── rset-with-rsip-permuted.yaml
│ │ │ ├── rset-with-rsip.yaml
│ │ │ ├── rsip-labeled.yaml
│ │ │ ├── rsip-named.yaml
│ │ │ └── rsip.yaml
│ │ ├── trace_test.go
│ │ ├── trace_types.go
│ │ ├── trace.go
│ │ ├── tree_helmrelease.go
│ │ ├── tree_kustomization.go
│ │ ├── tree_resourceset_test.go
│ │ ├── tree_resourceset.go
│ │ ├── tree.go
│ │ ├── uninstall.go
│ │ ├── version_test.go
│ │ ├── version.go
│ │ ├── wait_inputprovider_test.go
│ │ ├── wait_inputprovider.go
│ │ ├── wait_instance_test.go
│ │ ├── wait_instance.go
│ │ ├── wait_resourceset_test.go
│ │ ├── wait_resourceset.go
│ │ └── wait.go
│ ├── mcp
│ │ ├── Dockerfile
│ │ ├── k8s
│ │ │ ├── actions_test.go
│ │ │ ├── actions.go
│ │ │ ├── client_test.go
│ │ │ ├── client.go
│ │ │ ├── config.go
│ │ │ ├── events_test.go
│ │ │ ├── events.go
│ │ │ ├── export_test.go
│ │ │ ├── export.go
│ │ │ ├── helm.go
│ │ │ ├── logs.go
│ │ │ ├── metrics.go
│ │ │ └── suite_test.go
│ │ ├── main.go
│ │ ├── prompter
│ │ │ ├── debug_helmrelease_test.go
│ │ │ ├── debug_helmrelease.go
│ │ │ ├── debug_kustomization_test.go
│ │ │ ├── debug_kustomization.go
│ │ │ ├── index.go
│ │ │ └── manager.go
│ │ ├── README.md
│ │ └── toolbox
│ │ ├── apply_manifest_test.go
│ │ ├── apply_manifest.go
│ │ ├── delete_resource_test.go
│ │ ├── delete_resource.go
│ │ ├── get_apis_test.go
│ │ ├── get_apis.go
│ │ ├── get_contexts_test.go
│ │ ├── get_contexts.go
│ │ ├── get_instance_test.go
│ │ ├── get_instance.go
│ │ ├── get_logs_test.go
│ │ ├── get_logs.go
│ │ ├── get_metrics_test.go
│ │ ├── get_metrics.go
│ │ ├── get_resource_test.go
│ │ ├── get_resource.go
│ │ ├── helpers.go
│ │ ├── indexer
│ │ │ └── main.go
│ │ ├── install_instance_test.go
│ │ ├── install_instance.go
│ │ ├── library
│ │ │ ├── bm25_test.go
│ │ │ ├── bm25.go
│ │ │ ├── index.go
│ │ │ ├── index.gob
│ │ │ ├── library.go
│ │ │ ├── search_test.go
│ │ │ ├── search.go
│ │ │ ├── tokenizer_test.go
│ │ │ └── tokenizer.go
│ │ ├── manager_test.go
│ │ ├── manager.go
│ │ ├── reconcile_helmrelease_test.go
│ │ ├── reconcile_helmrelease.go
│ │ ├── reconcile_kustomization_test.go
│ │ ├── reconcile_kustomization.go
│ │ ├── reconcile_resourceset_test.go
│ │ ├── reconcile_resourceset.go
│ │ ├── reconcile_source_test.go
│ │ ├── reconcile_source.go
│ │ ├── resume_reconciliation_test.go
│ │ ├── resume_reconciliation.go
│ │ ├── scopes_test.go
│ │ ├── scopes.go
│ │ ├── search_flux_docs_test.go
│ │ ├── search_flux_docs.go
│ │ ├── set_context_test.go
│ │ ├── set_context.go
│ │ ├── suspend_reconciliation_test.go
│ │ ├── suspend_reconciliation.go
│ │ └── testdata
│ │ ├── kubeconfig_golden.yaml
│ │ └── kubeconfig.yaml
│ └── operator
│ └── main.go
├── config
│ ├── crd
│ │ ├── bases
│ │ │ ├── fluxcd.controlplane.io_fluxinstances.yaml
│ │ │ ├── fluxcd.controlplane.io_fluxreports.yaml
│ │ │ ├── fluxcd.controlplane.io_resourcesetinputproviders.yaml
│ │ │ └── fluxcd.controlplane.io_resourcesets.yaml
│ │ ├── kustomization.yaml
│ │ └── kustomizeconfig.yaml
│ ├── data
│ │ ├── flux
│ │ │ ├── v2.2.3
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.3.0
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.4.0
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.5.0
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.5.1
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.6.0
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.6.1
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.6.2
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.6.3
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.6.4
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.7.0
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ ├── source-controller.yaml
│ │ │ │ └── source-watcher.yaml
│ │ │ ├── v2.7.1
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ ├── source-controller.yaml
│ │ │ │ └── source-watcher.yaml
│ │ │ ├── v2.7.2
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ ├── source-controller.yaml
│ │ │ │ └── source-watcher.yaml
│ │ │ ├── v2.7.3
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ ├── source-controller.yaml
│ │ │ │ └── source-watcher.yaml
│ │ │ ├── v2.7.4
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ ├── source-controller.yaml
│ │ │ │ └── source-watcher.yaml
│ │ │ └── v2.7.5
│ │ │ ├── helm-controller.yaml
│ │ │ ├── image-automation-controller.yaml
│ │ │ ├── image-reflector-controller.yaml
│ │ │ ├── kustomize-controller.yaml
│ │ │ ├── notification-controller.yaml
│ │ │ ├── policies.yaml
│ │ │ ├── rbac.yaml
│ │ │ ├── source-controller.yaml
│ │ │ └── source-watcher.yaml
│ │ ├── flux-images
│ │ │ ├── v2.2.0
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.2.1
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.2.2
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.2.3
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.3.0
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.4.0
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.5.0
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.5.1
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless-fips.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.6.0
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.6.1
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.6.2
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.6.3
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.6.4
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless-fips.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.7.0
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.7.1
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.7.2
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.7.3
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.7.4
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── v2.7.5
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless-fips.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ └── VERSION
│ │ └── flux-vex
│ │ ├── v2.2.json
│ │ ├── v2.3.json
│ │ ├── v2.4.json
│ │ ├── v2.5.json
│ │ ├── v2.6.json
│ │ └── v2.7.json
│ ├── default
│ │ ├── kustomization.yaml
│ │ ├── namespace.yaml
│ │ └── rbac.yaml
│ ├── manager
│ │ ├── account.yaml
│ │ ├── deployment.yaml
│ │ ├── kustomization.yaml
│ │ └── service.yaml
│ ├── mcp
│ │ ├── deployment.yaml
│ │ ├── kustomization.yaml
│ │ └── service.yaml
│ ├── monitoring
│ │ ├── dashboards
│ │ │ ├── flux-k8s-api-performance.json
│ │ │ └── flux-performance.json
│ │ ├── flux-controllers.yaml
│ │ ├── flux-operator.yaml
│ │ └── kustomization.yaml
│ ├── olm
│ │ ├── build
│ │ │ └── Dockerfile
│ │ ├── bundle
│ │ │ ├── manifests
│ │ │ │ ├── flux-operator.clusterserviceversion.yaml
│ │ │ │ ├── flux-operator.service.yaml
│ │ │ │ ├── fluxinstances.fluxcd.controlplane.io.crd.yaml
│ │ │ │ ├── fluxreports.fluxcd.controlplane.io.crd.yaml
│ │ │ │ ├── resourcesetinputproviders.fluxcd.controlplane.io.crd.yaml
│ │ │ │ └── resourcesets.fluxcd.controlplane.io.crd.yaml
│ │ │ ├── metadata
│ │ │ │ └── annotations.yaml
│ │ │ └── tests
│ │ │ └── scorecard
│ │ │ └── config.yaml
│ │ ├── ci.yaml
│ │ └── test
│ │ ├── bundle.Dockerfile
│ │ ├── olm.yaml
│ │ └── opm.Dockerfile
│ ├── rbac
│ │ ├── fluxinstance_editor_role.yaml
│ │ ├── fluxinstance_viewer_role.yaml
│ │ ├── fluxreport_editor_role.yaml
│ │ ├── fluxreport_viewer_role.yaml
│ │ ├── kustomization.yaml
│ │ ├── leader_election_role_binding.yaml
│ │ ├── leader_election_role.yaml
│ │ ├── resourceset_editor_role.yaml
│ │ ├── resourceset_viewer_role.yaml
│ │ ├── role_binding.yaml
│ │ ├── role.yaml
│ │ └── service_account.yaml
│ ├── samples
│ │ ├── fluxcd_v1_fluxinstance.yaml
│ │ ├── fluxcd_v1_fluxreport.yaml
│ │ ├── fluxcd_v1_resourceset.yaml
│ │ ├── fluxcd_v1_resourcesetinputprovider.yaml
│ │ └── kustomization.yaml
│ └── terraform
│ ├── main.tf
│ ├── outputs.tf
│ ├── providers.tf
│ ├── README.md
│ ├── values
│ │ └── components.yaml
│ ├── variables.tf
│ └── versions.tf
├── CONTRIBUTING.md
├── Dockerfile
├── docs
│ ├── api
│ │ └── v1
│ │ ├── fluxinstance.md
│ │ ├── fluxreport.md
│ │ ├── resourceset.md
│ │ └── resourcesetinputprovider.md
│ ├── dev
│ │ └── README.md
│ ├── guides
│ │ ├── instance
│ │ │ ├── instance-controllers.md
│ │ │ ├── instance-customization.md
│ │ │ ├── instance-monitoring.md
│ │ │ ├── instance-sharding.md
│ │ │ └── instance-sync.md
│ │ ├── operator
│ │ │ ├── operator-install.md
│ │ │ └── operator-migration.md
│ │ └── resourcesets
│ │ ├── rset-app-definition.md
│ │ ├── rset-github-pull-requests.md
│ │ ├── rset-gitlab-environments.md
│ │ ├── rset-gitlab-merge-requests.md
│ │ ├── rset-image-automation.md
│ │ ├── rset-introduction.md
│ │ └── rset-time-based-delivery.md
│ ├── lkm
│ │ └── README.md
│ ├── logo
│ │ ├── flux-operator-banner.png
│ │ ├── flux-operator-banner.svg
│ │ ├── flux-operator-icon.png
│ │ ├── flux-operator-icon.svg
│ │ ├── flux-operator-logo.png
│ │ └── flux-operator-logo.svg
│ ├── mcp
│ │ ├── instructions.md
│ │ ├── mcp-config.md
│ │ ├── mcp-install.md
│ │ ├── mcp-prompting.md
│ │ ├── prompts.md
│ │ └── tools.md
│ └── web
│ ├── web-config-api.md
│ ├── web-ingress.md
│ ├── web-sso-dex.md
│ ├── web-sso-keycloak.md
│ ├── web-sso-openshift.md
│ ├── web-standalone.md
│ └── web-user-management.md
├── go.mod
├── go.sum
├── hack
│ ├── boilerplate.go.txt
│ ├── build-dist-manifests.sh
│ ├── build-olm-images.sh
│ ├── build-olm-manifests.sh
│ ├── install-operator-sdk.sh
│ ├── prep-release.sh
│ ├── vendor-flux-manifests.sh
│ └── web-ui-load-test.sh
├── internal
│ ├── builder
│ │ ├── build_test.go
│ │ ├── build.go
│ │ ├── components.go
│ │ ├── digest.go
│ │ ├── images_test.go
│ │ ├── images.go
│ │ ├── options.go
│ │ ├── preflight_test.go
│ │ ├── preflight.go
│ │ ├── profiles.go
│ │ ├── pull.go
│ │ ├── resourceset_test.go
│ │ ├── resourceset.go
│ │ ├── result.go
│ │ ├── semver_test.go
│ │ ├── semver.go
│ │ ├── templates.go
│ │ ├── testdata
│ │ │ ├── flux
│ │ │ │ ├── v2.2.0
│ │ │ │ │ └── .gitkeep
│ │ │ │ ├── v2.2.1
│ │ │ │ │ └── .gitkeep
│ │ │ │ └── v2.3.0
│ │ │ │ └── .gitkeep
│ │ │ ├── flux-images
│ │ │ │ └── v2.3.0
│ │ │ │ ├── enterprise-alpine.yaml
│ │ │ │ ├── enterprise-distroless.yaml
│ │ │ │ └── upstream-alpine.yaml
│ │ │ ├── resourceset
│ │ │ │ ├── dedup.golden.yaml
│ │ │ │ ├── dedup.yaml
│ │ │ │ ├── empty.yaml
│ │ │ │ ├── exclude.golden.yaml
│ │ │ │ ├── exclude.yaml
│ │ │ │ ├── invalid-output.yaml
│ │ │ │ ├── missing-inputs.yaml
│ │ │ │ ├── multi-doc-template.golden.yaml
│ │ │ │ ├── multi-doc-template.yaml
│ │ │ │ ├── nestedinputs.golden.yaml
│ │ │ │ ├── nestedinputs.yaml
│ │ │ │ ├── noinputs.golden.yaml
│ │ │ │ ├── noinputs.yaml
│ │ │ │ ├── slugify.golden.yaml
│ │ │ │ └── slugify.yaml
│ │ │ ├── v2.3.0
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.3.0-golden
│ │ │ │ ├── default.kustomization.yaml
│ │ │ │ ├── patches.kustomization.yaml
│ │ │ │ ├── profiles.kustomization.yaml
│ │ │ │ ├── sharding.kustomization.yaml
│ │ │ │ ├── storage.kustomization.yaml
│ │ │ │ └── sync.kustomization.yaml
│ │ │ ├── v2.6.0
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ └── source-controller.yaml
│ │ │ ├── v2.6.0-golden
│ │ │ │ ├── shard1.kustomization.yaml
│ │ │ │ ├── shard2.kustomization.yaml
│ │ │ │ ├── sharding.kustomization.yaml
│ │ │ │ ├── size.large.kustomization.yaml
│ │ │ │ ├── size.medium.kustomization.yaml
│ │ │ │ └── size.small.kustomization.yaml
│ │ │ ├── v2.7.0
│ │ │ │ ├── helm-controller.yaml
│ │ │ │ ├── image-automation-controller.yaml
│ │ │ │ ├── image-reflector-controller.yaml
│ │ │ │ ├── kustomize-controller.yaml
│ │ │ │ ├── notification-controller.yaml
│ │ │ │ ├── policies.yaml
│ │ │ │ ├── rbac.yaml
│ │ │ │ ├── source-controller.yaml
│ │ │ │ └── source-watcher.yaml
│ │ │ └── v2.7.0-golden
│ │ │ └── source-watcher.kustomization.yaml
│ │ └── workload_identity.go
│ ├── controller
│ │ ├── common.go
│ │ ├── entitlement_controller_test.go
│ │ ├── entitlement_controller.go
│ │ ├── fluxinstance_artifact_controller_test.go
│ │ ├── fluxinstance_artifact_controller.go
│ │ ├── fluxinstance_artifact_manager_test.go
│ │ ├── fluxinstance_artifact_manager.go
│ │ ├── fluxinstance_controller_test.go
│ │ ├── fluxinstance_controller.go
│ │ ├── fluxinstance_manager.go
│ │ ├── fluxinstance_migrator.go
│ │ ├── fluxinstance_uninstaller.go
│ │ ├── fluxreport_controller_test.go
│ │ ├── fluxreport_controller.go
│ │ ├── resourceset_controller_test.go
│ │ ├── resourceset_controller.go
│ │ ├── resourceset_manager_test.go
│ │ ├── resourceset_manager.go
│ │ ├── resourcesetinputprovider_controller_git_test.go
│ │ ├── resourcesetinputprovider_controller_oci_test.go
│ │ ├── resourcesetinputprovider_controller_test.go
│ │ ├── resourcesetinputprovider_controller.go
│ │ ├── resourcesetinputprovider_manager.go
│ │ ├── suite_test.go
│ │ └── testdata
│ │ └── rsa-private-key.pem
│ ├── entitlement
│ │ ├── aws.go
│ │ ├── client_test.go
│ │ ├── client.go
│ │ ├── default_test.go
│ │ └── default.go
│ ├── filtering
│ │ ├── filters_test.go
│ │ └── filters.go
│ ├── gitprovider
│ │ ├── azuredevops_test.go
│ │ ├── azuredevops.go
│ │ ├── github_test.go
│ │ ├── github.go
│ │ ├── gitlab_test.go
│ │ ├── gitlab.go
│ │ ├── interface.go
│ │ ├── options.go
│ │ ├── result_test.go
│ │ └── result.go
│ ├── inputs
│ │ ├── combine_test.go
│ │ ├── combine.go
│ │ ├── flattener.go
│ │ ├── id.go
│ │ ├── json_test.go
│ │ ├── json.go
│ │ ├── keys_test.go
│ │ ├── keys.go
│ │ ├── permuter_test.go
│ │ ├── permuter.go
│ │ └── provider.go
│ ├── install
│ │ ├── autoupdate.go
│ │ ├── client.go
│ │ ├── credentials.go
│ │ ├── deploy.go
│ │ ├── download.go
│ │ ├── events.go
│ │ ├── installer.go
│ │ ├── options.go
│ │ └── uninstall.go
│ ├── inventory
│ │ ├── inventory_test.go
│ │ ├── inventory.go
│ │ ├── reader_test.go
│ │ ├── reader.go
│ │ └── testdata
│ │ ├── inventory1.yaml
│ │ └── inventory2.yaml
│ ├── lkm
│ │ ├── artifacts_attestation_test.go
│ │ ├── artifacts_attestation.go
│ │ ├── attestation_test.go
│ │ ├── attestation.go
│ │ ├── doc.go
│ │ ├── errors.go
│ │ ├── fetch_test.go
│ │ ├── fetch.go
│ │ ├── jwe_test.go
│ │ ├── jwe.go
│ │ ├── jwt_test.go
│ │ ├── jwt.go
│ │ ├── keygen_test.go
│ │ ├── keygen.go
│ │ ├── keyset_test.go
│ │ ├── keyset.go
│ │ ├── license_test.go
│ │ ├── license.go
│ │ ├── licensekey.go
│ │ ├── manifests_attestation_test.go
│ │ ├── manifests_attestation.go
│ │ ├── revocation_test.go
│ │ └── revocation.go
│ ├── notifier
│ │ └── notifier.go
│ ├── reporter
│ │ ├── cluster.go
│ │ ├── components.go
│ │ ├── crds.go
│ │ ├── distribution.go
│ │ ├── metrics_test.go
│ │ ├── metrics.go
│ │ ├── reconcilers.go
│ │ ├── reporter.go
│ │ └── sync.go
│ ├── schedule
│ │ ├── scheduler_test.go
│ │ └── scheduler.go
│ ├── tests
│ │ ├── fluxinstance
│ │ │ ├── health_check_test.go
│ │ │ └── suite_test.go
│ │ └── resourceset
│ │ ├── health_check_test.go
│ │ └── suite_test.go
│ ├── testutils
│ │ ├── log.go
│ │ └── time.go
│ └── web
│ ├── action_test.go
│ ├── action.go
│ ├── auth
│ │ ├── claims_test.go
│ │ ├── claims.go
│ │ ├── cookies_test.go
│ │ ├── cookies.go
│ │ ├── errors_test.go
│ │ ├── errors.go
│ │ ├── middlewares_test.go
│ │ ├── middlewares.go
│ │ ├── oauth2_test.go
│ │ ├── oauth2.go
│ │ └── oidc.go
│ ├── config
│ │ ├── authentication_types_test.go
│ │ ├── authentication_types.go
│ │ ├── config_types_test.go
│ │ ├── config_types.go
│ │ ├── groupversion_info.go
│ │ ├── loader_test.go
│ │ ├── loader.go
│ │ ├── user_actions_types_test.go
│ │ ├── user_actions_types.go
│ │ └── watcher.go
│ ├── events_test.go
│ ├── events.go
│ ├── favorites_test.go
│ ├── favorites.go
│ ├── fs.go
│ ├── handler.go
│ ├── inventory.go
│ ├── kubeclient
│ │ ├── client_test.go
│ │ ├── client.go
│ │ └── suite_test.go
│ ├── middlewares_test.go
│ ├── middlewares.go
│ ├── report_test.go
│ ├── report.go
│ ├── resource_test.go
│ ├── resource.go
│ ├── resources_test.go
│ ├── resources.go
│ ├── search_test.go
│ ├── search.go
│ ├── server_test.go
│ ├── server.go
│ ├── source.go
│ ├── suite_test.go
│ ├── user
│ │ ├── user_test.go
│ │ └── user.go
│ ├── workload_test.go
│ ├── workload.go
│ ├── workloads_test.go
│ └── workloads.go
├── LICENSE
├── Makefile
├── PROJECT
├── README.md
├── SECURITY.md
├── test
│ ├── e2e
│ │ ├── e2e_suite_test.go
│ │ ├── e2e_test.go
│ │ ├── instance_test.go
│ │ └── utils.go
│ └── olm
│ ├── e2e_suite_test.go
│ ├── e2e_test.go
│ ├── instance_test.go
│ └── scorecard_test.go
└── web
├── .gitignore
├── embed.go
├── eslint.config.js
├── index.html
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│ ├── favicon.svg
│ └── fonts
│ └── inter.woff2
├── README.md
├── src
│ ├── app.jsx
│ ├── app.test.jsx
│ ├── components
│ │ ├── auth
│ │ │ ├── LoginPage.jsx
│ │ │ └── LoginPage.test.jsx
│ │ ├── dashboards
│ │ │ ├── cluster
│ │ │ │ ├── ClusterPage.jsx
│ │ │ │ ├── ClusterPage.test.jsx
│ │ │ │ ├── ControllersPanel.jsx
│ │ │ │ ├── ControllersPanel.test.jsx
│ │ │ │ ├── InfoPanel.jsx
│ │ │ │ ├── InfoPanel.test.jsx
│ │ │ │ ├── OverallStatusPanel.jsx
│ │ │ │ ├── OverallStatusPanel.test.jsx
│ │ │ │ ├── ReconcilersPanel.jsx
│ │ │ │ ├── ReconcilersPanel.test.jsx
│ │ │ │ ├── SyncPanel.jsx
│ │ │ │ └── SyncPanel.test.jsx
│ │ │ ├── common
│ │ │ │ ├── panel.jsx
│ │ │ │ ├── panel.test.jsx
│ │ │ │ ├── yaml.jsx
│ │ │ │ └── yaml.test.jsx
│ │ │ └── resource
│ │ │ ├── ActionBar.jsx
│ │ │ ├── ActionBar.test.jsx
│ │ │ ├── ArtifactPanel.jsx
│ │ │ ├── ArtifactPanel.test.jsx
│ │ │ ├── ExportedInputsPanel.jsx
│ │ │ ├── ExportedInputsPanel.test.jsx
│ │ │ ├── GraphTabContent.jsx
│ │ │ ├── GraphTabContent.test.jsx
│ │ │ ├── HistoryTimeline.jsx
│ │ │ ├── HistoryTimeline.test.jsx
│ │ │ ├── InputsPanel.jsx
│ │ │ ├── InputsPanel.test.jsx
│ │ │ ├── InventoryPanel.jsx
│ │ │ ├── InventoryPanel.test.jsx
│ │ │ ├── ReconcilerPanel.jsx
│ │ │ ├── ReconcilerPanel.test.jsx
│ │ │ ├── ResourcePage.jsx
│ │ │ ├── ResourcePage.test.jsx
│ │ │ ├── SourcePanel.jsx
│ │ │ ├── SourcePanel.test.jsx
│ │ │ ├── WorkloadsTabContent.jsx
│ │ │ └── WorkloadsTabContent.test.jsx
│ │ ├── favorites
│ │ │ ├── FavoriteCard.jsx
│ │ │ ├── FavoriteCard.test.jsx
│ │ │ ├── FavoritesHeader.jsx
│ │ │ ├── FavoritesHeader.test.jsx
│ │ │ ├── FavoritesPage.jsx
│ │ │ ├── FavoritesPage.test.jsx
│ │ │ ├── FavoritesSearch.jsx
│ │ │ └── FavoritesSearch.test.jsx
│ │ ├── layout
│ │ │ ├── ConnectionStatus.jsx
│ │ │ ├── ConnectionStatus.test.jsx
│ │ │ ├── Footer.jsx
│ │ │ ├── Footer.test.jsx
│ │ │ ├── Header.jsx
│ │ │ ├── Header.test.jsx
│ │ │ ├── Icons.jsx
│ │ │ ├── NotFoundPage.jsx
│ │ │ ├── NotFoundPage.test.jsx
│ │ │ ├── ThemeToggle.jsx
│ │ │ ├── ThemeToggle.test.jsx
│ │ │ ├── UserMenu.jsx
│ │ │ └── UserMenu.test.jsx
│ │ └── search
│ │ ├── EventList.jsx
│ │ ├── EventList.test.jsx
│ │ ├── FilterForm.jsx
│ │ ├── FilterForm.test.jsx
│ │ ├── QuickSearch.jsx
│ │ ├── QuickSearch.test.jsx
│ │ ├── ResourceDetailsView.jsx
│ │ ├── ResourceDetailsView.test.jsx
│ │ ├── ResourceList.jsx
│ │ ├── ResourceList.test.jsx
│ │ ├── StatusChart.jsx
│ │ └── StatusChart.test.jsx
│ ├── index.css
│ ├── main.jsx
│ ├── mock
│ │ ├── action.js
│ │ ├── events.js
│ │ ├── events.test.js
│ │ ├── report.js
│ │ ├── resource.js
│ │ ├── resources.js
│ │ ├── resources.test.js
│ │ ├── workload.js
│ │ └── workload.test.js
│ └── utils
│ ├── constants.js
│ ├── cookies.js
│ ├── cookies.test.js
│ ├── favorites.js
│ ├── favorites.test.js
│ ├── fetch.js
│ ├── fetch.test.js
│ ├── hash.js
│ ├── hash.test.js
│ ├── meta.js
│ ├── meta.test.js
│ ├── navHistory.js
│ ├── navHistory.test.js
│ ├── routing.js
│ ├── routing.test.js
│ ├── scroll.js
│ ├── scroll.test.js
│ ├── status.js
│ ├── status.test.js
│ ├── theme.js
│ ├── theme.test.js
│ ├── time.js
│ ├── time.test.js
│ ├── version.js
│ └── version.test.js
├── tailwind.config.js
├── vite.config.js
└── vitest.setup.js
```
# Files
--------------------------------------------------------------------------------
/internal/builder/testdata/flux/v2.2.0/.gitkeep:
--------------------------------------------------------------------------------
```
1 |
```
--------------------------------------------------------------------------------
/internal/builder/testdata/flux/v2.2.1/.gitkeep:
--------------------------------------------------------------------------------
```
1 |
```
--------------------------------------------------------------------------------
/internal/builder/testdata/flux/v2.3.0/.gitkeep:
--------------------------------------------------------------------------------
```
1 |
```
--------------------------------------------------------------------------------
/web/.gitignore:
--------------------------------------------------------------------------------
```
1 | node_modules
2 | dist
3 | coverage
4 | .DS_Store
5 | *.log
6 | .vite
7 |
```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | # If you prefer the allow list template instead of the deny list, see community template:
2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3 | #
4 | # Binaries for programs and plugins
5 | *.exe
6 | *.exe~
7 | *.dll
8 | *.so
9 | *.dylib
10 |
11 | # Test binary, built with `go test -c`
12 | *.test
13 |
14 | # Output of the go coverage tool, specifically when used with LiteIDE
15 | *.out
16 |
17 | # Dependency directories (remove the comment below to include it)
18 | # vendor/
19 |
20 | # Go workspace file
21 | go.work
22 | bin/
23 | disto/
24 |
25 | # Terraform
26 | **/.terraform
27 | *.tfstate
28 | *.tfstate.*
29 | .terraform.lock.hcl
30 | .terraformrc
31 | /internal/builder/testdata/output/
32 | /cmd/cli/testdata/distro/
33 |
34 | # Status Page config.
35 | web-config.yaml
36 |
```
--------------------------------------------------------------------------------
/.golangci.yml:
--------------------------------------------------------------------------------
```yaml
1 | version: "2"
2 | run:
3 | allow-parallel-runners: true
4 | linters:
5 | default: none
6 | enable:
7 | - copyloopvar
8 | - dupl
9 | - errcheck
10 | - ginkgolinter
11 | - goconst
12 | - gocyclo
13 | - govet
14 | - ineffassign
15 | - lll
16 | - misspell
17 | - nakedret
18 | - prealloc
19 | - revive
20 | - staticcheck
21 | - unconvert
22 | - unparam
23 | - unused
24 | settings:
25 | gocyclo:
26 | min-complexity: 35
27 | revive:
28 | rules:
29 | - name: comment-spacings
30 | - name: import-shadowing
31 | - name: use-any
32 | - name: unreachable-code
33 | - name: struct-tag
34 | arguments:
35 | - "json,inline"
36 | - name: file-header
37 | arguments:
38 | - "SPDX-License-Identifier: AGPL-3.0"
39 | staticcheck:
40 | checks:
41 | - all
42 | # Incorrect or missing package comment.
43 | # https://staticcheck.dev/docs/checks/#ST1000
44 | - -ST1000
45 | # Dot imports are discouraged.
46 | # https://staticcheck.dev/docs/checks/#ST1001
47 | - -ST1001
48 | # Use consistent method receiver names.
49 | # https://staticcheck.dev/docs/checks/#ST1016
50 | - -ST1016
51 | # Omit embedded fields from selector expression.
52 | # https://staticcheck.dev/docs/checks/#QF1008
53 | - -QF1008
54 | exclusions:
55 | generated: lax
56 | rules:
57 | - linters:
58 | - errcheck
59 | source: "^\\s*defer\\s+"
60 | - linters:
61 | - staticcheck
62 | source: "r\\.Requeue"
63 | - linters:
64 | - lll
65 | path: api/*
66 | - linters:
67 | - dupl
68 | - lll
69 | - goconst
70 | path: cmd/*
71 | - linters:
72 | - dupl
73 | - lll
74 | path: internal/*
75 | - linters:
76 | - dupl
77 | - lll
78 | path: test/*
79 | - linters:
80 | - goconst
81 | path: ".*_test\\.go$"
82 | paths:
83 | - third_party$
84 | - builtin$
85 | - examples$
86 | formatters:
87 | enable:
88 | - gofmt
89 | - goimports
90 | exclusions:
91 | generated: lax
92 | paths:
93 | - third_party$
94 | - builtin$
95 | - examples$
96 |
```
--------------------------------------------------------------------------------
/.goreleaser.yml:
--------------------------------------------------------------------------------
```yaml
1 | version: 2
2 |
3 | # xref: https://goreleaser.com/errors/multiple-tokens/
4 | force_token: github
5 |
6 | # xref: https://goreleaser.com/customization/project/
7 | project_name: flux-operator
8 |
9 | # xref: https://goreleaser.com/customization/hooks/
10 | before:
11 | hooks:
12 | - go mod download
13 |
14 | # xref: https://goreleaser.com/customization/env/
15 | env:
16 | - CGO_ENABLED=0
17 |
18 | # xref: https://goreleaser.com/customization/build/
19 | builds:
20 | - <<: &cmd_defaults
21 | binary: flux-operator
22 | main: ./cmd/cli
23 | ldflags:
24 | - -s -w -X main.VERSION={{ .Version }}
25 | id: cli
26 | goos:
27 | - linux
28 | - darwin
29 | goarch:
30 | - amd64
31 | - arm64
32 | - <<: *cmd_defaults
33 | id: cli-windows
34 | goos:
35 | - windows
36 | goarch:
37 | - amd64
38 | - arm64
39 | - <<: &mcp_defaults
40 | binary: flux-operator-mcp
41 | main: ./cmd/mcp
42 | ldflags:
43 | - -s -w -X main.VERSION={{ .Version }}
44 | id: mcp
45 | goos:
46 | - linux
47 | - darwin
48 | goarch:
49 | - amd64
50 | - arm64
51 | - <<: *mcp_defaults
52 | id: mcp-windows
53 | goos:
54 | - windows
55 | goarch:
56 | - amd64
57 | - arm64
58 |
59 | # xref: https://goreleaser.com/customization/archive/
60 | archives:
61 | - name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
62 | id: unix-cli
63 | ids:
64 | - cli
65 | formats: ['tar.gz']
66 | files:
67 | - LICENSE
68 | - name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
69 | id: unix-mcp
70 | ids:
71 | - mcp
72 | formats: ['tar.gz']
73 | files:
74 | - LICENSE
75 | - name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
76 | id: windows-cli
77 | ids:
78 | - cli-windows
79 | formats: ['zip']
80 | files:
81 | - LICENSE
82 | - name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
83 | id: windows-mcp
84 | ids:
85 | - mcp-windows
86 | formats: ['zip']
87 | files:
88 | - LICENSE
89 |
90 | # xref: https://goreleaser.com/customization/checksum/
91 | checksum:
92 | extra_files:
93 | - glob: ./bin/release/install.yaml
94 | - glob: ./bin/release/crd-schemas.tar.gz
95 |
96 | # xref: https://goreleaser.com/customization/source/
97 | source:
98 | enabled: true
99 | name_template: '{{ .ProjectName }}_{{ .Version }}_source_code'
100 |
101 | # xref: https://goreleaser.com/customization/sbom/
102 | sboms:
103 | - id: source
104 | artifacts: source
105 | documents:
106 | - "{{ .ProjectName }}_{{ .Version }}_sbom.spdx.json"
107 |
108 | # xref: https://goreleaser.com/customization/changelog/
109 | changelog:
110 | use: github-native
111 |
112 | # xref: https://goreleaser.com/customization/release/
113 | release:
114 | extra_files:
115 | - glob: ./bin/release/install.yaml
116 | - glob: ./bin/release/crd-schemas.tar.gz
117 |
```
--------------------------------------------------------------------------------
/actions/setup/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Setup Flux Operator CLI GitHub Action
2 |
3 | This GitHub Action can be used to install the Flux Operator CLI on GitHub runners for usage in workflows.
4 | All GitHub runners are supported, including Ubuntu, Windows, and macOS.
5 |
6 | ## Usage
7 |
8 | Example workflow for printing the latest version:
9 |
10 | ```yaml
11 | name: Check the latest version
12 |
13 | on:
14 | workflow_dispatch:
15 |
16 | jobs:
17 | check-latest-flux-operator-version:
18 | runs-on: ubuntu-latest
19 | steps:
20 | - name: Setup Flux Operator CLI
21 | uses: controlplaneio-fluxcd/flux-operator/actions/setup@main
22 | with:
23 | version: latest
24 | - name: Print Flux Operator Version
25 | run: flux-operator version --client
26 | ```
27 |
28 | ## Action Inputs
29 |
30 | | Name | Description | Default |
31 | |--------------------|----------------------------------|---------------------------|
32 | | `version` | Flux Operator version | The latest stable release |
33 | | `bindir` | Alternative location for the CLI | `$RUNNER_TOOL_CACHE` |
34 |
35 | ## Action Outputs
36 |
37 | | Name | Description |
38 | |--------------------|--------------------------------------------------------------|
39 | | `version` | The Flux Operator CLI version that was effectively installed |
40 |
```
--------------------------------------------------------------------------------
/config/terraform/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Install Flux with Terraform
2 |
3 | This example demonstrates how to deploy Flux on a Kubernetes cluster using Terraform
4 | and the `flux-operator` and `flux-instance` Helm charts.
5 |
6 | ## Usage
7 |
8 | Create a Kubernetes cluster using KinD:
9 |
10 | ```shell
11 | kind create cluster --name flux
12 | ```
13 |
14 | Install the Flux Operator and deploy the Flux instance on the cluster
15 | set as the default context in the `~/.kube/config` file:
16 |
17 | ```shell
18 | terraform apply \
19 | -var flux_version="2.x" \
20 | -var flux_registry="ghcr.io/fluxcd" \
21 | -var git_token="${GITHUB_TOKEN}" \
22 | -var git_url="https://github.com/fluxcd/flux2-kustomize-helm-example.git" \
23 | -var git_ref="refs/heads/main" \
24 | -var git_path="clusters/production"
25 | ```
26 |
27 | Note that the `GITHUB_TOKEN` env var must be set to a GitHub personal access token.
28 | The `git_token` variable is used to create a Kubernetes secret in the `flux-system` namespace for
29 | Flux to authenticate with the Git repository over HTTPS.
30 | If the repository is public, the token variable can be omitted.
31 |
32 | Alternatively, you can use a GitHub App to authenticate with a GitHub repository:
33 |
34 | ```shell
35 | export GITHUB_APP_PEM=`cat path/to/app.private-key.pem`
36 |
37 | terraform apply \
38 | -var flux_version="2.x" \
39 | -var flux_registry="ghcr.io/fluxcd" \
40 | -var github_app_id="1" \
41 | -var github_app_installation_id="2" \
42 | -var github_app_pem="$GITHUB_APP_PEM" \
43 | -var git_url="https://github.com/org/repo.git" \
44 | -var git_ref="refs/heads/main" \
45 | -var git_path="clusters/production"
46 | ```
47 |
48 | Verify the Flux components are running:
49 |
50 | ```shell
51 | kubectl -n flux-system get pods
52 | ```
53 |
54 | Verify the Flux instance is syncing the cluster state from the Git repository:
55 |
56 | ```shell
57 | kubectl -n flux-system get fluxreport/flux -o yaml
58 | ```
59 |
60 | The output should show the sync status:
61 |
62 | ```yaml
63 | apiVersion: fluxcd.controlplane.io/v1
64 | kind: FluxReport
65 | metadata:
66 | name: flux
67 | namespace: flux-system
68 | spec:
69 | # Distribution status omitted for brevity
70 | sync:
71 | id: kustomization/flux-system
72 | path: clusters/production
73 | ready: true
74 | source: https://github.com/fluxcd/flux2-kustomize-helm-example.git
75 | status: 'Applied revision: refs/heads/main@sha1:21486401be9bcdc37e6ebda48a3b68f8350777c9'
76 | ```
77 |
```
--------------------------------------------------------------------------------
/cmd/mcp/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Flux MCP Server
2 |
3 | The Flux MCP Server connects AI assistants directly to your Kubernetes clusters running Flux Operator,
4 | enabling GitOps analysis and troubleshooting through natural language.
5 |
6 | Using AI assistants with the Flux MCP Server, you can:
7 |
8 | - Debug GitOps pipelines end-to-end from Flux resources to application logs
9 | - Get intelligent root cause analysis for failed deployments
10 | - Compare Flux configurations and Kubernetes resources between clusters
11 | - Visualize Flux dependencies with diagrams generated from the cluster state
12 | - Instruct Flux to perform operations using conversational prompts
13 |
14 | ## Quickstart
15 |
16 | Install the Flux MCP Server using Homebrew:
17 |
18 | ```shell
19 | brew install controlplaneio-fluxcd/tap/flux-operator-mcp
20 | ```
21 |
22 | For other installation options, refer to the [installation guide](https://fluxcd.control-plane.io/mcp/install/).
23 |
24 | Add the following configuration to your AI assistant's MCP settings:
25 |
26 | ```json
27 | {
28 | "flux-operator-mcp":{
29 | "command":"flux-operator-mcp",
30 | "args":[
31 | "serve",
32 | "--read-only=false"
33 | ],
34 | "env":{
35 | "KUBECONFIG":"/path/to/.kube/config"
36 | }
37 | }
38 | }
39 | ```
40 |
41 | Replace `/path/to/.kube/config` with the absolute path to your kubeconfig file,
42 | you can find it with: `echo $HOME/.kube/config`.
43 |
44 | Copy the AI rules from
45 | [instructions.md](https://raw.githubusercontent.com/controlplaneio-fluxcd/distribution/refs/heads/main/docs/mcp/instructions.md)
46 | and place them into the appropriate file for your assistant.
47 |
48 | Restart the AI assistant app and test the MCP Server with the following prompts:
49 |
50 | - "Which cluster contexts are available in my kubeconfig?"
51 | - "What version of Flux is running in my current cluster?"
52 |
53 | For more information on how to use the MCP Server with Claude, Cursor, GitHub Copilot,
54 | and other assistants, please refer to the [documentation website](https://fluxcd.control-plane.io/mcp/).
55 |
56 | ## Documentation
57 |
58 | - [Flux MCP Server Overview](https://fluxcd.control-plane.io/mcp/)
59 | - [Installation Guide](https://fluxcd.control-plane.io/mcp/install/)
60 | - [Transport Modes and Security Configurations](https://fluxcd.control-plane.io/mcp/config/)
61 | - [Effective Prompting Guide](https://fluxcd.control-plane.io/mcp/prompt-engineering/)
62 | - [MCP Tools Reference](https://fluxcd.control-plane.io/mcp/tools/)
63 | - [MCP Prompts Reference](https://fluxcd.control-plane.io/mcp/prompts/)
64 |
65 | ## Contributing
66 |
67 | We welcome contributions to the Flux MCP Server project via GitHub pull requests.
68 | Please see the [CONTRIBUTING](https://github.com/controlplaneio-fluxcd/flux-operator/blob/main/CONTRIBUTING.md)
69 | guide for details on how to set up your development environment and start contributing to the project.
70 |
71 | ## License
72 |
73 | The MCP Server is open-source and part of the [Flux Operator](https://github.com/controlplaneio-fluxcd/flux-operator)
74 | project licensed under the [AGPL-3.0 license](https://github.com/controlplaneio-fluxcd/flux-operator/blob/main/LICENSE).
75 |
```
--------------------------------------------------------------------------------
/web/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Flux Status Page
2 |
3 | **Mission control dashboard for Kubernetes app delivery powered by Flux CD**
4 |
5 | The **Flux Status Page** is a lightweight, mobile-friendly web interface providing real-time
6 | visibility into your GitOps pipelines. Embedded directly within the **Flux Operator**,
7 | it requires no additional installation steps.
8 |
9 | Designed for DevOps engineers and platform teams, the Status Page offers direct insight
10 | into your Kubernetes clusters. It allows you to track app deployments, monitor
11 | controller readiness, and troubleshoot issues instantly, without needing to access the CLI.
12 |
13 | Built with security in mind, the interface is strictly read-only, ensuring it never
14 | interferes with Flux controllers or compromises cluster security.
15 | Together with the **Flux MCP Server**, it provides a comprehensive solution for
16 | on-call monitoring and Agentic AI incident response in production environments.
17 |
18 | ## Features
19 |
20 | - **Operational Insight:** View the real-time status and readiness of all workloads managed by Flux.
21 | - **Monitor Reconciliation:** Track the sync state of GitOps pipelines across your cluster and infrastructure.
22 | - **Pinpoint Issues:** Quickly identify and troubleshoot failures within your app delivery pipelines.
23 | - **Navigate Efficiently:** Use advanced search and filtering to find specific resources instantly.
24 | - **Deep Dive:** Access dedicated dashboards for ResourceSets, HelmReleases, Kustomizations and Flux sources.
25 | - **Favorites:** Mark important resources as favorites for quick access and at-a-glance status monitoring.
26 | - **Mobile-Optimized:** Stay informed with a fully responsive interface designed for on-the-go checks.
27 | - **Adaptive Theming:** Toggle between dark and light modes to suit your environment and preference.
28 |
29 | ## Accessing the Status Page
30 |
31 | The Flux Status Page is exposed on port `9080` by the `flux-operator` Kubernetes service.
32 |
33 | To access the Status Page, you can port-forward the service to your local machine:
34 |
35 | ```bash
36 | kubectl -n flux-system port-forward svc/flux-operator 9080:9080
37 | ```
38 |
39 | To expose the Status Page externally, you can create an Ingress or Gateway HTTPRoute resource
40 | pointing to the `flux-operator` service on port `9080`.
41 |
42 | > [!IMPORTANT]
43 | > Ensure you secure access to the Flux Status Page appropriately!
44 | > While the UI is read-only and doesn't show sensitive data from Kubernetes secrets,
45 | > it does expose details about your cluster's infrastructure and app deployments.
46 |
47 | ## Contributing
48 |
49 | We welcome contributions to the Flux Status Page project via GitHub pull requests.
50 | Please see the [CONTRIBUTING](https://github.com/controlplaneio-fluxcd/flux-operator/blob/main/CONTRIBUTING.md)
51 | guide for details on how to set up your development environment and start contributing to the project.
52 |
53 | ## License
54 |
55 | The Flux Status Page is open-source and part of the [Flux Operator](https://github.com/controlplaneio-fluxcd/flux-operator)
56 | project licensed under the [AGPL-3.0 license](https://github.com/controlplaneio-fluxcd/flux-operator/blob/main/LICENSE).
57 |
```
--------------------------------------------------------------------------------
/docs/lkm/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Flux Operator License Key Management (LKM)
2 |
3 | Flux Operator LKM provides cryptographic license key management and attestation functionality
4 | for the Flux distribution. LKM is built on industry-standard cryptographic primitives:
5 |
6 | - **Ed25519 digital signatures** compliant with FIPS 186-5 for license signing
7 | - **ECDH-ES key agreement** for secure key exchange
8 | - **SHA-256 hashing** for data integrity verification
9 | - **JSON Web Key (JWK)** format for interoperable key management
10 | - **JSON Web Token (JWT)** format following RFC 7519 for standardized claims
11 | - **JSON Web Encryption (JWE)** for secure data transmission
12 | - **UUID v6** for unique, chronologically sortable identifiers
13 |
14 | ## Core Capabilities
15 |
16 | LKM serves both the Flux Operator command-line interface and the Kubernetes controller,
17 | enabling comprehensive license management and artifact attestation across the Flux ecosystem.
18 |
19 | ### License Management
20 |
21 | - EdDSA-based license signing and verification using Ed25519 keys
22 | - JWT-based license keys with standard header and payload structure
23 | - Time-based license expiration with customizable validity periods
24 | - Capability-based access control for fine-grained feature management
25 | - License key revocation and ledger management
26 |
27 | ### Attestation Services
28 |
29 | - OCI artifacts and container image attestation with SHA-256 digest verification
30 | - Manifest attestation using directory hash checksums
31 | - Cryptographic signing and verification of attestation claims
32 | - Support for offline verification workflows
33 |
34 | ### Secure Secrets Exchange
35 |
36 | - ECC (Elliptic Curve) public/private key pair generation
37 | - JWK formatting for public key distribution
38 | - JWE compact format encryption using ECDH-ES key agreement
39 | - JWE token decryption using recipient's private ECC key
40 |
41 | ## Flux Operator CLI Distro Operations
42 |
43 | Build the CLI binary from source code:
44 |
45 | ```shell
46 | make cli-build
47 | ```
48 |
49 | Create the directory structure for the distro operations:
50 |
51 | ```shell
52 | mkdir -p \
53 | bin/distro/keys \
54 | bin/distro/licenses \
55 | bin/distro/attestations \
56 | bin/distro/secrets
57 | ```
58 |
59 | ### Bootstrap the JSON Web Key Sets
60 |
61 | Generate encryption and signing keys:
62 |
63 | ```shell
64 | bin/flux-operator-cli distro keygen enc fluxcd.control-plane.io \
65 | --output-dir=bin/distro/keys
66 |
67 | bin/flux-operator-cli distro keygen sig https://fluxcd.control-plane.io \
68 | --output-dir=bin/distro/keys
69 | ```
70 |
71 | Export the JWKS to env variables:
72 |
73 | ```shell
74 | export FLUX_DISTRO_ENC_PRIVATE_JWKS=$(cat bin/distro/keys/*enc-private.jwks)
75 | export FLUX_DISTRO_ENC_PUBLIC_JWKS=$(cat bin/distro/keys/*enc-public.jwks)
76 | export FLUX_DISTRO_SIG_PRIVATE_JWKS=$(cat bin/distro/keys/*sig-private.jwks)
77 | export FLUX_DISTRO_SIG_PUBLIC_JWKS=$(cat bin/distro/keys/*sig-public.jwks)
78 | ```
79 |
80 | ### Working with licenses
81 |
82 | Create a license:
83 |
84 | ```shell
85 | bin/flux-operator-cli distro sign license-key \
86 | --customer="ControlPlane Group Limited" \
87 | --duration=365 \
88 | --capabilities="feature1,feature2" \
89 | --output=bin/distro/licenses/cp-license.jwt
90 | ```
91 |
92 | Verify a license:
93 |
94 | ```shell
95 | bin/flux-operator-cli distro verify license-key \
96 | bin/distro/licenses/cp-license.jwt
97 | ```
98 |
99 | Revoke a license:
100 |
101 | ```shell
102 | bin/flux-operator-cli distro revoke license-key \
103 | bin/distro/licenses/cp-license.jwt \
104 | --output=bin/distro/licenses/revocations.json
105 | ```
106 |
107 | Verify a license against the revocation set:
108 |
109 | ```shell
110 | bin/flux-operator-cli distro verify license-key \
111 | bin/distro/licenses/cp-license.jwt \
112 | --revoked-set=bin/distro/licenses/revocations.json
113 | ```
114 |
115 | ### Working with attestations
116 |
117 | Create an attestation for artifacts:
118 |
119 | ```shell
120 | bin/flux-operator-cli distro sign artifacts \
121 | --attestation=bin/distro/attestations/flux-v2.6.4.jwt \
122 | --url=ghcr.io/fluxcd/source-controller:v1.6.2 \
123 | --url=ghcr.io/fluxcd/kustomize-controller:v1.6.1 \
124 | --url=ghcr.io/fluxcd/notification-controller:v1.6.0 \
125 | --url=ghcr.io/fluxcd/helm-controller:v1.3.0 \
126 | --url=ghcr.io/fluxcd/image-reflector-controller:v0.35.2 \
127 | --url=ghcr.io/fluxcd/image-automation-controller:v0.41.2
128 | ```
129 |
130 | Verify the attestation of artifacts:
131 |
132 | ```shell
133 | bin/flux-operator-cli distro verify artifacts \
134 | --attestation=bin/distro/attestations/flux-v2.6.4.jwt \
135 | --url=ghcr.io/fluxcd/source-controller:v1.6.2 \
136 | --url=ghcr.io/fluxcd/kustomize-controller:v1.6.1 \
137 | --url=ghcr.io/fluxcd/notification-controller:v1.6.0 \
138 | --url=ghcr.io/fluxcd/helm-controller:v1.3.0 \
139 | --url=ghcr.io/fluxcd/image-reflector-controller:v0.35.2 \
140 | --url=ghcr.io/fluxcd/image-automation-controller:v0.41.2
141 | ```
142 |
143 | Create an attestation for manifests:
144 |
145 | ```shell
146 | bin/flux-operator-cli distro sign manifests api/ \
147 | --attestation=bin/distro/attestations/api-source.jwt
148 | ```
149 |
150 | Verify the attestation of manifests:
151 |
152 | ```shell
153 | bin/flux-operator-cli distro verify manifests api/ \
154 | --attestation=bin/distro/attestations/api-source.jwt
155 | ```
156 |
157 | ### Working with secrets
158 |
159 | Encrypt a token:
160 |
161 | ```shell
162 | bin/flux-operator-cli distro encrypt token \
163 | --input=bin/distro/licenses/cp-license.jwt \
164 | --output=bin/distro/secrets/cp-license.jwe
165 | ```
166 |
167 | Decrypt a token:
168 |
169 | ```shell
170 | bin/flux-operator-cli distro decrypt token \
171 | --input=bin/distro/secrets/cp-license.jwe \
172 | --output=bin/distro/secrets/cp-license.jwt
173 | ```
174 |
175 | Encrypt manifests:
176 |
177 | ```shell
178 | bin/flux-operator-cli distro encrypt manifests api/ \
179 | --output=bin/distro/secrets/api-source.jwe
180 | ```
181 |
182 | Decrypt manifests:
183 |
184 | ```shell
185 | bin/flux-operator-cli distro decrypt manifests \
186 | bin/distro/secrets/api-source.jwe \
187 | --output-dir=bin/distro/secrets/api-source/
188 | ```
189 |
190 | ### Clean up
191 |
192 | Unset the environment variables:
193 |
194 | ```shell
195 | unset FLUX_DISTRO_ENC_PRIVATE_JWKS
196 | unset FLUX_DISTRO_ENC_PUBLIC_JWKS
197 | unset FLUX_DISTRO_SIG_PRIVATE_JWKS
198 | unset FLUX_DISTRO_SIG_PUBLIC_JWKS
199 | ```
200 |
201 | Remove the distro directory
202 |
203 | ```shell
204 | rm -rf bin/distro
205 | ```
206 |
```
--------------------------------------------------------------------------------
/docs/dev/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Flux Operator Dev Documentation
2 |
3 | ## Release Procedure
4 |
5 | ### Flux Operator
6 |
7 | 1. Switch to the `main` branch and pull the latest commit of the [`controlplaneio-fluxcd/flux-operator` repository](https://github.com/controlplaneio-fluxcd/flux-operator).
8 | 2. Run `make prep-release` that increments the minor version and opens a PR with the changes. (Or set a version with `NEXT_VERSION=v1.2.3 make prep-release`.)
9 | 3. Merge the PR and pull the latest commit from the `main` branch locally.
10 | 4. Run `make release` that creates a new tag for the release and pushes it to the remote repository.
11 | 5. Wait for the `release` GitHub Workflow to finish.
12 |
13 | ### Helm Chart
14 |
15 | 1. Run the `update` GitHub Workflow in the [`controlplaneio-fluxcd/charts` repository](https://github.com/controlplaneio-fluxcd/charts/actions/workflows/update.yaml).
16 | 2. Merge the PR opened by the `update` GitHub Workflow.
17 | 3. Wait for the `test` workflow to pass on the `main` branch.
18 | 4. Tag the `main` branch with the new next semver from [`controlplaneio-fluxcd/charts` repository](https://github.com/controlplaneio-fluxcd/charts/tags), e.g. `git tag -s -m "v0.2.0" "v0.2.0"`.
19 | 5. Wait for the `release` GitHub Workflow to finish.
20 | 6. After the Helm chart is published, the new version will be available at [artifacthub.io/packages/helm/flux-operator/flux-operator](https://artifacthub.io/packages/helm/flux-operator/flux-operator).
21 |
22 | ### OperatorHub Bundle
23 |
24 | 1. Validate the new version by running the `e2e-olm` GitHub Workflow in the [`controlplaneio-fluxcd/flux-operator` repository](https://github.com/controlplaneio-fluxcd/flux-operator/actions/workflows/e2e-olm.yaml).
25 | 2. Generate the OLM manifests locally by running `make build-olm-manifests`.
26 | 3. Fork the [OperatorHub.io repository](https://github.com/k8s-operatorhub/community-operators) and clone it locally.
27 | 4. Create a new branch from `main`, e.g. `flux-operator-1.0.0`.
28 | 5. Copy the OLM manifests from the `flux-operator/bin/olm/1.0.0` dir to the `community-operators/operators/flux-operator/1.0.0`.
29 | 6. Commit the changes with the title `operator flux-operator (1.0.0)` and push the branch to the fork.
30 | 7. Open a PR in the upstream repository and wait for the CI to pass.
31 | 8. After the PR is merged, the new version will be available at [operatorhub.io/operator/flux-operator](https://operatorhub.io/operator/flux-operator).
32 |
33 | ### RedHat OpenShift Bundle
34 |
35 | 1. Generate the OLM manifests for the UBI version locally by running `make build-olm-manifests-ubi`.
36 | 2. Fork the [redhat-openshift-ecosystem/community-operators-prod repository](https://github.com/redhat-openshift-ecosystem/community-operators-prod) and clone it locally.
37 | 3. Create a new branch from `main`, e.g. `flux-operator-1.0.0`.
38 | 4. Copy the OLM manifests from the `flux-operator/bin/olm/1.0.0` dir to the `community-operators-prod/operators/flux-operator/1.0.0`.
39 | 5. Commit the changes with the title `operator flux-operator (1.0.0)` and push the branch to the fork.
40 | 6. Open a PR in the upstream repository and wait for the CI to pass.
41 | 7. After the PR is merged, the new version will be available in the OpenShift Container Platform catalog.
42 |
43 | ### Homebrew Tap
44 |
45 | 1. Trigger the `release` GitHub Workflow in the [`controlplaneio-fluxcd/homebrew-tap` repository](https://github.com/controlplaneio-fluxcd/homebrew-tap/blob/main/.github/workflows/release.yml).
46 | 2. Merge the PR opened by the `release` workflow.
47 | 3. Verify the new version is available by running `brew upgrade flux-operator flux-operator-mcp` on your local machine.
48 |
49 | ### Documentation Website
50 |
51 | 1. Trigger the `vendor-operator-docs` GitHub Workflow in the [`controlplaneio-fluxcd/distribution` repository](https://github.com/controlplaneio-fluxcd/distribution/blob/main/.github/workflows/vendor-operator-docs.yaml).
52 | 2. Merge the PR opened by the `vendor-operator-docs` workflow.
53 | 3. Trigger the `docs` GitHub Workflow in the [`controlplaneio-fluxcd/distribution` repository](https://github.com/controlplaneio-fluxcd/distribution/blob/main/.github/workflows/docs.yaml).
54 | 4. Wait for the `docs` workflow to finish and verify the changes on the [Flux Operator documentation site](https://fluxcd.control-plane.io/operator/).
55 |
56 | ## Manifests Release Procedure
57 |
58 | ### Manifests Update for a New Flux Version
59 |
60 | 1. Create a new branch from `main`, e.g. `flux-v2.x.x` in the [`controlplaneio-fluxcd/flux-operator` repository](https://github.com/controlplaneio-fluxcd/flux-operator).
61 | 2. Generate the manifests for the latest Flux version by running `make vendor-flux`.
62 | 3. Build the manifests with images digests by running `make build-manifests`.
63 | 4. Write an end-to-end test for the upgrade if the new Flux version is a minor release.
64 | 5. Run `make mcp-build-search-index` to rebuild the docs index if the new Flux version is a minor release.
65 | 6. Commit changes and open a PR.
66 | 7. After the PR is merged, publish the OCI artifact with the manifests by running the [`push-manifests` GitHub Workflow](https://github.com/controlplaneio-fluxcd/flux-operator/actions/workflows/push-manifests.yml).
67 |
68 | ### Manifests Update for Enterprise CVE Fixes
69 |
70 | 1. Create a new branch from `main`, e.g. `enterprise-cve-fixes` in the [`controlplaneio-fluxcd/flux-operator` repository](https://github.com/controlplaneio-fluxcd/flux-operator).
71 | 2. Rebuild the Flux manifests with the latest image patches by running `make vendor-flux`.
72 | 3. Commit changes and open a PR.
73 | 4. After the PR is merged, publish the OCI artifact with the manifests by running the [`push-manifests` GitHub Workflow](https://github.com/controlplaneio-fluxcd/flux-operator/actions/workflows/push-manifests.yml).
74 |
75 | ## Local Development
76 |
77 | ### Prerequisites
78 |
79 | - [Go](https://golang.org/doc/install) 1.25+
80 | - [Docker](https://docs.docker.com/get-docker/)
81 | - [Kind](https://kind.sigs.k8s.io/docs/user/quick-start/)
82 | - [Kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
83 |
84 | ### Building
85 |
86 | After code changes, run the following command:
87 |
88 | ```sh
89 | make all
90 | ```
91 |
92 | ### Unit Testing
93 |
94 | Unit tests can be run with:
95 |
96 | ```sh
97 | make test
98 | ```
99 |
100 | ### End-to-End Testing
101 |
102 | First, create a cluster named `kind`:
103 |
104 | ```sh
105 | kind create cluster
106 | ```
107 |
108 | End-to-end tests can be run with:
109 |
110 | ```sh
111 | make test-e2e
112 | ```
113 |
114 | ### Manual Testing
115 |
116 | Build and run the operator in a Kind cluster:
117 |
118 | ```sh
119 | IMG=flux-operator:test1 make docker-build load-image deploy
120 | ```
121 |
122 | Make sure to increment the `test1` tag for each new build.
123 |
124 | Apply the instance from the `config/samples` dir:
125 |
126 | ```sh
127 | kubectl -n flux-system apply -f config/samples/fluxcd_v1_fluxinstance.yaml
128 | ```
129 |
130 | Check the logs:
131 |
132 | ```sh
133 | kubectl -n flux-system logs deployment/flux-operator --follow
134 | ```
135 |
136 | To test the Flux Operator CLI, build it with:
137 |
138 | ```sh
139 | make cli-build
140 | ```
141 |
142 | Then run the CLI with:
143 |
144 | ```sh
145 | ./bin/flux-operator-cli get instance flux -n flux-system
146 | ```
147 |
148 | To clean up the resources, run:
149 |
150 | ```sh
151 | kubectl -n flux-system delete fluxinstance/flux
152 | make undeploy
153 | ```
154 |
155 | ### Upgrading the Go Version
156 |
157 | To upgrade Go to the latest minor version, follow these steps:
158 |
159 | 1. Bump the `go` minor version in the `go.mod` file.
160 | 2. Bump `GOLANGCI_LINT_VERSION` to match the new Go version.
161 | 3. Run `make` to validate that the build and tests pass with the new Go version.
162 | 4. Bump the `golang` image tag in all `Dockerfile`s.
163 | 5. Bump the `go-version` in all GitHub workflows.
164 | 6. Bump the Go version in [prerequisites](#prerequisites) section of this document.
165 |
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # flux-operator
2 |
3 | [](https://github.com/controlplaneio-fluxcd/flux-operator/releases)
4 | [](https://artifacthub.io/packages/helm/flux-operator/flux-operator)
5 | [](https://operatorhub.io/operator/flux-operator)
6 | [](https://github.com/controlplaneio-fluxcd/flux-operator/actions/workflows/test.yaml)
7 | [](https://github.com/controlplaneio-fluxcd/flux-operator/blob/main/LICENSE)
8 | [](https://fluxcd.control-plane.io/distribution/security/)
9 |
10 | The Flux Operator is a Kubernetes CRD controller that manages
11 | the lifecycle of CNCF [Flux CD](https://fluxcd.io) and the [ControlPlane enterprise distribution](https://github.com/controlplaneio-fluxcd/distribution).
12 | The operator extends Flux with self-service capabilities, deployment windows,
13 | and preview environments for GitHub, GitLab and Azure DevOps pull requests testing.
14 |
15 | ---
16 |
17 | <p align="center">
18 | <a href="https://fluxoperator.dev">
19 | <img src="https://raw.githubusercontent.com/controlplaneio-fluxcd/flux-operator/refs/heads/main/docs/logo/flux-operator-banner.png" width="100%">
20 | </a>
21 | </p>
22 |
23 | ---
24 |
25 | **Autopilot for Flux CD** - The operator offers an alternative to the Flux Bootstrap procedure, it
26 | removes the operational burden of managing Flux across fleets of clusters by fully automating the
27 | installation, configuration, and upgrade of the Flux controllers based on a declarative API.
28 |
29 | **Advanced Configuration** - The operator simplifies the configuration of Flux multi-tenancy lockdown,
30 | sharding, horizontal and vertical scaling, persistent storage, and allows fine-tuning the Flux
31 | controllers with Kustomize patches. The operator streamlines the transition from Git as the delivery
32 | mechanism for the cluster desired state to OCI artifacts and S3-compatible storage.
33 |
34 | **Deep Insights** - The operator provides deep insights into the delivery pipelines managed by Flux,
35 | including detailed reports and Prometheus metrics about the Flux controllers
36 | readiness status, reconcilers statistics, and cluster state synchronization.
37 | The [Flux Web UI](https://fluxoperator.dev/web-ui/) offers a real-time view of the GitOps pipelines,
38 | allowing you to monitor deployments, track reconciliation status, and troubleshoot issues.
39 |
40 | **Self-Service Environments** - The operator [ResourceSet API](https://fluxoperator.dev/docs/resourcesets/introduction/)
41 | enables platform teams to define their own application standard as a group of Flux and Kubernetes resources
42 | that can be templated, parameterized and deployed as a single unit on self-service environments.
43 | The ResourceSet API integrates with Git pull requests to create ephemeral environments
44 | for testing and validation.
45 |
46 | **AI-Assisted GitOps** - The [Flux MCP Server](https://fluxoperator.dev/mcp-server/) connects
47 | AI assistants to Kubernetes clusters running the operator, enabling seamless interaction
48 | through natural language. It serves as a bridge between AI tools and GitOps pipelines,
49 | allowing you to analyze deployment across environments, troubleshoot issues,
50 | and perform operations using conversational prompts.
51 |
52 | **Enterprise Support** - The operator is a key component of the ControlPlane
53 | [Enterprise offering](https://fluxcd.control-plane.io/pricing/), and is designed to automate the
54 | rollout of new Flux versions, CVE patches and hotfixes to production environments in a secure and reliable way.
55 | The operator is end-to-end tested along with the ControlPlane Flux distribution on
56 | Red Hat OpenShift, Amazon EKS, Azure AKS and Google GKE.
57 |
58 | ## Quickstart Guide
59 |
60 | ### Install the Flux Operator
61 |
62 | Install the Flux Operator in the `flux-system` namespace, for example using Helm:
63 |
64 | ```shell
65 | helm install flux-operator oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator \
66 | --namespace flux-system
67 | ```
68 |
69 | > [!NOTE]
70 | > The Flux Operator can be installed using Helm, Terraform, OperatorHub, kubectl and other methods.
71 | > For more information, refer to the
72 | > [installation guide](https://fluxoperator.dev/docs/guides/install/).
73 |
74 | ### Install the Flux Controllers
75 |
76 | Create a [FluxInstance](https://fluxoperator.dev/docs/crd/fluxinstance/) resource
77 | named `flux` in the `flux-system` namespace to install the latest Flux stable version:
78 |
79 | ```yaml
80 | apiVersion: fluxcd.controlplane.io/v1
81 | kind: FluxInstance
82 | metadata:
83 | name: flux
84 | namespace: flux-system
85 | annotations:
86 | fluxcd.controlplane.io/reconcileEvery: "1h"
87 | fluxcd.controlplane.io/reconcileArtifactEvery: "10m"
88 | fluxcd.controlplane.io/reconcileTimeout: "5m"
89 | spec:
90 | distribution:
91 | version: "2.x"
92 | registry: "ghcr.io/fluxcd"
93 | artifact: "oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests"
94 | components:
95 | - source-controller
96 | - kustomize-controller
97 | - helm-controller
98 | - notification-controller
99 | - image-reflector-controller
100 | - image-automation-controller
101 | cluster:
102 | type: kubernetes
103 | size: medium
104 | multitenant: false
105 | networkPolicy: true
106 | domain: "cluster.local"
107 | kustomize:
108 | patches:
109 | - target:
110 | kind: Deployment
111 | patch: |
112 | - op: replace
113 | path: /spec/template/spec/nodeSelector
114 | value:
115 | kubernetes.io/os: linux
116 | - op: add
117 | path: /spec/template/spec/tolerations
118 | value:
119 | - key: "CriticalAddonsOnly"
120 | operator: "Exists"
121 | ```
122 |
123 | > [!NOTE]
124 | > The Flux instance can be customized in various ways.
125 | > For more information, refer to the
126 | > [configuration guide](https://fluxoperator.dev/docs/instance/controllers/).
127 |
128 | ### Sync from a Git Repository
129 |
130 | To sync the cluster state from a Git repository, add the following configuration to the `FluxInstance`:
131 |
132 | ```yaml
133 | apiVersion: fluxcd.controlplane.io/v1
134 | kind: FluxInstance
135 | metadata:
136 | name: flux
137 | namespace: flux-system
138 | spec:
139 | sync:
140 | kind: GitRepository
141 | url: "https://github.com/my-org/my-fleet.git"
142 | ref: "refs/heads/main"
143 | path: "clusters/my-cluster"
144 | pullSecret: "flux-system"
145 | # distribution omitted for brevity
146 | ```
147 |
148 | If the source repository is private, the Kubernetes secret must be created in the `flux-system` namespace
149 | and should contain the credentials to clone the repository:
150 |
151 | ```shell
152 | flux create secret git flux-system \
153 | --url=https://github.com/my-org/my-fleet.git \
154 | --username=git \
155 | --password=$GITHUB_TOKEN
156 | ```
157 |
158 | > [!NOTE]
159 | > For more information on how to configure syncing from Git repositories,
160 | > container registries and S3-compatible storage, refer to the
161 | > [cluster sync guide](https://fluxoperator.dev/docs/instance/sync/).
162 |
163 | ### Monitor the Flux Installation
164 |
165 | To monitor the Flux deployment status, check the
166 | [FluxReport](https://fluxoperator.dev/docs/crd/fluxreport/)
167 | resource in the `flux-system` namespace:
168 |
169 | ```shell
170 | kubectl get fluxreport/flux -n flux-system -o yaml
171 | ```
172 |
173 | The report is update at regular intervals and contains information about the deployment
174 | readiness status, the distribution details, reconcilers statistics, Flux CRDs versions,
175 | the cluster sync status and more.
176 |
177 | ### Access the Flux Web UI
178 |
179 | To access the [Flux Web UI](https://fluxoperator.dev/web-ui/),
180 | you can port-forward the operator service:
181 |
182 | ```shell
183 | kubectl -n flux-system port-forward svc/flux-operator 9080:9080
184 | ```
185 |
186 | Note that the Flux Web UI can be configured with [Ingress](https://fluxoperator.dev/docs/web-ui/ingress/)
187 | and [Single Sign-On](https://fluxoperator.dev/docs/web-ui/user-management/) for secure external access.
188 |
189 | ## ResourceSet APIs
190 |
191 | The Flux Operator [ResourceSet APIs](https://fluxoperator.dev/docs/resourcesets/introduction/)
192 | offer a high-level abstraction for defining and managing Flux resources and related Kubernetes
193 | objects as a single unit.
194 | The ResourceSet API is designed to reduce the complexity of GitOps workflows and to
195 | enable self-service for developers and platform teams.
196 |
197 | Guides:
198 |
199 | - [Using ResourceSets for Application Definitions](https://fluxoperator.dev/docs/resourcesets/app-definition/)
200 | - [Using ResourceSets for Time-Based Delivery](https://fluxoperator.dev/docs/resourcesets/time-based-delivery/)
201 | - [Ephemeral Environments for GitHub Pull Requests](https://fluxoperator.dev/docs/resourcesets/github-pull-requests/)
202 | - [Ephemeral Environments for GitLab Merge Requests](https://fluxoperator.dev/docs/resourcesets/gitlab-merge-requests/)
203 |
204 | ## Documentation
205 |
206 | - Installation
207 | - [Flux Operator installation](https://fluxoperator.dev/docs/guides/install/)
208 | - [Migration of bootstrapped clusters](https://fluxoperator.dev/docs/guides/migration/)
209 | - [Flux Operator CLI](https://fluxoperator.dev/docs/guides/cli/)
210 | - Flux Configuration
211 | - [Flux controllers configuration](https://fluxoperator.dev/docs/instance/controllers/)
212 | - [Flux instance customization](https://fluxoperator.dev/docs/instance/customization/)
213 | - [Cluster sync configuration](https://fluxoperator.dev/docs/instance/sync/)
214 | - [Flux controllers sharding](https://fluxoperator.dev/docs/instance/sharding/)
215 | - [Flux monitoring and reporting](https://fluxoperator.dev/docs/instance/monitoring/)
216 | - CRD references
217 | - [FluxInstance API reference](https://fluxoperator.dev/docs/crd/fluxinstance/)
218 | - [FluxReport API reference](https://fluxoperator.dev/docs/crd/fluxreport/)
219 | - [ResourceSet API reference](https://fluxoperator.dev/docs/crd/resourceset/)
220 | - [ResourceSetInputProvider API reference](https://fluxoperator.dev/docs/crd/resourcesetinputprovider/)
221 |
222 | ## Contributing
223 |
224 | We welcome contributions to the Flux Operator project via GitHub pull requests.
225 | Please see the [CONTRIBUTING](https://github.com/controlplaneio-fluxcd/flux-operator/blob/main/CONTRIBUTING.md)
226 | guide for details on how to set up your development environment and start contributing to the project.
227 |
228 | ## License
229 |
230 | The Flux Operator is an open-source project licensed under the
231 | [AGPL-3.0 license](https://github.com/controlplaneio-fluxcd/flux-operator/blob/main/LICENSE).
232 |
233 | The project is developed by CNCF Flux core maintainers part of the [ControlPlane](https://control-plane.io) team.
234 |
```
--------------------------------------------------------------------------------
/cmd/cli/README.md:
--------------------------------------------------------------------------------
```markdown
1 | ---
2 | title: Flux Operator CLI
3 | description: Flux Operator command line tool installation and usage guide
4 | ---
5 |
6 | # Flux Operator CLI
7 |
8 | The Flux Operator CLI is a command line tool that allows you to manage the Flux Operator resources
9 | in your Kubernetes clusters. It provides a convenient way to interact with the operator
10 | and perform various operations.
11 |
12 | ## Installation
13 |
14 | The Flux Operator CLI is available as a binary executable for Linux, macOS, and Windows. The binaries
15 | can be downloaded from GitHub [releases page](https://github.com/controlplaneio-fluxcd/flux-operator/releases).
16 |
17 | If you are using macOS or Linux, you can install the CLI using Homebrew:
18 |
19 | ```shell
20 | brew install controlplaneio-fluxcd/tap/flux-operator
21 | ```
22 |
23 | To configure your shell to load `flux-operator` Bash completions add to your profile:
24 |
25 | ```shell
26 | echo "source <(flux-operator completion bash)" >> ~/.bash_profile
27 | ```
28 |
29 | Zsh, Fish, and PowerShell are also supported with their own sub-commands.
30 |
31 | ### Container Image
32 |
33 | The Flux Operator CLI is also available as a container image, which can be used in CI pipelines
34 | or Kubernetes Jobs. The image contains the `flux-operator` CLI binary and the `kubectl` binary.
35 |
36 | The multi-arch image (Linux AMD64/ARM64) is hosted on GitHub Container Registry at
37 | `ghcr.io/controlplaneio-fluxcd/flux-operator-cli`.
38 |
39 | ```shell
40 | version=$(gh release view --repo controlplaneio-fluxcd/flux-operator --json tagName -q '.tagName')
41 | docker run --rm -it --entrypoint=flux-operator ghcr.io/controlplaneio-fluxcd/flux-operator-cli:$version help
42 | docker run --rm -it --entrypoint=kubectl ghcr.io/controlplaneio-fluxcd/flux-operator-cli:$version help
43 | ```
44 |
45 | ## Commands
46 |
47 | The Flux Operator CLI provides commands to manage the Flux Operator resources.
48 | Except for the `build` commands, all others require access to the Kubernetes cluster
49 | and the Flux Operator to be installed.
50 |
51 | The CLI connects to the cluster using the `~.kube/config` file, similar to `kubectl`.
52 |
53 | All commands display help information and example usage when run with the `-h` or `--help` flag.
54 |
55 | ### Build Commands
56 |
57 | The `flux-operator build` commands are used to build and validate the Flux Operator resources.
58 | These commands do not require access to a Kubernetes cluster and can be run in any environment.
59 |
60 | The following commands are available:
61 |
62 | - `flux-operator build instance`: Generates the Flux Kubernetes manifests from a FluxInstance definition.
63 | - `-f, --file`: Path to the FluxInstance YAML manifest (required).
64 | - `flux-operator build rset`: Generates the Kubernetes manifests from a ResourceSet definition.
65 | - `-f, --file`: Path to the ResourceSet YAML manifest (required).
66 | - `--inputs-from`: Path to the ResourceSet inputs YAML manifest.
67 | - `--inputs-from-provider`: Path to the ResourceSetInputProvider static type YAML manifest.
68 |
69 | ### Get Commands
70 |
71 | The `flux-operator get` commands are used to retrieve information about the Flux Operator resources in the cluster.
72 |
73 | The following commands are available:
74 |
75 | - `flux-operator get instance`: Retrieves the FluxInstance resource in the cluster.
76 | - `flux-operator get rset`: Retrieves the ResourceSet resources in the cluster.
77 | - `flux-operator get rsip`: Retrieves the ResourceSetInputProvider resources in the cluster.
78 |
79 | Arguments:
80 |
81 | - `-n, --namespace`: Specifies the namespace to filter the resources.
82 | - `-A, --all-namespaces`: Retrieves resources from all namespaces.
83 |
84 | ### Get All Command
85 |
86 | This command can be used to retrieve information about all Flux resources in the cluster,
87 | it supports filtering by resource kind, namespace and ready status.
88 |
89 | - `flux-operator get all`: Retrieves all Flux resources and their status.
90 |
91 | Arguments:
92 |
93 | - `--kind`: Specifies the kind of resources to filter (e.g. Kustomization, HelmRelease, etc.).
94 | - `--ready-status`: Filters resources by their ready status (True, False, Unknown or Suspended).
95 | - `-o, --output`: Specifies the output format (table, json, yaml). Default is table.
96 | - `-n, --namespace`: Specifies the namespace to filter the resources.
97 | - `-A, --all-namespaces`: Retrieves resources from all namespaces.
98 |
99 | ### Export Commands
100 |
101 | The `flux-operator export` commands are used to export the Flux Operator resources in YAML or JSON format.
102 | The exported resources can be used for backup, migration, or inspection purposes.
103 |
104 | The following commands are available:
105 |
106 | - `flux-operator export report`: Exports the FluxReport resource containing the distribution status and version information.
107 | - `flux-operator export resource <kind>/<name>`: Exports a Flux resource from the specified namespace.
108 |
109 | Arguments:
110 |
111 | - `-n, --namespace`: Specifies the namespace scope of the command.
112 | - `-o, --output`: Specifies the output format (yaml, json). Default is yaml.
113 |
114 | ### Reconcile Commands
115 |
116 | The `flux-operator reconcile` commands are used to trigger the reconciliation of the Flux Operator resources.
117 |
118 | The following commands are available:
119 |
120 | - `flux-operator reconcile instance <name>`: Reconciles the FluxInstance resource in the cluster.
121 | - `flux-operator reconcile rset <name>`: Reconciles the ResourceSet resource in the cluster.
122 | - `flux-operator reconcile rsip <name>`: Reconciles the ResourceSetInputProvider resource in the cluster.
123 | - `flux-operator reconcile resource <kind>/<name>`: Reconciles a Flux resource in the specified namespace.
124 | - `flux-operator reconcile all`: Reconciles all Flux resources in the cluster (supports filtering by ready status).
125 |
126 | Arguments:
127 |
128 | - `-n, --namespace`: Specifies the namespace scope of the command.
129 | - `--wait`: Waits for the reconciliation to complete before returning.
130 |
131 | ### Suspend/Resume Commands
132 |
133 | The `flux-operator suspend` and `flux-operator resume` commands are used
134 | to suspend or resume the reconciliation of the Flux Operator resources.
135 |
136 | The following commands are available:
137 |
138 | - `flux-operator suspend instance <name>`: Suspends the reconciliation of the FluxInstance resource in the cluster.
139 | - `flux-operator resume instance <name>`: Resumes the reconciliation of the FluxInstance resource in the cluster.
140 | - `flux-operator suspend rset <name>`: Suspends the reconciliation of the ResourceSet resource in the cluster.
141 | - `flux-operator resume rset <name>`: Resumes the reconciliation of the ResourceSet resource in the cluster.
142 | - `flux-operator suspend rsip <name>`: Suspends the reconciliation of the ResourceSetInputProvider resource in the cluster.
143 | - `flux-operator resume rsip <name>`: Resumes the reconciliation of the ResourceSetInputProvider resource in the cluster.
144 | - `flux-operator suspend resource <kind>/<name>`: Suspends the reconciliation of the Flux resource in the cluster.
145 | - `flux-operator resume resource <kind>/<name>`: Resumes the reconciliation of the Flux resource in the cluster.
146 |
147 | Arguments:
148 |
149 | - `-n, --namespace`: Specifies the namespace scope of the command.
150 | - `--wait`: On resume, waits for the reconciliation to complete before returning.
151 |
152 | ### Delete Commands
153 |
154 | The `flux-operator delete` commands are used to delete the Flux Operator resources from the cluster.
155 |
156 | The following commands are available:
157 |
158 | - `flux-operator delete instance <name>`: Deletes the FluxInstance resource from the cluster.
159 | - `flux-operator delete rset <name>`: Deletes the ResourceSet resource from the cluster.
160 | - `flux-operator delete rsip <name>`: Deletes the ResourceSetInputProvider resource from the cluster.
161 |
162 | Arguments:
163 |
164 | - `-n, --namespace`: Specifies the namespace scope of the command.
165 | - `--wait`: Waits for the resource to be deleted before returning (enabled by default).
166 | - `--with-suspend`: Suspends the resource before deleting it (leaving the managed resources in-place).
167 |
168 | ### Statistics Command
169 |
170 | This command is used to retrieve statistics about the Flux resources
171 | including their reconciliation status and the amount of cumulative storage used for each source type.
172 |
173 | - `flux-operator stats`: Displays statistics about the Flux resources in the cluster.
174 |
175 | ### Trace Command
176 |
177 | This command is used to trace Kubernetes objects throughout the GitOps delivery pipeline
178 | to identify which Flux reconciler manages them and from which source they originate.
179 |
180 | - `flux-operator trace <kind>/<name>`: Trace a Kubernetes object to its Flux reconciler and source.
181 |
182 | Arguments:
183 |
184 | - `-n, --namespace`: Specifies the namespace scope of the command.
185 |
186 | ### Tree Commands
187 |
188 | The `flux-operator tree` commands are used to visualize the Flux-managed Kubernetes objects in a tree format
189 | by recursively traversing the Flux resources such as ResourceSets, Kustomizations and HelmReleases.
190 |
191 | The following commands are available:
192 |
193 | - `flux-operator tree rset <name>`: Print a tree view of the ResourceSet managed objects.
194 | - `flux-operator tree ks <name>`: Print a tree view of the Flux Kustomization managed objects.
195 | - `flux-operator tree hr <name>`: Print a tree view of the Flux HelmRelease managed objects.
196 |
197 | Arguments:
198 |
199 | - `-n, --namespace`: Specifies the namespace scope of the command.
200 |
201 | ### Wait Commands
202 |
203 | The `flux-operator wait` commands are used to wait for Flux Operator resources to become ready.
204 | These commands will poll the resource status until it reaches a ready state or times out.
205 | If the resource is not created or its status is not ready within the specified timeout,
206 | the command will return an error.
207 |
208 | The following commands are available:
209 |
210 | - `flux-operator wait instance <name>`: Wait for a FluxInstance to become ready.
211 | - `flux-operator wait rset <name>`: Wait for a ResourceSet to become ready.
212 | - `flux-operator wait rsip <name>`: Wait for a ResourceSetInputProvider to become ready.
213 |
214 | Arguments:
215 |
216 | - `-n, --namespace`: Specifies the namespace scope of the command.
217 | - `--timeout`: The length of time to wait before giving up (default 1m).
218 |
219 | ### Create Secret Commands
220 |
221 | The `flux-operator create secret` commands are used to create Kubernetes secrets specific to Flux.
222 | These commands can be used to create or update secrets directly in the cluster, or to export them in YAML format.
223 |
224 | The following commands are available:
225 |
226 | - `flux-operator create secret basic-auth`: Create a Kubernetes Secret containing basic auth credentials.
227 | - `--username`: Set the username for basic authentication (required).
228 | - `--password`: Set the password for basic authentication (required if --password-stdin is not used).
229 | - `--password-stdin`: Read the password from stdin.
230 | - `flux-operator create secret githubapp`: Create a Kubernetes Secret containing GitHub App credentials.
231 | - `--app-id`: GitHub App ID (required).
232 | - `--app-installation-id`: GitHub App Installation ID (required).
233 | - `--app-private-key-file`: Path to GitHub App private key file (required).
234 | - `--app-base-url`: GitHub base URL for GitHub Enterprise Server (optional).
235 | - `flux-operator create secret proxy`: Create a Kubernetes Secret containing HTTP/S proxy credentials.
236 | - `--address`: Set the proxy address (required).
237 | - `--username`: Set the username for proxy authentication (optional).
238 | - `--password`: Set the password for proxy authentication (optional).
239 | - `--password-stdin`: Read the password from stdin.
240 | - `flux-operator create secret registry`: Create a Kubernetes Secret containing registry credentials.
241 | - `--server`: Set the registry server (required).
242 | - `--username`: Set the username for registry authentication (required).
243 | - `--password`: Set the password for registry authentication (required if --password-stdin is not used).
244 | - `--password-stdin`: Read the password from stdin.
245 | - `flux-operator create secret sops`: Create a Kubernetes Secret containing SOPS decryption keys.
246 | - `--age-key-file`: Path to Age private key file (can be used multiple times).
247 | - `--gpg-key-file`: Path to GPG private key file (can be used multiple times).
248 | - `--age-key-stdin`: Read Age private key from stdin.
249 | - `--gpg-key-stdin`: Read GPG private key from stdin.
250 | - `flux-operator create secret ssh`: Create a Kubernetes Secret containing SSH credentials.
251 | - `--private-key-file`: Path to SSH private key file (required).
252 | - `--public-key-file`: Path to SSH public key file (optional).
253 | - `--knownhosts-file`: Path to SSH known_hosts file (required).
254 | - `--password`: Password for encrypted SSH private key (optional).
255 | - `--password-stdin`: Read the password from stdin.
256 | - `flux-operator create secret tls`: Create a Kubernetes Secret containing TLS certs.
257 | - `--tls-crt-file`: Path to TLS client certificate file.
258 | - `--tls-key-file`: Path to TLS client private key file.
259 | - `--ca-crt-file`: Path to CA certificate file (optional).
260 |
261 | Arguments:
262 |
263 | - `-n, --namespace`: Specifies the namespace to create the secret in.
264 | - `--annotation`: Set annotations on the resource (can specify multiple annotations with commas: annotation1=value1,annotation2=value2).
265 | - `--label`: Set labels on the resource (can specify multiple labels with commas: label1=value1,label2=value2).
266 | - `--immutable`: Set the immutable flag on the Secret.
267 | - `--export`: Export secret in YAML format to stdout instead of creating it in the cluster.
268 |
269 | ### Version Command
270 |
271 | This command is used to display the version of the CLI, of the Flux Operator
272 | and of the Flux distribution running in the cluster.
273 |
274 | - `flux-operator version`: Displays the version information for the CLI and the Flux Operator.
275 | - `--client`: If true, shows the client version only (no server required).
276 |
277 | ### Install Command
278 |
279 | The `flux-operator install` command provides a quick way to bootstrap a Kubernetes cluster with the Flux Operator and a Flux instance.
280 |
281 | This command performs the following steps:
282 |
283 | 1. Downloads the Flux Operator distribution artifact from `oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests`.
284 | 2. Installs the Flux Operator in the `flux-system` namespace and waits for it to become ready.
285 | 3. Installs the Flux instance in the `flux-system` namespace according to the provided configuration.
286 | 4. Configures the pull secret for the instance sync source if credentials are provided.
287 | 5. Configures Flux to bootstrap the cluster from a Git repository or OCI repository if a sync URL is provided.
288 | 6. Configures automatic updates of the Flux Operator from the distribution artifact.
289 |
290 | This command is intended for development and testing purposes. On production environments,
291 | it is recommended to follow the [installation guide](https://fluxcd.control-plane.io/operator/install/).
292 |
293 | - `flux-operator install`: Installs the Flux Operator and a Flux instance in the cluster.
294 | - `--instance-file, -f`: Path to FluxInstance YAML file (local file, OCI or HTTPS URL).
295 | - `--instance-distribution-version`: Flux distribution version.
296 | - `--instance-distribution-registry`: Container registry to pull Flux images from.
297 | - `--instance-distribution-artifact`: OCI artifact containing the Flux distribution manifests.
298 | - `--instance-components`: List of Flux components to install.
299 | - `--instance-components-extra`: Additional Flux components to install on top of the default set.
300 | - `--instance-cluster-type`: Cluster type (kubernetes, openshift, aws, azure, gcp).
301 | - `--instance-cluster-size`: Cluster size profile for vertical scaling (small, medium, large).
302 | - `--instance-cluster-domain`: Cluster domain used for generating the FQDN of services.
303 | - `--instance-cluster-multitenant`: Enable multitenant lockdown for Flux controllers.
304 | - `--instance-cluster-network-policy`: Restrict network access to the current namespace.
305 | - `--instance-sync-url`: URL of the source for cluster sync (Git repository URL or OCI repository address).
306 | - `--instance-sync-ref`: Source reference for cluster sync (Git ref name or OCI tag).
307 | - `--instance-sync-path`: Path to the manifests directory in the source.
308 | - `--instance-sync-creds`: Credentials for the source in the format `username:token`.
309 | - `--auto-update`: Enable automatic updates of the Flux Operator from the distribution artifact.
310 |
311 | ### Uninstall Command
312 |
313 | The `flux-operator uninstall` command safely removes the Flux Operator and Flux instance from the cluster.
314 |
315 | This command performs the following steps:
316 |
317 | 1. Deletes the cluster role bindings of Flux Operator and Flux controllers.
318 | 2. Deletes the deployments of Flux Operator and Flux controllers.
319 | 3. Removes finalizers from Flux Operator and Flux custom resources.
320 | 4. Deletes the CustomResourceDefinitions of Flux Operator and Flux.
321 | 5. Deletes the namespace where Flux Operator is installed (unless `--keep-namespace` is specified).
322 |
323 | - `flux-operator -n flux-system uninstall`: Uninstalls the Flux Operator and Flux instance from the cluster.
324 | - `--keep-namespace`: Keep the namespace after uninstalling Flux Operator and Flux instance.
325 |
326 | Note that the `uninstall` command will not delete any Kubernetes objects or Helm releases
327 | that were reconciled on the cluster by Flux. It is safe to run this command and re-install
328 | Flux Operator later to resume managing the existing resources.
329 |
```
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
```markdown
1 | # Security Policy
2 |
3 | This document defines security reporting, handling and disclosure for the Flux Operator project.
4 |
5 | ## Report a Vulnerability
6 |
7 | You can privately disclose a vulnerability through GitHub's
8 | [private vulnerability reporting](https://github.com/controlplaneio-fluxcd/flux-operator/security) mechanism.
9 |
10 | You will be able to choose if you want public acknowledgement of your effort and how you would like to be credited.
11 |
12 | ## Disclosures
13 |
14 | Vulnerability disclosures are made public on GitHub's
15 | [security advisories](https://github.com/controlplaneio-fluxcd/flux-operator/security/advisories) page.
16 |
17 | Disclosures will contain an overview, details about the vulnerability,
18 | a fix that will typically be an update, and optionally a workaround if one is available.
19 |
20 | Disclosures will be made public in a timely manner after a release is published that fixes the vulnerability.
21 |
```
--------------------------------------------------------------------------------
/AGENTS.md:
--------------------------------------------------------------------------------
```markdown
1 | # AGENTS instructions
2 |
3 | For detailed information on source code structure and development guidelines,
4 | refer to the project's [CONTRIBUTING.md](CONTRIBUTING.md) file.
5 |
6 | ## Project Overview
7 |
8 | This project is a Kubernetes operator for managing the lifecycle of Flux CD.
9 | It provides a declarative API for installing, configuring, and upgrading the Flux distribution.
10 | The operator extends Flux with self-service capabilities, deployment windows, and preview environments.
11 |
12 | The project is structured as a Go module with the following components:
13 |
14 | * **Flux Operator Kubernetes Controller**: The main component of the project. It is built using the Kubernetes controller-runtime managing the following CRDs:
15 | - **FluxInstance CRD**: Manages the Flux controllers installation and configuration
16 | - **FluxReport CRD**: Reflects the state of a Flux installation
17 | - **ResourceSet CRD**: Manages groups of Kubernetes and Flux resources based on input matrices
18 | - **ResourceSetInputProvider CRD**: Fetches input values from external services (GitHub, GitLab, Azure DevOps, Container Registries)
19 | * **Flux Operator CLI**: A command-line interface for interacting with the Flux Operator. It is built using the Cobra library.
20 | * **Flux Operator MCP Server**: A server that connects AI assistants to Kubernetes clusters running the operator. It is built using the mcp-go library.
21 | * **Flux Status Page**: A web UI for displaying the status of the Flux GitOps pipelines. It is built using Preact, Vite, and Tailwind CSS.
22 |
23 | ## Directory Structure
24 |
25 | ```bash
26 | ├── api/ # Go API definitions for Kubernetes CRDs
27 | ├── cmd/ # Main entrypoint for the binaries
28 | │ ├── cli/ # Flux Operator CLI
29 | │ ├── mcp/ # Flux Operator MCP Server
30 | │ └── operator/ # Flux Operator Kubernetes Controller
31 | ├── config/ # Kubernetes manifests for deploying the operator
32 | ├── docs/ # Kubernetes APIs and MCP tools documentation
33 | ├── hack/ # Scripts for development, building, and releases
34 | ├── internal/ # Internal Go packages
35 | │ ├── controller/ # Controller reconciliation logic
36 | │ └── web/ # Backend for the Flux Status Page
37 | ├── test/ # End-to-end tests with Kubernetes Kind
38 | └── web/ # Preact frontend for the Flux Status Page
39 | ```
40 |
41 | ## Rules of Engagement for AI Agents
42 |
43 | - Do not deviate from the established patterns in the codebase
44 | - If files are modified between reads, assume the change is intentional
45 | - Never run `git tag` and never push tags
46 | - Follow the Go code style used in the project
47 | - Add proper doc comments for new functions and types
48 | - After modifying a function or type, update its doc comment
49 | - Add comments for complex logic but don't comment obvious code
50 | - Read existing tests before writing new ones
51 | - Run individual tests when debugging
52 | - Replace `interface{}` with `any` type alias
53 | - Use `go doc` to read func signatures in external packages
54 |
55 | ## Development Commands for AI Agents
56 |
57 | - Run `make generate` after modifying types in the `api` dir
58 | - Run `make fmt lint` after completing a task and fix lint errors
59 | - Run `make test` to execute all Go tests
60 | - Run `make cli-test` for Flux Operator CLI specific tests
61 | - Run `make mcp-test` for Flux Operator MCP server specific tests
62 | - Run `make web-test` for Flux Status Page frontend tests
63 |
```
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
```markdown
1 | # Contributing
2 |
3 | Flux Operator is [AGPL-3.0 licensed](https://github.com/controlplaneio-fluxcd/flux-operator/blob/main/LICENSE)
4 | and accepts contributions via GitHub pull requests. This document outlines
5 | some of the conventions on how to make it easier to get your contribution accepted.
6 |
7 | We gratefully welcome improvements to code and documentation!
8 |
9 | ## Certificate of Origin
10 |
11 | By contributing to this project, you agree to the Developer Certificate of
12 | Origin ([DCO](https://developercertificate.org/)). This document was created by the Linux Kernel community and is a
13 | simple statement that you, as a contributor, have the legal right to make the contribution.
14 |
15 | > You must sign-off your commits with your name and email address using `git commit -s`.
16 |
17 | ## Project Overview
18 |
19 | The project is structured as a [Go module](https://go.dev/doc/modules/developing) with the following components:
20 |
21 | - [Flux Operator Kubernetes Controller](#flux-operator-kubernetes-controller)
22 | - [Flux Operator CLI](#flux-operator-cli)
23 | - [Flux Operator MCP Server](#flux-operator-mcp-server)
24 | - [Flux Status Web UI](#flux-status-web-ui)
25 |
26 | The documentation is structured as follows:
27 |
28 | - [API documentation](#api-documentation-flux-operator-repository)
29 | - [User Guides](#website-distribution-repository)
30 |
31 | ## Source Code Structure
32 |
33 | ### Flux Operator Kubernetes Controller
34 |
35 | The Flux Operator is built using the Kubernetes [controller-runtime](https://github.com/kubernetes-sigs/controller-runtime)
36 | framework and the [Flux runtime SDK](https://pkg.go.dev/github.com/fluxcd/pkg/runtime).
37 |
38 | The test framework is based on controller-runtime's [envtest](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest)
39 | and [Gomega](https://pkg.go.dev/github.com/onsi/gomega).
40 |
41 | Packages:
42 |
43 | - [api](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/api/) - contains the API definitions for the Flux Operator Kubernetes CRDs
44 | - [cmd/operator](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/cmd/operator/) - contains the entrypoint of the Kubernetes controller
45 | - [internal/controller](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/internal/controller/) - contains the reconcilers for `FluxInstance`, `FluxReport`, `ResourceSet`, and `ResourceSetInputProvider` resources
46 | - [internal/builder](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/internal/builder/) - contains utilities for building and templating Flux manifests
47 | - [internal/entitlement](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/internal/entitlement/) - contains metering and entitlement validation logic
48 | - [internal/gitprovider](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/internal/gitprovider/) - contains integrations for GitHub, GitLab, and Azure DevOps
49 | - [internal/inventory](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/internal/inventory/) - contains inventory management for tracking applied resources
50 | - [internal/reporter](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/internal/reporter/) - contains cluster reporting and metrics collection utilities
51 | - [internal/schedule](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/internal/schedule/) - contains scheduling utilities for automated operations
52 |
53 | To test and build the operator binary, run:
54 |
55 | ```shell
56 | make test build
57 | ```
58 |
59 | The build command writes the binary at `bin/flux-operator` relative to the repository root.
60 |
61 | To run the controller locally, first create a Kubernetes cluster using `kind`:
62 |
63 | ```shell
64 | kind create cluster
65 | ```
66 |
67 | To run the integration tests against the kind cluster, run:
68 |
69 | ```shell
70 | make test-e2e
71 | ```
72 |
73 | For more information on how to run the controller locally and perform manual testing, refer to the
74 | [development](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/docs/dev#local-development) guide.
75 |
76 | ### Flux Operator CLI
77 |
78 | The Flux Operator command-line interface (CLI) is built using the [Cobra](https://github.com/spf13/cobra) library.
79 |
80 | Packages:
81 |
82 | - [cmd/cli](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/cmd/cli/) - contains the commands for the Flux Operator CLI
83 |
84 | To test and build the CLI binary, run:
85 |
86 | ```shell
87 | make cli-test cli-build
88 | ```
89 |
90 | The build command writes the binary at `bin/flux-operator-cli` relative to the repository root.
91 |
92 | To run the CLI locally, use the binary built in the previous step:
93 |
94 | ```shell
95 | ./bin/flux-operator-cli --help
96 | ```
97 |
98 | The CLI commands documentation is maintained in the
99 | [cmd/cli/README.md](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/cmd/cli/README.md) file.
100 |
101 | ### Flux Operator MCP Server
102 |
103 | The Flux Operator MCP Server is built using the [mcp-go](https://github.com/mark3labs/mcp-go) library.
104 |
105 | Packages:
106 |
107 | - [cmd/mcp/k8s](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/cmd/mcp/k8s/) - contains the Kubernetes client
108 | - [cmd/mcp/prompter](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/cmd/mcp/prompter/) - contains the MCP prompts
109 | - [cmd/mcp/toolbox](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/cmd/mcp/toolbox/) - contains the MCP tools
110 | - [cmd/mcp/main.go](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/cmd/mcp/main.go) - contains the server entrypoint
111 |
112 | To test and build the MCP Server binary, run:
113 |
114 | ```shell
115 | make mcp-test mcp-build
116 | ```
117 |
118 | The build command writes the binary at `bin/flux-operator-mcp` relative to the repository root.
119 |
120 | To run the MCP Server using stdio, add the following configuration to your AI assistant's settings:
121 |
122 | ```json
123 | {
124 | "mcpServers": {
125 | "flux-operator-mcp": {
126 | "command": "/path/to/bin/flux-operator-mcp",
127 | "args": ["serve"],
128 | "env": {
129 | "KUBECONFIG": "/path/to/.kube/config"
130 | }
131 | }
132 | }
133 | }
134 | ```
135 |
136 | Replace `/path/to/bin/flux-operator-mcp` with the absolute path to the binary
137 | and `/path/to/.kube/config` with the absolute path to your kubeconfig file.
138 |
139 | After rebuilding the MCP Server binary, you need to restart the AI assistant app to test the new build.
140 |
141 | To run the MCP Server using SSE, use the following command:
142 |
143 | ```shell
144 | export KUBECONFIG=$HOME/.kube/config
145 | ./bin/flux-operator-mcp serve --transport sse --port 8080
146 | ```
147 |
148 | To connect to the server from VS Code, use the following configuration:
149 |
150 | ```json
151 | {
152 | "mcp": {
153 | "servers": {
154 | "flux-operator-mcp": {
155 | "type": "sse",
156 | "url": "http://localhost:8080/sse"
157 | }
158 | }
159 | }
160 | }
161 | ```
162 |
163 | After rebuilding the MCP Server binary, you need to restart the server to test the new build.
164 |
165 | ### Flux Status Page
166 |
167 | The Flux Status Web UI is a single-page application (SPA) built using [Preact](https://preactjs.com/),
168 | [Tailwind CSS](https://tailwindcss.com/), and [Vite](https://vite.dev/).
169 |
170 | The test framework is based on [Vitest](https://vitest.dev/) with [jsdom](https://github.com/jsdom/jsdom)
171 | for DOM simulation and [@testing-library/preact](https://testing-library.com/docs/preact-testing-library/intro/)
172 | for component testing.
173 |
174 | Packages:
175 |
176 | - [web/src](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/web/src/) - contains the Preact components and utilities
177 | - [web/src/components](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/web/src/components/) - contains the UI components
178 | - [web/src/utils](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/web/src/utils/) - contains utility functions for theming, time formatting, etc.
179 | - [web/src/mock](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/web/src/mock/) - contains mock data for development
180 | - [web/dist](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/web/dist/) - build output embedded in the Go binary via `web/embed.go`
181 | - [internal/web](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/internal/web/) - contains the Go HTTP server, API routes, and embedded frontend serving
182 |
183 | To test and build the web UI, run:
184 |
185 | ```shell
186 | make web-test web-build
187 | ```
188 |
189 | The build command writes the production assets to the `web/dist/` directory, which is embedded
190 | into the Go binary and served by the status web server.
191 |
192 | To run the web UI locally with mock data:
193 |
194 | ```shell
195 | make web-dev-mock
196 | ```
197 |
198 | This starts a Vite dev server with hot module replacement at `http://localhost:5173`.
199 |
200 | To run the web UI with a live backend connected to Kubernetes:
201 |
202 | ```shell
203 | # Terminal 1: Start the status web server
204 | make web-run
205 |
206 | # Terminal 2: Start the Vite dev server
207 | make web-dev
208 | ```
209 |
210 | The Vite dev server will proxy API requests to the Go backend running on port 35000.
211 |
212 | To run the web server as cluster-admin (for testing user actions that require elevated permissions),
213 | first create a `web-config.yaml` file with the following content:
214 |
215 | ```yaml
216 | apiVersion: web.fluxcd.controlplane.io/v1
217 | kind: Config
218 | spec:
219 | baseURL: http://localhost:9080
220 | authentication:
221 | type: Anonymous
222 | anonymous:
223 | username: cluster-admin
224 | groups:
225 | - system:masters
226 | ```
227 |
228 | Then run the web server with the config:
229 |
230 | ```shell
231 | make web-run WEB_RUN_ARGS=--web-config=web-config.yaml
232 | ```
233 |
234 | ## Project Documentation Structure
235 |
236 | The project documentation is written in Markdown.
237 | To contribute to the documentation, you can edit the Markdown files in the following locations:
238 |
239 | ### API documentation (flux-operator repository)
240 |
241 | - [docs/api](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/docs/api/v1) - contains the API documentation for the Flux Operator Kubernetes CRDs
242 | - [docs/mcp](https://github.com/controlplaneio-fluxcd/flux-operator/tree/main/docs/mcp) - contains the documentation for the MCP Server tools and prompts
243 |
244 | ### Website (distribution repository)
245 |
246 | - [docs/operator](https://github.com/controlplaneio-fluxcd/distribution/tree/main/docs/operator) - contains the user guides for the Flux Operator
247 | - [docs/mcp](https://github.com/controlplaneio-fluxcd/distribution/tree/main/docs/mcp) - contains the user guides for the MCP Server
248 |
249 | The documentation website is built using [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/).
250 |
251 | ## Acceptance policy
252 |
253 | These things will make a PR more likely to be accepted:
254 |
255 | - a well-described requirement
256 | - tests for new code
257 | - tests for old code!
258 | - new code and tests follow the conventions in old code and tests
259 | - a good commit message (see below)
260 | - all code must abide [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments)
261 | - names should abide [What's in a name](https://talks.golang.org/2014/names.slide#1)
262 | - code must build on Linux, macOS and Windows via plain `go build`
263 | - code should have appropriate test coverage, and tests should be written
264 | to work with `go test`
265 |
266 | Before opening a PR, please check that your code passes the following:
267 |
268 | ```shell
269 | make all
270 | ```
271 |
272 | In general, we will merge a PR once one maintainer has endorsed it.
273 | For significant changes, more people may become involved, and you might
274 | get asked to resubmit the PR or divide the changes into more than one PR.
275 |
276 | ### Format of the Commit Message
277 |
278 | For this project, we prefer the following rules for good commit messages:
279 |
280 | - Limit the subject to 50 characters and write as the continuation
281 | of the sentence "If applied, this commit will ..."
282 | - Explain what and why in the body, if more than a trivial change;
283 | wrap it at 72 characters.
284 |
285 | The [following article](https://chris.beams.io/posts/git-commit/#seven-rules)
286 | has some more helpful advice on documenting your work.
287 |
```
--------------------------------------------------------------------------------
/config/olm/bundle/manifests/fluxinstances.fluxcd.controlplane.io.crd.yaml:
--------------------------------------------------------------------------------
```yaml
1 |
```
--------------------------------------------------------------------------------
/config/olm/bundle/manifests/fluxreports.fluxcd.controlplane.io.crd.yaml:
--------------------------------------------------------------------------------
```yaml
1 |
```
--------------------------------------------------------------------------------
/config/olm/bundle/manifests/resourcesetinputproviders.fluxcd.controlplane.io.crd.yaml:
--------------------------------------------------------------------------------
```yaml
1 |
```
--------------------------------------------------------------------------------
/config/olm/bundle/manifests/resourcesets.fluxcd.controlplane.io.crd.yaml:
--------------------------------------------------------------------------------
```yaml
1 |
```
--------------------------------------------------------------------------------
/hack/boilerplate.go.txt:
--------------------------------------------------------------------------------
```
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
```
--------------------------------------------------------------------------------
/web/postcss.config.js:
--------------------------------------------------------------------------------
```javascript
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
```
--------------------------------------------------------------------------------
/internal/builder/testdata/resourceset/nestedinputs.golden.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: v1
2 | data:
3 | k1: v1
4 | k2: v2
5 | kind: ConfigMap
6 | metadata:
7 | name: configmap1
8 | ---
9 |
```
--------------------------------------------------------------------------------
/config/default/namespace.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | labels:
5 | app.kubernetes.io/name: flux-operator
6 | name: flux-system
7 |
```
--------------------------------------------------------------------------------
/cmd/mcp/toolbox/testdata/kubeconfig_golden.yaml:
--------------------------------------------------------------------------------
```yaml
1 | - cluster: kind-dev
2 | context: kind-dev
3 | current: true
4 | - cluster: kind-staging
5 | context: kind-staging
6 | current: false
7 |
```
--------------------------------------------------------------------------------
/config/manager/account.yaml:
--------------------------------------------------------------------------------
```yaml
1 | ---
2 | apiVersion: v1
3 | kind: ServiceAccount
4 | metadata:
5 | labels:
6 | app.kubernetes.io/name: flux-operator
7 | name: flux-operator
8 |
9 |
```
--------------------------------------------------------------------------------
/config/default/kustomization.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: kustomize.config.k8s.io/v1beta1
2 | kind: Kustomization
3 | namespace: flux-system
4 | resources:
5 | - namespace.yaml
6 | - rbac.yaml
7 | - ../crd
8 | - ../manager
9 |
```
--------------------------------------------------------------------------------
/config/samples/fluxcd_v1_fluxreport.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: fluxcd.controlplane.io/v1
2 | kind: FluxReport
3 | metadata:
4 | name: flux
5 | spec:
6 | distribution:
7 | entitlement: "unknown"
8 | status: "unknown"
9 |
```
--------------------------------------------------------------------------------
/internal/inventory/testdata/inventory1.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: test
5 | ---
6 | apiVersion: v1
7 | kind: ConfigMap
8 | metadata:
9 | name: test1
10 | namespace: test
11 | data:
12 | key: value1
13 |
```
--------------------------------------------------------------------------------
/internal/builder/testdata/resourceset/empty.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: fluxcd.controlplane.io/v1
2 | kind: ResourceSet
3 | metadata:
4 | name: app1
5 | namespace: apps
6 | spec:
7 | commonMetadata:
8 | labels:
9 | app.kubernetes.io/name: podinfo
10 |
```
--------------------------------------------------------------------------------
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
```yaml
1 | version: 2
2 |
3 | updates:
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | groups:
7 | actions:
8 | patterns:
9 | - "*"
10 | schedule:
11 | interval: "daily"
12 |
```
--------------------------------------------------------------------------------
/cmd/cli/testdata/build_resourceset/inputs.yaml:
--------------------------------------------------------------------------------
```yaml
1 | - tenantName: team1
2 | id: 340788154
3 | applications:
4 | - name: app1
5 | envs:
6 | - name: staging
7 | version: v1.0.1
8 | - name: production
9 | version: v1.0.0
10 |
```
--------------------------------------------------------------------------------
/config/samples/kustomization.yaml:
--------------------------------------------------------------------------------
```yaml
1 | ## Append samples of your project ##
2 | resources:
3 | - fluxcd_v1_fluxinstance.yaml
4 | - fluxcd_v1_fluxreport.yaml
5 | - fluxcd_v1_resourceset.yaml
6 | # +kubebuilder:scaffold:manifestskustomizesamples
7 |
```
--------------------------------------------------------------------------------
/config/rbac/service_account.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: v1
2 | kind: ServiceAccount
3 | metadata:
4 | labels:
5 | app.kubernetes.io/name: flux-operator
6 | app.kubernetes.io/managed-by: kustomize
7 | name: controller-manager
8 | namespace: system
9 |
```
--------------------------------------------------------------------------------
/config/olm/ci.yaml:
--------------------------------------------------------------------------------
```yaml
1 | ---
2 | # Use `replaces-mode` or `semver-mode`. Once you switch to `semver-mode`, there is no easy way back.
3 | updateGraph: semver-mode
4 | addReviewers: true
5 | reviewers:
6 | - stefanprodan
7 | - matheuscscp
8 |
```
--------------------------------------------------------------------------------
/web/src/main.jsx:
--------------------------------------------------------------------------------
```javascript
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | import { render } from 'preact'
5 | import { App } from './app'
6 | import './index.css'
7 |
8 | render(<App />, document.getElementById('app'))
9 |
```
--------------------------------------------------------------------------------
/web/embed.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package web
5 |
6 | import "embed"
7 |
8 | //go:embed dist/*
9 | var web embed.FS
10 |
11 | // GetFS returns the embedded SPA filesystem.
12 | func GetFS() embed.FS {
13 | return web
14 | }
15 |
```
--------------------------------------------------------------------------------
/config/manager/kustomization.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: kustomize.config.k8s.io/v1beta1
2 | kind: Kustomization
3 | resources:
4 | - account.yaml
5 | - deployment.yaml
6 | - service.yaml
7 | images:
8 | - name: flux-operator
9 | newName: ghcr.io/controlplaneio-fluxcd/flux-operator
10 | newTag: v0.38.1
11 |
```
--------------------------------------------------------------------------------
/internal/inventory/testdata/inventory2.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: test
5 | ---
6 | apiVersion: v1
7 | kind: ConfigMap
8 | metadata:
9 | name: test1
10 | namespace: test
11 | data:
12 | key: value1
13 | ---
14 | apiVersion: v1
15 | kind: ConfigMap
16 | metadata:
17 | name: test2
18 | namespace: test
19 | data:
20 | key: value2
21 |
```
--------------------------------------------------------------------------------
/config/mcp/kustomization.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: kustomize.config.k8s.io/v1beta1
2 | kind: Kustomization
3 | namespace: flux-system
4 | resources:
5 | - deployment.yaml
6 | - service.yaml
7 | images:
8 | - name: flux-operator-mcp
9 | newName: ghcr.io/controlplaneio-fluxcd/flux-operator-mcp
10 | newTag: v0.38.1
11 |
```
--------------------------------------------------------------------------------
/internal/inputs/id.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package inputs
5 |
6 | import (
7 | "fmt"
8 | "hash/adler32"
9 | )
10 |
11 | // ID returns a short, opaque ID for input sets.
12 | func ID(s string) string {
13 | return fmt.Sprintf("%v", adler32.Checksum([]byte(s)))
14 | }
15 |
```
--------------------------------------------------------------------------------
/cmd/cli/debug.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var debugCmd = &cobra.Command{
11 | Use: "debug",
12 | Short: "Debug Flux Operator features",
13 | }
14 |
15 | func init() {
16 | rootCmd.AddCommand(debugCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/build.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var buildCmd = &cobra.Command{
11 | Use: "build",
12 | Short: "Build Flux Operator resources",
13 | }
14 |
15 | func init() {
16 | rootCmd.AddCommand(buildCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/create.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var createCmd = &cobra.Command{
11 | Use: "create",
12 | Short: "Create Kubernetes resources",
13 | }
14 |
15 | func init() {
16 | rootCmd.AddCommand(createCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/delete.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var deleteCmd = &cobra.Command{
11 | Use: "delete",
12 | Short: "Delete Flux Operator resources",
13 | }
14 |
15 | func init() {
16 | rootCmd.AddCommand(deleteCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/export.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var exportCmd = &cobra.Command{
11 | Use: "export",
12 | Short: "Export Flux Operator resources",
13 | }
14 |
15 | func init() {
16 | rootCmd.AddCommand(exportCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/config/mcp/service.yaml:
--------------------------------------------------------------------------------
```yaml
1 | ---
2 | apiVersion: v1
3 | kind: Service
4 | metadata:
5 | name: flux-operator-mcp
6 | labels:
7 | app.kubernetes.io/name: flux-operator-mcp
8 | spec:
9 | ports:
10 | - name: http
11 | port: 9090
12 | protocol: TCP
13 | targetPort: http
14 | selector:
15 | app.kubernetes.io/name: flux-operator-mcp
16 |
```
--------------------------------------------------------------------------------
/cmd/cli/debug_web.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var debugWebCmd = &cobra.Command{
11 | Use: "web",
12 | Short: "Debug Flux Operator Web UI features",
13 | }
14 |
15 | func init() {
16 | debugCmd.AddCommand(debugWebCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/wait.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var waitCmd = &cobra.Command{
11 | Use: "wait",
12 | Short: "Wait for Flux Operator resources to become ready",
13 | }
14 |
15 | func init() {
16 | rootCmd.AddCommand(waitCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/resume.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var resumeCmd = &cobra.Command{
11 | Use: "resume",
12 | Short: "Resume Flux Operator resources reconciliation",
13 | }
14 |
15 | func init() {
16 | rootCmd.AddCommand(resumeCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/suspend.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var suspendCmd = &cobra.Command{
11 | Use: "suspend",
12 | Short: "Suspend Flux Operator resources reconciliation",
13 | }
14 |
15 | func init() {
16 | rootCmd.AddCommand(suspendCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/config/crd/kustomization.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: kustomize.config.k8s.io/v1beta1
2 | kind: Kustomization
3 | resources:
4 | - bases/fluxcd.controlplane.io_fluxinstances.yaml
5 | - bases/fluxcd.controlplane.io_fluxreports.yaml
6 | - bases/fluxcd.controlplane.io_resourcesets.yaml
7 | - bases/fluxcd.controlplane.io_resourcesetinputproviders.yaml
8 |
```
--------------------------------------------------------------------------------
/cmd/cli/distro_revoke.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var distroRevokeCmd = &cobra.Command{
11 | Use: "revoke",
12 | Short: "Maintain a ledger of revoked license keys",
13 | }
14 |
15 | func init() {
16 | distroCmd.AddCommand(distroRevokeCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/reconcile.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var reconcileCmd = &cobra.Command{
11 | Use: "reconcile",
12 | Short: "Trigger Flux Operator resources reconciliation",
13 | }
14 |
15 | func init() {
16 | rootCmd.AddCommand(reconcileCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/internal/builder/testdata/resourceset/nestedinputs.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: fluxcd.controlplane.io/v1
2 | kind: ResourceSet
3 | metadata:
4 | name: app1
5 | namespace: apps
6 | spec:
7 | inputs:
8 | - foo:
9 | bar:
10 | k1: v1
11 | k2: v2
12 | resources:
13 | - apiVersion: v1
14 | kind: ConfigMap
15 | metadata:
16 | name: configmap1
17 | data: << inputs.foo.bar | toYaml | nindent 2 >>
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/distro_keygen.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var distroKeygenCmd = &cobra.Command{
11 | Use: "keygen",
12 | Short: "Generate asymmetric key pairs for encryption and signing",
13 | }
14 |
15 | func init() {
16 | distroCmd.AddCommand(distroKeygenCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/distro_sign.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var distroSignCmd = &cobra.Command{
11 | Use: "sign",
12 | Short: "Issue signed license keys and attestations of artifacts and manifests",
13 | }
14 |
15 | func init() {
16 | distroCmd.AddCommand(distroSignCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/distro_verify.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var distroVerifyCmd = &cobra.Command{
11 | Use: "verify",
12 | Short: "Verify license keys and attestations of artifacts and manifests",
13 | }
14 |
15 | func init() {
16 | distroCmd.AddCommand(distroVerifyCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/web/src/mock/action.js:
--------------------------------------------------------------------------------
```javascript
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | // Mock action response for POST /api/v1/action
5 | export const mockAction = (body) => {
6 | return {
7 | success: true,
8 | message: `${body.action.charAt(0).toUpperCase() + body.action.slice(1)} triggered for ${body.namespace}/${body.name}`
9 | }
10 | }
11 |
```
--------------------------------------------------------------------------------
/cmd/cli/distro_decrypt.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var distroDecryptCmd = &cobra.Command{
11 | Use: "decrypt",
12 | Short: "Decrypt sensitive information using JWE with asymmetric key pairs",
13 | }
14 |
15 | func init() {
16 | distroCmd.AddCommand(distroDecryptCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/cmd/cli/distro_encrypt.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | var distroEncryptCmd = &cobra.Command{
11 | Use: "encrypt",
12 | Short: "Encrypt sensitive information using JWE with asymmetric key pairs",
13 | }
14 |
15 | func init() {
16 | distroCmd.AddCommand(distroEncryptCmd)
17 | }
18 |
```
--------------------------------------------------------------------------------
/internal/web/config/groupversion_info.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package config
5 |
6 | import (
7 | "k8s.io/apimachinery/pkg/runtime/schema"
8 | )
9 |
10 | var (
11 | // GroupVersion is group and version of the Flux Status Page configuration API.
12 | GroupVersion = schema.GroupVersion{Group: "web.fluxcd.controlplane.io", Version: "v1"}
13 | )
14 |
```
--------------------------------------------------------------------------------
/config/manager/service.yaml:
--------------------------------------------------------------------------------
```yaml
1 | ---
2 | apiVersion: v1
3 | kind: Service
4 | metadata:
5 | labels:
6 | app.kubernetes.io/name: flux-operator
7 | name: flux-operator
8 | spec:
9 | ports:
10 | - name: http-web
11 | port: 9080
12 | protocol: TCP
13 | targetPort: 9080
14 | - name: http
15 | port: 8080
16 | protocol: TCP
17 | targetPort: 8080
18 | selector:
19 | app.kubernetes.io/name: flux-operator
20 |
```
--------------------------------------------------------------------------------
/config/olm/bundle/manifests/flux-operator.service.yaml:
--------------------------------------------------------------------------------
```yaml
1 | ---
2 | apiVersion: v1
3 | kind: Service
4 | metadata:
5 | name: flux-operator
6 | labels:
7 | app.kubernetes.io/name: flux-operator
8 | spec:
9 | ports:
10 | - name: http-web
11 | port: 9080
12 | protocol: TCP
13 | targetPort: 9080
14 | - name: http
15 | port: 8080
16 | protocol: TCP
17 | targetPort: 8080
18 | selector:
19 | app.kubernetes.io/name: flux-operator
20 |
```
--------------------------------------------------------------------------------
/cmd/mcp/prompter/index.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package prompter
5 |
6 | // PromptSet returns a slice of predefined Prompt objects
7 | // with their associated names, descriptions, and handlers.
8 | func (m *Manager) PromptSet() []SystemPrompt {
9 | return []SystemPrompt{
10 | m.NewDebugKustomizationPrompt(),
11 | m.NewDebugHelmReleasePrompt(),
12 | }
13 | }
14 |
```
--------------------------------------------------------------------------------
/internal/builder/result.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2024 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package builder
5 |
6 | import "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
7 |
8 | // Result holds the build result.
9 | type Result struct {
10 | Version string
11 | Digest string
12 | Revision string
13 | Objects []*unstructured.Unstructured
14 | ComponentImages []ComponentImage
15 | }
16 |
```
--------------------------------------------------------------------------------
/internal/gitprovider/options.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2024 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package gitprovider
5 |
6 | import (
7 | "crypto/tls"
8 |
9 | "github.com/controlplaneio-fluxcd/flux-operator/internal/filtering"
10 | )
11 |
12 | // Options holds the configuration for the Git SaaS provider.
13 | type Options struct {
14 | URL string
15 | TLSConfig *tls.Config
16 | Token string
17 | Filters filtering.Filters
18 | }
19 |
```
--------------------------------------------------------------------------------
/config/rbac/role_binding.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: rbac.authorization.k8s.io/v1
2 | kind: ClusterRoleBinding
3 | metadata:
4 | labels:
5 | app.kubernetes.io/name: flux-operator
6 | app.kubernetes.io/managed-by: kustomize
7 | name: manager-rolebinding
8 | roleRef:
9 | apiGroup: rbac.authorization.k8s.io
10 | kind: ClusterRole
11 | name: manager-role
12 | subjects:
13 | - kind: ServiceAccount
14 | name: controller-manager
15 | namespace: system
16 |
```
--------------------------------------------------------------------------------
/config/monitoring/flux-operator.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: monitoring.coreos.com/v1
2 | kind: ServiceMonitor
3 | metadata:
4 | name: flux-operator
5 | labels:
6 | app.kubernetes.io/component: metrics
7 | app.kubernetes.io/part-of: flux
8 | spec:
9 | namespaceSelector:
10 | matchNames:
11 | - flux-system
12 | selector:
13 | matchLabels:
14 | app.kubernetes.io/name: flux-operator
15 | endpoints:
16 | - targetPort: 8080
17 | path: /metrics
18 |
```
--------------------------------------------------------------------------------
/config/rbac/leader_election_role_binding.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: rbac.authorization.k8s.io/v1
2 | kind: RoleBinding
3 | metadata:
4 | labels:
5 | app.kubernetes.io/name: flux-operator
6 | app.kubernetes.io/managed-by: kustomize
7 | name: leader-election-rolebinding
8 | roleRef:
9 | apiGroup: rbac.authorization.k8s.io
10 | kind: Role
11 | name: leader-election-role
12 | subjects:
13 | - kind: ServiceAccount
14 | name: controller-manager
15 | namespace: system
16 |
```
--------------------------------------------------------------------------------
/test/e2e/e2e_suite_test.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2024 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package e2e
5 |
6 | import (
7 | "fmt"
8 | "testing"
9 |
10 | . "github.com/onsi/ginkgo/v2"
11 | . "github.com/onsi/gomega"
12 | )
13 |
14 | // Run e2e tests using the Ginkgo runner.
15 | func TestE2E(t *testing.T) {
16 | RegisterFailHandler(Fail)
17 | fmt.Fprintf(GinkgoWriter, "Starting flux-operator suite\n") //nolint:errcheck
18 | RunSpecs(t, "e2e suite")
19 | }
20 |
```
--------------------------------------------------------------------------------
/internal/builder/testdata/resourceset/noinputs.golden.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: source.toolkit.fluxcd.io/v1beta2
2 | kind: OCIRepository
3 | metadata:
4 | name: app1
5 | namespace: apps
6 | spec:
7 | interval: 10m
8 | ref:
9 | semver: '*'
10 | url: oci://ghcr.io/org/charts/app1
11 | ---
12 | apiVersion: helm.toolkit.fluxcd.io/v2
13 | kind: HelmRelease
14 | metadata:
15 | name: app1
16 | namespace: apps
17 | spec:
18 | chartRef:
19 | kind: OCIRepository
20 | name: app1
21 | interval: 1h
22 | releaseName: app1
23 | ---
24 |
```
--------------------------------------------------------------------------------
/test/olm/e2e_suite_test.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2024 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package e2eolm
5 |
6 | import (
7 | "fmt"
8 | "testing"
9 |
10 | . "github.com/onsi/ginkgo/v2"
11 | . "github.com/onsi/gomega"
12 | )
13 |
14 | // Run e2e tests using the Ginkgo runner.
15 | func TestE2E(t *testing.T) {
16 | RegisterFailHandler(Fail)
17 | fmt.Fprintf(GinkgoWriter, "Starting flux-operator olm e2e suite\n") //nolint:errcheck
18 | RunSpecs(t, "olm e2e suite")
19 | }
20 |
```
--------------------------------------------------------------------------------
/config/data/flux-vex/v2.4.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "@context": "https://openvex.dev/ns/v0.2.0",
3 | "@id": "https://openvex.dev/docs/public/vex-f843e58a33079b9f9344d4b4e72a3dcc0ee7ad51825e087b96692dccaf21f2d8",
4 | "author": "[email protected]",
5 | "role": "Enterprise Flux Maintainers",
6 | "timestamp": "2024-09-30T17:26:04.422544+03:00",
7 | "last_updated": "2024-09-30T17:26:04.422544+03:00",
8 | "version": 2,
9 | "statements": [
10 | ]
11 | }
12 |
```
--------------------------------------------------------------------------------
/cmd/cli/testdata/build_resourceset/rsip.yaml:
--------------------------------------------------------------------------------
```yaml
1 | ---
2 | apiVersion: fluxcd.controlplane.io/v1
3 | kind: ResourceSetInputProvider
4 | metadata:
5 | name: team1-apps
6 | namespace: test
7 | labels:
8 | fluxcd.controlplane.io/role: provisioning
9 | spec:
10 | type: Static
11 | defaultValues:
12 | tenantName: team1
13 | applications:
14 | - name: app1
15 | envs:
16 | - name: staging
17 | version: v1.0.1
18 | - name: production
19 | version: v1.0.0
20 |
```
--------------------------------------------------------------------------------
/internal/testutils/time.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package testutils
5 |
6 | import (
7 | "testing"
8 | "time"
9 |
10 | . "github.com/onsi/gomega"
11 | )
12 |
13 | // ParseTime parses a time string in RFC3339 format and returns a time.Time object.
14 | func ParseTime(t *testing.T, s string) time.Time {
15 | t.Helper()
16 | g := NewWithT(t)
17 | tm, err := time.Parse(time.RFC3339, s)
18 | g.Expect(err).NotTo(HaveOccurred())
19 | return tm
20 | }
21 |
```
--------------------------------------------------------------------------------
/config/monitoring/flux-controllers.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: monitoring.coreos.com/v1
2 | kind: PodMonitor
3 | metadata:
4 | name: flux-controllers
5 | labels:
6 | app.kubernetes.io/component: metrics
7 | app.kubernetes.io/part-of: flux
8 | spec:
9 | namespaceSelector:
10 | matchNames:
11 | - flux-system
12 | selector:
13 | matchExpressions:
14 | - key: app.kubernetes.io/part-of
15 | operator: In
16 | values:
17 | - flux
18 | podMetricsEndpoints:
19 | - port: http-prom
20 |
```
--------------------------------------------------------------------------------
/config/monitoring/kustomization.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: kustomize.config.k8s.io/v1beta1
2 | kind: Kustomization
3 | resources:
4 | - flux-controllers.yaml
5 | - flux-operator.yaml
6 | configMapGenerator:
7 | - name: flux-grafana-dashboards
8 | files:
9 | - dashboards/flux-k8s-api-performance.json
10 | - dashboards/flux-performance.json
11 | options:
12 | labels:
13 | grafana_dashboard: "1"
14 | app.kubernetes.io/component: monitoring
15 | app.kubernetes.io/part-of: flux
16 |
```
--------------------------------------------------------------------------------
/internal/inputs/json_test.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package inputs_test
5 |
6 | import (
7 | "testing"
8 |
9 | apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
10 |
11 | "github.com/controlplaneio-fluxcd/flux-operator/internal/inputs"
12 | )
13 |
14 | func mustJSON(t *testing.T, s string) *apiextensionsv1.JSON {
15 | id, err := inputs.JSON(s)
16 | if err != nil {
17 | t.Fatalf("failed to compute JSON: %v", err)
18 | }
19 | return id
20 | }
21 |
```
--------------------------------------------------------------------------------
/web/tailwind.config.js:
--------------------------------------------------------------------------------
```javascript
1 | /** @type {import('tailwindcss').Config} */
2 | export default {
3 | darkMode: 'class',
4 | content: [
5 | "./index.html",
6 | "./src/**/*.{js,ts,jsx,tsx}",
7 | ],
8 | theme: {
9 | extend: {
10 | fontFamily: {
11 | sans: ['inter', 'system-ui', 'sans-serif'],
12 | },
13 | colors: {
14 | 'flux-blue': '#0066CC',
15 | 'success': '#10B981',
16 | 'warning': '#F59E0B',
17 | 'danger': '#EF4444',
18 | },
19 | },
20 | },
21 | plugins: [],
22 | }
23 |
```
--------------------------------------------------------------------------------
/internal/inputs/json.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package inputs
5 |
6 | import (
7 | apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
8 | "k8s.io/apimachinery/pkg/util/json"
9 | )
10 |
11 | // JSON returns the Kubernetes API JSON representation of any value.
12 | func JSON(v any) (*apiextensionsv1.JSON, error) {
13 | b, err := json.Marshal(v)
14 | if err != nil {
15 | return nil, err
16 | }
17 | return &apiextensionsv1.JSON{Raw: b}, nil
18 | }
19 |
```
--------------------------------------------------------------------------------
/config/rbac/fluxreport_viewer_role.yaml:
--------------------------------------------------------------------------------
```yaml
1 | # permissions for end users to view fluxreports.
2 | apiVersion: rbac.authorization.k8s.io/v1
3 | kind: ClusterRole
4 | metadata:
5 | labels:
6 | app.kubernetes.io/name: flux-operator
7 | app.kubernetes.io/managed-by: kustomize
8 | name: fluxreport-viewer-role
9 | rules:
10 | - apiGroups:
11 | - fluxcd.controlplane.io
12 | resources:
13 | - fluxreports
14 | verbs:
15 | - get
16 | - list
17 | - watch
18 | - apiGroups:
19 | - fluxcd.controlplane.io
20 | resources:
21 | - fluxreports/status
22 | verbs:
23 | - get
24 |
```
--------------------------------------------------------------------------------
/config/rbac/resourceset_viewer_role.yaml:
--------------------------------------------------------------------------------
```yaml
1 | # permissions for end users to view fluxinstances.
2 | apiVersion: rbac.authorization.k8s.io/v1
3 | kind: ClusterRole
4 | metadata:
5 | labels:
6 | app.kubernetes.io/name: flux-operator
7 | app.kubernetes.io/managed-by: kustomize
8 | name: resourceset-viewer-role
9 | rules:
10 | - apiGroups:
11 | - fluxcd.controlplane.io
12 | resources:
13 | - resourcesets
14 | verbs:
15 | - get
16 | - list
17 | - watch
18 | - apiGroups:
19 | - fluxcd.controlplane.io
20 | resources:
21 | - resourcesets/status
22 | verbs:
23 | - get
24 |
```
--------------------------------------------------------------------------------
/config/rbac/fluxinstance_viewer_role.yaml:
--------------------------------------------------------------------------------
```yaml
1 | # permissions for end users to view fluxinstances.
2 | apiVersion: rbac.authorization.k8s.io/v1
3 | kind: ClusterRole
4 | metadata:
5 | labels:
6 | app.kubernetes.io/name: flux-operator
7 | app.kubernetes.io/managed-by: kustomize
8 | name: fluxinstance-viewer-role
9 | rules:
10 | - apiGroups:
11 | - fluxcd.controlplane.io
12 | resources:
13 | - fluxinstances
14 | verbs:
15 | - get
16 | - list
17 | - watch
18 | - apiGroups:
19 | - fluxcd.controlplane.io
20 | resources:
21 | - fluxinstances/status
22 | verbs:
23 | - get
24 |
```
--------------------------------------------------------------------------------
/cmd/cli/testdata/build_resourceset/rsip-named.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: fluxcd.controlplane.io/v1
2 | kind: ResourceSetInputProvider
3 | metadata:
4 | name: app1-tenant1
5 | namespace: apps
6 | spec:
7 | type: Static
8 | defaultValues:
9 | tenant: "tenant1"
10 | app:
11 | version: "7.8.x"
12 | replicas: 1
13 | ---
14 | apiVersion: fluxcd.controlplane.io/v1
15 | kind: ResourceSetInputProvider
16 | metadata:
17 | name: app1-tenant2
18 | namespace: apps
19 | spec:
20 | type: Static
21 | defaultValues:
22 | tenant: "tenant2"
23 | app:
24 | version: "5.9.x"
25 | replicas: 2
```
--------------------------------------------------------------------------------
/internal/builder/testdata/resourceset/missing-inputs.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: fluxcd.controlplane.io/v1
2 | kind: ResourceSet
3 | metadata:
4 | name: app1
5 | namespace: apps
6 | spec:
7 | inputs:
8 | - tenant: team1
9 | semver: "1.x"
10 | - tenant: team2
11 | resources:
12 | - apiVersion: source.toolkit.fluxcd.io/v1beta2
13 | kind: OCIRepository
14 | metadata:
15 | name: app1-<< inputs.tenant >>
16 | namespace: apps
17 | spec:
18 | interval: 10m
19 | url: oci://ghcr.io/org/charts/app1
20 | ref:
21 | semver: << inputs.semver >>
22 |
```
--------------------------------------------------------------------------------
/config/rbac/fluxreport_editor_role.yaml:
--------------------------------------------------------------------------------
```yaml
1 | # permissions for end users to edit fluxreports.
2 | apiVersion: rbac.authorization.k8s.io/v1
3 | kind: ClusterRole
4 | metadata:
5 | labels:
6 | app.kubernetes.io/name: flux-operator
7 | app.kubernetes.io/managed-by: kustomize
8 | name: fluxreport-editor-role
9 | rules:
10 | - apiGroups:
11 | - fluxcd.controlplane.io
12 | resources:
13 | - fluxreports
14 | verbs:
15 | - create
16 | - delete
17 | - get
18 | - list
19 | - patch
20 | - update
21 | - watch
22 | - apiGroups:
23 | - fluxcd.controlplane.io
24 | resources:
25 | - fluxreports/status
26 | verbs:
27 | - get
28 |
```
--------------------------------------------------------------------------------
/config/rbac/resourceset_editor_role.yaml:
--------------------------------------------------------------------------------
```yaml
1 | # permissions for end users to edit fluxinstances.
2 | apiVersion: rbac.authorization.k8s.io/v1
3 | kind: ClusterRole
4 | metadata:
5 | labels:
6 | app.kubernetes.io/name: flux-operator
7 | app.kubernetes.io/managed-by: kustomize
8 | name: resourceset-editor-role
9 | rules:
10 | - apiGroups:
11 | - fluxcd.controlplane.io
12 | resources:
13 | - resourcesets
14 | verbs:
15 | - create
16 | - delete
17 | - get
18 | - list
19 | - patch
20 | - update
21 | - watch
22 | - apiGroups:
23 | - fluxcd.controlplane.io
24 | resources:
25 | - resourcesets/status
26 | verbs:
27 | - get
28 |
```
--------------------------------------------------------------------------------
/config/rbac/fluxinstance_editor_role.yaml:
--------------------------------------------------------------------------------
```yaml
1 | # permissions for end users to edit fluxinstances.
2 | apiVersion: rbac.authorization.k8s.io/v1
3 | kind: ClusterRole
4 | metadata:
5 | labels:
6 | app.kubernetes.io/name: flux-operator
7 | app.kubernetes.io/managed-by: kustomize
8 | name: fluxinstance-editor-role
9 | rules:
10 | - apiGroups:
11 | - fluxcd.controlplane.io
12 | resources:
13 | - fluxinstances
14 | verbs:
15 | - create
16 | - delete
17 | - get
18 | - list
19 | - patch
20 | - update
21 | - watch
22 | - apiGroups:
23 | - fluxcd.controlplane.io
24 | resources:
25 | - fluxinstances/status
26 | verbs:
27 | - get
28 |
```
--------------------------------------------------------------------------------
/config/crd/kustomizeconfig.yaml:
--------------------------------------------------------------------------------
```yaml
1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD
2 | nameReference:
3 | - kind: Service
4 | version: v1
5 | fieldSpecs:
6 | - kind: CustomResourceDefinition
7 | version: v1
8 | group: apiextensions.k8s.io
9 | path: spec/conversion/webhook/clientConfig/service/name
10 |
11 | namespace:
12 | - kind: CustomResourceDefinition
13 | version: v1
14 | group: apiextensions.k8s.io
15 | path: spec/conversion/webhook/clientConfig/service/namespace
16 | create: false
17 |
18 | varReference:
19 | - path: metadata/annotations
20 |
```
--------------------------------------------------------------------------------
/config/olm/test/opm.Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
1 | FROM alpine:3.20
2 |
3 | ARG DOCKER_VERSION=26.1.3
4 | ARG OPM_VERSION=4.15.16
5 | # x86_64 or aarch64
6 | ARG ARCH=x86_64
7 |
8 | WORKDIR /opt
9 | RUN wget https://download.docker.com/linux/static/stable/${ARCH}/docker-${DOCKER_VERSION}.tgz
10 | RUN tar xf docker-${DOCKER_VERSION}.tgz
11 |
12 | RUN wget https://mirror.openshift.com/pub/openshift-v4/${ARCH}/clients/ocp/${OPM_VERSION}/opm-linux-${OPM_VERSION}.tar.gz
13 | RUN tar xf opm-linux-${OPM_VERSION}.tar.gz
14 |
15 | FROM ubuntu:24.04
16 |
17 | WORKDIR /opt
18 |
19 | COPY --from=0 /opt/docker/docker /usr/bin/
20 | COPY --from=0 /opt/opm /opt/
21 |
22 | ENTRYPOINT ["/opt/opm"]
23 |
```
--------------------------------------------------------------------------------
/config/samples/fluxcd_v1_resourcesetinputprovider.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: fluxcd.controlplane.io/v1
2 | kind: ResourceSetInputProvider
3 | metadata:
4 | name: demo
5 | namespace: default
6 | annotations:
7 | fluxcd.controlplane.io/reconcile: "enabled"
8 | fluxcd.controlplane.io/reconcileEvery: "10m"
9 | fluxcd.controlplane.io/reconcileTimeout: "1m"
10 | spec:
11 | type: GitHubPullRequest
12 | url: "https://github.com/fluxcd-testing/pr-testing"
13 | filter:
14 | limit: 10
15 | includeBranch: "^stefanprodan-patch-.*$"
16 | labels:
17 | - "enhancement"
18 | skip:
19 | labels:
20 | - "deploy/flux-preview-pause"
21 | - "!test-build-push/passed"
22 |
```
--------------------------------------------------------------------------------
/cmd/cli/testdata/build_resourceset/rsip-labeled.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: fluxcd.controlplane.io/v1
2 | kind: ResourceSetInputProvider
3 | metadata:
4 | name: app1-tenant1
5 | namespace: apps
6 | labels:
7 | some: label
8 | anotherLabel: value1
9 | spec:
10 | type: Static
11 | defaultValues:
12 | tenant: "tenant1"
13 | app:
14 | version: "6.7.x"
15 | replicas: 2
16 | ---
17 | apiVersion: fluxcd.controlplane.io/v1
18 | kind: ResourceSetInputProvider
19 | metadata:
20 | name: app1-tenant2
21 | namespace: apps
22 | labels:
23 | some: label
24 | anotherLabel: value2
25 | spec:
26 | type: Static
27 | defaultValues:
28 | tenant: "tenant2"
29 | app:
30 | version: "6.6.x"
31 | replicas: 3
```
--------------------------------------------------------------------------------
/cmd/mcp/k8s/suite_test.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package k8s
5 |
6 | import (
7 | corev1 "k8s.io/api/core/v1"
8 | apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
9 | "k8s.io/apimachinery/pkg/runtime"
10 | utilruntime "k8s.io/apimachinery/pkg/util/runtime"
11 |
12 | fluxcdv1 "github.com/controlplaneio-fluxcd/flux-operator/api/v1"
13 | )
14 |
15 | func NewTestScheme() *runtime.Scheme {
16 | s := runtime.NewScheme()
17 | utilruntime.Must(corev1.AddToScheme(s))
18 | utilruntime.Must(apiextensionsv1.AddToScheme(s))
19 | utilruntime.Must(fluxcdv1.AddToScheme(s))
20 | return s
21 | }
22 |
```
--------------------------------------------------------------------------------
/.github/workflows/actions-test.yaml:
--------------------------------------------------------------------------------
```yaml
1 | name: actions
2 |
3 | on:
4 | pull_request:
5 | paths:
6 | - 'action/**'
7 | - '.github/workflows/actions-test.yaml'
8 | push:
9 | branches:
10 | - 'main'
11 | paths:
12 | - 'actions/**'
13 | - '.github/workflows/actions-test.yaml'
14 |
15 | permissions:
16 | contents: read # for actions/checkout to fetch code
17 |
18 | jobs:
19 | test:
20 | runs-on: ubuntu-latest
21 | steps:
22 | - name: Checkout
23 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
24 | - name: Setup CLI
25 | uses: ./actions/setup
26 | - name: Run CLI
27 | run: flux-operator version --client
28 |
```
--------------------------------------------------------------------------------
/config/rbac/leader_election_role.yaml:
--------------------------------------------------------------------------------
```yaml
1 | # permissions to do leader election.
2 | apiVersion: rbac.authorization.k8s.io/v1
3 | kind: Role
4 | metadata:
5 | labels:
6 | app.kubernetes.io/name: flux-operator
7 | app.kubernetes.io/managed-by: kustomize
8 | name: leader-election-role
9 | rules:
10 | - apiGroups:
11 | - ""
12 | resources:
13 | - configmaps
14 | verbs:
15 | - get
16 | - list
17 | - watch
18 | - create
19 | - update
20 | - patch
21 | - delete
22 | - apiGroups:
23 | - coordination.k8s.io
24 | resources:
25 | - leases
26 | verbs:
27 | - get
28 | - list
29 | - watch
30 | - create
31 | - update
32 | - patch
33 | - delete
34 | - apiGroups:
35 | - ""
36 | resources:
37 | - events
38 | verbs:
39 | - create
40 | - patch
41 |
```
--------------------------------------------------------------------------------
/config/terraform/values/components.yaml:
--------------------------------------------------------------------------------
```yaml
1 | instance:
2 | components:
3 | - source-controller
4 | - kustomize-controller
5 | - helm-controller
6 | - notification-controller
7 | - image-reflector-controller
8 | - image-automation-controller
9 | kustomize:
10 | patches:
11 | - target:
12 | kind: Deployment
13 | patch: |
14 | - op: replace
15 | path: /spec/template/spec/nodeSelector
16 | value:
17 | kubernetes.io/os: linux
18 | - op: add
19 | path: /spec/template/spec/tolerations
20 | value:
21 | - key: "CriticalAddonsOnly"
22 | operator: "Exists"
23 |
```
--------------------------------------------------------------------------------
/internal/builder/testdata/resourceset/noinputs.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: fluxcd.controlplane.io/v1
2 | kind: ResourceSet
3 | metadata:
4 | name: app1
5 | namespace: apps
6 | spec:
7 | resources:
8 | - apiVersion: source.toolkit.fluxcd.io/v1beta2
9 | kind: OCIRepository
10 | metadata:
11 | name: app1
12 | namespace: apps
13 | spec:
14 | interval: 10m
15 | url: oci://ghcr.io/org/charts/app1
16 | ref:
17 | semver: '*'
18 | - apiVersion: helm.toolkit.fluxcd.io/v2
19 | kind: HelmRelease
20 | metadata:
21 | name: app1
22 | namespace: apps
23 | spec:
24 | interval: 1h
25 | releaseName: app1
26 | chartRef:
27 | kind: OCIRepository
28 | name: app1
29 |
```
--------------------------------------------------------------------------------
/.github/actions/runner-cleanup/action.yml:
--------------------------------------------------------------------------------
```yaml
1 | name: Runner Cleanup
2 | description: A GitHub Action for removing bloat from Ubuntu GitHub Actions runner.
3 | author: Stefan Prodan
4 | branding:
5 | color: blue
6 | icon: command
7 | runs:
8 | using: composite
9 | steps:
10 | - name: "Disk Usage Before Cleanup"
11 | shell: bash
12 | run: |
13 | df -h
14 | - name: "Remove .NET, Android and Haskell"
15 | shell: bash
16 | run: |
17 | sudo rm -rf /usr/share/dotnet || true
18 | sudo rm -rf /usr/local/lib/android || true
19 | sudo rm -rf /opt/ghc || true
20 | sudo rm -rf /usr/local/.ghcup || true
21 | - name: "Disk Usage After Cleanup"
22 | shell: bash
23 | run: |
24 | df -h
25 |
```
--------------------------------------------------------------------------------
/test/olm/scorecard_test.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2024 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package e2eolm
5 |
6 | import (
7 | "os/exec"
8 |
9 | . "github.com/onsi/ginkgo/v2"
10 | . "github.com/onsi/gomega"
11 |
12 | utils "github.com/controlplaneio-fluxcd/flux-operator/test/e2e"
13 | )
14 |
15 | var _ = Describe("Scorecard", Ordered, func() {
16 | Context("test", func() {
17 | It("should run successfully", func() {
18 | By("run scorecard tests")
19 | cmd := exec.Command(operatorsdkBin, "scorecard",
20 | img, "-c", bundlePath+"/"+version+"/tests/scorecard/config.yaml",
21 | "-w", "5m", "-o", "json")
22 | _, err := utils.Run(cmd, "/test/olm")
23 | ExpectWithOffset(2, err).NotTo(HaveOccurred())
24 | })
25 | })
26 | })
27 |
```
--------------------------------------------------------------------------------
/internal/builder/testdata/resourceset/dedup.golden.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: source.toolkit.fluxcd.io/v1beta2
2 | kind: OCIRepository
3 | metadata:
4 | name: app1
5 | namespace: apps
6 | spec:
7 | interval: 10m
8 | ref:
9 | semver: '*'
10 | url: oci://ghcr.io/org/charts/app1
11 | ---
12 | apiVersion: helm.toolkit.fluxcd.io/v2
13 | kind: HelmRelease
14 | metadata:
15 | name: app1-team1
16 | namespace: apps
17 | spec:
18 | chartRef:
19 | kind: OCIRepository
20 | name: app1
21 | interval: 1h
22 | releaseName: app1-team1
23 | values:
24 | replicas: 2
25 | ---
26 | apiVersion: helm.toolkit.fluxcd.io/v2
27 | kind: HelmRelease
28 | metadata:
29 | name: app1-team2
30 | namespace: apps
31 | spec:
32 | chartRef:
33 | kind: OCIRepository
34 | name: app1
35 | interval: 1h
36 | releaseName: app1-team2
37 | values:
38 | replicas: 3
39 | ---
40 |
```
--------------------------------------------------------------------------------
/internal/web/auth/errors.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package auth
5 |
6 | import (
7 | "errors"
8 | )
9 |
10 | var (
11 | errUserError = errors.New("user error")
12 | errInternalError = errors.New("internal error")
13 | )
14 |
15 | // sanitizeErrorMessage returns a user-friendly error message. It
16 | // avoids exposing internal error details that could aid attackers.
17 | func sanitizeErrorMessage(err error) string {
18 | switch {
19 | case errors.Is(err, errInternalError), errors.Is(err, errInvalidOAuth2Scopes):
20 | return "An internal error occurred. Please try again. Contact your administrator if the problem persists."
21 | default:
22 | return "Authentication failed. Please try again."
23 | }
24 | }
25 |
```
--------------------------------------------------------------------------------
/cmd/cli/completion_bash.go:
--------------------------------------------------------------------------------
```go
1 | // Copyright 2025 Stefan Prodan.
2 | // SPDX-License-Identifier: AGPL-3.0
3 |
4 | package main
5 |
6 | import (
7 | "os"
8 |
9 | "github.com/spf13/cobra"
10 | )
11 |
12 | var completionBashCmd = &cobra.Command{
13 | Use: "bash",
14 | Short: "Generates bash completion scripts",
15 | Example: `To load completion run
16 |
17 | . <(flux-operator completion bash)
18 |
19 | To configure your bash shell to load completions for each session add to your bashrc
20 |
21 | # ~/.bashrc or ~/.profile
22 | command -v flux-operator >/dev/null && . <(flux-operator completion bash)`,
23 | Run: func(cmd *cobra.Command, args []string) {
24 | rootCmd.GenBashCompletion(os.Stdout) //nolint:errcheck
25 | },
26 | }
27 |
28 | func init() {
29 | completionCmd.AddCommand(completionBashCmd)
30 | }
31 |
```
--------------------------------------------------------------------------------
/config/data/flux/v2.2.3/policies.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: networking.k8s.io/v1
2 | kind: NetworkPolicy
3 | metadata:
4 | name: allow-egress
5 | spec:
6 | egress:
7 | - {}
8 | ingress:
9 | - from:
10 | - podSelector: {}
11 | podSelector: {}
12 | policyTypes:
13 | - Ingress
14 | - Egress
15 | ---
16 | apiVersion: networking.k8s.io/v1
17 | kind: NetworkPolicy
18 | metadata:
19 | name: allow-scraping
20 | spec:
21 | ingress:
22 | - from:
23 | - namespaceSelector: {}
24 | ports:
25 | - port: 8080
26 | protocol: TCP
27 | podSelector: {}
28 | policyTypes:
29 | - Ingress
30 | ---
31 | apiVersion: networking.k8s.io/v1
32 | kind: NetworkPolicy
33 | metadata:
34 | name: allow-webhooks
35 | spec:
36 | ingress:
37 | - from:
38 | - namespaceSelector: {}
39 | podSelector:
40 | matchLabels:
41 | app: notification-controller
42 | policyTypes:
43 | - Ingress
44 |
```
--------------------------------------------------------------------------------
/config/data/flux/v2.3.0/policies.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: networking.k8s.io/v1
2 | kind: NetworkPolicy
3 | metadata:
4 | name: allow-egress
5 | spec:
6 | egress:
7 | - {}
8 | ingress:
9 | - from:
10 | - podSelector: {}
11 | podSelector: {}
12 | policyTypes:
13 | - Ingress
14 | - Egress
15 | ---
16 | apiVersion: networking.k8s.io/v1
17 | kind: NetworkPolicy
18 | metadata:
19 | name: allow-scraping
20 | spec:
21 | ingress:
22 | - from:
23 | - namespaceSelector: {}
24 | ports:
25 | - port: 8080
26 | protocol: TCP
27 | podSelector: {}
28 | policyTypes:
29 | - Ingress
30 | ---
31 | apiVersion: networking.k8s.io/v1
32 | kind: NetworkPolicy
33 | metadata:
34 | name: allow-webhooks
35 | spec:
36 | ingress:
37 | - from:
38 | - namespaceSelector: {}
39 | podSelector:
40 | matchLabels:
41 | app: notification-controller
42 | policyTypes:
43 | - Ingress
44 |
```
--------------------------------------------------------------------------------
/config/data/flux/v2.4.0/policies.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: networking.k8s.io/v1
2 | kind: NetworkPolicy
3 | metadata:
4 | name: allow-egress
5 | spec:
6 | egress:
7 | - {}
8 | ingress:
9 | - from:
10 | - podSelector: {}
11 | podSelector: {}
12 | policyTypes:
13 | - Ingress
14 | - Egress
15 | ---
16 | apiVersion: networking.k8s.io/v1
17 | kind: NetworkPolicy
18 | metadata:
19 | name: allow-scraping
20 | spec:
21 | ingress:
22 | - from:
23 | - namespaceSelector: {}
24 | ports:
25 | - port: 8080
26 | protocol: TCP
27 | podSelector: {}
28 | policyTypes:
29 | - Ingress
30 | ---
31 | apiVersion: networking.k8s.io/v1
32 | kind: NetworkPolicy
33 | metadata:
34 | name: allow-webhooks
35 | spec:
36 | ingress:
37 | - from:
38 | - namespaceSelector: {}
39 | podSelector:
40 | matchLabels:
41 | app: notification-controller
42 | policyTypes:
43 | - Ingress
44 |
```
--------------------------------------------------------------------------------
/config/data/flux/v2.5.0/policies.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: networking.k8s.io/v1
2 | kind: NetworkPolicy
3 | metadata:
4 | name: allow-egress
5 | spec:
6 | egress:
7 | - {}
8 | ingress:
9 | - from:
10 | - podSelector: {}
11 | podSelector: {}
12 | policyTypes:
13 | - Ingress
14 | - Egress
15 | ---
16 | apiVersion: networking.k8s.io/v1
17 | kind: NetworkPolicy
18 | metadata:
19 | name: allow-scraping
20 | spec:
21 | ingress:
22 | - from:
23 | - namespaceSelector: {}
24 | ports:
25 | - port: 8080
26 | protocol: TCP
27 | podSelector: {}
28 | policyTypes:
29 | - Ingress
30 | ---
31 | apiVersion: networking.k8s.io/v1
32 | kind: NetworkPolicy
33 | metadata:
34 | name: allow-webhooks
35 | spec:
36 | ingress:
37 | - from:
38 | - namespaceSelector: {}
39 | podSelector:
40 | matchLabels:
41 | app: notification-controller
42 | policyTypes:
43 | - Ingress
44 |
```
--------------------------------------------------------------------------------
/config/data/flux/v2.5.1/policies.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: networking.k8s.io/v1
2 | kind: NetworkPolicy
3 | metadata:
4 | name: allow-egress
5 | spec:
6 | egress:
7 | - {}
8 | ingress:
9 | - from:
10 | - podSelector: {}
11 | podSelector: {}
12 | policyTypes:
13 | - Ingress
14 | - Egress
15 | ---
16 | apiVersion: networking.k8s.io/v1
17 | kind: NetworkPolicy
18 | metadata:
19 | name: allow-scraping
20 | spec:
21 | ingress:
22 | - from:
23 | - namespaceSelector: {}
24 | ports:
25 | - port: 8080
26 | protocol: TCP
27 | podSelector: {}
28 | policyTypes:
29 | - Ingress
30 | ---
31 | apiVersion: networking.k8s.io/v1
32 | kind: NetworkPolicy
33 | metadata:
34 | name: allow-webhooks
35 | spec:
36 | ingress:
37 | - from:
38 | - namespaceSelector: {}
39 | podSelector:
40 | matchLabels:
41 | app: notification-controller
42 | policyTypes:
43 | - Ingress
44 |
```
--------------------------------------------------------------------------------
/config/data/flux/v2.6.0/policies.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: networking.k8s.io/v1
2 | kind: NetworkPolicy
3 | metadata:
4 | name: allow-egress
5 | spec:
6 | egress:
7 | - {}
8 | ingress:
9 | - from:
10 | - podSelector: {}
11 | podSelector: {}
12 | policyTypes:
13 | - Ingress
14 | - Egress
15 | ---
16 | apiVersion: networking.k8s.io/v1
17 | kind: NetworkPolicy
18 | metadata:
19 | name: allow-scraping
20 | spec:
21 | ingress:
22 | - from:
23 | - namespaceSelector: {}
24 | ports:
25 | - port: 8080
26 | protocol: TCP
27 | podSelector: {}
28 | policyTypes:
29 | - Ingress
30 | ---
31 | apiVersion: networking.k8s.io/v1
32 | kind: NetworkPolicy
33 | metadata:
34 | name: allow-webhooks
35 | spec:
36 | ingress:
37 | - from:
38 | - namespaceSelector: {}
39 | podSelector:
40 | matchLabels:
41 | app: notification-controller
42 | policyTypes:
43 | - Ingress
44 |
```
--------------------------------------------------------------------------------
/config/data/flux/v2.6.1/policies.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: networking.k8s.io/v1
2 | kind: NetworkPolicy
3 | metadata:
4 | name: allow-egress
5 | spec:
6 | egress:
7 | - {}
8 | ingress:
9 | - from:
10 | - podSelector: {}
11 | podSelector: {}
12 | policyTypes:
13 | - Ingress
14 | - Egress
15 | ---
16 | apiVersion: networking.k8s.io/v1
17 | kind: NetworkPolicy
18 | metadata:
19 | name: allow-scraping
20 | spec:
21 | ingress:
22 | - from:
23 | - namespaceSelector: {}
24 | ports:
25 | - port: 8080
26 | protocol: TCP
27 | podSelector: {}
28 | policyTypes:
29 | - Ingress
30 | ---
31 | apiVersion: networking.k8s.io/v1
32 | kind: NetworkPolicy
33 | metadata:
34 | name: allow-webhooks
35 | spec:
36 | ingress:
37 | - from:
38 | - namespaceSelector: {}
39 | podSelector:
40 | matchLabels:
41 | app: notification-controller
42 | policyTypes:
43 | - Ingress
44 |
```
--------------------------------------------------------------------------------
/config/data/flux/v2.6.2/policies.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: networking.k8s.io/v1
2 | kind: NetworkPolicy
3 | metadata:
4 | name: allow-egress
5 | spec:
6 | egress:
7 | - {}
8 | ingress:
9 | - from:
10 | - podSelector: {}
11 | podSelector: {}
12 | policyTypes:
13 | - Ingress
14 | - Egress
15 | ---
16 | apiVersion: networking.k8s.io/v1
17 | kind: NetworkPolicy
18 | metadata:
19 | name: allow-scraping
20 | spec:
21 | ingress:
22 | - from:
23 | - namespaceSelector: {}
24 | ports:
25 | - port: 8080
26 | protocol: TCP
27 | podSelector: {}
28 | policyTypes:
29 | - Ingress
30 | ---
31 | apiVersion: networking.k8s.io/v1
32 | kind: NetworkPolicy
33 | metadata:
34 | name: allow-webhooks
35 | spec:
36 | ingress:
37 | - from:
38 | - namespaceSelector: {}
39 | podSelector:
40 | matchLabels:
41 | app: notification-controller
42 | policyTypes:
43 | - Ingress
44 |
```
--------------------------------------------------------------------------------
/config/data/flux/v2.6.3/policies.yaml:
--------------------------------------------------------------------------------
```yaml
1 | apiVersion: networking.k8s.io/v1
2 | kind: NetworkPolicy
3 | metadata:
4 | name: allow-egress
5 | spec:
6 | egress:
7 | - {}
8 | ingress:
9 | - from:
10 | - podSelector: {}
11 | podSelector: {}
12 | policyTypes:
13 | - Ingress
14 | - Egress
15 | ---
16 | apiVersion: networking.k8s.io/v1
17 | kind: NetworkPolicy
18 | metadata:
19 | name: allow-scraping
20 | spec:
21 | ingress:
22 | - from:
23 | - namespaceSelector: {}
24 | ports:
25 | - port: 8080
26 | protocol: TCP
27 | podSelector: {}
28 | policyTypes:
29 | - Ingress
30 | ---
31 | apiVersion: networking.k8s.io/v1
32 | kind: NetworkPolicy
33 | metadata:
34 | name: allow-webhooks
35 | spec:
36 | ingress:
37 | - from:
38 | - namespaceSelector: {}
39 | podSelector:
40 | matchLabels:
41 | app: notification-controller
42 | policyTypes:
43 | - Ingress
44 |
```