From 8ab19c92ad678aeca6bdef6eab2128daa6851221 Mon Sep 17 00:00:00 2001
From: Stefan Prodan
Date: Wed, 3 Apr 2024 17:42:04 +0300
Subject: [PATCH] docs: Add API spec for Helm v1
Signed-off-by: Stefan Prodan
---
README.md | 14 +-
api/v1/helmchart_types.go | 11 +
api/v1/zz_generated.deepcopy.go | 5 +
.../source.toolkit.fluxcd.io_helmcharts.yaml | 13 +
docs/api/v1/source.md | 40 +
docs/spec/v1/README.md | 2 +
docs/spec/v1/helmcharts.md | 855 ++++++++++++++++
docs/spec/v1/helmrepositories.md | 914 ++++++++++++++++++
.../controller/helmchart_controller_test.go | 28 +-
9 files changed, 1861 insertions(+), 21 deletions(-)
create mode 100644 docs/spec/v1/helmcharts.md
create mode 100644 docs/spec/v1/helmrepositories.md
diff --git a/README.md b/README.md
index ee43f8e0c..393d35169 100644
--- a/README.md
+++ b/README.md
@@ -16,13 +16,13 @@ and is a core component of the [GitOps toolkit](https://fluxcd.io/flux/component
## APIs
-| Kind | API Version |
-|---------------------------------------------------------|------------------------------------|
-| [GitRepository](docs/spec/v1/gitrepositories.md) | `source.toolkit.fluxcd.io/v1` |
-| [OCIRepository](docs/spec/v1beta2/ocirepositories.md) | `source.toolkit.fluxcd.io/v1beta2` |
-| [HelmRepository](docs/spec/v1beta2/helmrepositories.md) | `source.toolkit.fluxcd.io/v1beta2` |
-| [HelmChart](docs/spec/v1beta2/helmcharts.md) | `source.toolkit.fluxcd.io/v1beta2` |
-| [Bucket](docs/spec/v1beta2/buckets.md) | `source.toolkit.fluxcd.io/v1beta2` |
+| Kind | API Version |
+|-------------------------------------------------------|------------------------------------|
+| [GitRepository](docs/spec/v1/gitrepositories.md) | `source.toolkit.fluxcd.io/v1` |
+| [OCIRepository](docs/spec/v1beta2/ocirepositories.md) | `source.toolkit.fluxcd.io/v1beta2` |
+| [HelmRepository](docs/spec/v1/helmrepositories.md) | `source.toolkit.fluxcd.io/v1` |
+| [HelmChart](docs/spec/v1/helmcharts.md) | `source.toolkit.fluxcd.io/v1` |
+| [Bucket](docs/spec/v1beta2/buckets.md) | `source.toolkit.fluxcd.io/v1beta2` |
## Features
diff --git a/api/v1/helmchart_types.go b/api/v1/helmchart_types.go
index c01700c29..1527e6bc9 100644
--- a/api/v1/helmchart_types.go
+++ b/api/v1/helmchart_types.go
@@ -78,6 +78,11 @@ type HelmChartSpec struct {
// +deprecated
ValuesFile string `json:"valuesFile,omitempty"`
+ // IgnoreMissingValuesFiles controls whether to silently ignore missing values
+ // files rather than failing.
+ // +optional
+ IgnoreMissingValuesFiles bool `json:"ignoreMissingValuesFiles,omitempty"`
+
// Suspend tells the controller to suspend the reconciliation of this
// source.
// +optional
@@ -141,6 +146,12 @@ type HelmChartStatus struct {
// +optional
ObservedChartName string `json:"observedChartName,omitempty"`
+ // ObservedValuesFiles are the observed value files of the last successful
+ // reconciliation.
+ // It matches the chart in the last successfully reconciled artifact.
+ // +optional
+ ObservedValuesFiles []string `json:"observedValuesFiles,omitempty"`
+
// Conditions holds the conditions for the HelmChart.
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go
index 6ef308061..38f4c41e3 100644
--- a/api/v1/zz_generated.deepcopy.go
+++ b/api/v1/zz_generated.deepcopy.go
@@ -360,6 +360,11 @@ func (in *HelmChartSpec) DeepCopy() *HelmChartSpec {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HelmChartStatus) DeepCopyInto(out *HelmChartStatus) {
*out = *in
+ if in.ObservedValuesFiles != nil {
+ in, out := &in.ObservedValuesFiles, &out.ObservedValuesFiles
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]metav1.Condition, len(*in))
diff --git a/config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml b/config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml
index 7f69d4347..45591d54a 100644
--- a/config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml
+++ b/config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml
@@ -745,6 +745,11 @@ spec:
Chart is the name or path the Helm chart is available at in the
SourceRef.
type: string
+ ignoreMissingValuesFiles:
+ description: |-
+ IgnoreMissingValuesFiles controls whether to silently ignore missing values
+ files rather than failing.
+ type: boolean
interval:
description: |-
Interval at which the HelmChart SourceRef is checked for updates.
@@ -1020,6 +1025,14 @@ spec:
ObservedSourceArtifactRevision is the last observed Artifact.Revision
of the HelmChartSpec.SourceRef.
type: string
+ observedValuesFiles:
+ description: |-
+ ObservedValuesFiles are the observed value files of the last successful
+ reconciliation.
+ It matches the chart in the last successfully reconciled artifact.
+ items:
+ type: string
+ type: array
url:
description: |-
URL is the dynamic fetch link for the latest Artifact.
diff --git a/docs/api/v1/source.md b/docs/api/v1/source.md
index 547572b5e..3746ad76c 100644
--- a/docs/api/v1/source.md
+++ b/docs/api/v1/source.md
@@ -408,6 +408,19 @@ is merged before the ValuesFiles items. Ignored when omitted.
+ignoreMissingValuesFiles
+
+bool
+
+ |
+
+(Optional)
+ IgnoreMissingValuesFiles controls whether to silently ignore missing values
+files rather than failing.
+ |
+
+
+
suspend
bool
@@ -1492,6 +1505,19 @@ is merged before the ValuesFiles items. Ignored when omitted.
|
+ignoreMissingValuesFiles
+
+bool
+
+ |
+
+(Optional)
+ IgnoreMissingValuesFiles controls whether to silently ignore missing values
+files rather than failing.
+ |
+
+
+
suspend
bool
@@ -1599,6 +1625,20 @@ resolved chart reference.
|
+observedValuesFiles
+
+[]string
+
+ |
+
+(Optional)
+ ObservedValuesFiles are the observed value files of the last successful
+reconciliation.
+It matches the chart in the last successfully reconciled artifact.
+ |
+
+
+
conditions
diff --git a/docs/spec/v1/README.md b/docs/spec/v1/README.md
index ae989ceb0..a87051a52 100644
--- a/docs/spec/v1/README.md
+++ b/docs/spec/v1/README.md
@@ -6,6 +6,8 @@ This is the v1 API specification for defining the desired state sources of Kuber
* Source kinds:
+ [GitRepository](gitrepositories.md)
+ + [HelmRepository](helmrepositories.md)
+ + [HelmChart](helmcharts.md)
## Implementation
diff --git a/docs/spec/v1/helmcharts.md b/docs/spec/v1/helmcharts.md
new file mode 100644
index 000000000..408bcf795
--- /dev/null
+++ b/docs/spec/v1/helmcharts.md
@@ -0,0 +1,855 @@
+# Helm Charts
+
+
+
+The `HelmChart` API defines a Source to produce an Artifact for a Helm chart
+archive with a set of specific configurations.
+
+## Example
+
+The following is an example of a HelmChart. It fetches and/or packages a Helm
+chart and exposes it as a tarball (`.tgz`) Artifact for the specified
+configuration:
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmChart
+metadata:
+ name: podinfo
+ namespace: default
+spec:
+ interval: 5m0s
+ chart: podinfo
+ reconcileStrategy: ChartVersion
+ sourceRef:
+ kind: HelmRepository
+ name: podinfo
+ version: '5.*'
+```
+
+In the above example:
+
+- A HelmChart named `podinfo` is created, indicated by the `.metadata.name`
+ field.
+- The source-controller fetches the Helm chart every five minutes from the
+ `podinfo` HelmRepository source reference, indicated by the
+ `.spec.sourceRef.kind` and `.spec.sourceRef.name` fields.
+- The fetched Helm chart version is the latest available chart
+ version in the range specified in `spec.version`. This version is also used as
+ Artifact revision, reported in-cluster in the `.status.artifact.revision`
+ field.
+- When the current Helm Chart version differs from the latest available chart
+ in the version range, it is fetched and/or packaged as a new Artifact.
+- The new Artifact is reported in the `.status.artifact` field.
+
+You can run this example by saving the manifest into `helmchart.yaml`.
+
+**Note:** HelmChart is usually used by the helm-controller. Based on the
+HelmRelease configuration, an associated HelmChart is created by the
+helm-controller.
+
+1. Apply the resource on the cluster:
+
+ ```sh
+ kubectl apply -f helmchart.yaml
+ ```
+
+2. Run `kubectl get helmchart` to see the HelmChart:
+
+ ```console
+ NAME CHART VERSION SOURCE KIND SOURCE NAME AGE READY STATUS
+ podinfo podinfo 5.* HelmRepository podinfo 53s True pulled 'podinfo' chart with version '5.2.1'
+ ```
+
+3. Run `kubectl describe helmchart podinfo` to see the [Artifact](#artifact) and
+ [Conditions](#conditions) in the HelmChart's Status:
+
+ ```console
+ Status:
+ Observed Source Artifact Revision: sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111
+ Artifact:
+ Digest: sha256:6c3cc3b955bce1686036ae6822ee2ca0ef6ecb994e3f2d19eaf3ec03dcba84b3
+ Last Update Time: 2022-02-13T11:24:10Z
+ Path: helmchart/default/podinfo/podinfo-5.2.1.tgz
+ Revision: 5.2.1
+ Size: 14166
+ URL: http://source-controller.flux-system.svc.cluster.local./helmchart/default/podinfo/podinfo-5.2.1.tgz
+ Conditions:
+ Last Transition Time: 2022-02-13T11:24:10Z
+ Message: pulled 'podinfo' chart with version '5.2.1'
+ Observed Generation: 1
+ Reason: ChartPullSucceeded
+ Status: True
+ Type: Ready
+ Last Transition Time: 2022-02-13T11:24:10Z
+ Message: pulled 'podinfo' chart with version '5.2.1'
+ Observed Generation: 1
+ Reason: ChartPullSucceeded
+ Status: True
+ Type: ArtifactInStorage
+ Observed Chart Name: podinfo
+ Observed Generation: 1
+ URL: http://source-controller.flux-system.svc.cluster.local./helmchart/default/podinfo/latest.tar.gz
+ Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal ChartPullSucceeded 2m51s source-controller pulled 'podinfo' chart with version '5.2.1'
+ ```
+
+## Writing a HelmChart spec
+
+As with all other Kubernetes config, a HelmChart needs `apiVersion`, `kind`, and
+`metadata` fields. The name of a HelmChart object must be a valid
+[DNS subdomain name](https://kubernetes.io/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
+
+A HelmChart also needs a
+[`.spec` section](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
+
+### Source reference
+
+`.spec.sourceRef` is a required field that specifies a reference to the Source
+the chart is available at.
+
+Supported references are:
+- [`HelmRepository`](helmrepositories.md)
+- [`GitRepository`](gitrepositories.md)
+- [`Bucket`](buckets.md)
+
+Although there are three kinds of source references, there are only two
+underlying implementations. The artifact building process for `GitRepository`
+and `Bucket` are the same as they are already built source artifacts. In case
+of `HelmRepository`, a chart is fetched and/or packaged based on the
+configuration of the Helm chart.
+
+For a `HelmChart` to be reconciled, the associated artifact in the source
+reference must be ready. If the source artifact is not ready, the `HelmChart`
+reconciliation is retried.
+
+When the `metadata.generation` of the `HelmChart` don't match with the
+`status.observedGeneration`, the chart is fetched from source and/or packaged.
+If there's no `.spec.valuesFiles` specified, the chart is only fetched from the
+source, and not packaged. If `.spec.valuesFiles` are specified, the chart is
+fetched and packaged with the values files. When the `metadata.generation`
+matches the `status.observedGeneration`, the chart is only fetched from source
+or from the cache if available, and not packaged.
+
+When using a `HelmRepository` source reference, the secret reference defined in
+the Helm repository is used to fetch the chart.
+
+The HelmChart reconciliation behavior varies depending on the source reference
+kind, see [reconcile strategy](#reconcile-strategy).
+
+The attributes of the generated artifact also varies depending on the source
+reference kind, see [artifact](#artifact).
+
+### Chart
+
+`.spec.chart` is a required field that specifies the name or path the Helm chart
+is available at in the [Source reference](#source-reference).
+
+For `HelmRepository` Source reference, it'll be just the name of the chart.
+
+```yaml
+spec:
+ chart: podinfo
+ sourceRef:
+ name: podinfo
+ kind: HelmRepository
+```
+
+For `GitRepository` and `Bucket` Source reference, it'll be the path to the
+Helm chart directory.
+
+```yaml
+spec:
+ chart: ./charts/podinfo
+ sourceRef:
+ name: podinfo
+ kind:
+```
+
+### Version
+
+`.spec.version` is an optional field to specify the version of the chart in
+semver. It is applicable only when the Source reference is a `HelmRepository`.
+It is ignored for `GitRepository` and `Bucket` Source reference. It defaults to
+the latest version of the chart with value `*`.
+
+Version can be a fixed semver, minor or patch semver range of a specific
+version (i.e. `4.0.x`) or any semver range (i.e. `>=4.0.0 <5.0.0`).
+
+### Values files
+
+`.spec.valuesFiles` is an optional field to specify an alternative list of
+values files to use as the chart values (values.yaml). The file paths are
+expected to be relative to the Source reference. Values files are merged in the
+order of the list with the last file overriding the first. It is ignored when
+omitted. When values files are specified, the chart is fetched and packaged
+with the provided values.
+
+```yaml
+spec:
+ chart:
+ spec:
+ chart: podinfo
+ ...
+ valuesFiles:
+ - values.yaml
+ - values-production.yaml
+```
+
+Values files also affect the generated artifact revision, see
+[artifact](#artifact).
+
+### Reconcile strategy
+
+`.spec.reconcileStrategy` is an optional field to specify what enables the
+creation of a new Artifact. Valid values are `ChartVersion` and `Revision`.
+`ChartVersion` is used for creating a new artifact when the chart version
+changes in a `HelmRepository`. `Revision` is used for creating a new artifact
+when the source revision changes in a `GitRepository` or a `Bucket` Source. It
+defaults to `ChartVersion`.
+
+**Note:** If the reconcile strategy is `ChartVersion` and the source reference
+is a `GitRepository` or a `Bucket`, no new chart artifact is produced on updates
+to the source unless the `version` in `Chart.yaml` is incremented. To produce
+new chart artifact on change in source revision, set the reconcile strategy to
+`Revision`.
+
+Reconcile strategy also affects the artifact version, see [artifact](#artifact)
+for more details.
+
+### Interval
+
+`.spec.interval` is a required field that specifies the interval at which the
+Helm Chart source must be checked for updates.
+
+After successfully reconciling a HelmChart object, the source-controller
+requeues the object for inspection after the specified interval. The value must
+be in a [Go recognized duration string format](https://pkg.go.dev/time#ParseDuration),
+e.g. `10m0s` to look at the source for updates every 10 minutes.
+
+If the `.metadata.generation` of a resource changes (due to e.g. applying a
+change to the spec), this is handled instantly outside the interval window.
+
+**Note:** The controller can be configured to apply a jitter to the interval in
+order to distribute the load more evenly when multiple HelmChart objects are set
+up with the same interval. For more information, please refer to the
+[source-controller configuration options](https://fluxcd.io/flux/components/source/options/).
+
+### Suspend
+
+`.spec.suspend` is an optional field to suspend the reconciliation of a
+HelmChart. When set to `true`, the controller will stop reconciling the
+HelmChart, and changes to the resource or the Helm chart Source will not result
+in a new Artifact. When the field is set to `false` or removed, it will resume.
+
+For practical information, see
+[suspending and resuming](#suspending-and-resuming).
+
+### Verification
+
+**Note:** This feature is available only for Helm charts fetched from an OCI Registry.
+
+`.spec.verify` is an optional field to enable the verification of [Cosign](https://github.com/sigstore/cosign) or [Notation](https://github.com/notaryproject/notation)
+signatures. The field offers three subfields:
+
+- `.provider`, to specify the verification provider. The supported options are `cosign` and `notation` at present.
+- `.secretRef.name`, to specify a reference to a Secret in the same namespace as
+ the HelmChart, containing the public keys of trusted authors. For Notation this Secret should also include the [trust policy](https://github.com/notaryproject/specifications/blob/v1.0.0/specs/trust-store-trust-policy.md#trust-policy) in
+ addition to the CA certificate.
+- `.matchOIDCIdentity`, to specify a list of OIDC identity matchers (only supported when using `cosign` as the verification provider). Please see
+ [Keyless verification](#keyless-verification) for more details.
+
+#### Cosign
+
+The `cosign` provider can be used to verify the signature of an OCI artifact using either a known public key or via the [Cosign Keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) procedure.
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmChart
+metadata:
+ name: podinfo
+spec:
+ verify:
+ provider: cosign
+ secretRef:
+ name: cosign-public-keys
+```
+
+When the verification succeeds, the controller adds a Condition with the
+following attributes to the HelmChart's `.status.conditions`:
+
+- `type: SourceVerified`
+- `status: "True"`
+- `reason: Succeeded`
+
+##### Public keys verification
+
+To verify the authenticity of HelmChart hosted in an OCI Registry, create a Kubernetes
+secret with the Cosign public keys:
+
+```yaml
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: cosign-public-keys
+type: Opaque
+data:
+ key1.pub:
+ key2.pub:
+```
+
+Note that the keys must have the `.pub` extension for Flux to make use of them.
+
+Flux will loop over the public keys and use them to verify a HelmChart's signature.
+This allows for older HelmCharts to be valid as long as the right key is in the secret.
+
+##### Keyless verification
+
+For publicly available HelmCharts, which are signed using the
+[Cosign Keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) procedure,
+you can enable the verification by omitting the `.verify.secretRef` field.
+
+To verify the identity's subject and the OIDC issuer present in the Fulcio
+certificate, you can specify a list of OIDC identity matchers using
+`.spec.verify.matchOIDCIdentity`. The matcher provides two required fields:
+
+- `.issuer`, to specify a regexp that matches against the OIDC issuer.
+- `.subject`, to specify a regexp that matches against the subject identity in
+ the certificate.
+Both values should follow the [Go regular expression syntax](https://golang.org/s/re2syntax).
+
+The matchers are evaluated in an OR fashion, i.e. the identity is deemed to be
+verified if any one matcher successfully matches against the identity.
+
+Example of verifying HelmCharts signed by the
+[Cosign GitHub Action](https://github.com/sigstore/cosign-installer) with GitHub OIDC Token:
+
+```yaml
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmChart
+metadata:
+ name: podinfo
+spec:
+ interval: 5m
+ chart: podinfo
+ reconcileStrategy: ChartVersion
+ sourceRef:
+ kind: HelmRepository
+ name: podinfo
+ version: ">=6.1.6"
+ verify:
+ provider: cosign
+ matchOIDCIdentity:
+ - issuer: "^https://token.actions.githubusercontent.com$"
+ subject: "^https://github.com/stefanprodan/podinfo.*$"
+```
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmRepository
+metadata:
+ name: podinfo
+spec:
+ interval: 1m0s
+ url: oci://ghcr.io/stefanprodan/charts
+ type: "oci"
+```
+
+The controller verifies the signatures using the Fulcio root CA and the Rekor
+instance hosted at [rekor.sigstore.dev](https://rekor.sigstore.dev/).
+
+Note that keyless verification is an **experimental feature**, using
+custom root CAs or self-hosted Rekor instances are not currently supported.
+
+#### Notation
+
+The `notation` provider can be used to verify the signature of an OCI artifact using known
+trust policy and CA certificate.
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmChart
+metadata:
+ name: podinfo
+spec:
+ verify:
+ provider: notation
+ secretRef:
+ name: notation-config
+```
+
+When the verification succeeds, the controller adds a Condition with the
+following attributes to the HelmChart's `.status.conditions`:
+
+- `type: SourceVerified`
+- `status: "True"`
+- `reason: Succeeded`
+
+To verify the authenticity of an OCI artifact, create a Kubernetes secret
+containing Certificate Authority (CA) root certificates and the a `trust policy`
+
+```yaml
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: notation-config
+type: Opaque
+data:
+ certificate1.pem:
+ certificate2.crt:
+ trustpolicy.json:
+```
+
+Note that the CA certificates must have either `.pem` or `.crt` extension and your trust policy must
+be named `trustpolicy.json` for Flux to make use of them.
+
+For more information on the signing and verification process see [Signing and Verification Workflow](https://github.com/notaryproject/specifications/blob/v1.0.0/specs/signing-and-verification-workflow.md).
+
+Flux will loop over the certificates and use them to verify an artifact's signature.
+This allows for older artifacts to be valid as long as the right certificate is in the secret.
+
+## Working with HelmCharts
+
+### Triggering a reconcile
+
+To manually tell the source-controller to reconcile a HelmChart outside the
+[specified interval window](#interval), a HelmCHart can be annotated with
+`reconcile.fluxcd.io/requestedAt: `. Annotating the resource
+queues the object for reconciliation if the `` differs from
+the last value the controller acted on, as reported in
+[`.status.lastHandledReconcileAt`](#last-handled-reconcile-at).
+
+Using `kubectl`:
+
+```sh
+kubectl annotate --field-manager=flux-client-side-apply --overwrite helmchart/ reconcile.fluxcd.io/requestedAt="$(date +%s)"
+```
+
+### Waiting for `Ready`
+
+When a change is applied, it is possible to wait for the HelmChart to reach a
+[ready state](#ready-helmchart) using `kubectl`:
+
+```sh
+kubectl wait helmchart/ --for=condition=ready --timeout=1m
+```
+
+### Suspending and resuming
+
+When you find yourself in a situation where you temporarily want to pause the
+reconciliation of a HelmChart, you can suspend it using the
+[`.spec.suspend` field](#suspend).
+
+#### Suspend a HelmChart
+
+In your YAML declaration:
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmChart
+metadata:
+ name:
+spec:
+ suspend: true
+```
+
+Using `kubectl`:
+
+```sh
+kubectl patch helmchart --field-manager=flux-client-side-apply -p '{\"spec\": {\"suspend\" : true }}'
+```
+
+**Note:** When a HelmChart has an Artifact and is suspended, and this
+Artifact later disappears from the storage due to e.g. the source-controller
+Pod being evicted from a Node, this will not be reflected in the
+HelmChart's Status until it is resumed.
+
+#### Resume a HelmChart
+
+In your YAML declaration, comment out (or remove) the field:
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmChart
+metadata:
+ name:
+spec:
+ # suspend: true
+```
+
+**Note:** Setting the field value to `false` has the same effect as removing
+it, but does not allow for "hot patching" using e.g. `kubectl` while practicing
+GitOps; as the manually applied patch would be overwritten by the declared
+state in Git.
+
+Using `kubectl`:
+
+```sh
+kubectl patch helmchart --field-manager=flux-client-side-apply -p '{\"spec\" : {\"suspend\" : false }}'
+```
+
+### Debugging a HelmChart
+
+There are several ways to gather information about a HelmChart for debugging
+purposes.
+
+#### Describe the HelmChart
+
+Describing a HelmChart using `kubectl describe helmchart ` displays
+the latest recorded information for the resource in the `Status` and `Events`
+sections:
+
+```console
+...
+Status:
+...
+ Conditions:
+ Last Transition Time: 2022-02-13T14:06:27Z
+ Message: invalid chart reference: failed to get chart version for remote reference: no 'podinfo' chart with version matching '9.*' found
+ Observed Generation: 3
+ Reason: InvalidChartReference
+ Status: True
+ Type: Stalled
+ Last Transition Time: 2022-02-13T14:06:27Z
+ Message: invalid chart reference: failed to get chart version for remote reference: no 'podinfo' chart with version matching '9.*' found
+ Observed Generation: 3
+ Reason: InvalidChartReference
+ Status: False
+ Type: Ready
+ Last Transition Time: 2022-02-13T14:06:27Z
+ Message: invalid chart reference: failed to get chart version for remote reference: no 'podinfo' chart with version matching '9.*' found
+ Observed Generation: 3
+ Reason: InvalidChartReference
+ Status: True
+ Type: FetchFailed
+ Last Handled Reconcile At: 1644759954
+ Observed Chart Name: podinfo
+ Observed Generation: 3
+ URL: http://source-controller.flux-system.svc.cluster.local./helmchart/default/podinfo/latest.tar.gz
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Warning InvalidChartReference 11s source-controller invalid chart reference: failed to get chart version for remote reference: no 'podinfo' chart with ver
+sion matching '9.*' found
+```
+
+#### Trace emitted Events
+
+To view events for specific HelmChart(s), `kubectl events` can be used in
+combination with `--for` to list the Events for specific objects. For example,
+running
+
+```sh
+kubectl events --for HelmChart/
+```
+
+lists
+
+```console
+LAST SEEN TYPE REASON OBJECT MESSAGE
+22s Warning InvalidChartReference helmchart/ invalid chart reference: failed to get chart version for remote reference: no 'podinfo' chart with version matching '9.*' found
+2s Normal ChartPullSucceeded helmchart/ pulled 'podinfo' chart with version '6.0.3'
+2s Normal ArtifactUpToDate helmchart/ artifact up-to-date with remote revision: '6.0.3'
+```
+
+Besides being reported in Events, the reconciliation errors are also logged by
+the controller. The Flux CLI offer commands for filtering the logs for a
+specific HelmChart, e.g. `flux logs --level=error --kind=HelmChart --name=`.
+
+### Improving resource consumption by enabling the cache
+
+When using a `HelmRepository` as Source for a `HelmChart`, the controller loads
+the repository index in memory to find the latest version of the chart.
+
+The controller can be configured to cache Helm repository indexes in memory.
+The cache is used to avoid loading repository indexes for every `HelmChart`
+reconciliation.
+
+The following flags are provided to enable and configure the cache:
+- `helm-cache-max-size`: The maximum size of the cache in number of indexes.
+ If `0`, then the cache is disabled.
+- `helm-cache-ttl`: The TTL of an index in the cache.
+- `helm-cache-purge-interval`: The interval at which the cache is purged of
+ expired items.
+
+The caching strategy is to pull a repository index from the cache if it is
+available, otherwise to load the index, retrieve and build the chart,
+then cache the index. The cached index TTL is refreshed every time the
+Helm repository index is loaded with the `helm-cache-ttl` value.
+
+The cache is purged of expired items every `helm-cache-purge-interval`.
+
+When the cache is full, no more items can be added to the cache, and the
+source-controller will report a warning event instead.
+
+In order to use the cache, set the related flags in the source-controller
+Deployment config:
+
+```yaml
+ spec:
+ containers:
+ - args:
+ - --watch-all-namespaces
+ - --log-level=info
+ - --log-encoding=json
+ - --enable-leader-election
+ - --storage-path=/data
+ - --storage-adv-addr=source-controller.$(RUNTIME_NAMESPACE).svc.cluster.local.
+ ## Helm cache with up to 10 items, i.e. 10 indexes.
+ - --helm-cache-max-size=10
+ ## TTL of an index is 1 hour.
+ - --helm-cache-ttl=1h
+ ## Purge expired index every 10 minutes.
+ - --helm-cache-purge-interval=10m
+```
+
+## HelmChart Status
+
+### Artifact
+
+The HelmChart reports the last built chart as an Artifact object in the
+`.status.artifact` of the resource.
+
+The Artifact file is a gzip compressed TAR archive (`-.tgz`),
+and can be retrieved in-cluster from the `.status.artifact.url` HTTP address.
+
+#### Artifact example
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmChart
+metadata:
+ name:
+status:
+ artifact:
+ digest: sha256:e30b95a08787de69ffdad3c232d65cfb131b5b50c6fd44295f48a078fceaa44e
+ lastUpdateTime: "2022-02-10T18:53:47Z"
+ path: helmchart///-.tgz
+ revision: 6.0.3
+ size: 14166
+ url: http://source-controller.flux-system.svc.cluster.local./helmchart///-.tgz
+```
+
+When using a `HelmRepository` as the source reference and values files are
+provided, the value of `status.artifact.revision` is the chart version combined
+with the `HelmChart` object generation. For example, if the chart version is
+`6.0.3` and the `HelmChart` object generation is `1`, the
+`status.artifact.revision` value will be `6.0.3+1`.
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmChart
+metadata:
+ name:
+status:
+ artifact:
+ digest: sha256:ee68224ded207ebb18a8e9730cf3313fa6bc1f31e6d8d3943ab541113559bb52
+ lastUpdateTime: "2022-02-28T08:07:12Z"
+ path: helmchart///-6.0.3+1.tgz
+ revision: 6.0.3+1
+ size: 14166
+ url: http://source-controller.flux-system.svc.cluster.local./helmchart///-6.0.3+1.tgz
+ observedGeneration: 1
+ ...
+```
+
+When using a `GitRepository` or a `Bucket` as the source reference and
+`Revision` as the reconcile strategy, the value of `status.artifact.revision` is
+the chart version combined with the first 12 characters of the revision of the
+`GitRepository` or `Bucket`. For example if the chart version is `6.0.3` and the
+revision of the `Bucket` is `4e5cbb7b97d00a8039b8810b90b922f4256fd3bd8f78b934b4892dae13f7ca87`,
+the `status.artifact.revision` value will be `6.0.3+4e5cbb7b97d0`.
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmChart
+metadata:
+ name:
+status:
+ artifact:
+ digest: sha256:8d1f0ac3f4b0e8759a32180086f17ac87ca04e5d46c356e67f97e97616ef4718
+ lastUpdateTime: "2022-02-28T08:07:12Z"
+ path: helmchart///-6.0.3+4e5cbb7b97d0.tgz
+ revision: 6.0.3+4e5cbb7b97d0
+ size: 14166
+ url: http://source-controller.flux-system.svc.cluster.local./helmchart///-6.0.3+4e5cbb7b97d0.tgz
+```
+
+### Conditions
+
+A HelmChart enters various states during its lifecycle, reflected as [Kubernetes
+Conditions][typical-status-properties].
+It can be [reconciling](#reconciling-helmchart) while fetching or building the
+chart, it can be [ready](#ready-helmchart), it can
+[fail during reconciliation](#failed-helmchart), or it can
+[stall](#stalled-helmchart).
+
+The HelmChart API is compatible with the [kstatus
+specification][kstatus-spec],
+and reports `Reconciling` and `Stalled` conditions where applicable to
+provide better (timeout) support to solutions polling the HelmChart to become
+`Ready`.
+
+#### Reconciling HelmChart
+
+The source-controller marks a HelmChart as _reconciling_ when one of the
+following is true:
+
+- There is no current Artifact for the HelmChart, or the reported Artifact is
+ determined to have disappeared from the storage.
+- The generation of the HelmChart is newer than the [Observed
+ Generation](#observed-generation).
+- The newly fetched Artifact revision differs from the current Artifact.
+
+When the HelmChart is "reconciling", the `Ready` Condition status becomes
+`Unknown` when the controller detects drift, and the controller adds a Condition
+with the following attributes to the HelmChart's `.status.conditions`:
+
+- `type: Reconciling`
+- `status: "True"`
+- `reason: Progressing` | `reason: ProgressingWithRetry`
+
+If the reconciling state is due to a new version, it adds an additional
+Condition with the following attributes:
+
+- `type: ArtifactOutdated`
+- `status: "True"`
+- `reason: NewChart`
+
+Both Conditions have a ["negative polarity"][typical-status-properties],
+and are only present on the HelmChart while their status value is `"True"`.
+
+#### Ready HelmChart
+
+The source-controller marks a HelmChart as _ready_ when it has the following
+characteristics:
+
+- The HelmChart reports an [Artifact](#artifact).
+- The reported Artifact exists in the controller's Artifact storage.
+- The controller was able to fetch and build the Helm chart using the current
+ spec.
+- The version/revision of the reported Artifact is up-to-date with the
+ latest version/revision of the Helm chart.
+
+When the HelmChart is "ready", the controller sets a Condition with the
+following attributes in the HelmChart's `.status.conditions`:
+
+- `type: Ready`
+- `status: "True"`
+- `reason: Succeeded`
+
+This `Ready` Condition will retain a status value of `"True"` until the
+HelmChart is marked as [reconciling](#reconciling-helmchart), or e.g.
+a [transient error](#failed-helmchart) occurs due to a temporary network issue.
+
+When the HelmChart Artifact is archived in the controller's Artifact
+storage, the controller sets a Condition with the following attributes in the
+HelmChart's `.status.conditions`:
+
+- `type: ArtifactInStorage`
+- `status: "True"`
+- `reason: Succeeded`
+
+This `ArtifactInStorage` Condition will retain a status value of `"True"` until
+the Artifact in the storage no longer exists.
+
+#### Failed HelmChart
+
+The source-controller may get stuck trying to produce an Artifact for a
+HelmChart without completing. This can occur due to some of the following
+factors:
+
+- The Helm chart Source is temporarily unavailable.
+- The credentials in the [Source reference](#source-reference) Secret are
+ invalid.
+- The HelmChart spec contains a generic misconfiguration.
+- A storage related failure when storing the artifact.
+
+When this happens, the controller sets the `Ready` Condition status to `False`,
+and adds a Condition with the following attributes to the HelmChart's
+`.status.conditions`:
+
+- `type: FetchFailed` | `type: StorageOperationFailed`
+- `status: "True"`
+- `reason: AuthenticationFailed` | `reason: StorageOperationFailed` | `reason: URLInvalid` | `reason: IllegalPath` | `reason: Failed`
+
+This condition has a ["negative polarity"][typical-status-properties],
+and is only present on the HelmChart while the status value is `"True"`.
+There may be more arbitrary values for the `reason` field to provide accurate
+reason for a condition.
+
+While the HelmChart has this Condition, the controller will continue to
+attempt to produce an Artifact for the resource with an exponential backoff,
+until it succeeds and the HelmChart is marked as [ready](#ready-helmchart).
+
+Note that a HelmChart can be [reconciling](#reconciling-helmchart)
+while failing at the same time, for example due to a newly introduced
+configuration issue in the HelmChart spec. When a reconciliation fails, the
+`Reconciling` Condition reason would be `ProgressingWithRetry`. When the
+reconciliation is performed again after the failure, the reason is updated to
+`Progressing`.
+
+#### Stalled HelmChart
+
+The source-controller can mark a HelmChart as _stalled_ when it determines that
+without changes to the spec, the reconciliation can not succeed.
+For example because a HelmChart Version is set to a non-existing version.
+
+When this happens, the controller sets the same Conditions as when it
+[fails](#failed-helmchart), but adds another Condition with the following
+attributes to the HelmChart's `.status.conditions`:
+
+- `type: Stalled`
+- `status: "True"`
+- `reason: InvalidChartReference`
+
+While the HelmChart has this Condition, the controller will not requeue the
+resource any further, and will stop reconciling the resource until a change to
+the spec is made.
+
+### Observed Source Artifact Revision
+
+The source-controller reports the revision of the last
+[Source reference's](#source-reference) Artifact the current chart was fetched
+from in the HelmChart's `.status.observedSourceArtifactRevision`. It is used to
+keep track of the source artifact revision and detect when a new source
+artifact is available.
+
+### Observed Chart Name
+
+The source-controller reports the last resolved chart name of the Artifact
+for the [`.spec.chart` field](#chart) in the HelmChart's
+`.status.observedChartName`. It is used to keep track of the chart and detect
+when a new chart is found.
+
+### Observed Generation
+
+The source-controller reports an [observed generation][typical-status-properties]
+in the HelmChart's `.status.observedGeneration`. The observed generation is the
+latest `.metadata.generation` which resulted in either a [ready state](#ready-helmchart),
+or stalled due to error it can not recover from without human
+intervention.
+
+### Last Handled Reconcile At
+
+The source-controller reports the last `reconcile.fluxcd.io/requestedAt`
+annotation value it acted on in the `.status.lastHandledReconcileAt` field.
+
+For practical information about this field, see [triggering a
+reconcile](#triggering-a-reconcile).
+
+[typical-status-properties]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
+[kstatus-spec]: https://github.com/kubernetes-sigs/cli-utils/tree/master/pkg/kstatus
diff --git a/docs/spec/v1/helmrepositories.md b/docs/spec/v1/helmrepositories.md
new file mode 100644
index 000000000..d8b6748e9
--- /dev/null
+++ b/docs/spec/v1/helmrepositories.md
@@ -0,0 +1,914 @@
+# Helm Repositories
+
+
+
+There are 2 [Helm repository types](#type) defined by the `HelmRepository` API:
+- Helm HTTP/S repository, which defines a Source to produce an Artifact for a Helm
+repository index YAML (`index.yaml`).
+- OCI Helm repository, which defines a source that does not produce an Artifact.
+ It's a data container to store the information about the OCI repository that
+ can be used by [HelmChart](helmcharts.md) to access OCI Helm charts.
+
+## Examples
+
+### Helm HTTP/S repository
+
+The following is an example of a HelmRepository. It creates a YAML (`.yaml`)
+Artifact from the fetched Helm repository index (in this example the [podinfo
+repository](https://github.com/stefanprodan/podinfo)):
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmRepository
+metadata:
+ name: podinfo
+ namespace: default
+spec:
+ interval: 5m0s
+ url: https://stefanprodan.github.io/podinfo
+```
+
+In the above example:
+
+- A HelmRepository named `podinfo` is created, indicated by the
+ `.metadata.name` field.
+- The source-controller fetches the Helm repository index YAML every five
+ minutes from `https://stefanprodan.github.io/podinfo`, indicated by the
+ `.spec.interval` and `.spec.url` fields.
+- The digest (algorithm defaults to SHA256) of the Helm repository index after
+ stable sorting the entries is used as Artifact revision, reported in-cluster
+ in the `.status.artifact.revision` field.
+- When the current HelmRepository revision differs from the latest fetched
+ revision, it is stored as a new Artifact.
+- The new Artifact is reported in the `.status.artifact` field.
+
+You can run this example by saving the manifest into `helmrepository.yaml`.
+
+1. Apply the resource on the cluster:
+
+ ```sh
+ kubectl apply -f helmrepository.yaml
+ ```
+
+2. Run `kubectl get helmrepository` to see the HelmRepository:
+
+ ```console
+ NAME URL AGE READY STATUS
+ podinfo https://stefanprodan.github.io/podinfo 4s True stored artifact for revision 'sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111'
+ ```
+
+3. Run `kubectl describe helmrepository podinfo` to see the [Artifact](#artifact)
+ and [Conditions](#conditions) in the HelmRepository's Status:
+
+ ```console
+ ...
+ Status:
+ Artifact:
+ Digest: sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111
+ Last Update Time: 2022-02-04T09:55:58Z
+ Path: helmrepository/default/podinfo/index-83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111.yaml
+ Revision: sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111
+ Size: 40898
+ URL: http://source-controller.flux-system.svc.cluster.local./helmrepository/default/podinfo/index-83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111.yaml
+ Conditions:
+ Last Transition Time: 2022-02-04T09:55:58Z
+ Message: stored artifact for revision 'sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111'
+ Observed Generation: 1
+ Reason: Succeeded
+ Status: True
+ Type: Ready
+ Last Transition Time: 2022-02-04T09:55:58Z
+ Message: stored artifact for revision 'sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111'
+ Observed Generation: 1
+ Reason: Succeeded
+ Status: True
+ Type: ArtifactInStorage
+ Observed Generation: 1
+ URL: http://source-controller.flux-system.svc.cluster.local./helmrepository/default/podinfo/index.yaml
+ Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Normal NewArtifact 1m source-controller fetched index of size 30.88kB from 'https://stefanprodan.github.io/podinfo'
+ ```
+
+### Helm OCI repository
+
+The following is an example of an OCI HelmRepository.
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmRepository
+metadata:
+ name: podinfo
+ namespace: default
+spec:
+ type: "oci"
+ interval: 5m0s
+ url: oci://ghcr.io/stefanprodan/charts
+```
+
+In the above example:
+
+- A HelmRepository named `podinfo` is created, indicated by the
+ `.metadata.name` field.
+- A HelmChart that refers to this HelmRepository uses the URL in the `.spec.url`
+ field to access the OCI Helm chart.
+
+**NOTE:** The `.spec.interval` field is only used by the `default` Helm
+repository and is ignored for any value in `oci` Helm repository.
+
+You can run this example by saving the manifest into `helmrepository.yaml`.
+
+1. Apply the resource on the cluster:
+
+ ```sh
+ kubectl apply -f helmrepository.yaml
+ ```
+
+2. Run `kubectl get helmrepository` to see the HelmRepository:
+
+ ```console
+ NAME URL AGE READY STATUS
+ podinfo oci://ghcr.io/stefanprodan/charts 3m22s
+ ```
+
+Because the OCI Helm repository is a data container, there's nothing to report
+for `READY` and `STATUS` columns above. The existence of the object can be
+considered to be ready for use.
+
+## Writing a HelmRepository spec
+
+As with all other Kubernetes config, a HelmRepository needs `apiVersion`,
+`kind`, and `metadata` fields. The name of a HelmRepository object must be a
+valid [DNS subdomain name](https://kubernetes.io/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
+
+A HelmRepository also needs a
+[`.spec` section](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
+
+### Type
+
+`.spec.type` is an optional field that specifies the Helm repository type.
+
+Possible values are `default` for a Helm HTTP/S repository, or `oci` for an OCI Helm repository.
+
+### Provider
+
+`.spec.provider` is an optional field that allows specifying an OIDC provider used
+for authentication purposes.
+
+Supported options are:
+- `generic`
+- `aws`
+- `azure`
+- `gcp`
+
+The `generic` provider can be used for public repositories or when static credentials
+are used for authentication. If you do not specify `.spec.provider`, it defaults
+to `generic`.
+
+**Note**: The provider field is supported only for Helm OCI repositories. The `spec.type`
+field must be set to `oci`.
+
+#### AWS
+
+The `aws` provider can be used to authenticate automatically using the EKS worker
+node IAM role or IAM Role for Service Accounts (IRSA), and by extension gain access
+to ECR.
+
+##### EKS Worker Node IAM Role
+
+When the worker node IAM role has access to ECR, source-controller running on it
+will also have access to ECR.
+
+##### IAM Role for Service Accounts (IRSA)
+
+When using IRSA to enable access to ECR, add the following patch to your bootstrap
+repository, in the `flux-system/kustomization.yaml` file:
+
+```yaml
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+ - gotk-components.yaml
+ - gotk-sync.yaml
+patches:
+ - patch: |
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: source-controller
+ annotations:
+ eks.amazonaws.com/role-arn:
+ target:
+ kind: ServiceAccount
+ name: source-controller
+```
+
+Note that you can attach the AWS managed policy `arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly`
+to the IAM role when using IRSA.
+
+#### Azure
+
+The `azure` provider can be used to authenticate automatically using Workload Identity, Kubelet Managed
+Identity or Azure Active Directory pod-managed identity (aad-pod-identity), and
+by extension gain access to ACR.
+
+##### Kubelet Managed Identity
+
+When the kubelet managed identity has access to ACR, source-controller running on
+it will also have access to ACR.
+
+**Note:** If you have more than one identity configured on the cluster, you have to specify which one to use
+by setting the `AZURE_CLIENT_ID` environment variable in the source-controller deployment.
+
+If you are running into further issues, please look at the
+[troubleshooting guide](https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/azidentity/TROUBLESHOOTING.md#azure-virtual-machine-managed-identity).
+
+##### Azure Workload Identity
+
+When using Workload Identity to enable access to ACR, add the following patch to
+your bootstrap repository, in the `flux-system/kustomization.yaml` file:
+
+```yaml
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+ - gotk-components.yaml
+ - gotk-sync.yaml
+patches:
+ - patch: |-
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: source-controller
+ namespace: flux-system
+ annotations:
+ azure.workload.identity/client-id:
+ labels:
+ azure.workload.identity/use: "true"
+ - patch: |-
+ apiVersion: apps/v1
+ kind: Deployment
+ metadata:
+ name: source-controller
+ namespace: flux-system
+ labels:
+ azure.workload.identity/use: "true"
+ spec:
+ template:
+ metadata:
+ labels:
+ azure.workload.identity/use: "true"
+```
+
+Ensure Workload Identity is properly set up on your cluster and the mutating webhook is installed.
+Create an identity that has access to ACR. Next, establish
+a federated identity between the source-controller ServiceAccount and the
+identity. Patch the source-controller Deployment and ServiceAccount as shown in the patch
+above. Please take a look at this [guide](https://azure.github.io/azure-workload-identity/docs/quick-start.html#6-establish-federated-identity-credential-between-the-identity-and-the-service-account-issuer--subject).
+
+##### Deprecated: AAD Pod Identity
+
+**Warning:** The AAD Pod Identity project will be archived in
+[September 2023](https://github.com/Azure/aad-pod-identity#-announcement),
+and you are advised to use Workload Identity instead.
+
+When using aad-pod-identity to enable access to ACR, add the following patch to
+your bootstrap repository, in the `flux-system/kustomization.yaml` file:
+
+```yaml
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+ - gotk-components.yaml
+ - gotk-sync.yaml
+patches:
+ - patch: |
+ - op: add
+ path: /spec/template/metadata/labels/aadpodidbinding
+ value:
+ target:
+ kind: Deployment
+ name: source-controller
+```
+
+When using pod-managed identity on an AKS cluster, AAD Pod Identity has to be used
+to give the `source-controller` pod access to the ACR. To do this, you have to install
+`aad-pod-identity` on your cluster, create a managed identity that has access to the
+container registry (this can also be the Kubelet identity if it has `AcrPull` role
+assignment on the ACR), create an `AzureIdentity` and `AzureIdentityBinding` that describe
+the managed identity and then label the `source-controller` deployment with the name of the
+AzureIdentity as shown in the patch above. Please take a look at [this guide](https://azure.github.io/aad-pod-identity/docs/)
+or [this one](https://docs.microsoft.com/en-us/azure/aks/use-azure-ad-pod-identity)
+if you want to use AKS pod-managed identities add-on that is in preview.
+
+#### GCP
+
+The `gcp` provider can be used to authenticate automatically using OAuth scopes or
+Workload Identity, and by extension gain access to GCR or Artifact Registry.
+
+##### Access Scopes
+
+When the GKE nodes have the appropriate OAuth scope for accessing GCR and Artifact Registry,
+source-controller running on it will also have access to them.
+
+##### GKE Workload Identity
+
+When using Workload Identity to enable access to GCR or Artifact Registry, add the
+following patch to your bootstrap repository, in the `flux-system/kustomization.yaml`
+file:
+
+```yaml
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+ - gotk-components.yaml
+ - gotk-sync.yaml
+patches:
+ - patch: |
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: source-controller
+ annotations:
+ iam.gke.io/gcp-service-account:
+ target:
+ kind: ServiceAccount
+ name: source-controller
+```
+
+The Artifact Registry service uses the permission `artifactregistry.repositories.downloadArtifacts`
+that is located under the Artifact Registry Reader role. If you are using Google Container Registry service,
+the needed permission is instead `storage.objects.list` which can be bound as part
+of the Container Registry Service Agent role. Take a look at [this guide](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity)
+for more information about setting up GKE Workload Identity.
+
+### Insecure
+
+`.spec.insecure` is an optional field to allow connecting to an insecure (HTTP)
+container registry server, if set to `true`. The default value is `false`,
+denying insecure non-TLS connections when fetching Helm chart OCI artifacts.
+
+**Note**: The insecure field is supported only for Helm OCI repositories.
+The `spec.type` field must be set to `oci`.
+
+### Interval
+
+**Note:** This field is ineffectual for [OCI Helm
+Repositories](#helm-oci-repository).
+
+`.spec.interval` is a an optional field that specifies the interval which the
+Helm repository index must be consulted at. When not set, the default value is
+`1m`.
+
+After successfully reconciling a HelmRepository object, the source-controller
+requeues the object for inspection after the specified interval. The value
+must be in a [Go recognized duration string format](https://pkg.go.dev/time#ParseDuration),
+e.g. `10m0s` to fetch the HelmRepository index YAML every 10 minutes.
+
+If the `.metadata.generation` of a resource changes (due to e.g. applying a
+change to the spec), this is handled instantly outside the interval window.
+
+**Note:** The controller can be configured to apply a jitter to the interval in
+order to distribute the load more evenly when multiple HelmRepository objects
+are set up with the same interval. For more information, please refer to the
+[source-controller configuration options](https://fluxcd.io/flux/components/source/options/).
+
+### URL
+
+`.spec.url` is a required field that depending on the [type of the HelmRepository object](#type)
+specifies the HTTP/S or OCI address of a Helm repository.
+
+For OCI, the URL is expected to point to a registry repository, e.g. `oci://ghcr.io/fluxcd/source-controller`.
+
+For Helm repositories which require authentication, see [Secret reference](#secret-reference).
+
+### Timeout
+
+**Note:** This field is not applicable to [OCI Helm
+Repositories](#helm-oci-repository).
+
+`.spec.timeout` is an optional field to specify a timeout for the fetch
+operation. The value must be in a
+[Go recognized duration string format](https://pkg.go.dev/time#ParseDuration),
+e.g. `1m30s` for a timeout of one minute and thirty seconds. When not set, the
+default value is `1m`.
+
+### Secret reference
+
+`.spec.secretRef.name` is an optional field to specify a name reference to a
+Secret in the same namespace as the HelmRepository, containing authentication
+credentials for the repository.
+
+#### Basic access authentication
+
+To authenticate towards a Helm repository using basic access authentication
+(in other words: using a username and password), the referenced Secret is
+expected to contain `.data.username` and `.data.password` values.
+
+For example:
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmRepository
+metadata:
+ name: example
+ namespace: default
+spec:
+ interval: 5m0s
+ url: https://example.com
+ secretRef:
+ name: example-user
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: example-user
+ namespace: default
+stringData:
+ username: "user-123456"
+ password: "pass-123456"
+```
+
+OCI Helm repository example:
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmRepository
+metadata:
+ name: podinfo
+ namespace: default
+spec:
+ interval: 5m0s
+ url: oci://ghcr.io/my-user/my-private-repo
+ type: "oci"
+ secretRef:
+ name: oci-creds
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: oci-creds
+ namespace: default
+stringData:
+ username: "user-123456"
+ password: "pass-123456"
+```
+
+For OCI Helm repositories, Kubernetes secrets of type [kubernetes.io/dockerconfigjson](https://kubernetes.io/docs/concepts/configuration/secret/#secret-types) are also supported.
+It is possible to create one such secret with `kubectl create secret docker-registry`
+or using the Flux CLI:
+
+```yaml
+flux create secret oci ghcr-auth \
+ --url=ghcr.io \
+ --username=flux \
+ --password=${GITHUB_PAT}
+```
+
+**Warning:** Support for specifying TLS authentication data using this API has been
+deprecated. Please use [`.spec.certSecretRef`](#cert-secret-reference) instead.
+If the controller uses the secret specified by this field to configure TLS, then
+a deprecation warning will be logged.
+
+### Cert secret reference
+
+`.spec.certSecretRef.name` is an optional field to specify a secret containing
+TLS certificate data. The secret can contain the following keys:
+
+* `tls.crt` and `tls.key`, to specify the client certificate and private key used
+for TLS client authentication. These must be used in conjunction, i.e.
+specifying one without the other will lead to an error.
+* `ca.crt`, to specify the CA certificate used to verify the server, which is
+required if the server is using a self-signed certificate.
+
+If the server is using a self-signed certificate and has TLS client
+authentication enabled, all three values are required.
+
+The Secret should be of type `Opaque` or `kubernetes.io/tls`. All the files in
+the Secret are expected to be [PEM-encoded][pem-encoding]. Assuming you have
+three files; `client.key`, `client.crt` and `ca.crt` for the client private key,
+client certificate and the CA certificate respectively, you can generate the
+required Secret using the `flux create secret tls` command:
+
+```sh
+flux create secret tls --tls-key-file=client.key --tls-crt-file=client.crt --ca-crt-file=ca.crt
+```
+
+Example usage:
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmRepository
+metadata:
+ name: example
+ namespace: default
+spec:
+ interval: 5m0s
+ url: https://example.com
+ certSecretRef:
+ name: example-tls
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: example-tls
+ namespace: default
+type: kubernetes.io/tls # or Opaque
+data:
+ tls.crt:
+ tls.key:
+ # NOTE: Can be supplied without the above values
+ ca.crt:
+```
+
+### Pass credentials
+
+`.spec.passCredentials` is an optional field to allow the credentials from the
+[Secret reference](#secret-reference) to be passed on to a host that does not
+match the host as defined in URL. This may for example be required if the host
+advertised chart URLs in the index differ from the specified URL.
+
+Enabling this should be done with caution, as it can potentially result in
+credentials getting stolen in a man-in-the-middle attack. This feature only applies
+to HTTP/S Helm repositories.
+
+### Suspend
+
+**Note:** This field is not applicable to [OCI Helm
+Repositories](#helm-oci-repository).
+
+`.spec.suspend` is an optional field to suspend the reconciliation of a
+HelmRepository. When set to `true`, the controller will stop reconciling the
+HelmRepository, and changes to the resource or the Helm repository index will
+not result in a new Artifact. When the field is set to `false` or removed, it
+will resume.
+
+For practical information, see
+[suspending and resuming](#suspending-and-resuming).
+
+## Working with HelmRepositories
+
+**Note:** This section does not apply to [OCI Helm
+Repositories](#helm-oci-repository), being a data container, once created, they
+are ready to used by [HelmCharts](helmcharts.md).
+
+### Triggering a reconcile
+
+To manually tell the source-controller to reconcile a HelmRepository outside the
+[specified interval window](#interval), a HelmRepository can be annotated with
+`reconcile.fluxcd.io/requestedAt: `. Annotating the resource
+queues the object for reconciliation if the `` differs from
+the last value the controller acted on, as reported in
+[`.status.lastHandledReconcileAt`](#last-handled-reconcile-at).
+
+Using `kubectl`:
+
+```sh
+kubectl annotate --field-manager=flux-client-side-apply --overwrite helmrepository/ reconcile.fluxcd.io/requestedAt="$(date +%s)"
+```
+
+Using `flux`:
+
+```sh
+flux reconcile source helm
+```
+
+### Waiting for `Ready`
+
+When a change is applied, it is possible to wait for the HelmRepository to
+reach a [ready state](#ready-helmrepository) using `kubectl`:
+
+```sh
+kubectl wait helmrepository/ --for=condition=ready --timeout=1m
+```
+
+### Suspending and resuming
+
+When you find yourself in a situation where you temporarily want to pause the
+reconciliation of a HelmRepository, you can suspend it using the
+[`.spec.suspend` field](#suspend).
+
+#### Suspend a HelmRepository
+
+In your YAML declaration:
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmRepository
+metadata:
+ name:
+spec:
+ suspend: true
+```
+
+Using `kubectl`:
+
+```sh
+kubectl patch helmrepository --field-manager=flux-client-side-apply -p '{\"spec\": {\"suspend\" : true }}'
+```
+
+Using `flux`:
+
+```sh
+flux suspend source helm
+```
+
+**Note:** When a HelmRepository has an Artifact and is suspended, and this
+Artifact later disappears from the storage due to e.g. the source-controller
+Pod being evicted from a Node, this will not be reflected in the
+HelmRepository's Status until it is resumed.
+
+#### Resume a HelmRepository
+
+In your YAML declaration, comment out (or remove) the field:
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmRepository
+metadata:
+ name:
+spec:
+ # suspend: true
+```
+
+**Note:** Setting the field value to `false` has the same effect as removing
+it, but does not allow for "hot patching" using e.g. `kubectl` while practicing
+GitOps; as the manually applied patch would be overwritten by the declared
+state in Git.
+
+Using `kubectl`:
+
+```sh
+kubectl patch helmrepository --field-manager=flux-client-side-apply -p '{\"spec\" : {\"suspend\" : false }}'
+```
+
+Using `flux`:
+
+```sh
+flux resume source helm
+```
+
+### Debugging a HelmRepository
+
+**Note:** This section does not apply to [OCI Helm
+Repositories](#helm-oci-repository), being a data container, they are static
+objects that don't require debugging if valid.
+
+There are several ways to gather information about a HelmRepository for debugging
+purposes.
+
+#### Describe the HelmRepository
+
+Describing a HelmRepository using `kubectl describe helmrepository `
+displays the latest recorded information for the resource in the `Status` and
+`Events` sections:
+
+```console
+...
+Status:
+...
+ Conditions:
+ Last Transition Time: 2022-02-04T13:41:56Z
+ Message: failed to construct Helm client: scheme "invalid" not supported
+ Observed Generation: 2
+ Reason: Failed
+ Status: True
+ Type: Stalled
+ Last Transition Time: 2022-02-04T13:41:56Z
+ Message: failed to construct Helm client: scheme "invalid" not supported
+ Observed Generation: 2
+ Reason: Failed
+ Status: False
+ Type: Ready
+ Last Transition Time: 2022-02-04T13:41:56Z
+ Message: failed to construct Helm client: scheme "invalid" not supported
+ Observed Generation: 2
+ Reason: Failed
+ Status: True
+ Type: FetchFailed
+ Observed Generation: 2
+ URL: http://source-controller.source-system.svc.cluster.local./helmrepository/default/podinfo/index.yaml
+Events:
+ Type Reason Age From Message
+ ---- ------ ---- ---- -------
+ Warning Failed 6s source-controller failed to construct Helm client: scheme "invalid" not supported
+```
+
+#### Trace emitted Events
+
+To view events for specific HelmRepository(s), `kubectl events` can be used in
+combination with `--for` to list the Events for specific objects. For example,
+running
+
+```sh
+kubectl events --for HelmRepository/
+```
+
+lists
+
+```console
+LAST SEEN TYPE REASON OBJECT MESSAGE
+107s Warning Failed helmrepository/ failed to construct Helm client: scheme "invalid" not supported
+7s Normal NewArtifact helmrepository/ fetched index of size 30.88kB from 'https://stefanprodan.github.io/podinfo'
+3s Normal ArtifactUpToDate helmrepository/ artifact up-to-date with remote revision: 'sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111'
+```
+
+Besides being reported in Events, the reconciliation errors are also logged by
+the controller. The Flux CLI offer commands for filtering the logs for a
+specific HelmRepository, e.g. `flux logs --level=error --kind=HelmRepository --name=`.
+
+## HelmRepository Status
+
+**Note:** This section does not apply to [OCI Helm
+Repositories](#helm-oci-repository), they do not contain any information in the
+status.
+
+### Artifact
+
+The HelmRepository reports the last fetched repository index as an Artifact
+object in the `.status.artifact` of the resource.
+
+The Artifact file is an exact copy of the Helm repository index YAML
+(`index-.yaml`) as fetched, and can be retrieved in-cluster from the
+`.status.artifact.url` HTTP address.
+
+#### Artifact example
+
+```yaml
+---
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmRepository
+metadata:
+ name:
+status:
+ artifact:
+ digest: sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111
+ lastUpdateTime: "2022-02-04T09:55:58Z"
+ path: helmrepository///index-83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111.yaml
+ revision: sha256:83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111
+ size: 40898
+ url: http://source-controller.flux-system.svc.cluster.local./helmrepository///index-83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111.yaml
+```
+
+### Conditions
+
+A HelmRepository enters various states during its lifecycle, reflected as [Kubernetes
+Conditions][typical-status-properties].
+It can be [reconciling](#reconciling-helmrepository) while fetching the
+repository index, it can be [ready](#ready-helmrepository), it can
+[fail during reconciliation](#failed-helmrepository), or it can
+[stall](#stalled-helmrepository).
+
+The HelmRepository API is compatible with the [kstatus
+specification][kstatus-spec],
+and reports `Reconciling` and `Stalled` conditions where applicable to
+provide better (timeout) support to solutions polling the HelmRepository to become
+`Ready`.
+
+#### Reconciling HelmRepository
+
+The source-controller marks a HelmRepository as _reconciling_ when one of the following
+is true:
+
+- There is no current Artifact for the HelmRepository, or the reported Artifact
+ is determined to have disappeared from the storage.
+- The generation of the HelmRepository is newer than the [Observed
+ Generation](#observed-generation).
+- The newly fetched Artifact revision differs from the current Artifact.
+
+When the HelmRepository is "reconciling", the `Ready` Condition status becomes
+`Unknown` when the controller detects drift, and the controller adds a Condition
+with the following attributes to the HelmRepository's `.status.conditions`:
+
+- `type: Reconciling`
+- `status: "True"`
+- `reason: Progressing` | `reason: ProgressingWithRetry`
+
+If the reconciling state is due to a new revision, it adds an additional
+Condition with the following attributes:
+
+- `type: ArtifactOutdated`
+- `status: "True"`
+- `reason: NewRevision`
+
+Both Conditions have a ["negative polarity"][typical-status-properties],
+and are only present on the HelmRepository while their status value is `"True"`.
+
+#### Ready HelmRepository
+
+The source-controller marks a HelmRepository as _ready_ when it has the following
+characteristics:
+
+- The HelmRepository reports an [Artifact](#artifact).
+- The reported Artifact exists in the controller's Artifact storage.
+- The controller was able to fetch the Helm repository index using the current
+ spec.
+- The revision of the reported Artifact is up-to-date with the latest
+ revision of the Helm repository.
+
+When the HelmRepository is "ready", the controller sets a Condition with the following
+attributes in the HelmRepository's `.status.conditions`:
+
+- `type: Ready`
+- `status: "True"`
+- `reason: Succeeded`
+
+This `Ready` Condition will retain a status value of `"True"` until the
+HelmRepository is marked as [reconciling](#reconciling-helmrepository), or e.g.
+a [transient error](#failed-helmrepository) occurs due to a temporary network
+issue.
+
+When the HelmRepository Artifact is archived in the controller's Artifact
+storage, the controller sets a Condition with the following attributes in the
+HelmRepository's `.status.conditions`:
+
+- `type: ArtifactInStorage`
+- `status: "True"`
+- `reason: Succeeded`
+
+This `ArtifactInStorage` Condition will retain a status value of `"True"` until
+the Artifact in the storage no longer exists.
+
+#### Failed HelmRepository
+
+The source-controller may get stuck trying to produce an Artifact for a
+HelmRepository without completing. This can occur due to some of the following
+factors:
+
+- The Helm repository [URL](#url) is temporarily unavailable.
+- The [Secret reference](#secret-reference) contains a reference to a
+ non-existing Secret.
+- The credentials in the referenced Secret are invalid.
+- The HelmRepository spec contains a generic misconfiguration.
+- A storage related failure when storing the artifact.
+
+When this happens, the controller sets the `Ready` Condition status to `False`,
+and adds a Condition with the following attributes to the HelmRepository's
+`.status.conditions`:
+
+- `type: FetchFailed` | `type: StorageOperationFailed`
+- `status: "True"`
+- `reason: AuthenticationFailed` | `reason: IndexationFailed` | `reason: Failed`
+
+This condition has a ["negative polarity"][typical-status-properties],
+and is only present on the HelmRepository while the status value is `"True"`.
+There may be more arbitrary values for the `reason` field to provide accurate
+reason for a condition.
+
+While the HelmRepository has this Condition, the controller will continue to
+attempt to produce an Artifact for the resource with an exponential backoff,
+until it succeeds and the HelmRepository is marked as [ready](#ready-helmrepository).
+
+Note that a HelmRepository can be [reconciling](#reconciling-helmrepository)
+while failing at the same time, for example due to a newly introduced
+configuration issue in the HelmRepository spec. When a reconciliation fails, the
+`Reconciling` Condition reason would be `ProgressingWithRetry`. When the
+reconciliation is performed again after the failure, the reason is updated to
+`Progressing`.
+
+#### Stalled HelmRepository
+
+The source-controller can mark a HelmRepository as _stalled_ when it determines
+that without changes to the spec, the reconciliation can not succeed.
+For example because a Helm repository URL with an unsupported protocol is
+specified.
+
+When this happens, the controller sets the same Conditions as when it
+[fails](#failed-helmrepository), but adds another Condition with the following
+attributes to the HelmRepository's
+`.status.conditions`:
+
+- `type: Stalled`
+- `status: "True"`
+- `reason: URLInvalid`
+
+While the HelmRepository has this Condition, the controller will not requeue
+the resource any further, and will stop reconciling the resource until a change
+to the spec is made.
+
+### Observed Generation
+
+The source-controller reports an [observed generation][typical-status-properties]
+in the HelmRepository's `.status.observedGeneration`. The observed generation is
+the latest `.metadata.generation` which resulted in either a [ready state](#ready-helmrepository),
+or stalled due to error it can not recover from without human intervention.
+
+### Last Handled Reconcile At
+
+The source-controller reports the last `reconcile.fluxcd.io/requestedAt`
+annotation value it acted on in the `.status.lastHandledReconcileAt` field.
+
+For practical information about this field, see [triggering a
+reconcile](#triggering-a-reconcile).
+
+[pem-encoding]: https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail
+[typical-status-properties]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
+[kstatus-spec]: https://github.com/kubernetes-sigs/cli-utils/tree/master/pkg/kstatus
diff --git a/internal/controller/helmchart_controller_test.go b/internal/controller/helmchart_controller_test.go
index 06426068a..39f9991f1 100644
--- a/internal/controller/helmchart_controller_test.go
+++ b/internal/controller/helmchart_controller_test.go
@@ -929,14 +929,14 @@ func TestHelmChartReconciler_buildFromHelmRepository(t *testing.T) {
},
{
name: "Uses artifact as build cache with observedValuesFiles",
- beforeFunc: func(obj *helmv1.HelmChart, repository *helmv1.HelmRepository) {
+ beforeFunc: func(obj *sourcev1.HelmChart, repository *sourcev1.HelmRepository) {
obj.Spec.Chart = chartName
obj.Spec.Version = chartVersion
obj.Status.Artifact = &sourcev1.Artifact{Path: chartName + "-" + chartVersion + ".tgz"}
obj.Status.ObservedValuesFiles = []string{"values.yaml", "override.yaml"}
},
want: sreconcile.ResultSuccess,
- assertFunc: func(g *WithT, obj *helmv1.HelmChart, build chart.Build) {
+ assertFunc: func(g *WithT, obj *sourcev1.HelmChart, build chart.Build) {
g.Expect(build.Name).To(Equal(chartName))
g.Expect(build.Version).To(Equal(chartVersion))
g.Expect(build.Path).To(Equal(filepath.Join(serverFactory.Root(), obj.Status.Artifact.Path)))
@@ -965,7 +965,7 @@ func TestHelmChartReconciler_buildFromHelmRepository(t *testing.T) {
},
{
name: "Missing values files are an error",
- beforeFunc: func(obj *helmv1.HelmChart, repository *helmv1.HelmRepository) {
+ beforeFunc: func(obj *sourcev1.HelmChart, repository *sourcev1.HelmRepository) {
obj.Spec.Chart = chartName
obj.Spec.ValuesFiles = []string{"missing.yaml"}
},
@@ -973,14 +973,14 @@ func TestHelmChartReconciler_buildFromHelmRepository(t *testing.T) {
},
{
name: "All missing values files ignored",
- beforeFunc: func(obj *helmv1.HelmChart, repository *helmv1.HelmRepository) {
+ beforeFunc: func(obj *sourcev1.HelmChart, repository *sourcev1.HelmRepository) {
obj.Spec.Chart = chartName
obj.Spec.Version = chartVersion
obj.Spec.ValuesFiles = []string{"missing.yaml"}
obj.Spec.IgnoreMissingValuesFiles = true
},
want: sreconcile.ResultSuccess,
- assertFunc: func(g *WithT, obj *helmv1.HelmChart, build chart.Build) {
+ assertFunc: func(g *WithT, obj *sourcev1.HelmChart, build chart.Build) {
g.Expect(build.Name).To(Equal(chartName))
g.Expect(build.Version).To(Equal(chartVersion + "+0"))
g.Expect(build.ValuesFiles).To(BeEmpty())
@@ -991,14 +991,14 @@ func TestHelmChartReconciler_buildFromHelmRepository(t *testing.T) {
},
{
name: "Partial missing values files ignored",
- beforeFunc: func(obj *helmv1.HelmChart, repository *helmv1.HelmRepository) {
+ beforeFunc: func(obj *sourcev1.HelmChart, repository *sourcev1.HelmRepository) {
obj.Spec.Chart = chartName
obj.Spec.Version = chartVersion
obj.Spec.ValuesFiles = []string{"values.yaml", "override.yaml", "invalid.yaml"}
obj.Spec.IgnoreMissingValuesFiles = true
},
want: sreconcile.ResultSuccess,
- assertFunc: func(g *WithT, obj *helmv1.HelmChart, build chart.Build) {
+ assertFunc: func(g *WithT, obj *sourcev1.HelmChart, build chart.Build) {
g.Expect(build.Name).To(Equal(chartName))
g.Expect(build.Version).To(Equal(chartVersion + "+0"))
g.Expect(build.ValuesFiles).To(Equal([]string{"values.yaml", "override.yaml"}))
@@ -1524,7 +1524,7 @@ func TestHelmChartReconciler_buildFromTarballArtifact(t *testing.T) {
{
name: "Chart from storage cache with ObservedValuesFiles",
source: *chartsArtifact.DeepCopy(),
- beforeFunc: func(obj *helmv1.HelmChart) {
+ beforeFunc: func(obj *sourcev1.HelmChart) {
obj.Spec.Chart = "testdata/charts/helmchart-0.1.0.tgz"
obj.Status.Artifact = cachedArtifact.DeepCopy()
obj.Status.ObservedValuesFiles = []string{"values.yaml", "override.yaml"}
@@ -1751,10 +1751,10 @@ func TestHelmChartReconciler_reconcileArtifact(t *testing.T) {
{
name: "Updates ObservedValuesFiles after creating new artifact",
build: mockChartBuild("helmchart", "0.1.0", "testdata/charts/helmchart-0.1.0.tgz", []string{"values.yaml", "override.yaml"}),
- beforeFunc: func(obj *helmv1.HelmChart) {
+ beforeFunc: func(obj *sourcev1.HelmChart) {
conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "Foo", "")
},
- afterFunc: func(t *WithT, obj *helmv1.HelmChart) {
+ afterFunc: func(t *WithT, obj *sourcev1.HelmChart) {
t.Expect(obj.GetArtifact()).ToNot(BeNil())
t.Expect(obj.GetArtifact().Digest).To(Equal("sha256:bbdf96023c912c393b49d5238e227576ed0d20d1bb145d7476d817b80e20c11a"))
t.Expect(obj.GetArtifact().Revision).To(Equal("0.1.0"))
@@ -1764,18 +1764,18 @@ func TestHelmChartReconciler_reconcileArtifact(t *testing.T) {
},
want: sreconcile.ResultSuccess,
assertConditions: []metav1.Condition{
- *conditions.TrueCondition(sourcev1.ArtifactInStorageCondition, helmv1.ChartPullSucceededReason, "pulled 'helmchart' chart with version '0.1.0'"),
+ *conditions.TrueCondition(sourcev1.ArtifactInStorageCondition, sourcev1.ChartPullSucceededReason, "pulled 'helmchart' chart with version '0.1.0'"),
},
},
{
name: "Updates ObservedValuesFiles with IgnoreMissingValuesFiles after creating new artifact",
build: mockChartBuild("helmchart", "0.1.0", "testdata/charts/helmchart-0.1.0.tgz", []string{"values.yaml", "override.yaml"}),
- beforeFunc: func(obj *helmv1.HelmChart) {
+ beforeFunc: func(obj *sourcev1.HelmChart) {
conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "Foo", "")
obj.Spec.ValuesFiles = []string{"values.yaml", "missing.yaml", "override.yaml"}
obj.Spec.IgnoreMissingValuesFiles = true
},
- afterFunc: func(t *WithT, obj *helmv1.HelmChart) {
+ afterFunc: func(t *WithT, obj *sourcev1.HelmChart) {
t.Expect(obj.GetArtifact()).ToNot(BeNil())
t.Expect(obj.GetArtifact().Digest).To(Equal("sha256:bbdf96023c912c393b49d5238e227576ed0d20d1bb145d7476d817b80e20c11a"))
t.Expect(obj.GetArtifact().Revision).To(Equal("0.1.0"))
@@ -1785,7 +1785,7 @@ func TestHelmChartReconciler_reconcileArtifact(t *testing.T) {
},
want: sreconcile.ResultSuccess,
assertConditions: []metav1.Condition{
- *conditions.TrueCondition(sourcev1.ArtifactInStorageCondition, helmv1.ChartPullSucceededReason, "pulled 'helmchart' chart with version '0.1.0'"),
+ *conditions.TrueCondition(sourcev1.ArtifactInStorageCondition, sourcev1.ChartPullSucceededReason, "pulled 'helmchart' chart with version '0.1.0'"),
},
},
}
|