diff --git a/.gitignore b/.gitignore index 417770d..d42828a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ config/crd/bases/ocirepositories.yaml config/crd/bases/gitrepositories.yaml config/crd/bases/buckets.yaml config/crd/bases/externalartifacts.yaml +config/crd/bases/helmcharts.yaml # Release manifests generated at build time config/release/ diff --git a/Makefile b/Makefile index 1f74f47..3656479 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,7 @@ SOURCE_CRD_VER=$(BUILD_DIR)/.src-crd-$(SOURCE_VER) GITREPO_CRD ?= config/crd/bases/gitrepositories.yaml BUCKET_CRD ?= config/crd/bases/buckets.yaml OCIREPO_CRD ?= config/crd/bases/ocirepositories.yaml +HELMCHART_CRD ?= config/crd/bases/helmcharts.yaml EA_CRD ?= config/crd/bases/externalartifacts.yaml all: manager @@ -65,15 +66,18 @@ $(BUCKET_CRD): $(OCIREPO_CRD): curl -s https://raw.githubusercontent.com/fluxcd/source-controller/${SOURCE_VER}/config/crd/bases/source.toolkit.fluxcd.io_ocirepositories.yaml -o $(OCIREPO_CRD) +$(HELMCHART_CRD): + curl -s https://raw.githubusercontent.com/fluxcd/source-controller/${SOURCE_VER}/config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml -o $(HELMCHART_CRD) + $(EA_CRD): curl -s https://raw.githubusercontent.com/fluxcd/source-controller/${SOURCE_VER}/config/crd/bases/source.toolkit.fluxcd.io_externalartifacts.yaml -o $(EA_CRD) # Download the CRDs the controller depends on -download-crd-deps: $(SOURCE_CRD_VER) $(GITREPO_CRD) $(BUCKET_CRD) $(OCIREPO_CRD) $(EA_CRD) +download-crd-deps: $(SOURCE_CRD_VER) $(GITREPO_CRD) $(BUCKET_CRD) $(OCIREPO_CRD) $(HELMCHART_CRD) $(EA_CRD) # Delete the downloaded CRD dependencies. cleanup-crd-deps: - rm -f $(GITREPO_CRD) $(BUCKET_CRD) $(OCIREPO_CRD) $(EA_CRD) + rm -f $(GITREPO_CRD) $(BUCKET_CRD) $(OCIREPO_CRD) $(HELMCHART_CRD) $(EA_CRD) # Install CRDs into a cluster install: manifests diff --git a/README.md b/README.md index 9a1ad22..66ca86c 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ that extends Flux with advanced source composition and decomposition patterns. The source-watcher controller implements the [ArtifactGenerator](docs/README.md) API, which allows Flux users to: -- 🔗 **Compose** multiple Flux sources (GitRepository, OCIRepository, Bucket) into a single deployable artifact +- 🔗 **Compose** multiple Flux sources (GitRepository, OCIRepository, Bucket, HelmChart) into a single deployable artifact - 📦 **Decompose** monorepos into multiple independent artifacts with separate deployment lifecycles - 🎯 **Optimize** reconciliation by only triggering updates when specific paths change - 🏗️ **Structure** complex deployments from distributed sources maintained by different teams diff --git a/api/v1beta1/artifactgenerator_types.go b/api/v1beta1/artifactgenerator_types.go index 5f4c76b..2ab2302 100644 --- a/api/v1beta1/artifactgenerator_types.go +++ b/api/v1beta1/artifactgenerator_types.go @@ -83,7 +83,7 @@ type SourceReference struct { Namespace string `json:"namespace,omitempty"` // Kind of the source. - // +kubebuilder:validation:Enum=Bucket;GitRepository;OCIRepository + // +kubebuilder:validation:Enum=Bucket;GitRepository;OCIRepository;HelmChart // +required Kind string `json:"kind"` } diff --git a/config/crd/bases/source.extensions.fluxcd.io_artifactgenerators.yaml b/config/crd/bases/source.extensions.fluxcd.io_artifactgenerators.yaml index 36a8c22..0c94867 100644 --- a/config/crd/bases/source.extensions.fluxcd.io_artifactgenerators.yaml +++ b/config/crd/bases/source.extensions.fluxcd.io_artifactgenerators.yaml @@ -158,6 +158,7 @@ spec: - Bucket - GitRepository - OCIRepository + - HelmChart type: string name: description: Name of the source. diff --git a/config/samples/source_v1beta1_artifactgenerator.yaml b/config/samples/source_v1beta1_artifactgenerator.yaml index 5b1c9a5..270eb44 100644 --- a/config/samples/source_v1beta1_artifactgenerator.yaml +++ b/config/samples/source_v1beta1_artifactgenerator.yaml @@ -4,7 +4,7 @@ metadata: name: podinfo spec: # Sources is a list of references to Flux source-controller resources - # (GitRepository, OCIRepository and Bucket) that will be + # (GitRepository, OCIRepository, Bucket and HelmChart) that will be # used to generate ExternalArtifact resources. sources: - alias: chart diff --git a/docs/spec/v1beta1/artifactgenerators.md b/docs/spec/v1beta1/artifactgenerators.md index e9f4ca7..7fb9183 100644 --- a/docs/spec/v1beta1/artifactgenerators.md +++ b/docs/spec/v1beta1/artifactgenerators.md @@ -4,7 +4,7 @@ The ArtifactGenerator is an extension of Flux APIs that allows source composition and decomposition. It enables the generation of [ExternalArtifacts][externalartifact] from multiple sources -([GitRepositories][gitrepository], [OCIRepositories][ocirepository] and [Buckets][bucket]) +([GitRepositories][gitrepository], [OCIRepositories][ocirepository], [Buckets][bucket] and [HelmChart][helmchart]) or the splitting of a single source into multiple artifacts. ## Source Composition Example @@ -203,7 +203,7 @@ for artifact generation. Each source must specify: - `alias`: A unique identifier used to reference the source in copy operations. Alias names must be unique within the same ArtifactGenerator and can only contain alphanumeric characters, dashes and underscores. -- `kind`: The type of Flux source resource (`GitRepository`, `OCIRepository`, or `Bucket`) +- `kind`: The type of Flux source resource (`GitRepository`, `OCIRepository`, `Bucket` or `HelmChart`) - `name`: The name of the source resource - `namespace` (optional): The namespace of the source resource if different from the ArtifactGenerator namespace @@ -462,3 +462,4 @@ the ArtifactGenerator name and namespace. [gitrepository]: https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1/gitrepositories.md [ocirepository]: https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1/ocirepositories.md [bucket]: https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1/buckets.md +[helmchart]: https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1/helmcharts.md diff --git a/internal/controller/artifactgenerator_controller.go b/internal/controller/artifactgenerator_controller.go index eed897d..4c9b68d 100644 --- a/internal/controller/artifactgenerator_controller.go +++ b/internal/controller/artifactgenerator_controller.go @@ -308,6 +308,16 @@ func (r *ArtifactGeneratorReconciler) observeSources(ctx context.Context, return nil, fmt.Errorf("unable to get source '%s': %w", namespacedName, err) } source = &bucket + case sourcev1.HelmChartKind: + var chart sourcev1.HelmChart + err := r.Get(ctx, namespacedName, &chart) + if err != nil { + if apierrors.IsNotFound(err) { + return nil, err + } + return nil, fmt.Errorf("unable to get source '%s': %w", namespacedName, err) + } + source = &chart default: return nil, fmt.Errorf("source `%s` kind '%s' not supported", src.Name, src.Kind) diff --git a/internal/controller/artifactgenerator_manager.go b/internal/controller/artifactgenerator_manager.go index e2fa042..6b94334 100644 --- a/internal/controller/artifactgenerator_manager.go +++ b/internal/controller/artifactgenerator_manager.go @@ -80,6 +80,11 @@ func (r *ArtifactGeneratorReconciler) SetupWithManager(ctx context.Context, handler.EnqueueRequestsFromMapFunc(r.requestsForSourceChange), builder.WithPredicates(sourceChangePredicate), ). + Watches( + &sourcev1.HelmChart{}, + handler.EnqueueRequestsFromMapFunc(r.requestsForSourceChange), + builder.WithPredicates(sourceChangePredicate), + ). WithOptions(controller.Options{ RateLimiter: opts.RateLimiter, }).