Document HelmChart API v1beta2 spec

Signed-off-by: Sunny <darkowlzz@protonmail.com>
This commit is contained in:
Sunny 2022-02-14 14:36:55 +05:30 committed by Hidde Beydals
parent 0d3170f193
commit a2515900c8
7 changed files with 684 additions and 165 deletions

View File

@ -28,28 +28,29 @@ import (
// HelmChartKind is the string representation of a HelmChart.
const HelmChartKind = "HelmChart"
// HelmChartSpec defines the desired state of a Helm chart.
// HelmChartSpec specifies the desired state of a Helm chart.
type HelmChartSpec struct {
// The name or path the Helm chart is available at in the SourceRef.
// Chart is the name or path the Helm chart is available at in the
// SourceRef.
// +required
Chart string `json:"chart"`
// The chart version semver expression, ignored for charts from GitRepository
// and Bucket sources. Defaults to latest when omitted.
// Version is the chart version semver expression, ignored for charts from
// GitRepository and Bucket sources. Defaults to latest when omitted.
// +kubebuilder:default:=*
// +optional
Version string `json:"version,omitempty"`
// The reference to the Source the chart is available at.
// SourceRef is the reference to the Source the chart is available at.
// +required
SourceRef LocalHelmChartSourceReference `json:"sourceRef"`
// The interval at which to check the Source for updates.
// Interval is the interval at which to check the Source for updates.
// +required
Interval metav1.Duration `json:"interval"`
// Determines what enables the creation of a new artifact. Valid values are
// ('ChartVersion', 'Revision').
// ReconcileStrategy determines what enables the creation of a new artifact.
// Valid values are ('ChartVersion', 'Revision').
// See the documentation of the values for an explanation on their behavior.
// Defaults to ChartVersion when omitted.
// +kubebuilder:validation:Enum=ChartVersion;Revision
@ -57,26 +58,30 @@ type HelmChartSpec struct {
// +optional
ReconcileStrategy string `json:"reconcileStrategy,omitempty"`
// Alternative list of values files to use as the chart values (values.yaml
// is not included by default), expected to be a relative path in the SourceRef.
// Values files are merged in the order of this list with the last file overriding
// the first. Ignored when omitted.
// ValuesFiles is an alternative list of values files to use as the chart
// values (values.yaml is not included by default), expected to be a
// relative path in the SourceRef.
// Values files are merged in the order of this list with the last file
// overriding the first. Ignored when omitted.
// +optional
ValuesFiles []string `json:"valuesFiles,omitempty"`
// Alternative values file to use as the default chart values, expected to
// be a relative path in the SourceRef. Deprecated in favor of ValuesFiles,
// for backwards compatibility the file defined here is merged before the
// ValuesFiles items. Ignored when omitted.
// ValuesFile is an alternative values file to use as the default chart
// values, expected to be a relative path in the SourceRef. Deprecated in
// favor of ValuesFiles, for backwards compatibility the file specified here
// is merged before the ValuesFiles items. Ignored when omitted.
// +optional
// +deprecated
ValuesFile string `json:"valuesFile,omitempty"`
// This flag tells the controller to suspend the reconciliation of this source.
// Suspend tells the controller to suspend the reconciliation of this
// source.
// +optional
Suspend bool `json:"suspend,omitempty"`
// AccessFrom defines an Access Control List for allowing cross-namespace references to this object.
// AccessFrom specifies an Access Control List for allowing cross-namespace
// references to this object.
// NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092
// +optional
AccessFrom *acl.AccessFrom `json:"accessFrom,omitempty"`
}
@ -107,18 +112,19 @@ type LocalHelmChartSourceReference struct {
Name string `json:"name"`
}
// HelmChartStatus defines the observed state of the HelmChart.
// HelmChartStatus records the observed state of the HelmChart.
type HelmChartStatus struct {
// ObservedGeneration is the last observed generation.
// ObservedGeneration is the last observed generation of the HelmChart
// object.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// ObservedSourceArtifactRevision is the last observed Artifact.Revision
// of the Source reference.
// of the HelmChartSpec.SourceRef.
// +optional
ObservedSourceArtifactRevision string `json:"observedSourceArtifactRevision,omitempty"`
// ObservedChartName is the last observed chart name as defined by the
// ObservedChartName is the last observed chart name as specified by the
// resolved chart reference.
// +optional
ObservedChartName string `json:"observedChartName,omitempty"`
@ -127,11 +133,13 @@ type HelmChartStatus struct {
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
// URL is the fetch link for the last chart pulled.
// URL is the dynamic fetch link for the latest Artifact.
// It is provided on a "best effort" basis, and using the precise
// BucketStatus.Artifact data is recommended.
// +optional
URL string `json:"url,omitempty"`
// Artifact represents the output of the last successful chart sync.
// Artifact represents the output of the last successful reconciliation.
// +optional
Artifact *Artifact `json:"artifact,omitempty"`
@ -139,19 +147,11 @@ type HelmChartStatus struct {
}
const (
// ChartPullFailedReason represents the fact that the pull of the Helm chart
// failed.
ChartPullFailedReason string = "ChartPullFailed"
// ChartPullSucceededReason represents the fact that the pull of the Helm chart
// ChartPullSucceededReason signals that the pull of the Helm chart
// succeeded.
ChartPullSucceededReason string = "ChartPullSucceeded"
// ChartPackageFailedReason represent the fact that the package of the Helm
// chart failed.
ChartPackageFailedReason string = "ChartPackageFailed"
// ChartPackageSucceededReason represents the fact that the package of the Helm
// ChartPackageSucceededReason signals that the package of the Helm
// chart succeeded.
ChartPackageSucceededReason string = "ChartPackageSucceeded"
)
@ -166,23 +166,19 @@ func (in *HelmChart) SetConditions(conditions []metav1.Condition) {
in.Status.Conditions = conditions
}
// GetRequeueAfter returns the duration after which the source must be reconciled again.
// GetRequeueAfter returns the duration after which the source must be
// reconciled again.
func (in HelmChart) GetRequeueAfter() time.Duration {
return in.Spec.Interval.Duration
}
// GetInterval returns the interval at which the source is reconciled.
// Deprecated: use GetRequeueAfter instead.
func (in HelmChart) GetInterval() metav1.Duration {
return in.Spec.Interval
}
// GetArtifact returns the latest artifact from the source if present in the status sub-resource.
// GetArtifact returns the latest artifact from the source if present in the
// status sub-resource.
func (in *HelmChart) GetArtifact() *Artifact {
return in.Status.Artifact
}
// GetValuesFiles returns a merged list of ValuesFiles.
// GetValuesFiles returns a merged list of HelmChartSpec.ValuesFiles.
func (in *HelmChart) GetValuesFiles() []string {
valuesFiles := in.Spec.ValuesFiles
@ -193,12 +189,6 @@ func (in *HelmChart) GetValuesFiles() []string {
return valuesFiles
}
// GetStatusConditions returns a pointer to the Status.Conditions slice.
// Deprecated: use GetConditions instead.
func (in *HelmChart) GetStatusConditions() *[]metav1.Condition {
return &in.Status.Conditions
}
// +genclient
// +genclient:Namespaced
// +kubebuilder:storageversion
@ -213,7 +203,7 @@ func (in *HelmChart) GetStatusConditions() *[]metav1.Condition {
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
// HelmChart is the Schema for the helmcharts API
// HelmChart is the Schema for the helmcharts API.
type HelmChart struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
@ -223,9 +213,8 @@ type HelmChart struct {
Status HelmChartStatus `json:"status,omitempty"`
}
// HelmChartList contains a list of HelmChart objects.
// +kubebuilder:object:root=true
// HelmChartList contains a list of HelmChart
type HelmChartList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`

View File

@ -299,7 +299,7 @@ spec:
name: v1beta2
schema:
openAPIV3Schema:
description: HelmChart is the Schema for the helmcharts API
description: HelmChart is the Schema for the helmcharts API.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
@ -314,11 +314,12 @@ spec:
metadata:
type: object
spec:
description: HelmChartSpec defines the desired state of a Helm chart.
description: HelmChartSpec specifies the desired state of a Helm chart.
properties:
accessFrom:
description: AccessFrom defines an Access Control List for allowing
cross-namespace references to this object.
description: 'AccessFrom specifies an Access Control List for allowing
cross-namespace references to this object. NOTE: Not implemented,
provisional as of https://github.com/fluxcd/flux2/pull/2092'
properties:
namespaceSelectors:
description: NamespaceSelectors is the list of namespace selectors
@ -344,24 +345,26 @@ spec:
- namespaceSelectors
type: object
chart:
description: The name or path the Helm chart is available at in the
SourceRef.
description: Chart is the name or path the Helm chart is available
at in the SourceRef.
type: string
interval:
description: The interval at which to check the Source for updates.
description: Interval is the interval at which to check the Source
for updates.
type: string
reconcileStrategy:
default: ChartVersion
description: Determines what enables the creation of a new artifact.
Valid values are ('ChartVersion', 'Revision'). See the documentation
of the values for an explanation on their behavior. Defaults to
ChartVersion when omitted.
description: ReconcileStrategy determines what enables the creation
of a new artifact. Valid values are ('ChartVersion', 'Revision').
See the documentation of the values for an explanation on their
behavior. Defaults to ChartVersion when omitted.
enum:
- ChartVersion
- Revision
type: string
sourceRef:
description: The reference to the Source the chart is available at.
description: SourceRef is the reference to the Source the chart is
available at.
properties:
apiVersion:
description: APIVersion of the referent.
@ -382,28 +385,30 @@ spec:
- name
type: object
suspend:
description: This flag tells the controller to suspend the reconciliation
description: Suspend tells the controller to suspend the reconciliation
of this source.
type: boolean
valuesFile:
description: Alternative values file to use as the default chart values,
expected to be a relative path in the SourceRef. Deprecated in favor
of ValuesFiles, for backwards compatibility the file defined here
is merged before the ValuesFiles items. Ignored when omitted.
description: ValuesFile is an alternative values file to use as the
default chart values, expected to be a relative path in the SourceRef.
Deprecated in favor of ValuesFiles, for backwards compatibility
the file specified here is merged before the ValuesFiles items.
Ignored when omitted.
type: string
valuesFiles:
description: Alternative list of values files to use as the chart
values (values.yaml is not included by default), expected to be
a relative path in the SourceRef. Values files are merged in the
order of this list with the last file overriding the first. Ignored
when omitted.
description: ValuesFiles is an alternative list of values files to
use as the chart values (values.yaml is not included by default),
expected to be a relative path in the SourceRef. Values files are
merged in the order of this list with the last file overriding the
first. Ignored when omitted.
items:
type: string
type: array
version:
default: '*'
description: The chart version semver expression, ignored for charts
from GitRepository and Bucket sources. Defaults to latest when omitted.
description: Version is the chart version semver expression, ignored
for charts from GitRepository and Bucket sources. Defaults to latest
when omitted.
type: string
required:
- chart
@ -413,11 +418,11 @@ spec:
status:
default:
observedGeneration: -1
description: HelmChartStatus defines the observed state of the HelmChart.
description: HelmChartStatus records the observed state of the HelmChart.
properties:
artifact:
description: Artifact represents the output of the last successful
chart sync.
reconciliation.
properties:
checksum:
description: Checksum is the SHA256 checksum of the Artifact file.
@ -524,18 +529,21 @@ spec:
type: string
observedChartName:
description: ObservedChartName is the last observed chart name as
defined by the resolved chart reference.
specified by the resolved chart reference.
type: string
observedGeneration:
description: ObservedGeneration is the last observed generation.
description: ObservedGeneration is the last observed generation of
the HelmChart object.
format: int64
type: integer
observedSourceArtifactRevision:
description: ObservedSourceArtifactRevision is the last observed Artifact.Revision
of the Source reference.
of the HelmChartSpec.SourceRef.
type: string
url:
description: URL is the fetch link for the last chart pulled.
description: URL is the dynamic fetch link for the latest Artifact.
It is provided on a "best effort" basis, and using the precise BucketStatus.Artifact
data is recommended.
type: string
type: object
type: object

View File

@ -63,9 +63,9 @@ import (
"github.com/fluxcd/source-controller/internal/util"
)
// helmChartReadyConditions contains all the conditions information
// helmChartReadyCondition contains all the conditions information
// needed for HelmChart Ready status conditions summary calculation.
var helmChartReadyConditions = summarize.Conditions{
var helmChartReadyCondition = summarize.Conditions{
Target: meta.ReadyCondition,
Owned: []string{
sourcev1.BuildFailedCondition,
@ -114,7 +114,10 @@ type HelmChartReconcilerOptions struct {
MaxConcurrentReconciles int
}
type helmChartReconcilerFunc func(ctx context.Context, obj *sourcev1.HelmChart, build *chart.Build) (sreconcile.Result, error)
// helmChartReconcileFunc is the function type for all the v1beta2.HelmChart
// (sub)reconcile functions. The type implementations are grouped and
// executed serially to perform the complete reconcile of the object.
type helmChartReconcileFunc func(ctx context.Context, obj *sourcev1.HelmChart, build *chart.Build) (sreconcile.Result, error)
func (r *HelmChartReconciler) SetupWithManagerAndOptions(mgr ctrl.Manager, opts HelmChartReconcilerOptions) error {
if err := mgr.GetCache().IndexField(context.TODO(), &sourcev1.HelmRepository{}, sourcev1.HelmRepositoryURLIndexKey,
@ -182,7 +185,7 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
defer func() {
summarizeHelper := summarize.NewHelper(r.EventRecorder, patchHelper)
summarizeOpts := []summarize.Option{
summarize.WithConditions(helmChartReadyConditions),
summarize.WithConditions(helmChartReadyCondition),
summarize.WithReconcileResult(recResult),
summarize.WithReconcileError(retErr),
summarize.WithIgnoreNotFound(),
@ -190,7 +193,7 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
summarize.RecordContextualError,
summarize.RecordReconcileReq,
),
summarize.WithResultBuilder(sreconcile.AlwaysRequeueResultBuilder{RequeueAfter: obj.GetInterval().Duration}),
summarize.WithResultBuilder(sreconcile.AlwaysRequeueResultBuilder{RequeueAfter: obj.GetRequeueAfter()}),
}
result, retErr = summarizeHelper.SummarizeAndPatch(ctx, obj, summarizeOpts...)
@ -214,7 +217,7 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
}
// Reconcile actual object
reconcilers := []helmChartReconcilerFunc{
reconcilers := []helmChartReconcileFunc{
r.reconcileStorage,
r.reconcileSource,
r.reconcileArtifact,
@ -223,9 +226,10 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
return
}
// reconcile steps through the actual reconciliation tasks for the object, it returns early on the first step that
// produces an error.
func (r *HelmChartReconciler) reconcile(ctx context.Context, obj *sourcev1.HelmChart, reconcilers []helmChartReconcilerFunc) (sreconcile.Result, error) {
// reconcile iterates through the gitRepositoryReconcileFunc tasks for the
// object. It returns early on the first call that returns
// reconcile.ResultRequeue, or produces an error.
func (r *HelmChartReconciler) reconcile(ctx context.Context, obj *sourcev1.HelmChart, reconcilers []helmChartReconcileFunc) (sreconcile.Result, error) {
if obj.Generation != obj.Status.ObservedGeneration {
conditions.MarkReconciling(obj, "NewGeneration", "reconciling new object generation (%d)", obj.Generation)
}
@ -255,14 +259,17 @@ func (r *HelmChartReconciler) reconcile(ctx context.Context, obj *sourcev1.HelmC
return res, resErr
}
// reconcileStorage ensures the current state of the storage matches the desired and previously observed state.
// reconcileStorage ensures the current state of the storage matches the
// desired and previously observed state.
//
// All artifacts for the resource except for the current one are garbage collected from the storage.
// If the artifact in the Status object of the resource disappeared from storage, it is removed from the object.
// If the object does not have an artifact in its Status object, a v1beta1.ArtifactUnavailableCondition is set.
// If the hostname of the URLs on the object do not match the current storage server hostname, they are updated.
//
// The caller should assume a failure if an error is returned, or the BuildResult is zero.
// All Artifacts for the object except for the current one in the Status are
// garbage collected from the Storage.
// If the Artifact in the Status of the object disappeared from the Storage,
// it is removed from the object.
// If the object does not have an Artifact in its Status, a Reconciling
// condition is added.
// The hostname of any URL in the Status of the object are updated, to ensure
// they match the Storage server hostname of current runtime.
func (r *HelmChartReconciler) reconcileStorage(ctx context.Context, obj *sourcev1.HelmChart, build *chart.Build) (sreconcile.Result, error) {
// Garbage collect previous advertised artifact(s) from storage
_ = r.garbageCollect(ctx, obj)
@ -364,6 +371,11 @@ func (r *HelmChartReconciler) reconcileSource(ctx context.Context, obj *sourcev1
}
}
// buildFromHelmRepository attempts to pull and/or package a Helm chart with
// the specified data from the v1beta2.HelmRepository and v1beta2.HelmChart
// objects.
// In case of a failure it records v1beta2.FetchFailedCondition on the chart
// object, and returns early.
func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *sourcev1.HelmChart,
repo *sourcev1.HelmRepository, b *chart.Build) (sreconcile.Result, error) {
@ -460,6 +472,10 @@ func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *
return sreconcile.ResultSuccess, nil
}
// buildFromHelmRepository attempts to pull and/or package a Helm chart with
// the specified data v1beta2.HelmChart object and the given v1beta2.Artifact.
// In case of a failure it records v1beta2.FetchFailedCondition on the chart
// object, and returns early.
func (r *HelmChartReconciler) buildFromTarballArtifact(ctx context.Context, obj *sourcev1.HelmChart, source sourcev1.Artifact, b *chart.Build) (sreconcile.Result, error) {
// Create temporary working directory
tmpDir, err := util.TempDirForObj("", obj)
@ -589,8 +605,15 @@ func (r *HelmChartReconciler) buildFromTarballArtifact(ctx context.Context, obj
return sreconcile.ResultSuccess, nil
}
// reconcileArtifact reconciles the given chart.Build to an v1beta1.Artifact in the Storage, and records it
// on the object.
// reconcileArtifact archives a new Artifact to the Storage, if the current
// (Status) data on the object does not match the given.
//
// The inspection of the given data to the object is differed, ensuring any
// stale observations like v1beta2.ArtifactOutdatedCondition are removed.
// If the given Artifact does not differ from the object's current, it returns
// early.
// On a successful archive, the Artifact in the Status of the object is set,
// and the symlink in the Storage is updated to its path.
func (r *HelmChartReconciler) reconcileArtifact(ctx context.Context, obj *sourcev1.HelmChart, b *chart.Build) (sreconcile.Result, error) {
// Without a complete chart build, there is little to reconcile
if !b.Complete() {
@ -697,8 +720,9 @@ func (r *HelmChartReconciler) getSource(ctx context.Context, obj *sourcev1.HelmC
return s, nil
}
// reconcileDelete handles the delete of an object. It first garbage collects all artifacts for the object from the
// artifact storage, if successful, the finalizer is removed from the object.
// reconcileDelete handles the deletion of the object.
// It first garbage collects all Artifacts for the object from the Storage.
// Removing the finalizer from the object if successful.
func (r *HelmChartReconciler) reconcileDelete(ctx context.Context, obj *sourcev1.HelmChart) (sreconcile.Result, error) {
// Garbage collect the resource's artifacts
if err := r.garbageCollect(ctx, obj); err != nil {
@ -713,9 +737,11 @@ func (r *HelmChartReconciler) reconcileDelete(ctx context.Context, obj *sourcev1
return sreconcile.ResultEmpty, nil
}
// garbageCollect performs a garbage collection for the given v1beta1.HelmChart. It removes all but the current
// artifact, unless the deletion timestamp is set. Which will result in the removal of all artifacts for the
// resource.
// garbageCollect performs a garbage collection for the given object.
//
// It removes all but the current Artifact from the Storage, unless the
// deletion timestamp on the object is set. Which will result in the
// removal of all Artifacts for the objects.
func (r *HelmChartReconciler) garbageCollect(ctx context.Context, obj *sourcev1.HelmChart) error {
if !obj.DeletionTimestamp.IsZero() {
if deleted, err := r.Storage.RemoveAll(r.Storage.NewArtifactFor(obj.Kind, obj.GetObjectMeta(), "", "*")); err != nil {
@ -923,9 +949,11 @@ func (r *HelmChartReconciler) requestsForBucketChange(o client.Object) []reconci
return reqs
}
// eventLogf records event and logs at the same time. This log is different from
// the debug log in the event recorder in the sense that this is a simple log,
// the event recorder debug log contains complete details about the event.
// eventLogf records event and logs at the same time.
//
// This log is different from the debug log in the EventRecorder, in the sense
// that this is a simple log. While the debug log contains complete details
// about the event.
func (r *HelmChartReconciler) eventLogf(ctx context.Context, obj runtime.Object, eventType string, reason string, messageFmt string, args ...interface{}) {
msg := fmt.Sprintf(messageFmt, args...)
// Log and emit event.

View File

@ -125,7 +125,7 @@ func TestHelmChartReconciler_Reconcile(t *testing.T) {
}, timeout).Should(BeTrue())
// Check if the object status is valid.
condns := &status.Conditions{NegativePolarity: helmChartReadyConditions.NegativePolarity}
condns := &status.Conditions{NegativePolarity: helmChartReadyCondition.NegativePolarity}
checker := status.NewChecker(testEnv.Client, testEnv.GetScheme(), condns)
checker.CheckErr(ctx, obj)
@ -1342,8 +1342,8 @@ func TestHelmChartReconciler_reconcileDelete(t *testing.T) {
}
func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
// Helper to build simple helmChartReconcilerFunc with result and error.
buildReconcileFuncs := func(r sreconcile.Result, e error) helmChartReconcilerFunc {
// Helper to build simple helmChartReconcileFunc with result and error.
buildReconcileFuncs := func(r sreconcile.Result, e error) helmChartReconcileFunc {
return func(_ context.Context, _ *sourcev1.HelmChart, _ *chart.Build) (sreconcile.Result, error) {
return r, e
}
@ -1353,14 +1353,14 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
name string
generation int64
observedGeneration int64
reconcileFuncs []helmChartReconcilerFunc
reconcileFuncs []helmChartReconcileFunc
wantResult sreconcile.Result
wantErr bool
assertConditions []metav1.Condition
}{
{
name: "successful reconciliations",
reconcileFuncs: []helmChartReconcilerFunc{
reconcileFuncs: []helmChartReconcileFunc{
buildReconcileFuncs(sreconcile.ResultSuccess, nil),
},
wantResult: sreconcile.ResultSuccess,
@ -1370,7 +1370,7 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
name: "successful reconciliation with generation difference",
generation: 3,
observedGeneration: 2,
reconcileFuncs: []helmChartReconcilerFunc{
reconcileFuncs: []helmChartReconcileFunc{
buildReconcileFuncs(sreconcile.ResultSuccess, nil),
},
wantResult: sreconcile.ResultSuccess,
@ -1381,7 +1381,7 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
},
{
name: "failed reconciliation",
reconcileFuncs: []helmChartReconcilerFunc{
reconcileFuncs: []helmChartReconcileFunc{
buildReconcileFuncs(sreconcile.ResultEmpty, fmt.Errorf("some error")),
},
wantResult: sreconcile.ResultEmpty,
@ -1389,7 +1389,7 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
},
{
name: "multiple object status conditions mutations",
reconcileFuncs: []helmChartReconcilerFunc{
reconcileFuncs: []helmChartReconcileFunc{
func(_ context.Context, obj *sourcev1.HelmChart, _ *chart.Build) (sreconcile.Result, error) {
conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "NewRevision", "new index revision")
return sreconcile.ResultSuccess, nil
@ -1408,7 +1408,7 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
},
{
name: "subrecs with one result=Requeue, no error",
reconcileFuncs: []helmChartReconcilerFunc{
reconcileFuncs: []helmChartReconcileFunc{
buildReconcileFuncs(sreconcile.ResultSuccess, nil),
buildReconcileFuncs(sreconcile.ResultRequeue, nil),
buildReconcileFuncs(sreconcile.ResultSuccess, nil),
@ -1418,7 +1418,7 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
},
{
name: "subrecs with error before result=Requeue",
reconcileFuncs: []helmChartReconcilerFunc{
reconcileFuncs: []helmChartReconcileFunc{
buildReconcileFuncs(sreconcile.ResultSuccess, nil),
buildReconcileFuncs(sreconcile.ResultEmpty, fmt.Errorf("some error")),
buildReconcileFuncs(sreconcile.ResultRequeue, nil),

View File

@ -486,7 +486,7 @@ GitRepositoryStatus
</div>
<h3 id="source.toolkit.fluxcd.io/v1beta2.HelmChart">HelmChart
</h3>
<p>HelmChart is the Schema for the helmcharts API</p>
<p>HelmChart is the Schema for the helmcharts API.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
@ -549,7 +549,8 @@ string
</em>
</td>
<td>
<p>The name or path the Helm chart is available at in the SourceRef.</p>
<p>Chart is the name or path the Helm chart is available at in the
SourceRef.</p>
</td>
</tr>
<tr>
@ -561,8 +562,8 @@ string
</td>
<td>
<em>(Optional)</em>
<p>The chart version semver expression, ignored for charts from GitRepository
and Bucket sources. Defaults to latest when omitted.</p>
<p>Version is the chart version semver expression, ignored for charts from
GitRepository and Bucket sources. Defaults to latest when omitted.</p>
</td>
</tr>
<tr>
@ -575,7 +576,7 @@ LocalHelmChartSourceReference
</em>
</td>
<td>
<p>The reference to the Source the chart is available at.</p>
<p>SourceRef is the reference to the Source the chart is available at.</p>
</td>
</tr>
<tr>
@ -588,7 +589,7 @@ Kubernetes meta/v1.Duration
</em>
</td>
<td>
<p>The interval at which to check the Source for updates.</p>
<p>Interval is the interval at which to check the Source for updates.</p>
</td>
</tr>
<tr>
@ -600,8 +601,8 @@ string
</td>
<td>
<em>(Optional)</em>
<p>Determines what enables the creation of a new artifact. Valid values are
(&lsquo;ChartVersion&rsquo;, &lsquo;Revision&rsquo;).
<p>ReconcileStrategy determines what enables the creation of a new artifact.
Valid values are (&lsquo;ChartVersion&rsquo;, &lsquo;Revision&rsquo;).
See the documentation of the values for an explanation on their behavior.
Defaults to ChartVersion when omitted.</p>
</td>
@ -615,10 +616,11 @@ Defaults to ChartVersion when omitted.</p>
</td>
<td>
<em>(Optional)</em>
<p>Alternative list of values files to use as the chart values (values.yaml
is not included by default), expected to be a relative path in the SourceRef.
Values files are merged in the order of this list with the last file overriding
the first. Ignored when omitted.</p>
<p>ValuesFiles is an alternative list of values files to use as the chart
values (values.yaml is not included by default), expected to be a
relative path in the SourceRef.
Values files are merged in the order of this list with the last file
overriding the first. Ignored when omitted.</p>
</td>
</tr>
<tr>
@ -630,10 +632,10 @@ string
</td>
<td>
<em>(Optional)</em>
<p>Alternative values file to use as the default chart values, expected to
be a relative path in the SourceRef. Deprecated in favor of ValuesFiles,
for backwards compatibility the file defined here is merged before the
ValuesFiles items. Ignored when omitted.</p>
<p>ValuesFile is an alternative values file to use as the default chart
values, expected to be a relative path in the SourceRef. Deprecated in
favor of ValuesFiles, for backwards compatibility the file specified here
is merged before the ValuesFiles items. Ignored when omitted.</p>
</td>
</tr>
<tr>
@ -645,7 +647,8 @@ bool
</td>
<td>
<em>(Optional)</em>
<p>This flag tells the controller to suspend the reconciliation of this source.</p>
<p>Suspend tells the controller to suspend the reconciliation of this
source.</p>
</td>
</tr>
<tr>
@ -659,7 +662,9 @@ github.com/fluxcd/pkg/apis/acl.AccessFrom
</td>
<td>
<em>(Optional)</em>
<p>AccessFrom defines an Access Control List for allowing cross-namespace references to this object.</p>
<p>AccessFrom specifies an Access Control List for allowing cross-namespace
references to this object.
NOTE: Not implemented, provisional as of <a href="https://github.com/fluxcd/flux2/pull/2092">https://github.com/fluxcd/flux2/pull/2092</a></p>
</td>
</tr>
</table>
@ -1295,7 +1300,7 @@ string
</td>
<td>
<em>(Optional)</em>
<p>Branch to checkout, defaults to &lsquo;master&rsquo; if no other field is defined.</p>
<p>Branch to check out, defaults to &lsquo;master&rsquo; if no other field is defined.</p>
<p>When GitRepositorySpec.GitImplementation is set to &lsquo;go-git&rsquo;, a shallow
clone of the specified branch is performed.</p>
</td>
@ -1309,7 +1314,7 @@ string
</td>
<td>
<em>(Optional)</em>
<p>Tag to checkout, takes precedence over Branch.</p>
<p>Tag to check out, takes precedence over Branch.</p>
</td>
</tr>
<tr>
@ -1321,7 +1326,7 @@ string
</td>
<td>
<em>(Optional)</em>
<p>SemVer tag expression to checkout, takes precedence over Tag.</p>
<p>SemVer tag expression to check out, takes precedence over Tag.</p>
</td>
</tr>
<tr>
@ -1333,7 +1338,7 @@ string
</td>
<td>
<em>(Optional)</em>
<p>Commit SHA to checkout, takes precedence over all reference fields.</p>
<p>Commit SHA to check out, takes precedence over all reference fields.</p>
<p>When GitRepositorySpec.GitImplementation is set to &lsquo;go-git&rsquo;, this can be
combined with Branch to shallow clone the branch, in which the commit is
expected to exist.</p>
@ -1694,7 +1699,7 @@ authors.</p>
(<em>Appears on:</em>
<a href="#source.toolkit.fluxcd.io/v1beta2.HelmChart">HelmChart</a>)
</p>
<p>HelmChartSpec defines the desired state of a Helm chart.</p>
<p>HelmChartSpec specifies the desired state of a Helm chart.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
@ -1713,7 +1718,8 @@ string
</em>
</td>
<td>
<p>The name or path the Helm chart is available at in the SourceRef.</p>
<p>Chart is the name or path the Helm chart is available at in the
SourceRef.</p>
</td>
</tr>
<tr>
@ -1725,8 +1731,8 @@ string
</td>
<td>
<em>(Optional)</em>
<p>The chart version semver expression, ignored for charts from GitRepository
and Bucket sources. Defaults to latest when omitted.</p>
<p>Version is the chart version semver expression, ignored for charts from
GitRepository and Bucket sources. Defaults to latest when omitted.</p>
</td>
</tr>
<tr>
@ -1739,7 +1745,7 @@ LocalHelmChartSourceReference
</em>
</td>
<td>
<p>The reference to the Source the chart is available at.</p>
<p>SourceRef is the reference to the Source the chart is available at.</p>
</td>
</tr>
<tr>
@ -1752,7 +1758,7 @@ Kubernetes meta/v1.Duration
</em>
</td>
<td>
<p>The interval at which to check the Source for updates.</p>
<p>Interval is the interval at which to check the Source for updates.</p>
</td>
</tr>
<tr>
@ -1764,8 +1770,8 @@ string
</td>
<td>
<em>(Optional)</em>
<p>Determines what enables the creation of a new artifact. Valid values are
(&lsquo;ChartVersion&rsquo;, &lsquo;Revision&rsquo;).
<p>ReconcileStrategy determines what enables the creation of a new artifact.
Valid values are (&lsquo;ChartVersion&rsquo;, &lsquo;Revision&rsquo;).
See the documentation of the values for an explanation on their behavior.
Defaults to ChartVersion when omitted.</p>
</td>
@ -1779,10 +1785,11 @@ Defaults to ChartVersion when omitted.</p>
</td>
<td>
<em>(Optional)</em>
<p>Alternative list of values files to use as the chart values (values.yaml
is not included by default), expected to be a relative path in the SourceRef.
Values files are merged in the order of this list with the last file overriding
the first. Ignored when omitted.</p>
<p>ValuesFiles is an alternative list of values files to use as the chart
values (values.yaml is not included by default), expected to be a
relative path in the SourceRef.
Values files are merged in the order of this list with the last file
overriding the first. Ignored when omitted.</p>
</td>
</tr>
<tr>
@ -1794,10 +1801,10 @@ string
</td>
<td>
<em>(Optional)</em>
<p>Alternative values file to use as the default chart values, expected to
be a relative path in the SourceRef. Deprecated in favor of ValuesFiles,
for backwards compatibility the file defined here is merged before the
ValuesFiles items. Ignored when omitted.</p>
<p>ValuesFile is an alternative values file to use as the default chart
values, expected to be a relative path in the SourceRef. Deprecated in
favor of ValuesFiles, for backwards compatibility the file specified here
is merged before the ValuesFiles items. Ignored when omitted.</p>
</td>
</tr>
<tr>
@ -1809,7 +1816,8 @@ bool
</td>
<td>
<em>(Optional)</em>
<p>This flag tells the controller to suspend the reconciliation of this source.</p>
<p>Suspend tells the controller to suspend the reconciliation of this
source.</p>
</td>
</tr>
<tr>
@ -1823,7 +1831,9 @@ github.com/fluxcd/pkg/apis/acl.AccessFrom
</td>
<td>
<em>(Optional)</em>
<p>AccessFrom defines an Access Control List for allowing cross-namespace references to this object.</p>
<p>AccessFrom specifies an Access Control List for allowing cross-namespace
references to this object.
NOTE: Not implemented, provisional as of <a href="https://github.com/fluxcd/flux2/pull/2092">https://github.com/fluxcd/flux2/pull/2092</a></p>
</td>
</tr>
</tbody>
@ -1836,7 +1846,7 @@ github.com/fluxcd/pkg/apis/acl.AccessFrom
(<em>Appears on:</em>
<a href="#source.toolkit.fluxcd.io/v1beta2.HelmChart">HelmChart</a>)
</p>
<p>HelmChartStatus defines the observed state of the HelmChart.</p>
<p>HelmChartStatus records the observed state of the HelmChart.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
@ -1856,7 +1866,8 @@ int64
</td>
<td>
<em>(Optional)</em>
<p>ObservedGeneration is the last observed generation.</p>
<p>ObservedGeneration is the last observed generation of the HelmChart
object.</p>
</td>
</tr>
<tr>
@ -1869,7 +1880,7 @@ string
<td>
<em>(Optional)</em>
<p>ObservedSourceArtifactRevision is the last observed Artifact.Revision
of the Source reference.</p>
of the HelmChartSpec.SourceRef.</p>
</td>
</tr>
<tr>
@ -1881,7 +1892,7 @@ string
</td>
<td>
<em>(Optional)</em>
<p>ObservedChartName is the last observed chart name as defined by the
<p>ObservedChartName is the last observed chart name as specified by the
resolved chart reference.</p>
</td>
</tr>
@ -1908,7 +1919,9 @@ string
</td>
<td>
<em>(Optional)</em>
<p>URL is the fetch link for the last chart pulled.</p>
<p>URL is the dynamic fetch link for the latest Artifact.
It is provided on a &ldquo;best effort&rdquo; basis, and using the precise
BucketStatus.Artifact data is recommended.</p>
</td>
</tr>
<tr>
@ -1922,7 +1935,7 @@ Artifact
</td>
<td>
<em>(Optional)</em>
<p>Artifact represents the output of the last successful chart sync.</p>
<p>Artifact represents the output of the last successful reconciliation.</p>
</td>
</tr>
<tr>

View File

@ -7,7 +7,7 @@ This is the v1beta2 API specification for defining the desired state sources of
* Source kinds:
+ [GitRepository](gitrepositories.md)
+ [HelmRepository](helmrepositories.md)
+ HelmChart
+ [HelmChart](helmcharts.md)
+ [Bucket](buckets.md)
## Implementation

View File

@ -0,0 +1,481 @@
# 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/v1beta2
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 READY STATUS AGE
podinfo podinfo 5.* HelmRepository podinfo True pulled 'podinfo' chart with version '5.2.1' 53s
```
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: 83a3c595163a6ff0333e0154c790383b5be441b9db632cb36da11db1c4ece111
Artifact:
Checksum: 6c3cc3b955bce1686036ae6822ee2ca0ef6ecb994e3f2d19eaf3ec03dcba84b3
Last Update Time: 2022-02-13T11:24:10Z
Path: helmchart/default/podinfo/podinfo-5.2.1.tgz
Revision: 5.2.1
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
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).
### 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.
### Source reference
`.spec.sourceRef` is a required field that specifies a reference to the Source
the chart is available at. `.spec.sourceRef.kind` must be one of
`HelmRepository`, `GitRepository` or `Bucket`. `.spec.sourceRef.name` is the
name of the referred kind.
### 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. For GitRepository and
Bucket Source reference, it'll be the path to the Helm chart directory.
### 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 `*`.
### 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.
### 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 the HelmRepository. `Revision` is used for creating a new artifact
when the source revision changes in GitRepository or Bucket Source references.
It defaults to `ChartVersion`.
### 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).
## 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: <arbitrary value>`. Annotating the resource
queues the object for reconciliation if the `<arbitrary-value>` differs from
the last value the controller acted on, as reported in
[`.status.lastHandledReconcileAt`](#last-handled-reconcile-at).
Using `kubectl`:
```sh
kubectl annotate --overwrite helmchart/<chart-name> 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/<chart-name> --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/v1beta2
kind: HelmChart
metadata:
name: <chart-name>
spec:
suspend: true
```
Using `kubectl`:
```sh
kubectl patch helmchart <chart-name> -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/v1beta2
kind: HelmChart
metadata:
name: <chart-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 <chart-name> -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 <chart-name>` 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 get events` can be used in
combination with `--field-selector` to list the Events for specific objects.
For example, running
```sh
kubectl get events --field-selector involvedObject.kind=HelmChart,involvedObject.name=<chart-name>
```
lists
```console
LAST SEEN TYPE REASON OBJECT MESSAGE
22s Warning InvalidChartReference helmchart/<chart-name> invalid chart reference: failed to get chart version for remote reference: no 'podinfo' chart with version matching '9.*' found
2s Normal ChartPullSucceeded helmchart/<chart-name> pulled 'podinfo' chart with version '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=<chart-name>`.
## 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 (`<chart-name>-<chart-version>.tgz`),
and can be retrieved in-cluster from the `.status.artifact.url` HTTP address.
### Artifact example
```yaml
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmChart
metadata:
name: <chart-name>
status:
artifact:
checksum: e30b95a08787de69ffdad3c232d65cfb131b5b50c6fd44295f48a078fceaa44e
lastUpdateTime: "2022-02-10T18:53:47Z"
path: helmchart/<source-namespace>/<chart-name>/<chart-name>-<chart-version>.tgz
revision: 6.0.3
url: http://source-controller.flux-system.svc.cluster.local./helmchart/<source-namespace>/<chart-name>/<chart-name>-<chart-version>.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
`False`, and the controller adds a Condition with the following attributes to
the HelmChart's `.status.conditions`:
- `type: Reconciling`
- `status: "True"`
- `reason: NewGeneration` | `reason: NoArtifact`
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.
#### 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.
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`
- `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"`.
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.
#### 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
[Source reference's](#source-reference) Artifact the current chart was fetched
from in the HelmChart's `.status.observedSourceArtifactRevision`.
### Observed Chart Name
The source-controller reports the resolved chart name of the current Artifact
for the [`.spec.chart` field](#chart) in the HelmChart's
`.status.observedChartName`.
### 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