fluxcd

package
v0.2.0-beta.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 3, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

README

Flux Engine - FluxCD Workflow Implementation

Go Reference

The fluxcd package implements the stack.Workflow interface for FluxCD, providing complete Flux resource generation from domain model definitions.

Overview

The Flux engine transforms Kure's hierarchical domain model (Cluster, Node, Bundle, Application) into FluxCD resources (Kustomizations, source references) organized in a GitOps-ready directory structure.

The engine is composed of three specialized components:

Component Responsibility
ResourceGenerator Generates Flux resources from domain objects
LayoutIntegrator Integrates resources into directory structures
BootstrapGenerator Creates Flux bootstrap manifests

Quick Start

import "github.com/go-kure/kure/pkg/stack/fluxcd"

// Create engine with defaults
engine := fluxcd.Engine()

// Generate all Flux resources for a cluster
objects, err := engine.GenerateFromCluster(cluster)

// Or with a specific kustomization mode
engine = fluxcd.EngineWithConfig(layout.KustomizationExplicit)

// Placement is set on the LayoutRules passed to the layout call,
// not on the engine — see Layout Integration below.

Engine Construction

// Default engine
engine := fluxcd.Engine()

// Engine with specific kustomization mode
engine := fluxcd.EngineWithMode(layout.KustomizationExplicit)

// Engine with a specific kustomization mode (alias)
engine := fluxcd.EngineWithConfig(mode)

// Engine with custom components
engine := fluxcd.NewWorkflowEngine()

Placement (FluxIntegratedPerLayout vs FluxSeparate) is configured per call on layout.LayoutRules.FluxPlacement. FluxUnset is normalized to FluxSeparate by LayoutIntegrator.CreateLayoutWithResources — matching layout.DefaultLayoutRules() and the walker. See Layout Integration.

Resource Generation

Generate Flux resources at different hierarchy levels:

// From entire cluster
objects, err := engine.GenerateFromCluster(cluster)

// From a single node
objects, err := engine.GenerateFromNode(node)

// From a single bundle
objects, err := engine.GenerateFromBundle(bundle)

Each bundle produces a Flux Kustomization resource with:

  • Path matching the layout directory structure
  • Source reference from the node's package ref
  • Dependency ordering from Bundle.DependsOn
  • Interval and pruning configuration

Layout Integration

Combine resource generation with directory structure:

// Create layout with Flux resources integrated
ml, err := engine.CreateLayoutWithResources(cluster, rules)

// Write to disk
err = layout.WriteManifest(ml, "./clusters")

Bootstrap Generation

Generate Flux system bootstrap manifests. Two modes are supported:

Mode Description
"flux-operator" Default. Emits a full Flux Operator install bundle (CRDs, Deployment, RBAC). Recommended for new clusters.
"gotk" Legacy mode. Emits the GitOps Toolkit component manifests directly.

When FluxMode is empty, it defaults to "flux-operator".

bootstrapConfig := &stack.BootstrapConfig{
    Enabled:     true,
    FluxMode:    "flux-operator", // or "gotk"; empty defaults to "flux-operator"
    FluxVersion: "v2.8.2",
    SourceRef:   sourceRef,
}

objects, err := engine.GenerateBootstrap(bootstrapConfig, rootNode)

Configuration

Kustomization Mode

Controls how kustomization.yaml files reference resources:

  • KustomizationExplicit - Lists all manifest files explicitly
  • KustomizationRecursive - References subdirectories only
Flux Placement

Controls where Flux Kustomization resources are placed:

  • FluxSeparate - Flux resources collected in a separate directory tree; children referenced as directories
  • FluxIntegratedPerLayout - a Flux Kustomization CR for every layout node (incl. augmenter-added child layouts), placed alongside its manifests; children referenced as kustomization-<child>.yaml CR files. Finest granularity.
  • FluxIntegratedPerBundle - Flux Kustomization CRs at bundle/node boundaries only; a bundle's interior (incl. augmenter-added child layouts) is a single kustomize build, with children referenced as directories. Coarser: Flux reconciles per bundle, kustomize handles the interior.

