FluxCD Builders
pkg/kubernetes/fluxcd
Low-level builder functions for FluxCD Kubernetes resources. Each resource type follows the Create*(name, namespace) + Set*()/Add*() pattern.
Each block on this page, except the one marked as an excerpt, is the body of an Example function
in example_test.go, which go test runs: it imports this package as fluxcd, the Flux APIs as
sourcev1 (github.com/fluxcd/source-controller/api/v1), kustv1
(github.com/fluxcd/kustomize-controller/api/v1), helmv2
(github.com/fluxcd/helm-controller/api/v2), meta and kustomize
(github.com/fluxcd/pkg/apis/meta, github.com/fluxcd/pkg/apis/kustomize),
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1", time, and fmt for the line that prints what
the example built.
Constructors
Every kind this package registers has a generated Create<Kind> wrapper in zz_generated_create.go, produced from the scheme by pkg/kubernetes/internal/gen (make gen-builders, checked by make check-builders in CI). A wrapper delegates to kubernetes.Create[T] and emits TypeMeta and identity only: no default, no label, no spec value. Namespaced kinds take (name, namespace), cluster-scoped kinds take (name). The upstream struct is the construction API; set spec fields directly or through the admissible Set*/Add* sugar below.
obj := fluxcd.CreateGitRepository("my-repo", "flux-system")
fmt.Println(obj.Kind, obj.Namespace+"/"+obj.Name)Twenty-four hand-written constructors for spec fragments remain (CreateGitSpec, CreatePostBuild, CreateInstallRemediation, CreateCrossNamespaceSourceReference and the rest). Their sub-types are not client.Object, so they get no generated wrapper, and Flux’s spec fragments are deep enough that assembling one by literal at every call site is the less readable option. They are not identity constructors and are not covered by the identity test — for anything they do not cover, a struct literal is the idiom.
The kinds this package registers, their scope, and what stated that scope are rows in the generated Supported kinds and field maturity tables. The sections below are worked examples, not the coverage list.
See the Kubernetes Builders page for the full builder contract: construction, sugar admission classes, purity and the release-1 migration ledger.
Source Controllers
GitRepository
gr := fluxcd.CreateGitRepository("my-repo", "flux-system")
gr.Spec.URL = "https://github.com/org/repo"
fluxcd.SetGitRepositoryReference(gr, &sourcev1.GitRepositoryRef{Branch: "main"})
gr.Spec.Interval = metav1.Duration{Duration: 5 * time.Minute}
fluxcd.SetGitRepositorySecretRef(gr, &meta.LocalObjectReference{Name: "git-credentials"})
fmt.Println(gr.Spec.Reference.Branch, gr.Spec.Interval.Duration, gr.Spec.SecretRef.Name)Additional setters: SetGitRepositoryTimeout, SetGitRepositoryVerification,
SetGitRepositoryProxySecretRef, SetGitRepositoryIgnore, AddGitRepositoryInclude,
AddGitRepositorySparseCheckoutPath.
OCIRepository
oci := fluxcd.CreateOCIRepository("my-manifests", "flux-system")
oci.Spec.URL = "oci://registry.example.com/manifests"
fluxcd.SetOCIRepositoryReference(oci, &sourcev1.OCIRepositoryRef{Tag: "latest"})
oci.Spec.Interval = metav1.Duration{Duration: 10 * time.Minute}
fluxcd.SetOCIRepositorySecretRef(oci, &meta.LocalObjectReference{Name: "registry-credentials"})
fmt.Println(oci.Spec.Reference.Tag, oci.Spec.SecretRef.Name)Additional setters: SetOCIRepositoryLayerSelector, SetOCIRepositoryVerify,
SetOCIRepositoryCertSecretRef, SetOCIRepositoryProxySecretRef, SetOCIRepositoryTimeout,
SetOCIRepositoryIgnore.
HelmRepository
HTTP/HTTPS repository:
hr := fluxcd.CreateHelmRepository("bitnami", "flux-system")
hr.Spec.URL = "https://charts.bitnami.com/bitnami"
hr.Spec.Type = "default"
hr.Spec.Interval = metav1.Duration{Duration: 10 * time.Minute}
fluxcd.SetHelmRepositoryTimeout(hr, &metav1.Duration{Duration: 60 * time.Second})
hr.Spec.PassCredentials = true
fluxcd.SetHelmRepositorySecretRef(hr, &meta.LocalObjectReference{Name: "bitnami-auth"})
fmt.Println(hr.Spec.Timeout.Duration, hr.Spec.SecretRef.Name)OCI registry:
hr := fluxcd.CreateHelmRepository("ghcr-charts", "flux-system")
hr.Spec.URL = "oci://ghcr.io/example/charts"
hr.Spec.Type = "oci"
hr.Spec.Provider = "generic" // OCI-only: generic, aws, azure, gcp
hr.Spec.Interval = metav1.Duration{Duration: 5 * time.Minute}
fluxcd.SetHelmRepositorySecretRef(hr, &meta.LocalObjectReference{Name: "ghcr-auth"})
fmt.Println(hr.Spec.Type, hr.Spec.Provider)Additional setters: SetHelmRepositoryCertSecretRef, SetHelmRepositoryAccessFrom.
HelmChart
hc := fluxcd.CreateHelmChart("redis", "flux-system")
hc.Spec.Chart = "redis"
hc.Spec.Version = "19.0.0"
hc.Spec.SourceRef = sourcev1.LocalHelmChartSourceReference{
Kind: "HelmRepository",
Name: "bitnami",
}
hc.Spec.Interval = metav1.Duration{Duration: 10 * time.Minute}
fmt.Println(hc.Spec.Chart, hc.Spec.Version, hc.Spec.SourceRef.Kind)Additional setters: AddHelmChartValuesFile, SetHelmChartVerify.
Note (Flux 2.9):
source-controller/apiv1.9 split the verification types.SetHelmChartVerifynow takes*sourcev1.HelmChartVerification(previously*sourcev1.OCIRepositoryVerification);SetOCIRepositoryVerifystill takes*sourcev1.OCIRepositoryVerification. The API version is unchanged (both v1).
Bucket
b := fluxcd.CreateBucket("my-bucket", "flux-system")
b.Spec.Endpoint = "minio.example.com"
b.Spec.BucketName = "manifests"
b.Spec.Interval = metav1.Duration{Duration: 10 * time.Minute}
fluxcd.SetBucketSecretRef(b, &meta.LocalObjectReference{Name: "minio-credentials"})
fmt.Println(b.Spec.BucketName, b.Spec.SecretRef.Name)Additional setters: SetBucketSTS, SetBucketCertSecretRef, SetBucketProxySecretRef,
SetBucketTimeout, SetBucketIgnore.
Deployment Controllers
Kustomization
k := fluxcd.CreateKustomization("my-app", "flux-system")
k.Spec.SourceRef = kustv1.CrossNamespaceSourceReference{
Kind: "GitRepository",
Name: "my-repo",
}
k.Spec.Path = "./clusters/production/apps"
k.Spec.Interval = metav1.Duration{Duration: 10 * time.Minute}
k.Spec.Prune = true
k.Spec.TargetNamespace = "production"
k.Spec.Wait = true
fluxcd.AddKustomizationDependsOn(k, kustv1.DependencyReference{Name: "cert-manager"})
fmt.Println(k.Spec.Path, k.Spec.DependsOn[0].Name)Additional setters: SetKustomizationRetryInterval, SetKustomizationKubeConfig,
AddKustomizationHealthCheck, AddKustomizationHealthCheckExpr, AddKustomizationComponent,
SetKustomizationTimeout, AddKustomizationImage, AddKustomizationPatch,
SetKustomizationCommonMetadata, SetKustomizationDecryption, SetKustomizationPostBuild.
HelmRelease
Chart template (chart + version + source reference):
hr := fluxcd.CreateHelmRelease("redis", "apps")
hr.Spec.ReleaseName = "redis-prod"
hr.Spec.TargetNamespace = "apps"
hr.Spec.Interval = metav1.Duration{Duration: 10 * time.Minute}
fluxcd.SetHelmReleaseChart(hr, &helmv2.HelmChartTemplate{
Spec: helmv2.HelmChartTemplateSpec{
Chart: "redis",
Version: "19.0.0",
SourceRef: helmv2.CrossNamespaceObjectReference{
Kind: "HelmRepository",
Name: "bitnami",
Namespace: "flux-system",
},
},
})
// Panics if the map does not marshal (a channel, a function, a NaN).
fluxcd.SetHelmReleaseValuesFromMap(hr, map[string]any{"replicaCount": 3})
// Alternative — pre-marshalled JSON:
// fluxcd.SetHelmReleaseValues(hr, &apiextensionsv1.JSON{Raw: []byte(`{"replicaCount":3}`)})
fluxcd.AddHelmReleaseValuesFrom(hr, helmv2.ValuesReference{
Kind: "ConfigMap",
Name: "redis-defaults",
})
fmt.Println(hr.Spec.Chart.Spec.Chart, string(hr.Spec.Values.Raw), hr.Spec.ValuesFrom[0].Name)SetHelmReleaseValuesFromMap panics rather than returning an error, because a
sugar helper cannot return one under the builder contract. Only a value that
encoding/json refuses outright — a channel, a function, a NaN or +Inf
float, a cyclic structure — reaches that panic. Decoded YAML can carry one:
gopkg.in/yaml.v3 decodes the legal YAML scalars .nan and .inf into a
float64 NaN or +Inf without error. sigs.k8s.io/yaml converts through JSON
and returns that error at decode time instead, so a map it produced always
marshals. When values come from a decoder that could produce such a value,
marshal them yourself and hand the result to SetHelmReleaseValues:
import "github.com/go-kure/kure/pkg/errors"
raw, err := json.Marshal(values)
if err != nil {
return errors.Wrap(err, "helm values")
}
fluxcd.SetHelmReleaseValues(hr, &apiextensionsv1.JSON{Raw: raw})ChartRef mode (existing OCIRepository or HelmChart):
hr := fluxcd.CreateHelmRelease("my-app", "apps")
fluxcd.SetHelmReleaseChartRef(hr, &helmv2.CrossNamespaceSourceReference{
Kind: "OCIRepository",
Name: "my-oci-source",
Namespace: "flux-system",
})
fmt.Println(hr.Spec.ChartRef.Kind, hr.Spec.ChartRef.Name)Drift detection and remediation:
hr := fluxcd.CreateHelmRelease("my-app", "apps")
fluxcd.SetHelmReleaseDriftDetection(hr, fluxcd.CreateDriftDetection(helmv2.DriftDetectionEnabled))
fluxcd.SetHelmReleaseInstallCRDs(hr, helmv2.CreateReplace)
fluxcd.SetHelmReleaseInstallRemediation(hr, fluxcd.CreateInstallRemediation(3))
fluxcd.SetHelmReleaseUpgradeCRDs(hr, helmv2.CreateReplace)
fluxcd.SetHelmReleaseUpgradeRemediation(hr, fluxcd.CreateUpgradeRemediation(3))
fmt.Println(hr.Spec.DriftDetection.Mode, hr.Spec.Install.CRDs, hr.Spec.Upgrade.Remediation.Retries)Post-render:
hr := fluxcd.CreateHelmRelease("my-app", "apps")
k := fluxcd.CreatePostRendererKustomize()
fluxcd.AddPostRendererKustomizeImage(k, kustomize.Image{Name: "redis", NewTag: "7.0"})
fluxcd.AddHelmReleasePostRenderer(hr, helmv2.PostRenderer{Kustomize: k})
fmt.Println(hr.Spec.PostRenderers[0].Kustomize.Images[0].NewTag)Additional setters: SetHelmReleaseKubeConfig, AddHelmReleaseDependsOn, SetHelmReleaseTimeout,
SetHelmReleaseMaxHistory, SetHelmReleasePersistentClient, SetHelmReleaseInstall,
SetHelmReleaseUpgrade, SetHelmReleaseRollback, SetHelmReleaseUninstall, SetHelmReleaseTest,
SetHelmReleaseValues, SetHelmReleaseValuesFromMap, SetHelmReleaseCommonMetadata,
AddHelmReleaseHealthCheckExpr, SetHelmReleaseWaitStrategy.
Install flag setters: SetHelmReleaseInstallTimeout, SetHelmReleaseInstallCRDs,
SetHelmReleaseInstallCreateNamespace, SetHelmReleaseInstallDisableSchemaValidation,
SetHelmReleaseInstallDisableOpenAPIValidation, SetHelmReleaseInstallDisableHooks,
SetHelmReleaseInstallDisableWait, SetHelmReleaseInstallDisableWaitForJobs,
SetHelmReleaseInstallDisableTakeOwnership, SetHelmReleaseInstallReplace,
SetHelmReleaseInstallRemediation.
Upgrade flag setters: SetHelmReleaseUpgradeTimeout, SetHelmReleaseUpgradeCRDs,
SetHelmReleaseUpgradeDisableSchemaValidation, SetHelmReleaseUpgradeDisableOpenAPIValidation,
SetHelmReleaseUpgradeDisableHooks, SetHelmReleaseUpgradeDisableWait,
SetHelmReleaseUpgradeDisableWaitForJobs, SetHelmReleaseUpgradeDisableTakeOwnership,
SetHelmReleaseUpgradeForce, SetHelmReleaseUpgradePreserveValues,
SetHelmReleaseUpgradeCleanupOnFail, SetHelmReleaseUpgradeRemediation.
Notification Controllers
Note: Provider and Alert use
notification.toolkit.fluxcd.io/v1beta3. Receiver is on v1. See compatibility for details and tracking issue #250 .
provider := fluxcd.CreateProvider("slack", "flux-system")
provider.Spec.Type = "slack" // plain fields: assigned, not set
provider.Spec.Channel = "#alerts"
fluxcd.SetProviderSecretRef(provider, &meta.LocalObjectReference{Name: "slack-webhook"})
alert := fluxcd.CreateAlert("slack-alert", "flux-system")
alert.Spec.ProviderRef = meta.LocalObjectReference{Name: "slack"}
alert.Spec.EventSeverity = "error" // no Alert setters remain: all were bare assignments
receiver := fluxcd.CreateReceiver("github-receiver", "flux-system")
receiver.Spec.Type = "github"
receiver.Spec.Events = []string{"push"}
fluxcd.SetReceiverSecretRef(receiver, meta.LocalObjectReference{Name: "webhook-token"})
fmt.Println(provider.Spec.SecretRef.Name, alert.Spec.EventSeverity, receiver.Spec.SecretRef.Name)Image Automation
The three kinds of image.toolkit.fluxcd.io/v1 each have a constructor:
CreateImageRepository and CreateImagePolicy (types from
github.com/fluxcd/image-reflector-controller/api) and CreateImageUpdateAutomation
(type from github.com/fluxcd/image-automation-controller/api). All three are
namespaced and carry identity only.
ImageRepository and ImagePolicy have no setters: every field of their specs is
assigned directly on the upstream type. ImageUpdateAutomation keeps the pointer
setters SetImageUpdateAutomationGitSpec, SetImageUpdateAutomationPolicySelector
and SetImageUpdateAutomationUpdateStrategy.
Flux Operator
instance := fluxcd.CreateFluxInstance("flux", "flux-system")
instance.Spec.Distribution.Variant = "upstream-alpine" // Distribution is a plain field
// Pointer setters remain for the optional blocks: SetFluxInstanceCluster,
// SetFluxInstanceSharding, SetFluxInstanceStorage, SetFluxInstanceKustomize,
// SetFluxInstanceSync, SetFluxInstanceWait, SetFluxInstanceCommonMetadata and
// SetFluxInstanceMigrateResources.
fmt.Println(instance.Spec.Distribution.Variant)Extended Resource Types
ExternalArtifact
Allows a Flux source artifact produced outside the cluster to be referenced by other Flux resources.
ea := fluxcd.CreateExternalArtifact("my-artifact", "flux-system")
fluxcd.SetExternalArtifactSourceRef(ea, &meta.NamespacedObjectKindReference{
APIVersion: "source.toolkit.fluxcd.io/v1",
Kind: "OCIRepository",
Name: "my-oci-source",
Namespace: "flux-system",
})
fmt.Println(ea.Spec.SourceRef.Kind, ea.Spec.SourceRef.Name)ArtifactGenerator
Provided by the optional source-watcher component. Assembles a new artifact by copying files from one or more source artifacts.
ag := fluxcd.CreateArtifactGenerator("my-gen", "flux-system")
src := fluxcd.CreateSourceReference("app", "my-oci-source", "OCIRepository")
src.Namespace = "flux-system"
fluxcd.AddArtifactGeneratorSource(ag, src)
out := fluxcd.CreateOutputArtifact("combined")
out.Revision = "@app"
cp := fluxcd.CreateCopyOperation("@app/manifests/**", "@artifact/manifests")
fluxcd.AddOutputArtifactCopyOperation(&out, cp)
fluxcd.AddArtifactGeneratorOutputArtifact(ag, out)
fmt.Println(ag.Spec.Sources[0].Alias, ag.Spec.OutputArtifacts[0].Name, ag.Spec.OutputArtifacts[0].Copy[0].From)Related Packages
- stack/fluxcd — high-level Flux workflow engine
- stack — domain model that produces Flux resources