Add progressive status in helmchart reconciler

Signed-off-by: Sunny <darkowlzz@protonmail.com>
This commit is contained in:
Sunny 2022-11-30 18:49:15 +00:00
parent 3d6a5e1203
commit 9c866ee49d
2 changed files with 244 additions and 49 deletions

View File

@ -30,6 +30,8 @@ import (
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1" eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
soci "github.com/fluxcd/source-controller/internal/oci" soci "github.com/fluxcd/source-controller/internal/oci"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/v1/remote"
helmgetter "helm.sh/helm/v3/pkg/getter" helmgetter "helm.sh/helm/v3/pkg/getter"
helmreg "helm.sh/helm/v3/pkg/registry" helmreg "helm.sh/helm/v3/pkg/registry"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
@ -56,9 +58,8 @@ import (
helper "github.com/fluxcd/pkg/runtime/controller" helper "github.com/fluxcd/pkg/runtime/controller"
"github.com/fluxcd/pkg/runtime/patch" "github.com/fluxcd/pkg/runtime/patch"
"github.com/fluxcd/pkg/runtime/predicates" "github.com/fluxcd/pkg/runtime/predicates"
rreconcile "github.com/fluxcd/pkg/runtime/reconcile"
"github.com/fluxcd/pkg/untar" "github.com/fluxcd/pkg/untar"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/v1/remote"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
"github.com/fluxcd/source-controller/internal/cache" "github.com/fluxcd/source-controller/internal/cache"
@ -133,6 +134,8 @@ type HelmChartReconciler struct {
Cache *cache.Cache Cache *cache.Cache
TTL time.Duration TTL time.Duration
*cache.CacheRecorder *cache.CacheRecorder
patchOptions []patch.Option
} }
func (r *HelmChartReconciler) SetupWithManager(mgr ctrl.Manager) error { func (r *HelmChartReconciler) SetupWithManager(mgr ctrl.Manager) error {
@ -147,9 +150,11 @@ type HelmChartReconcilerOptions struct {
// helmChartReconcileFunc is the function type for all the v1beta2.HelmChart // helmChartReconcileFunc is the function type for all the v1beta2.HelmChart
// (sub)reconcile functions. The type implementations are grouped and // (sub)reconcile functions. The type implementations are grouped and
// executed serially to perform the complete reconcile of the object. // 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) type helmChartReconcileFunc func(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmChart, build *chart.Build) (sreconcile.Result, error)
func (r *HelmChartReconciler) SetupWithManagerAndOptions(mgr ctrl.Manager, opts HelmChartReconcilerOptions) error { func (r *HelmChartReconciler) SetupWithManagerAndOptions(mgr ctrl.Manager, opts HelmChartReconcilerOptions) error {
r.patchOptions = getPatchOptions(helmChartReadyCondition.Owned, r.ControllerName)
if err := mgr.GetCache().IndexField(context.TODO(), &sourcev1.HelmRepository{}, sourcev1.HelmRepositoryURLIndexKey, if err := mgr.GetCache().IndexField(context.TODO(), &sourcev1.HelmRepository{}, sourcev1.HelmRepositoryURLIndexKey,
r.indexHelmRepositoryByURL); err != nil { r.indexHelmRepositoryByURL); err != nil {
return fmt.Errorf("failed setting index fields: %w", err) return fmt.Errorf("failed setting index fields: %w", err)
@ -200,10 +205,7 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
r.RecordSuspend(ctx, obj, obj.Spec.Suspend) r.RecordSuspend(ctx, obj, obj.Spec.Suspend)
// Initialize the patch helper with the current version of the object. // Initialize the patch helper with the current version of the object.
patchHelper, err := patch.NewHelper(obj, r.Client) serialPatcher := patch.NewSerialPatcher(obj, r.Client)
if err != nil {
return ctrl.Result{}, err
}
// recResult stores the abstracted reconcile result. // recResult stores the abstracted reconcile result.
var recResult sreconcile.Result var recResult sreconcile.Result
@ -211,7 +213,7 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
// Always attempt to patch the object after each reconciliation. // Always attempt to patch the object after each reconciliation.
// NOTE: The final runtime result and error are set in this block. // NOTE: The final runtime result and error are set in this block.
defer func() { defer func() {
summarizeHelper := summarize.NewHelper(r.EventRecorder, patchHelper) summarizeHelper := summarize.NewHelper(r.EventRecorder, serialPatcher)
summarizeOpts := []summarize.Option{ summarizeOpts := []summarize.Option{
summarize.WithConditions(helmChartReadyCondition), summarize.WithConditions(helmChartReadyCondition),
summarize.WithBiPolarityConditionTypes(sourcev1.SourceVerifiedCondition), summarize.WithBiPolarityConditionTypes(sourcev1.SourceVerifiedCondition),
@ -259,19 +261,35 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
r.reconcileSource, r.reconcileSource,
r.reconcileArtifact, r.reconcileArtifact,
} }
recResult, retErr = r.reconcile(ctx, obj, reconcilers) recResult, retErr = r.reconcile(ctx, serialPatcher, obj, reconcilers)
return return
} }
// reconcile iterates through the helmChartReconcileFunc tasks for the // reconcile iterates through the helmChartReconcileFunc tasks for the
// object. It returns early on the first call that returns // object. It returns early on the first call that returns
// reconcile.ResultRequeue, or produces an error. // reconcile.ResultRequeue, or produces an error.
func (r *HelmChartReconciler) reconcile(ctx context.Context, obj *sourcev1.HelmChart, reconcilers []helmChartReconcileFunc) (sreconcile.Result, error) { func (r *HelmChartReconciler) reconcile(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmChart, reconcilers []helmChartReconcileFunc) (sreconcile.Result, error) {
oldObj := obj.DeepCopy() oldObj := obj.DeepCopy()
// Mark as reconciling if generation differs. rreconcile.ProgressiveStatus(false, obj, meta.ProgressingReason, "reconciliation in progress")
if obj.Generation != obj.Status.ObservedGeneration {
conditions.MarkReconciling(obj, "NewGeneration", "reconciling new object generation (%d)", obj.Generation) var reconcileAtVal string
if v, ok := meta.ReconcileAnnotationValue(obj.GetAnnotations()); ok {
reconcileAtVal = v
}
// Persist reconciling if generation differs or reconciliation is requested.
switch {
case obj.Generation != obj.Status.ObservedGeneration:
rreconcile.ProgressiveStatus(false, obj, meta.ProgressingReason,
"processing object: new generation %d -> %d", obj.Status.ObservedGeneration, obj.Generation)
if err := sp.Patch(ctx, obj, r.patchOptions...); err != nil {
return sreconcile.ResultEmpty, err
}
case reconcileAtVal != obj.Status.GetLastHandledReconcileRequest():
if err := sp.Patch(ctx, obj, r.patchOptions...); err != nil {
return sreconcile.ResultEmpty, err
}
} }
// Run the sub-reconcilers and build the result of reconciliation. // Run the sub-reconcilers and build the result of reconciliation.
@ -281,7 +299,7 @@ func (r *HelmChartReconciler) reconcile(ctx context.Context, obj *sourcev1.HelmC
resErr error resErr error
) )
for _, rec := range reconcilers { for _, rec := range reconcilers {
recResult, err := rec(ctx, obj, &build) recResult, err := rec(ctx, sp, obj, &build)
// Exit immediately on ResultRequeue. // Exit immediately on ResultRequeue.
if recResult == sreconcile.ResultRequeue { if recResult == sreconcile.ResultRequeue {
return sreconcile.ResultRequeue, nil return sreconcile.ResultRequeue, nil
@ -344,22 +362,31 @@ func (r *HelmChartReconciler) notify(ctx context.Context, oldObj, newObj *source
// condition is added. // condition is added.
// The hostname of any URL in the Status of the object are updated, to ensure // The hostname of any URL in the Status of the object are updated, to ensure
// they match the Storage server hostname of current runtime. // 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) { func (r *HelmChartReconciler) reconcileStorage(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmChart, build *chart.Build) (sreconcile.Result, error) {
// Garbage collect previous advertised artifact(s) from storage // Garbage collect previous advertised artifact(s) from storage
_ = r.garbageCollect(ctx, obj) _ = r.garbageCollect(ctx, obj)
// Determine if the advertised artifact is still in storage // Determine if the advertised artifact is still in storage
var artifactMissing bool
if artifact := obj.GetArtifact(); artifact != nil && !r.Storage.ArtifactExist(*artifact) { if artifact := obj.GetArtifact(); artifact != nil && !r.Storage.ArtifactExist(*artifact) {
obj.Status.Artifact = nil obj.Status.Artifact = nil
obj.Status.URL = "" obj.Status.URL = ""
artifactMissing = true
// Remove the condition as the artifact doesn't exist. // Remove the condition as the artifact doesn't exist.
conditions.Delete(obj, sourcev1.ArtifactInStorageCondition) conditions.Delete(obj, sourcev1.ArtifactInStorageCondition)
} }
// Record that we do not have an artifact // Record that we do not have an artifact
if obj.GetArtifact() == nil { if obj.GetArtifact() == nil {
conditions.MarkReconciling(obj, "NoArtifact", "no artifact for resource in storage") msg := "building artifact"
if artifactMissing {
msg += ": disappeared from storage"
}
rreconcile.ProgressiveStatus(true, obj, meta.ProgressingReason, msg)
conditions.Delete(obj, sourcev1.ArtifactInStorageCondition) conditions.Delete(obj, sourcev1.ArtifactInStorageCondition)
if err := sp.Patch(ctx, obj, r.patchOptions...); err != nil {
return sreconcile.ResultEmpty, err
}
return sreconcile.ResultSuccess, nil return sreconcile.ResultSuccess, nil
} }
@ -371,7 +398,7 @@ func (r *HelmChartReconciler) reconcileStorage(ctx context.Context, obj *sourcev
return sreconcile.ResultSuccess, nil return sreconcile.ResultSuccess, nil
} }
func (r *HelmChartReconciler) reconcileSource(ctx context.Context, obj *sourcev1.HelmChart, build *chart.Build) (_ sreconcile.Result, retErr error) { func (r *HelmChartReconciler) reconcileSource(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmChart, build *chart.Build) (_ sreconcile.Result, retErr error) {
// Remove any failed verification condition. // Remove any failed verification condition.
// The reason is that a failing verification should be recalculated. // The reason is that a failing verification should be recalculated.
if conditions.IsFalse(obj, sourcev1.SourceVerifiedCondition) { if conditions.IsFalse(obj, sourcev1.SourceVerifiedCondition) {
@ -418,7 +445,7 @@ func (r *HelmChartReconciler) reconcileSource(ctx context.Context, obj *sourcev1
// Defer observation of build result // Defer observation of build result
defer func() { defer func() {
// Record both success and error observations on the object // Record both success and error observations on the object
observeChartBuild(obj, build, retErr) observeChartBuild(ctx, sp, r.patchOptions, obj, build, retErr)
// If we actually build a chart, take a historical note of any dependencies we resolved. // If we actually build a chart, take a historical note of any dependencies we resolved.
// The reason this is a done conditionally, is because if we have a cached one in storage, // The reason this is a done conditionally, is because if we have a cached one in storage,
@ -810,7 +837,7 @@ func (r *HelmChartReconciler) buildFromTarballArtifact(ctx context.Context, obj
// early. // early.
// On a successful archive, the Artifact in the Status of the object is set, // 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. // 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) { func (r *HelmChartReconciler) reconcileArtifact(ctx context.Context, sp *patch.SerialPatcher, obj *sourcev1.HelmChart, b *chart.Build) (sreconcile.Result, error) {
// Without a complete chart build, there is little to reconcile // Without a complete chart build, there is little to reconcile
if !b.Complete() { if !b.Complete() {
return sreconcile.ResultRequeue, nil return sreconcile.ResultRequeue, nil
@ -1265,11 +1292,17 @@ func (r *HelmChartReconciler) eventLogf(ctx context.Context, obj runtime.Object,
} }
// observeChartBuild records the observation on the given given build and error on the object. // observeChartBuild records the observation on the given given build and error on the object.
func observeChartBuild(obj *sourcev1.HelmChart, build *chart.Build, err error) { func observeChartBuild(ctx context.Context, sp *patch.SerialPatcher, pOpts []patch.Option, obj *sourcev1.HelmChart, build *chart.Build, err error) {
if build.HasMetadata() { if build.HasMetadata() {
if build.Name != obj.Status.ObservedChartName || !obj.GetArtifact().HasRevision(build.Version) { if build.Name != obj.Status.ObservedChartName || !obj.GetArtifact().HasRevision(build.Version) {
if obj.GetArtifact() != nil {
conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "NewChart", build.Summary()) conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "NewChart", build.Summary())
} }
rreconcile.ProgressiveStatus(true, obj, meta.ProgressingReason, "building artifact: %s", build.Summary())
if err := sp.Patch(ctx, obj, pOpts...); err != nil {
ctrl.LoggerFrom(ctx).Error(err, "failed to patch")
}
}
} }
if build.Complete() { if build.Complete() {

View File

@ -309,6 +309,7 @@ func TestHelmChartReconciler_reconcileStorage(t *testing.T) {
} }
} }
testStorage.SetArtifactURL(obj.Status.Artifact) testStorage.SetArtifactURL(obj.Status.Artifact)
conditions.MarkTrue(obj, meta.ReadyCondition, "foo", "bar")
return nil return nil
}, },
assertArtifact: &sourcev1.Artifact{ assertArtifact: &sourcev1.Artifact{
@ -325,6 +326,17 @@ func TestHelmChartReconciler_reconcileStorage(t *testing.T) {
"!/reconcile-storage/a.txt", "!/reconcile-storage/a.txt",
}, },
want: sreconcile.ResultSuccess, want: sreconcile.ResultSuccess,
assertConditions: []metav1.Condition{
*conditions.TrueCondition(meta.ReadyCondition, "foo", "bar"),
},
},
{
name: "build artifact first time",
want: sreconcile.ResultSuccess,
assertConditions: []metav1.Condition{
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact"),
},
}, },
{ {
name: "notices missing artifact in storage", name: "notices missing artifact in storage",
@ -341,7 +353,8 @@ func TestHelmChartReconciler_reconcileStorage(t *testing.T) {
"!/reconcile-storage/invalid.txt", "!/reconcile-storage/invalid.txt",
}, },
assertConditions: []metav1.Condition{ assertConditions: []metav1.Condition{
*conditions.TrueCondition(meta.ReconcilingCondition, "NoArtifact", "no artifact for resource in storage"), *conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: disappeared from storage"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: disappeared from storage"),
}, },
}, },
{ {
@ -359,6 +372,7 @@ func TestHelmChartReconciler_reconcileStorage(t *testing.T) {
if err := testStorage.AtomicWriteFile(obj.Status.Artifact, strings.NewReader("file"), 0o640); err != nil { if err := testStorage.AtomicWriteFile(obj.Status.Artifact, strings.NewReader("file"), 0o640); err != nil {
return err return err
} }
conditions.MarkTrue(obj, meta.ReadyCondition, "foo", "bar")
return nil return nil
}, },
want: sreconcile.ResultSuccess, want: sreconcile.ResultSuccess,
@ -372,6 +386,9 @@ func TestHelmChartReconciler_reconcileStorage(t *testing.T) {
URL: testStorage.Hostname + "/reconcile-storage/hostname.txt", URL: testStorage.Hostname + "/reconcile-storage/hostname.txt",
Size: int64p(int64(len("file"))), Size: int64p(int64(len("file"))),
}, },
assertConditions: []metav1.Condition{
*conditions.TrueCondition(meta.ReadyCondition, "foo", "bar"),
},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -383,20 +400,30 @@ func TestHelmChartReconciler_reconcileStorage(t *testing.T) {
}() }()
r := &HelmChartReconciler{ r := &HelmChartReconciler{
Client: fakeclient.NewClientBuilder().WithScheme(testEnv.GetScheme()).Build(),
EventRecorder: record.NewFakeRecorder(32), EventRecorder: record.NewFakeRecorder(32),
Storage: testStorage, Storage: testStorage,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
obj := &sourcev1.HelmChart{ obj := &sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
GenerateName: "test-", GenerateName: "test-",
Generation: 1,
}, },
} }
if tt.beforeFunc != nil { if tt.beforeFunc != nil {
g.Expect(tt.beforeFunc(obj, testStorage)).To(Succeed()) g.Expect(tt.beforeFunc(obj, testStorage)).To(Succeed())
} }
got, err := r.reconcileStorage(context.TODO(), obj, nil) g.Expect(r.Client.Create(context.TODO(), obj)).ToNot(HaveOccurred())
defer func() {
g.Expect(r.Client.Delete(context.TODO(), obj)).ToNot(HaveOccurred())
}()
sp := patch.NewSerialPatcher(obj, r.Client)
got, err := r.reconcileStorage(context.TODO(), sp, obj, nil)
g.Expect(err != nil).To(Equal(tt.wantErr)) g.Expect(err != nil).To(Equal(tt.wantErr))
g.Expect(got).To(Equal(tt.want)) g.Expect(got).To(Equal(tt.want))
@ -414,6 +441,10 @@ func TestHelmChartReconciler_reconcileStorage(t *testing.T) {
} }
g.Expect(absoluteP).NotTo(BeAnExistingFile()) g.Expect(absoluteP).NotTo(BeAnExistingFile())
} }
// In-progress status condition validity.
checker := conditionscheck.NewInProgressChecker(r.Client)
checker.CheckErr(ctx, obj)
}) })
} }
} }
@ -468,13 +499,51 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
g.Expect(obj.Status.ObservedSourceArtifactRevision).To(Equal(gitArtifact.Revision)) g.Expect(obj.Status.ObservedSourceArtifactRevision).To(Equal(gitArtifact.Revision))
g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{ g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{
*conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewChart", "pulled 'helmchart' chart with version '0.1.0'"), *conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: pulled 'helmchart' chart with version '0.1.0'"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: pulled 'helmchart' chart with version '0.1.0'"),
})) }))
}, },
cleanFunc: func(g *WithT, build *chart.Build) { cleanFunc: func(g *WithT, build *chart.Build) {
g.Expect(os.Remove(build.Path)).To(Succeed()) g.Expect(os.Remove(build.Path)).To(Succeed())
}, },
}, },
{
name: "Existing artifact makes AritfactOutdated=True",
source: &sourcev1.GitRepository{
ObjectMeta: metav1.ObjectMeta{
Name: "gitrepository",
Namespace: "default",
},
Status: sourcev1.GitRepositoryStatus{
Artifact: gitArtifact,
},
},
beforeFunc: func(obj *sourcev1.HelmChart) {
obj.Spec.Chart = "testdata/charts/helmchart-0.1.0.tgz"
obj.Spec.SourceRef = sourcev1.LocalHelmChartSourceReference{
Name: "gitrepository",
Kind: sourcev1.GitRepositoryKind,
}
obj.Status.Artifact = &sourcev1.Artifact{
Path: "some-path",
Revision: "some-rev",
}
},
want: sreconcile.ResultSuccess,
assertFunc: func(g *WithT, build chart.Build, obj sourcev1.HelmChart) {
g.Expect(build.Complete()).To(BeTrue())
g.Expect(build.Name).To(Equal("helmchart"))
g.Expect(build.Version).To(Equal("0.1.0"))
g.Expect(build.Path).To(BeARegularFile())
g.Expect(obj.Status.ObservedSourceArtifactRevision).To(Equal(gitArtifact.Revision))
g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{
*conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewChart", "pulled 'helmchart' chart with version '0.1.0'"),
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: pulled 'helmchart' chart with version '0.1.0'"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: pulled 'helmchart' chart with version '0.1.0'"),
}))
},
},
{ {
name: "Error on unavailable source", name: "Error on unavailable source",
beforeFunc: func(obj *sourcev1.HelmChart) { beforeFunc: func(obj *sourcev1.HelmChart) {
@ -482,6 +551,8 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
Name: "unavailable", Name: "unavailable",
Kind: sourcev1.GitRepositoryKind, Kind: sourcev1.GitRepositoryKind,
} }
conditions.MarkReconciling(obj, meta.ProgressingReason, "foo")
conditions.MarkUnknown(obj, meta.ReadyCondition, "foo", "bar")
}, },
want: sreconcile.ResultEmpty, want: sreconcile.ResultEmpty,
wantErr: &serror.Event{Err: errors.New("gitrepositories.source.toolkit.fluxcd.io \"unavailable\" not found")}, wantErr: &serror.Event{Err: errors.New("gitrepositories.source.toolkit.fluxcd.io \"unavailable\" not found")},
@ -490,6 +561,8 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{ g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{
*conditions.TrueCondition(sourcev1.FetchFailedCondition, "SourceUnavailable", "failed to get source: gitrepositories.source.toolkit.fluxcd.io \"unavailable\" not found"), *conditions.TrueCondition(sourcev1.FetchFailedCondition, "SourceUnavailable", "failed to get source: gitrepositories.source.toolkit.fluxcd.io \"unavailable\" not found"),
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "foo"),
*conditions.UnknownCondition(meta.ReadyCondition, "foo", "bar"),
})) }))
}, },
}, },
@ -500,6 +573,8 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
Name: "unavailable", Name: "unavailable",
Kind: "Unsupported", Kind: "Unsupported",
} }
conditions.MarkReconciling(obj, meta.ProgressingReason, "foo")
conditions.MarkUnknown(obj, meta.ReadyCondition, meta.ProgressingReason, "foo")
}, },
want: sreconcile.ResultEmpty, want: sreconcile.ResultEmpty,
wantErr: &serror.Stalling{Err: errors.New("unsupported source kind 'Unsupported'")}, wantErr: &serror.Stalling{Err: errors.New("unsupported source kind 'Unsupported'")},
@ -508,6 +583,8 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{ g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{
*conditions.TrueCondition(sourcev1.FetchFailedCondition, "SourceUnavailable", "failed to get source: unsupported source kind"), *conditions.TrueCondition(sourcev1.FetchFailedCondition, "SourceUnavailable", "failed to get source: unsupported source kind"),
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "foo"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "foo"),
})) }))
}, },
}, },
@ -529,6 +606,8 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
Kind: sourcev1.GitRepositoryKind, Kind: sourcev1.GitRepositoryKind,
} }
obj.Spec.ValuesFiles = []string{"invalid.yaml"} obj.Spec.ValuesFiles = []string{"invalid.yaml"}
conditions.MarkReconciling(obj, meta.ProgressingReason, "foo")
conditions.MarkUnknown(obj, meta.ReadyCondition, meta.ProgressingReason, "foo")
}, },
want: sreconcile.ResultEmpty, want: sreconcile.ResultEmpty,
wantErr: &serror.Stalling{Err: errors.New("values files merge error: no values file found at path")}, wantErr: &serror.Stalling{Err: errors.New("values files merge error: no values file found at path")},
@ -537,6 +616,8 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{ g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{
*conditions.TrueCondition(sourcev1.BuildFailedCondition, "ValuesFilesError", "values files merge error: no values file found at path"), *conditions.TrueCondition(sourcev1.BuildFailedCondition, "ValuesFilesError", "values files merge error: no values file found at path"),
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "foo"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "foo"),
})) }))
}, },
}, },
@ -556,6 +637,8 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
Kind: sourcev1.GitRepositoryKind, Kind: sourcev1.GitRepositoryKind,
} }
obj.Status.ObservedSourceArtifactRevision = "foo" obj.Status.ObservedSourceArtifactRevision = "foo"
conditions.MarkReconciling(obj, meta.ProgressingReason, "foo")
conditions.MarkUnknown(obj, meta.ReadyCondition, meta.ProgressingReason, "foo")
}, },
want: sreconcile.ResultRequeue, want: sreconcile.ResultRequeue,
assertFunc: func(g *WithT, build chart.Build, obj sourcev1.HelmChart) { assertFunc: func(g *WithT, build chart.Build, obj sourcev1.HelmChart) {
@ -564,6 +647,8 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
g.Expect(obj.Status.ObservedSourceArtifactRevision).To(Equal("foo")) g.Expect(obj.Status.ObservedSourceArtifactRevision).To(Equal("foo"))
g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{ g.Expect(obj.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{
*conditions.TrueCondition(sourcev1.FetchFailedCondition, "NoSourceArtifact", "no artifact available"), *conditions.TrueCondition(sourcev1.FetchFailedCondition, "NoSourceArtifact", "no artifact available"),
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "foo"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "foo"),
})) }))
}, },
}, },
@ -572,7 +657,7 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t) g := NewWithT(t)
clientBuilder := fake.NewClientBuilder() clientBuilder := fake.NewClientBuilder().WithScheme(testEnv.GetScheme())
if tt.source != nil { if tt.source != nil {
clientBuilder.WithRuntimeObjects(tt.source) clientBuilder.WithRuntimeObjects(tt.source)
} }
@ -581,12 +666,14 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
Client: clientBuilder.Build(), Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32), EventRecorder: record.NewFakeRecorder(32),
Storage: storage, Storage: storage,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
obj := sourcev1.HelmChart{ obj := sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "chart", Name: "chart",
Namespace: "default", Namespace: "default",
Generation: 1,
}, },
Spec: sourcev1.HelmChartSpec{}, Spec: sourcev1.HelmChartSpec{},
} }
@ -599,7 +686,14 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
defer tt.cleanFunc(g, &b) defer tt.cleanFunc(g, &b)
} }
got, err := r.reconcileSource(context.TODO(), &obj, &b) g.Expect(r.Client.Create(context.TODO(), &obj)).ToNot(HaveOccurred())
defer func() {
g.Expect(r.Client.Delete(context.TODO(), &obj)).ToNot(HaveOccurred())
}()
sp := patch.NewSerialPatcher(&obj, r.Client)
got, err := r.reconcileSource(context.TODO(), sp, &obj, &b)
g.Expect(err != nil).To(Equal(tt.wantErr != nil)) g.Expect(err != nil).To(Equal(tt.wantErr != nil))
if tt.wantErr != nil { if tt.wantErr != nil {
@ -611,6 +705,10 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
if tt.assertFunc != nil { if tt.assertFunc != nil {
tt.assertFunc(g, b, obj) tt.assertFunc(g, b, obj)
} }
// In-progress status condition validity.
checker := conditionscheck.NewInProgressChecker(r.Client)
checker.CheckErr(ctx, &obj)
}) })
} }
} }
@ -840,6 +938,7 @@ func TestHelmChartReconciler_buildFromHelmRepository(t *testing.T) {
EventRecorder: record.NewFakeRecorder(32), EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters, Getters: testGetters,
Storage: storage, Storage: storage,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
repository := &sourcev1.HelmRepository{ repository := &sourcev1.HelmRepository{
@ -1006,8 +1105,6 @@ func TestHelmChartReconciler_buildFromOCIHelmRepository(t *testing.T) {
assertFunc: func(g *WithT, obj *sourcev1.HelmChart, build chart.Build) { assertFunc: func(g *WithT, obj *sourcev1.HelmChart, build chart.Build) {
g.Expect(build.Name).To(Equal(metadata.Name)) g.Expect(build.Name).To(Equal(metadata.Name))
g.Expect(build.Version).To(Equal(metadata.Version)) g.Expect(build.Version).To(Equal(metadata.Version))
fmt.Println("buildpath", build.Path)
fmt.Println("storage Path", storage.LocalPath(*cachedArtifact.DeepCopy()))
g.Expect(build.Path).ToNot(Equal(storage.LocalPath(*cachedArtifact.DeepCopy()))) g.Expect(build.Path).ToNot(Equal(storage.LocalPath(*cachedArtifact.DeepCopy())))
g.Expect(build.Path).To(BeARegularFile()) g.Expect(build.Path).To(BeARegularFile())
}, },
@ -1071,6 +1168,7 @@ func TestHelmChartReconciler_buildFromOCIHelmRepository(t *testing.T) {
Getters: testGetters, Getters: testGetters,
Storage: storage, Storage: storage,
RegistryClientGenerator: registry.ClientGenerator, RegistryClientGenerator: registry.ClientGenerator,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
repository := &sourcev1.HelmRepository{ repository := &sourcev1.HelmRepository{
@ -1276,6 +1374,7 @@ func TestHelmChartReconciler_buildFromTarballArtifact(t *testing.T) {
Storage: storage, Storage: storage,
Getters: testGetters, Getters: testGetters,
RegistryClientGenerator: registry.ClientGenerator, RegistryClientGenerator: registry.ClientGenerator,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
obj := &sourcev1.HelmChart{ obj := &sourcev1.HelmChart{
@ -1433,8 +1532,10 @@ func TestHelmChartReconciler_reconcileArtifact(t *testing.T) {
g := NewWithT(t) g := NewWithT(t)
r := &HelmChartReconciler{ r := &HelmChartReconciler{
Client: fakeclient.NewClientBuilder().WithScheme(testEnv.GetScheme()).Build(),
EventRecorder: record.NewFakeRecorder(32), EventRecorder: record.NewFakeRecorder(32),
Storage: testStorage, Storage: testStorage,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
obj := &sourcev1.HelmChart{ obj := &sourcev1.HelmChart{
@ -1448,7 +1549,14 @@ func TestHelmChartReconciler_reconcileArtifact(t *testing.T) {
tt.beforeFunc(obj) tt.beforeFunc(obj)
} }
got, err := r.reconcileArtifact(ctx, obj, tt.build) g.Expect(r.Client.Create(context.TODO(), obj)).ToNot(HaveOccurred())
defer func() {
g.Expect(r.Client.Delete(context.TODO(), obj)).ToNot(HaveOccurred())
}()
sp := patch.NewSerialPatcher(obj, r.Client)
got, err := r.reconcileArtifact(ctx, sp, obj, tt.build)
g.Expect(err != nil).To(Equal(tt.wantErr)) g.Expect(err != nil).To(Equal(tt.wantErr))
g.Expect(got).To(Equal(tt.want)) g.Expect(got).To(Equal(tt.want))
g.Expect(obj.Status.Conditions).To(conditions.MatchConditions(tt.assertConditions)) g.Expect(obj.Status.Conditions).To(conditions.MatchConditions(tt.assertConditions))
@ -1478,6 +1586,7 @@ func TestHelmChartReconciler_getHelmRepositorySecret(t *testing.T) {
r := &HelmChartReconciler{ r := &HelmChartReconciler{
Client: clientBuilder.Build(), Client: clientBuilder.Build(),
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
tests := []struct { tests := []struct {
@ -1573,6 +1682,7 @@ func TestHelmChartReconciler_getSource(t *testing.T) {
r := &HelmChartReconciler{ r := &HelmChartReconciler{
Client: clientBuilder.Build(), Client: clientBuilder.Build(),
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
tests := []struct { tests := []struct {
@ -1678,6 +1788,7 @@ func TestHelmChartReconciler_reconcileDelete(t *testing.T) {
r := &HelmChartReconciler{ r := &HelmChartReconciler{
EventRecorder: record.NewFakeRecorder(32), EventRecorder: record.NewFakeRecorder(32),
Storage: testStorage, Storage: testStorage,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
obj := &sourcev1.HelmChart{ obj := &sourcev1.HelmChart{
@ -1704,7 +1815,7 @@ func TestHelmChartReconciler_reconcileDelete(t *testing.T) {
func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) { func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
// Helper to build simple helmChartReconcileFunc with result and error. // Helper to build simple helmChartReconcileFunc with result and error.
buildReconcileFuncs := func(r sreconcile.Result, e error) helmChartReconcileFunc { buildReconcileFuncs := func(r sreconcile.Result, e error) helmChartReconcileFunc {
return func(_ context.Context, _ *sourcev1.HelmChart, _ *chart.Build) (sreconcile.Result, error) { return func(_ context.Context, _ *patch.SerialPatcher, _ *sourcev1.HelmChart, _ *chart.Build) (sreconcile.Result, error) {
return r, e return r, e
} }
} }
@ -1725,6 +1836,10 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
}, },
wantResult: sreconcile.ResultSuccess, wantResult: sreconcile.ResultSuccess,
wantErr: false, wantErr: false,
assertConditions: []metav1.Condition{
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "reconciliation in progress"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "reconciliation in progress"),
},
}, },
{ {
name: "successful reconciliation with generation difference", name: "successful reconciliation with generation difference",
@ -1736,7 +1851,8 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
wantResult: sreconcile.ResultSuccess, wantResult: sreconcile.ResultSuccess,
wantErr: false, wantErr: false,
assertConditions: []metav1.Condition{ assertConditions: []metav1.Condition{
*conditions.TrueCondition(meta.ReconcilingCondition, "NewGeneration", "reconciling new object generation (3)"), *conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "processing object: new generation 2 -> 3"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "processing object: new generation 2 -> 3"),
}, },
}, },
{ {
@ -1746,15 +1862,19 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
}, },
wantResult: sreconcile.ResultEmpty, wantResult: sreconcile.ResultEmpty,
wantErr: true, wantErr: true,
assertConditions: []metav1.Condition{
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "reconciliation in progress"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "reconciliation in progress"),
},
}, },
{ {
name: "multiple object status conditions mutations", name: "multiple object status conditions mutations",
reconcileFuncs: []helmChartReconcileFunc{ reconcileFuncs: []helmChartReconcileFunc{
func(_ context.Context, obj *sourcev1.HelmChart, _ *chart.Build) (sreconcile.Result, error) { func(_ context.Context, _ *patch.SerialPatcher, obj *sourcev1.HelmChart, _ *chart.Build) (sreconcile.Result, error) {
conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "NewRevision", "new index revision") conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "NewRevision", "new index revision")
return sreconcile.ResultSuccess, nil return sreconcile.ResultSuccess, nil
}, },
func(_ context.Context, obj *sourcev1.HelmChart, _ *chart.Build) (sreconcile.Result, error) { func(_ context.Context, _ *patch.SerialPatcher, obj *sourcev1.HelmChart, _ *chart.Build) (sreconcile.Result, error) {
conditions.MarkTrue(obj, meta.ReconcilingCondition, "Progressing", "creating artifact") conditions.MarkTrue(obj, meta.ReconcilingCondition, "Progressing", "creating artifact")
return sreconcile.ResultSuccess, nil return sreconcile.ResultSuccess, nil
}, },
@ -1763,7 +1883,8 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
wantErr: false, wantErr: false,
assertConditions: []metav1.Condition{ assertConditions: []metav1.Condition{
*conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewRevision", "new index revision"), *conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewRevision", "new index revision"),
*conditions.TrueCondition(meta.ReconcilingCondition, "Progressing", "creating artifact"), *conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "creating artifact"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "reconciliation in progress"),
}, },
}, },
{ {
@ -1775,6 +1896,10 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
}, },
wantResult: sreconcile.ResultRequeue, wantResult: sreconcile.ResultRequeue,
wantErr: false, wantErr: false,
assertConditions: []metav1.Condition{
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "reconciliation in progress"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "reconciliation in progress"),
},
}, },
{ {
name: "subrecs with error before result=Requeue", name: "subrecs with error before result=Requeue",
@ -1785,6 +1910,10 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
}, },
wantResult: sreconcile.ResultEmpty, wantResult: sreconcile.ResultEmpty,
wantErr: true, wantErr: true,
assertConditions: []metav1.Condition{
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "reconciliation in progress"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "reconciliation in progress"),
},
}, },
} }
@ -1792,7 +1921,10 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t) g := NewWithT(t)
r := &HelmChartReconciler{} r := &HelmChartReconciler{
Client: fakeclient.NewClientBuilder().WithScheme(testEnv.GetScheme()).Build(),
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
}
obj := &sourcev1.HelmChart{ obj := &sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
GenerateName: "test-", GenerateName: "test-",
@ -1803,7 +1935,14 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
}, },
} }
got, err := r.reconcile(context.TODO(), obj, tt.reconcileFuncs) g.Expect(r.Client.Create(context.TODO(), obj)).ToNot(HaveOccurred())
defer func() {
g.Expect(r.Client.Delete(context.TODO(), obj)).ToNot(HaveOccurred())
}()
sp := patch.NewSerialPatcher(obj, r.Client)
got, err := r.reconcile(context.TODO(), sp, obj, tt.reconcileFuncs)
g.Expect(err != nil).To(Equal(tt.wantErr)) g.Expect(err != nil).To(Equal(tt.wantErr))
g.Expect(got).To(Equal(tt.wantResult)) g.Expect(got).To(Equal(tt.wantResult))
@ -1898,8 +2037,7 @@ func TestHelmChartReconciler_statusConditions(t *testing.T) {
clientBuilder.WithObjects(obj) clientBuilder.WithObjects(obj)
c := clientBuilder.Build() c := clientBuilder.Build()
patchHelper, err := patch.NewHelper(obj, c) serialPatcher := patch.NewSerialPatcher(obj, c)
g.Expect(err).ToNot(HaveOccurred())
if tt.beforeFunc != nil { if tt.beforeFunc != nil {
tt.beforeFunc(obj) tt.beforeFunc(obj)
@ -1909,9 +2047,10 @@ func TestHelmChartReconciler_statusConditions(t *testing.T) {
recResult := sreconcile.ResultSuccess recResult := sreconcile.ResultSuccess
var retErr error var retErr error
summarizeHelper := summarize.NewHelper(record.NewFakeRecorder(32), patchHelper) summarizeHelper := summarize.NewHelper(record.NewFakeRecorder(32), serialPatcher)
summarizeOpts := []summarize.Option{ summarizeOpts := []summarize.Option{
summarize.WithConditions(helmChartReadyCondition), summarize.WithConditions(helmChartReadyCondition),
summarize.WithBiPolarityConditionTypes(sourcev1.SourceVerifiedCondition),
summarize.WithReconcileResult(recResult), summarize.WithReconcileResult(recResult),
summarize.WithReconcileError(retErr), summarize.WithReconcileError(retErr),
summarize.WithIgnoreNotFound(), summarize.WithIgnoreNotFound(),
@ -2012,6 +2151,7 @@ func TestHelmChartReconciler_notify(t *testing.T) {
reconciler := &HelmChartReconciler{ reconciler := &HelmChartReconciler{
EventRecorder: recorder, EventRecorder: recorder,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
build := &chart.Build{ build := &chart.Build{
Name: "foo", Name: "foo",
@ -2061,7 +2201,8 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_authStrategy(t *testing.T) {
name: "HTTP without basic auth", name: "HTTP without basic auth",
want: sreconcile.ResultSuccess, want: sreconcile.ResultSuccess,
assertConditions: []metav1.Condition{ assertConditions: []metav1.Condition{
*conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewChart", "pulled '<helmchart>' chart with version '<version>'"), *conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: pulled 'helmchart' chart with version '0.1.0'"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: pulled 'helmchart' chart with version '0.1.0'"),
}, },
}, },
{ {
@ -2075,7 +2216,8 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_authStrategy(t *testing.T) {
password: testRegistryPassword, password: testRegistryPassword,
}, },
assertConditions: []metav1.Condition{ assertConditions: []metav1.Condition{
*conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewChart", "pulled '<helmchart>' chart with version '<version>'"), *conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: pulled 'helmchart' chart with version '0.1.0'"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: pulled 'helmchart' chart with version '0.1.0'"),
}, },
}, },
{ {
@ -2114,7 +2256,8 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_authStrategy(t *testing.T) {
}, },
provider: "azure", provider: "azure",
assertConditions: []metav1.Condition{ assertConditions: []metav1.Condition{
*conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewChart", "pulled '<helmchart>' chart with version '<version>'"), *conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: pulled 'helmchart' chart with version '0.1.0'"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: pulled 'helmchart' chart with version '0.1.0'"),
}, },
}, },
} }
@ -2200,6 +2343,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_authStrategy(t *testing.T) {
EventRecorder: record.NewFakeRecorder(32), EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters, Getters: testGetters,
RegistryClientGenerator: registry.ClientGenerator, RegistryClientGenerator: registry.ClientGenerator,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
var b chart.Build var b chart.Build
@ -2216,7 +2360,14 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_authStrategy(t *testing.T) {
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<version>", metadata.Version) assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<version>", metadata.Version)
} }
got, err := r.reconcileSource(ctx, obj, &b) g.Expect(r.Client.Create(context.TODO(), obj)).ToNot(HaveOccurred())
defer func() {
g.Expect(r.Client.Delete(context.TODO(), obj)).ToNot(HaveOccurred())
}()
sp := patch.NewSerialPatcher(obj, r.Client)
got, err := r.reconcileSource(ctx, sp, obj, &b)
g.Expect(err != nil).To(Equal(tt.wantErr)) g.Expect(err != nil).To(Equal(tt.wantErr))
g.Expect(got).To(Equal(tt.want)) g.Expect(got).To(Equal(tt.want))
g.Expect(obj.Status.Conditions).To(conditions.MatchConditions(tt.assertConditions)) g.Expect(obj.Status.Conditions).To(conditions.MatchConditions(tt.assertConditions))
@ -2323,8 +2474,9 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignature(t *testing.T
}, },
want: sreconcile.ResultSuccess, want: sreconcile.ResultSuccess,
assertConditions: []metav1.Condition{ assertConditions: []metav1.Condition{
*conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewChart", "pulled '<name>' chart with version '<version>'"),
*conditions.TrueCondition(sourcev1.SourceVerifiedCondition, meta.SucceededReason, "verified signature of version <version>"), *conditions.TrueCondition(sourcev1.SourceVerifiedCondition, meta.SucceededReason, "verified signature of version <version>"),
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: pulled '<name>' chart with version '<version>'"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: pulled '<name>' chart with version '<version>'"),
}, },
cleanFunc: func(g *WithT, build *chart.Build) { cleanFunc: func(g *WithT, build *chart.Build) {
g.Expect(os.Remove(build.Path)).To(Succeed()) g.Expect(os.Remove(build.Path)).To(Succeed())
@ -2342,6 +2494,8 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignature(t *testing.T
want: sreconcile.ResultSuccess, want: sreconcile.ResultSuccess,
assertConditions: []metav1.Condition{ assertConditions: []metav1.Condition{
*conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewChart", "pulled '<name>' chart with version '<version>'"), *conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewChart", "pulled '<name>' chart with version '<version>'"),
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: pulled '<name>' chart with version '<version>'"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: pulled '<name>' chart with version '<version>'"),
}, },
cleanFunc: func(g *WithT, build *chart.Build) { cleanFunc: func(g *WithT, build *chart.Build) {
g.Expect(os.Remove(build.Path)).To(Succeed()) g.Expect(os.Remove(build.Path)).To(Succeed())
@ -2383,6 +2537,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignature(t *testing.T
Getters: testGetters, Getters: testGetters,
Storage: storage, Storage: storage,
RegistryClientGenerator: registry.ClientGenerator, RegistryClientGenerator: registry.ClientGenerator,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
} }
obj := &sourcev1.HelmChart{ obj := &sourcev1.HelmChart{
@ -2434,7 +2589,14 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignature(t *testing.T
defer tt.cleanFunc(g, &b) defer tt.cleanFunc(g, &b)
} }
got, err := r.reconcileSource(ctx, obj, &b) g.Expect(r.Client.Create(context.TODO(), obj)).ToNot(HaveOccurred())
defer func() {
g.Expect(r.Client.Delete(context.TODO(), obj)).ToNot(HaveOccurred())
}()
sp := patch.NewSerialPatcher(obj, r.Client)
got, err := r.reconcileSource(ctx, sp, obj, &b)
if tt.wantErr { if tt.wantErr {
tt.wantErrMsg = strings.ReplaceAll(tt.wantErrMsg, "<url>", chartUrl) tt.wantErrMsg = strings.ReplaceAll(tt.wantErrMsg, "<url>", chartUrl)
g.Expect(err).ToNot(BeNil()) g.Expect(err).ToNot(BeNil())