@@ -19,19 +19,13 @@ package controllers
1919import (
2020 "bytes"
2121 "context"
22- "crypto/sha1"
23- "crypto/sha256"
2422 "fmt"
25- "io"
26- "net/http"
27- "net/url"
2823 "os"
2924 "sort"
3025 "strings"
3126 "time"
3227
3328 securejoin "github.com/cyphar/filepath-securejoin"
34- "github.com/hashicorp/go-retryablehttp"
3529 corev1 "k8s.io/api/core/v1"
3630 apierrors "k8s.io/apimachinery/pkg/api/errors"
3731 apimeta "k8s.io/apimachinery/pkg/api/meta"
@@ -62,7 +56,6 @@ import (
6256 "github.com/fluxcd/pkg/runtime/metrics"
6357 "github.com/fluxcd/pkg/runtime/predicates"
6458 "github.com/fluxcd/pkg/ssa"
65- "github.com/fluxcd/pkg/untar"
6659 sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
6760
6861 kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
@@ -79,7 +72,7 @@ import (
7972// KustomizationReconciler reconciles a Kustomization object
8073type KustomizationReconciler struct {
8174 client.Client
82- httpClient * retryablehttp. Client
75+ artifactDownloader * ArtifactDownloader
8376 requeueDependency time.Duration
8477 Scheme * runtime.Scheme
8578 EventRecorder kuberecorder.EventRecorder
@@ -122,15 +115,7 @@ func (r *KustomizationReconciler) SetupWithManager(mgr ctrl.Manager, opts Kustom
122115
123116 r .requeueDependency = opts .DependencyRequeueInterval
124117 r .statusManager = fmt .Sprintf ("gotk-%s" , r .ControllerName )
125-
126- // Configure the retryable http client used for fetching artifacts.
127- // By default it retries 10 times within a 3.5 minutes window.
128- httpClient := retryablehttp .NewClient ()
129- httpClient .RetryWaitMin = 5 * time .Second
130- httpClient .RetryWaitMax = 30 * time .Second
131- httpClient .RetryMax = opts .HTTPRetry
132- httpClient .Logger = nil
133- r .httpClient = httpClient
118+ r .artifactDownloader = NewArtifactDownloader (opts .HTTPRetry )
134119
135120 return ctrl .NewControllerManagedBy (mgr ).
136121 For (& kustomizev1.Kustomization {}, builder .WithPredicates (
@@ -268,6 +253,18 @@ func (r *KustomizationReconciler) Reconcile(ctx context.Context, req ctrl.Reques
268253
269254 // reconcile kustomization by applying the latest revision
270255 reconciledKustomization , reconcileErr := r .reconcile (ctx , * kustomization .DeepCopy (), source )
256+
257+ // requeue if the artifact is not found
258+ if reconcileErr == ArtifactNotFoundError {
259+ msg := fmt .Sprintf ("Source is not ready, artifact not found, retrying in %s" , r .requeueDependency .String ())
260+ log .Info (msg )
261+ if err := r .patchStatus (ctx , req , kustomizev1 .KustomizationProgressing (kustomization , msg ).Status ); err != nil {
262+ log .Error (err , "unable to update status for artifact not found" )
263+ return ctrl.Result {Requeue : true }, err
264+ }
265+ return ctrl.Result {RequeueAfter : r .requeueDependency }, nil
266+ }
267+
271268 if err := r .patchStatus (ctx , req , reconciledKustomization .Status ); err != nil {
272269 return ctrl.Result {Requeue : true }, err
273270 }
@@ -320,7 +317,7 @@ func (r *KustomizationReconciler) reconcile(
320317 defer os .RemoveAll (tmpDir )
321318
322319 // download artifact and extract files
323- err = r .download (source .GetArtifact (), tmpDir )
320+ err = r .artifactDownloader . Fetch (source .GetArtifact (), tmpDir )
324321 if err != nil {
325322 return kustomizev1 .KustomizationNotReady (
326323 kustomization ,
@@ -526,70 +523,6 @@ func (r *KustomizationReconciler) checkDependencies(source sourcev1.Source, kust
526523 return nil
527524}
528525
529- func (r * KustomizationReconciler ) download (artifact * sourcev1.Artifact , tmpDir string ) error {
530- artifactURL := artifact .URL
531- if hostname := os .Getenv ("SOURCE_CONTROLLER_LOCALHOST" ); hostname != "" {
532- u , err := url .Parse (artifactURL )
533- if err != nil {
534- return err
535- }
536- u .Host = hostname
537- artifactURL = u .String ()
538- }
539-
540- req , err := retryablehttp .NewRequest (http .MethodGet , artifactURL , nil )
541- if err != nil {
542- return fmt .Errorf ("failed to create a new request: %w" , err )
543- }
544-
545- resp , err := r .httpClient .Do (req )
546- if err != nil {
547- return fmt .Errorf ("failed to download artifact, error: %w" , err )
548- }
549- defer resp .Body .Close ()
550-
551- // check response
552- if resp .StatusCode != http .StatusOK {
553- return fmt .Errorf ("failed to download artifact from %s, status: %s" , artifactURL , resp .Status )
554- }
555-
556- var buf bytes.Buffer
557-
558- // verify checksum matches origin
559- if err := r .verifyArtifact (artifact , & buf , resp .Body ); err != nil {
560- return err
561- }
562-
563- // extract
564- if _ , err = untar .Untar (& buf , tmpDir ); err != nil {
565- return fmt .Errorf ("failed to untar artifact, error: %w" , err )
566- }
567-
568- return nil
569- }
570-
571- func (r * KustomizationReconciler ) verifyArtifact (artifact * sourcev1.Artifact , buf * bytes.Buffer , reader io.Reader ) error {
572- hasher := sha256 .New ()
573-
574- // for backwards compatibility with source-controller v0.17.2 and older
575- if len (artifact .Checksum ) == 40 {
576- hasher = sha1 .New ()
577- }
578-
579- // compute checksum
580- mw := io .MultiWriter (hasher , buf )
581- if _ , err := io .Copy (mw , reader ); err != nil {
582- return err
583- }
584-
585- if checksum := fmt .Sprintf ("%x" , hasher .Sum (nil )); checksum != artifact .Checksum {
586- return fmt .Errorf ("failed to verify artifact: computed checksum '%s' doesn't match advertised '%s'" ,
587- checksum , artifact .Checksum )
588- }
589-
590- return nil
591- }
592-
593526func (r * KustomizationReconciler ) getSource (ctx context.Context , kustomization kustomizev1.Kustomization ) (sourcev1.Source , error ) {
594527 var source sourcev1.Source
595528 sourceNamespace := kustomization .GetNamespace ()
0 commit comments