Umbrella Bundles

A Bundle with a non-empty Children slice becomes an umbrella: a parent Flux Kustomization that aggregates the readiness of its children via spec.wait: true and auto-generated spec.healthChecks. This gives downstream consumers a single stable anchor regardless of how many internal tiers the umbrella contains.

Resource generation

ResourceGenerator.createKustomization detects umbrella bundles and:

  • forces spec.wait = true
  • prepends one HealthChecks entry per direct child (referencing the child's own Kustomization by name/namespace)
  • leaves user-supplied HealthChecks appended after the auto entries

GenerateFromBundle(b) is strictly self-only — it never recurses into b.Children. Callers that want the entire umbrella closure as a flat list use GenerateFromNode or GenerateFromCluster, which walk umbrella children via generateUmbrellaClosure internally.

Placement in layouts

LayoutIntegrator places umbrella child Flux CRs at the parent layout node:

  • FluxIntegratedPerLayout, non-nodeOnly: the walker creates a bundle sub-layout under the node layout. Umbrella child Kustomization CRs (and their Source CRs, if the child has a SourceRef.URL) are appended to the bundle sub-layout's Resources. Nested umbrella children are placed at their enclosing umbrella child's layout node.
  • FluxIntegratedPerLayout, nodeOnly (GroupFlat): there is no intermediate bundle layer, so umbrella children become direct sub-layouts of the node layout, and their Flux CRs sit at the node layout alongside the umbrella self CR.
  • FluxSeparate: GenerateFromCluster walks the full umbrella closure, so the flux-system layout directory receives every descendant's Kustomization CR as a flat list.
On-disk shape

When a parent layout has an umbrella child, the parent's kustomization.yaml references the child via flux-system-kustomization-{child}.yaml (the Kustomization CR file sitting in the parent directory) instead of the child subdirectory. The child subdirectory still exists and still contains its own kustomization.yaml plus workload YAML files — but no Flux CR files, so Flux does not double-apply the child's resources.

Non-Bundle Child Layout CRs

In FluxIntegratedPerLayout mode the layout integrator generates Kustomization CRs for all eligible children of each node layout, not only the node's own bundle. A child is eligible when !UmbrellaChild && ApplicationFileMode != AppFileSingle.

This covers two cases with the same code path:

  • Flat/nodeOnly layouts — app layouts are direct children of the node layout. Each eligible app layout gets a Kustomization CR placed in the node layout's Resources, with spec.path set to child.FullRepoPath().
  • Augmenter sub-layouts — hook-group child layouts added by a LayoutAugmenter are children of an app layout. Each eligible child gets a CR placed in the app layout's Resources. spec.dependsOn is populated from ManifestLayout.DependsOn, enabling ordered reconciliation between hook groups.

The integrator applies this rule recursively: it covers children at any depth, always placing the CR in the immediate parent's Resources.

If the ancestor bundle has a nil, empty, or incomplete SourceRef (missing Kind or Name) and eligible children without existing CRs are present, IntegrateWithLayout returns a hard error. A Kustomization without a valid spec.sourceRef is rejected by Flux and must not be emitted silently.

Validation

All cluster-level entry points (GenerateFromCluster, CreateLayoutWithResources) call stack.ValidateCluster before walking the tree. Invalid umbrella configurations — such as a bundle referenced both by a Node and by another bundle's Children, shared umbrella ownership, or multi-package umbrellas — fail fast with a validation error rather than producing malformed output.

CreateLayoutWithResources additionally calls validateSourceRefsForFluxIntegrated for both inline placements (FluxIntegratedPerLayout and FluxIntegratedPerBundle) — both emit bundle/node CRs that carry a spec.sourceRef. (After normalization FluxUnset becomes FluxSeparate, which skips this gate.) This checks that every bundle reachable from the cluster node tree — node bundles and umbrella child bundles recursively — has a complete SourceRef with both Kind and Name set. A nil, zero-value, or partially-populated SourceRef is rejected before layout walking begins. The integrator also enforces this at CR-creation time as defense in depth. FluxSeparate and non-Flux paths are unaffected.

Documentation

Index

Constants

View Source
const FluxOperatorVersion = "v0.48.0"

FluxOperatorVersion is the upstream flux-operator release whose install manifest is vendored as fluxOperatorInstallYAML. It is pinned to match the github.com/controlplaneio-fluxcd/flux-operator Go module version in kure's go.mod so that the generated FluxInstance type and the install bundle stay in lockstep.

To refresh this vendoring:

  1. Bump github.com/controlplaneio-fluxcd/flux-operator in go.mod.
  2. Download the matching install.yaml from the flux-operator GitHub release page: https://github.com/controlplaneio-fluxcd/flux-operator/releases/download/{version}/install.yaml
  3. Replace pkg/stack/fluxcd/flux_operator_install.yaml with it.
  4. Update this constant.
  5. Run the tests in this package and confirm the resource inventory in TestFluxOperatorInstallObjects still matches.

Variables

This section is empty.

Functions

func FluxOperatorInstallObjects

func FluxOperatorInstallObjects() ([]client.Object, error)

FluxOperatorInstallObjects returns the parsed Flux Operator install manifest: Namespace, CRDs, RBAC, ServiceAccount, Service, and controller Deployment. The bytes are embedded at build time from flux_operator_install.yaml (version FluxOperatorVersion).

The returned slice is cached on first parse; callers must treat it as read-only. To mutate any object, deep-copy first.

The order of objects matches the order in the upstream install.yaml (Namespace → CRDs → RBAC → ServiceAccount → Deployment → Service), which is also a valid apply order.

Types

type BootstrapGenerator

type BootstrapGenerator struct {
	// DefaultNamespace is the namespace where bootstrap resources are created
	DefaultNamespace string
	// DefaultInterval is the default reconciliation interval
	DefaultInterval time.Duration
}

BootstrapGenerator implements the workflow.BootstrapGenerator interface for Flux. It handles the generation of bootstrap resources for setting up Flux.

func NewBootstrapGenerator

func NewBootstrapGenerator() *BootstrapGenerator

NewBootstrapGenerator creates a FluxCD bootstrap generator.

func (*BootstrapGenerator) GenerateBootstrap

func (bg *BootstrapGenerator) GenerateBootstrap(config *stack.BootstrapConfig, rootNode *stack.Node) ([]client.Object, error)

GenerateBootstrap creates bootstrap resources for setting up Flux. When FluxMode is empty, flux-operator is used as the default.

func (*BootstrapGenerator) GenerateFluxInstance

func (bg *BootstrapGenerator) GenerateFluxInstance(config *stack.BootstrapConfig, rootNode *stack.Node) (*fluxv1.FluxInstance, error)

GenerateFluxInstance returns only the FluxInstance CR configured for the given bootstrap settings, without the full Flux Operator install bundle. Returns (nil, nil) when config is nil. Unlike GenerateBootstrap, this method does not check config.Enabled — the caller is responsible for that gate.

func (*BootstrapGenerator) SupportedBootstrapModes

func (bg *BootstrapGenerator) SupportedBootstrapModes() []string

SupportedBootstrapModes returns the bootstrap modes supported by this generator. flux-operator is the primary (recommended) mode; gotk is the legacy mode.

type LayoutIntegrator

type LayoutIntegrator struct {
	// ResourceGenerator generates the Flux resources
	Generator *ResourceGenerator
}

LayoutIntegrator implements the workflow.LayoutIntegrator interface for Flux. It handles integration of Flux resources with manifest layouts.

Placement (FluxIntegratedPerLayout vs FluxSeparate) is configured via layout.LayoutRules.FluxPlacement on each call. CreateLayoutWithResources normalizes FluxUnset to FluxSeparate before invoking the SourceRef validation gate, WalkCluster, and IntegrateWithLayout, so all three observers agree on the effective placement.

func NewLayoutIntegrator

func NewLayoutIntegrator(generator *ResourceGenerator) *LayoutIntegrator

NewLayoutIntegrator creates a FluxCD layout integrator.

func (*LayoutIntegrator) CreateLayoutWithResources

func (li *LayoutIntegrator) CreateLayoutWithResources(c *stack.Cluster, rules layout.LayoutRules) (*layout.ManifestLayout, error)

CreateLayoutWithResources creates a new layout that includes Flux resources.

rules.FluxPlacement is normalized once at the top of this method (FluxUnset -> FluxSeparate) and the normalized rules are passed to the SourceRef validation gate, WalkCluster, and IntegrateWithLayout. This guarantees a single placement authority per call.

func (*LayoutIntegrator) IntegrateWithLayout

func (li *LayoutIntegrator) IntegrateWithLayout(ml *layout.ManifestLayout, c *stack.Cluster, rules layout.LayoutRules) error

IntegrateWithLayout adds Flux resources to an existing manifest layout.

Placement is driven by rules.FluxPlacement. FluxUnset is treated as FluxSeparate to match DefaultLayoutRules and the walker's normalization in pkg/stack/layout/walker.go:42-44.

If the layout was post-processed by FlattenSingleTier (recorded as flattenInfo on the absorbing layouts), this method consults nodeAliases during integrated placement (see findLayoutNode) and rewrites Flux Kustomization Spec.Path values via layout.ApplyFlattenPathRewrites before returning, regardless of placement mode.

type ResourceGenerator

type ResourceGenerator struct {
	// Mode controls how spec.path is generated in Kustomizations
	Mode layout.KustomizationMode
	// DefaultInterval is the default reconciliation interval for generated resources
	DefaultInterval time.Duration
	// DefaultNamespace is the default namespace for generated Flux resources
	DefaultNamespace string
}

ResourceGenerator implements the workflow.ResourceGenerator interface for Flux. It focuses purely on generating Flux CRDs from stack components.

func NewResourceGenerator

func NewResourceGenerator() *ResourceGenerator

NewResourceGenerator creates a FluxCD resource generator with sensible defaults.

func (*ResourceGenerator) GenerateFromBundle

func (g *ResourceGenerator) GenerateFromBundle(b *stack.Bundle) ([]client.Object, error)

GenerateFromBundle creates Flux resources (Kustomization, and optionally a Source) for b itself only. Umbrella Children are NOT recursed — callers that need the closure should use GenerateFromNode, which walks the subtree, or iterate b.Children directly.

func (*ResourceGenerator) GenerateFromCluster

func (g *ResourceGenerator) GenerateFromCluster(c *stack.Cluster) ([]client.Object, error)

GenerateFromCluster creates Flux Kustomizations and Sources from a cluster definition. It runs stack.ValidateCluster first to fail fast on structural errors (umbrella cycles, disjointness violations, etc.).

func (*ResourceGenerator) GenerateFromNode

func (g *ResourceGenerator) GenerateFromNode(n *stack.Node) ([]client.Object, error)

GenerateFromNode creates Flux resources from a node and its children. When a node's bundle is an umbrella (len(Bundle.Children) > 0), the umbrella closure is walked and flattened into the returned slice so flat-list consumers (e.g. separate Flux placement) see every child Kustomization CR.

func (*ResourceGenerator) GetName

func (g *ResourceGenerator) GetName() string

GetName returns the name of this resource generator.

func (*ResourceGenerator) GetVersion

func (g *ResourceGenerator) GetVersion() string

GetVersion returns the version of this resource generator.

type WorkflowEngine

type WorkflowEngine struct {
	// ResourceGen handles core resource generation
	ResourceGen *ResourceGenerator
	// LayoutInteg handles layout integration
	LayoutInteg *LayoutIntegrator
	// BootstrapGen handles bootstrap resource generation
	BootstrapGen *BootstrapGenerator
}

WorkflowEngine implements the stack.Workflow interface by composing the specialized generator components. This provides a complete FluxCD workflow implementation with clear separation of concerns.

func Engine

func Engine() *WorkflowEngine

Engine returns a WorkflowEngine initialized with defaults. This is the primary entry point for FluxCD workflow functionality.

func EngineWithConfig

func EngineWithConfig(mode layout.KustomizationMode) *WorkflowEngine

EngineWithConfig returns a WorkflowEngine with a specific kustomization mode. Placement is no longer a constructor argument; set it on layout.LayoutRules.FluxPlacement at call time.

func EngineWithMode

func EngineWithMode(mode layout.KustomizationMode) *WorkflowEngine

EngineWithMode returns a WorkflowEngine with a specific kustomization mode.

func NewWorkflowEngine

func NewWorkflowEngine() *WorkflowEngine

NewWorkflowEngine creates a FluxCD workflow engine with default components.

func NewWorkflowEngineWithConfig

func NewWorkflowEngineWithConfig(mode layout.KustomizationMode) *WorkflowEngine

NewWorkflowEngineWithConfig creates a workflow engine with custom configuration.

Placement is no longer a constructor argument; set it on layout.LayoutRules.FluxPlacement at call time. See LayoutIntegrator for the normalization semantics.

func (*WorkflowEngine) CreateLayoutWithResources

func (we *WorkflowEngine) CreateLayoutWithResources(c *stack.Cluster, rules stack.LayoutRulesProvider) (stack.ManifestLayoutResult, error)

CreateLayoutWithResources creates a new layout that includes Flux resources.

func (*WorkflowEngine) GenerateBootstrap

func (we *WorkflowEngine) GenerateBootstrap(config *stack.BootstrapConfig, rootNode *stack.Node) ([]client.Object, error)

GenerateBootstrap creates bootstrap resources for setting up Flux.

func (*WorkflowEngine) GenerateFromBundle

func (we *WorkflowEngine) GenerateFromBundle(b *stack.Bundle) ([]client.Object, error)

GenerateFromBundle creates Flux resources from a bundle definition.

func (*WorkflowEngine) GenerateFromCluster

func (we *WorkflowEngine) GenerateFromCluster(c *stack.Cluster) ([]client.Object, error)

GenerateFromCluster creates Flux resources from a cluster definition.

func (*WorkflowEngine) GenerateFromNode

func (we *WorkflowEngine) GenerateFromNode(n *stack.Node) ([]client.Object, error)

GenerateFromNode creates Flux resources from a node definition.

func (*WorkflowEngine) GetBootstrapGenerator

func (we *WorkflowEngine) GetBootstrapGenerator() *BootstrapGenerator

GetBootstrapGenerator returns the underlying bootstrap generator for advanced configuration.

func (*WorkflowEngine) GetLayoutIntegrator

func (we *WorkflowEngine) GetLayoutIntegrator() *LayoutIntegrator

GetLayoutIntegrator returns the underlying layout integrator for advanced configuration.

func (*WorkflowEngine) GetName

func (we *WorkflowEngine) GetName() string

GetName returns a human-readable name for this workflow engine.

func (*WorkflowEngine) GetResourceGenerator

func (we *WorkflowEngine) GetResourceGenerator() *ResourceGenerator

GetResourceGenerator returns the underlying resource generator for advanced configuration.

func (*WorkflowEngine) GetVersion

func (we *WorkflowEngine) GetVersion() string

GetVersion returns the version of this workflow engine.

func (*WorkflowEngine) IntegrateWithLayout

func (we *WorkflowEngine) IntegrateWithLayout(ml *layout.ManifestLayout, c *stack.Cluster, rules layout.LayoutRules) error

IntegrateWithLayout adds Flux resources to an existing manifest layout.

func (*WorkflowEngine) SetKustomizationMode

func (we *WorkflowEngine) SetKustomizationMode(mode layout.KustomizationMode)

SetKustomizationMode configures how Kustomization paths are generated.

func (*WorkflowEngine) SupportedBootstrapModes

func (we *WorkflowEngine) SupportedBootstrapModes() []string

SupportedBootstrapModes returns the bootstrap modes supported by this engine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL