Workflow Architecture
Overview
The workflow package provides a clean, composable architecture for generating GitOps resources from Kure stack definitions. This new architecture improves upon the previous monolithic workflow interface by introducing focused, single-responsibility interfaces.
Interface Architecture
Core Interfaces
ResourceGenerator
The primary interface for converting stack components into GitOps CRDs.
type ResourceGenerator interface {
GenerateFromCluster(*stack.Cluster) ([]client.Object, error)
GenerateFromNode(*stack.Node) ([]client.Object, error)
GenerateFromBundle(*stack.Bundle) ([]client.Object, error)
}
Responsibilities:
- Pure resource generation without side effects
- Converts stack abstractions to concrete GitOps CRDs
- Handles resource relationships and dependencies
LayoutIntegrator
Handles integration of GitOps resources with manifest layouts.
type LayoutIntegrator interface {
IntegrateWithLayout(*layout.ManifestLayout, *stack.Cluster, layout.LayoutRules) error
CreateLayoutWithResources(*stack.Cluster, layout.LayoutRules) (*layout.ManifestLayout, error)
}
Responsibilities:
- Layout-aware resource placement
- Directory structure organization
- Manifest grouping and organization
BootstrapGenerator
Handles bootstrap resource generation for GitOps system initialization.
type BootstrapGenerator interface {
GenerateBootstrap(*stack.BootstrapConfig, *stack.Node) ([]client.Object, error)
SupportedBootstrapModes() []string
}
Responsibilities:
- System initialization resources
- Bootstrap configuration management
- Multiple bootstrap mode support
WorkflowEngine
Composes all capabilities into a complete workflow implementation.
type WorkflowEngine interface {
ResourceGenerator
LayoutIntegrator
BootstrapGenerator
GetName() string
GetVersion() string
}
Responsibilities:
- Complete workflow orchestration
- Component composition
- Metadata and versioning
Implementation: FluxCD
The FluxCD package provides a reference implementation of the workflow architecture:
Components
-
ResourceGenerator
(pkg/stack/fluxcd/resource_generator.go
)- Generates Flux Kustomizations and sources
- Handles path generation modes (explicit/recursive)
- Manages source references and dependencies
-
LayoutIntegrator
(pkg/stack/fluxcd/layout_integrator.go
)- Integrates Flux resources with manifest layouts
- Supports integrated vs separate placement modes
- Handles hierarchical resource organization
-
BootstrapGenerator
(pkg/stack/fluxcd/bootstrap_generator.go
)- Supports multiple bootstrap modes (gotk, flux-operator)
- Generates bootstrap manifests and sources
- Handles different Flux installation methods
-
WorkflowEngine
(pkg/stack/fluxcd/workflow_engine.go
)- Composes all generators into complete workflow
- Provides configuration methods
- Implements both new and legacy interfaces
Clean Architecture
Since Kure hasn’t been released yet, we removed all legacy compatibility code and present a clean, focused architecture. Each workflow implementation (FluxCD, ArgoCD) provides a WorkflowEngine
that implements all the focused interfaces.
Benefits
Separation of Concerns
- Each interface has a single, well-defined responsibility
- Implementation complexity is distributed across focused components
- Testing becomes more granular and targeted
Composability
- Mix and match different generator implementations
- Easy to extend with new capabilities
- Clean dependency injection patterns
Maintainability
- Smaller, focused code units
- Clear interface boundaries
- Easier to reason about individual components
Extensibility
- New GitOps systems can implement the same interfaces
- Additional capabilities can be added through new interfaces
- Interface segregation prevents breaking changes
Usage Examples
FluxCD Usage
// Create FluxCD workflow engine
engine := fluxcd.Engine()
// Or with specific configuration
engine := fluxcd.EngineWithMode(layout.KustomizationRecursive)
engine := fluxcd.EngineWithConfig(layout.KustomizationExplicit, layout.FluxIntegrated)
// Generate resources
resources, err := engine.GenerateFromCluster(cluster)
// Create layout with resources
layout, err := engine.CreateLayoutWithResources(cluster, rules)
// Generate bootstrap resources
bootstrap, err := engine.GenerateBootstrap(config, rootNode)
ArgoCD Usage
// Create ArgoCD workflow engine
engine := argocd.Engine()
// Configure for specific repository
engine.SetRepoURL("https://github.com/myorg/k8s-manifests.git")
engine.SetDefaultNamespace("argocd-system")
// Generate ArgoCD Applications
apps, err := engine.GenerateFromCluster(cluster)
// Create layout with Applications
layout, err := engine.CreateLayoutWithResources(cluster, rules)
Interface-Based Usage
// Use focused interfaces for specific needs
var generator workflow.ResourceGenerator
switch gitopsProvider {
case "flux":
generator = fluxcd.Engine()
case "argocd":
generator = argocd.Engine()
}
// Generate resources using the interface
resources, err := generator.GenerateFromCluster(cluster)
Testing Strategy
The new architecture enables focused testing:
// Test resource generation in isolation
func TestResourceGeneration(t *testing.T) {
gen := fluxcd.NewResourceGenerator()
resources, err := gen.GenerateFromBundle(bundle)
// Assert on resources without layout concerns
}
// Test layout integration separately
func TestLayoutIntegration(t *testing.T) {
integrator := fluxcd.NewLayoutIntegrator(gen)
err := integrator.IntegrateWithLayout(layout, cluster, rules)
// Assert on layout modifications
}
This granular testing approach leads to:
- Better test coverage
- Faster test execution
- More focused test failures
- Easier debugging