From 87438e2b6ea0d9e88fa5838412400d824ae981c1 Mon Sep 17 00:00:00 2001 From: Sunny Date: Tue, 26 Jul 2022 16:18:25 +0530 Subject: [PATCH] imagerepo: Continue scan for unconfigured provider When a given image reference is identified as a known provider but is unconfigured, continue the reconciliation and scan to be able to scan public repositories. Abort the reconciliation for any other error during login. Also add a test for scanning public repos without rate limits. Signed-off-by: Sunny --- controllers/imagerepository_controller.go | 20 ++++++++---- controllers/scan_test.go | 40 +++++++++++++++++++++++ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/controllers/imagerepository_controller.go b/controllers/imagerepository_controller.go index 7822239e..483d0638 100644 --- a/controllers/imagerepository_controller.go +++ b/controllers/imagerepository_controller.go @@ -53,6 +53,7 @@ import ( "github.com/fluxcd/pkg/runtime/predicates" imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1" + "github.com/fluxcd/image-reflector-controller/internal/registry" "github.com/fluxcd/image-reflector-controller/internal/registry/login" ) @@ -257,13 +258,18 @@ func (r *ImageRepositoryReconciler) scan(ctx context.Context, imageRepo *imagev1 auth, authErr = login.NewManager().Login(ctx, imageRepo.Spec.Image, ref, r.ProviderOptions) } if authErr != nil { - imagev1.SetImageRepositoryReadiness( - imageRepo, - metav1.ConditionFalse, - imagev1.ReconciliationFailedReason, - authErr.Error(), - ) - return authErr + // If it's not unconfigured provider error, abort reconciliation. + // Continue reconciliation if it's unconfigured providers for scanning + // public repositories. + if !errors.Is(authErr, registry.ErrUnconfiguredProvider) { + imagev1.SetImageRepositoryReadiness( + imageRepo, + metav1.ConditionFalse, + imagev1.ReconciliationFailedReason, + authErr.Error(), + ) + return authErr + } } if auth != nil { options = append(options, remote.WithAuth(auth)) diff --git a/controllers/scan_test.go b/controllers/scan_test.go index 46e16ae7..23f91418 100644 --- a/controllers/scan_test.go +++ b/controllers/scan_test.go @@ -21,6 +21,7 @@ import ( "fmt" "strings" "testing" + "time" "github.com/fluxcd/pkg/apis/meta" "github.com/google/go-containerregistry/pkg/authn" @@ -492,3 +493,42 @@ func TestImageRepositoryReconciler_authRegistryWithServiceAccount(t *testing.T) // Cleanup. g.Expect(testEnv.Delete(ctx, &repo)).To(Succeed()) } + +func TestImageRepositoryReconciler_ScanPublicRepos(t *testing.T) { + tests := []struct { + name string + image string + }{ + {"gcr", "k8s.gcr.io/coredns/coredns"}, + {"ghcr", "ghcr.io/stefanprodan/podinfo"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewWithT(t) + repo := imagev1.ImageRepository{ + Spec: imagev1.ImageRepositorySpec{ + Interval: metav1.Duration{Duration: time.Hour}, + Image: tt.image, + }, + } + objectName := types.NamespacedName{ + Name: "public-repo" + randStringRunes(5), + Namespace: "default", + } + repo.Name = objectName.Name + repo.Namespace = objectName.Namespace + + ctx, cancel := context.WithTimeout(context.TODO(), contextTimeout) + defer cancel() + g.Expect(testEnv.Create(ctx, &repo)).To(Succeed()) + + g.Eventually(func() bool { + err := testEnv.Get(ctx, objectName, &repo) + return err == nil && repo.Status.LastScanResult != nil + }, timeout, interval).Should(BeTrue()) + g.Expect(repo.Status.LastScanResult.TagCount).ToNot(BeZero()) + g.Expect(testEnv.Delete(ctx, &repo)).To(Succeed()) + }) + } +}