Skip to content

Commit 0bf9de3

Browse files
authored
Merge pull request #832 from souleb/issue-830
Fix Panic when no artifact in source
2 parents 6868ff1 + f3ab2e0 commit 0bf9de3

File tree

2 files changed

+152
-1
lines changed

2 files changed

+152
-1
lines changed

controllers/helmchart_controller.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,8 @@ func (r *HelmChartReconciler) reconcileSource(ctx context.Context, obj *sourcev1
392392

393393
// Assert source has an artifact
394394
if s.GetArtifact() == nil || !r.Storage.ArtifactExist(*s.GetArtifact()) {
395-
if helmRepo, ok := s.(*sourcev1.HelmRepository); !ok || !helmreg.IsOCI(helmRepo.Spec.URL) {
395+
// Set the condition to indicate that the source has no artifact for all types except OCI HelmRepository
396+
if helmRepo, ok := s.(*sourcev1.HelmRepository); !ok || helmRepo.Spec.Type != sourcev1.HelmRepositoryTypeOCI {
396397
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, "NoSourceArtifact",
397398
"no artifact available for %s source '%s'", obj.Spec.SourceRef.Kind, obj.Spec.SourceRef.Name)
398399
r.eventLogf(ctx, obj, events.EventTypeTrace, "NoSourceArtifact",

controllers/helmchart_controller_test.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,156 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
515515
}
516516
}
517517

518+
func TestHelmChartReconciler_reconcileFromHelmRepository(t *testing.T) {
519+
g := NewWithT(t)
520+
521+
const (
522+
chartName = "helmchart"
523+
chartVersion = "0.2.0"
524+
higherChartVersion = "0.3.0"
525+
chartPath = "testdata/charts/helmchart"
526+
)
527+
528+
serverFactory, err := helmtestserver.NewTempHelmServer()
529+
g.Expect(err).NotTo(HaveOccurred())
530+
defer os.RemoveAll(serverFactory.Root())
531+
532+
for _, ver := range []string{chartVersion, higherChartVersion} {
533+
g.Expect(serverFactory.PackageChartWithVersion(chartPath, ver)).To(Succeed())
534+
}
535+
g.Expect(serverFactory.GenerateIndex()).To(Succeed())
536+
537+
tests := []struct {
538+
name string
539+
beforeFunc func(repository *sourcev1.HelmRepository)
540+
assertFunc func(g *WithT, obj *sourcev1.HelmChart)
541+
}{
542+
{
543+
name: "Reconciles chart build",
544+
assertFunc: func(g *WithT, obj *sourcev1.HelmChart) {
545+
key := client.ObjectKey{Name: obj.Name, Namespace: obj.Namespace}
546+
// Wait for HelmChart to be Ready
547+
g.Eventually(func() bool {
548+
if err := testEnv.Get(ctx, key, obj); err != nil {
549+
return false
550+
}
551+
if !conditions.IsReady(obj) || obj.Status.Artifact == nil {
552+
return false
553+
}
554+
readyCondition := conditions.Get(obj, meta.ReadyCondition)
555+
return obj.Generation == readyCondition.ObservedGeneration &&
556+
obj.Generation == obj.Status.ObservedGeneration
557+
}, timeout).Should(BeTrue())
558+
559+
// Check if the object status is valid.
560+
condns := &status.Conditions{NegativePolarity: helmChartReadyCondition.NegativePolarity}
561+
checker := status.NewChecker(testEnv.Client, condns)
562+
checker.CheckErr(ctx, obj)
563+
},
564+
},
565+
{
566+
name: "Stalling on invalid repository URL",
567+
beforeFunc: func(repository *sourcev1.HelmRepository) {
568+
repository.Spec.URL = "://unsupported" // Invalid URL
569+
},
570+
assertFunc: func(g *WithT, obj *sourcev1.HelmChart) {
571+
key := client.ObjectKey{Name: obj.Name, Namespace: obj.Namespace}
572+
// Wait for HelmChart to be FetchFailed == true
573+
g.Eventually(func() bool {
574+
if err := testEnv.Get(ctx, key, obj); err != nil {
575+
return false
576+
}
577+
if !conditions.IsTrue(obj, sourcev1.FetchFailedCondition) {
578+
return false
579+
}
580+
// observedGeneration is -1 because we have no successful reconciliation
581+
return obj.Status.ObservedGeneration == -1
582+
}, timeout).Should(BeTrue())
583+
584+
// Check if the object status is valid.
585+
condns := &status.Conditions{NegativePolarity: helmChartReadyCondition.NegativePolarity}
586+
checker := status.NewChecker(testEnv.Client, condns)
587+
checker.CheckErr(ctx, obj)
588+
},
589+
},
590+
{
591+
name: "Stalling on invalid oci repository URL",
592+
beforeFunc: func(repository *sourcev1.HelmRepository) {
593+
repository.Spec.URL = strings.Replace(repository.Spec.URL, "http", "oci", 1)
594+
},
595+
assertFunc: func(g *WithT, obj *sourcev1.HelmChart) {
596+
key := client.ObjectKey{Name: obj.Name, Namespace: obj.Namespace}
597+
// Wait for HelmChart to be Ready
598+
g.Eventually(func() bool {
599+
if err := testEnv.Get(ctx, key, obj); err != nil {
600+
return false
601+
}
602+
if !conditions.IsTrue(obj, sourcev1.FetchFailedCondition) {
603+
return false
604+
}
605+
// observedGeneration is -1 because we have no successful reconciliation
606+
return obj.Status.ObservedGeneration == -1
607+
}, timeout).Should(BeTrue())
608+
609+
// Check if the object status is valid.
610+
condns := &status.Conditions{NegativePolarity: helmChartReadyCondition.NegativePolarity}
611+
checker := status.NewChecker(testEnv.Client, condns)
612+
checker.CheckErr(ctx, obj)
613+
},
614+
},
615+
}
616+
617+
for _, tt := range tests {
618+
t.Run(tt.name, func(t *testing.T) {
619+
g := NewWithT(t)
620+
621+
server := testserver.NewHTTPServer(serverFactory.Root())
622+
server.Start()
623+
defer server.Stop()
624+
625+
ns, err := testEnv.CreateNamespace(ctx, "helmchart")
626+
g.Expect(err).ToNot(HaveOccurred())
627+
defer func() { g.Expect(testEnv.Delete(ctx, ns)).To(Succeed()) }()
628+
629+
repository := sourcev1.HelmRepository{
630+
ObjectMeta: metav1.ObjectMeta{
631+
GenerateName: "helmrepository-",
632+
Namespace: ns.Name,
633+
},
634+
Spec: sourcev1.HelmRepositorySpec{
635+
URL: server.URL(),
636+
},
637+
}
638+
639+
if tt.beforeFunc != nil {
640+
tt.beforeFunc(&repository)
641+
}
642+
643+
g.Expect(testEnv.CreateAndWait(ctx, &repository)).To(Succeed())
644+
645+
obj := sourcev1.HelmChart{
646+
ObjectMeta: metav1.ObjectMeta{
647+
GenerateName: "helmrepository-reconcile-",
648+
Namespace: ns.Name,
649+
},
650+
Spec: sourcev1.HelmChartSpec{
651+
Chart: chartName,
652+
Version: chartVersion,
653+
SourceRef: sourcev1.LocalHelmChartSourceReference{
654+
Kind: sourcev1.HelmRepositoryKind,
655+
Name: repository.Name,
656+
},
657+
},
658+
}
659+
g.Expect(testEnv.Create(ctx, &obj)).To(Succeed())
660+
661+
if tt.assertFunc != nil {
662+
tt.assertFunc(g, &obj)
663+
}
664+
})
665+
}
666+
}
667+
518668
func TestHelmChartReconciler_buildFromHelmRepository(t *testing.T) {
519669
g := NewWithT(t)
520670

0 commit comments

Comments
 (0)