11package release
22
33import (
4- "archive/tar"
54 "bytes"
65 "context"
76 "encoding/json"
87 "fmt"
98 "io"
109 "os"
11- "path"
1210 "path/filepath"
1311 "sync"
1412 "time"
@@ -20,11 +18,13 @@ import (
2018
2119 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2220 "k8s.io/apimachinery/pkg/runtime/schema"
21+ "k8s.io/apimachinery/pkg/util/sets"
2322 "k8s.io/cli-runtime/pkg/genericiooptions"
2423 "k8s.io/client-go/rest"
2524 kcmdutil "k8s.io/kubectl/pkg/cmd/util"
2625 "k8s.io/kubectl/pkg/util/templates"
2726
27+ configv1 "github.com/openshift/api/config/v1"
2828 imagev1 "github.com/openshift/api/image/v1"
2929 "github.com/openshift/library-go/pkg/image/dockerv1client"
3030 "github.com/openshift/library-go/pkg/manifest"
@@ -349,17 +349,16 @@ func (o *ExtractOptions) Run(ctx context.Context) error {
349349 }
350350 }
351351
352- tarEntryCallbacks := []extract. TarEntryFunc {}
352+ var manifestsCallbacks []func ( string , []manifest. Manifest , io. Reader , []configv1. ClusterVersionCapability ) ( bool , error )
353353
354- var manifestErrs []error
354+ var waitAll bool
355+ inclusionConfig := manifestInclusionConfiguration {}
355356 if o .ExtractManifests {
356357 expectedProviderSpecKind := credRequestCloudProviderSpecKindMapping [o .Cloud ]
357-
358- include := func (m * manifest.Manifest ) error { return nil } // default to including everything
359358 if o .Included {
360359 context := "connected cluster"
361- inclusionConfig := manifestInclusionConfiguration {}
362360 if o .InstallConfig == "" {
361+ waitAll = true
363362 inclusionConfig , err = findClusterIncludeConfig (ctx , o .RESTConfig )
364363 } else {
365364 inclusionConfig , err = findClusterIncludeConfigFromInstallConfig (ctx , o .InstallConfig )
@@ -377,11 +376,10 @@ func (o *ExtractOptions) Run(ctx context.Context) error {
377376 return fmt .Errorf ("unrecognized platform for CredentialsRequests: %q" , * inclusionConfig .Platform )
378377 }
379378 }
380- include = newIncluder (inclusionConfig )
381379 }
382380
383- tarEntryCallbacks = append (tarEntryCallbacks , func (hdr * tar. Header , _ extract. LayerInfo , r io.Reader ) (bool , error ) {
384- if hdr . Name == "image-references" && ! o .CredentialsRequests {
381+ manifestsCallbacks = append (manifestsCallbacks , func (name string , ms []manifest. Manifest , r io.Reader , enabled []configv1. ClusterVersionCapability ) (cont bool , err error ) {
382+ if name == "image-references" && ! o .CredentialsRequests {
385383 buf := & bytes.Buffer {}
386384 if _ , err := io .Copy (buf , r ); err != nil {
387385 return false , fmt .Errorf ("unable to load image-references from release payload: %w" , err )
@@ -399,7 +397,7 @@ func (o *ExtractOptions) Run(ctx context.Context) error {
399397
400398 out := o .Out
401399 if o .Directory != "" {
402- out , err = os .Create (filepath .Join (o .Directory , hdr . Name ))
400+ out , err = os .Create (filepath .Join (o .Directory , name ))
403401 if err != nil {
404402 return false , err
405403 }
@@ -409,10 +407,10 @@ func (o *ExtractOptions) Run(ctx context.Context) error {
409407 return true , err
410408 }
411409 return true , nil
412- } else if hdr . Name == "release-metadata" && ! o .CredentialsRequests {
410+ } else if name == "release-metadata" && ! o .CredentialsRequests {
413411 out := o .Out
414412 if o .Directory != "" {
415- out , err = os .Create (filepath .Join (o .Directory , hdr . Name ))
413+ out , err = os .Create (filepath .Join (o .Directory , name ))
416414 if err != nil {
417415 return false , err
418416 }
@@ -424,22 +422,18 @@ func (o *ExtractOptions) Run(ctx context.Context) error {
424422 return true , nil
425423 }
426424
427- if ext := path .Ext (hdr .Name ); len (ext ) == 0 || ! (ext == ".yaml" || ext == ".yml" || ext == ".json" ) {
428- return true , nil
429- }
430- klog .V (4 ).Infof ("Found manifest %s" , hdr .Name )
431- ms , err := manifest .ParseManifests (r )
432- if err != nil {
433- manifestErrs = append (manifestErrs , errors .Wrapf (err , "error parsing %s" , hdr .Name ))
434- return true , nil
435- }
436-
437425 for i := len (ms ) - 1 ; i >= 0 ; i -- {
438426 if o .Included && o .CredentialsRequests && ms [i ].GVK == credentialsRequestGVK && len (ms [i ].Obj .GetAnnotations ()) == 0 {
439427 klog .V (4 ).Infof ("Including %s for manual CredentialsRequests, despite lack of annotations" , ms [i ].String ())
440- } else if err := include (& ms [i ]); err != nil {
441- klog .V (4 ).Infof ("Excluding %s: %s" , ms [i ].String (), err )
442- ms = append (ms [:i ], ms [i + 1 :]... )
428+ } else if o .Included {
429+ clusterVersionCapabilitiesStatus := & configv1.ClusterVersionCapabilitiesStatus {
430+ KnownCapabilities : append (inclusionConfig .Capabilities .KnownCapabilities , configv1 .KnownClusterVersionCapabilities ... ),
431+ EnabledCapabilities : append (inclusionConfig .Capabilities .EnabledCapabilities , enabled ... ),
432+ }
433+ if err := ms [i ].Include (inclusionConfig .ExcludeIdentifier , inclusionConfig .RequiredFeatureSet , inclusionConfig .Profile , clusterVersionCapabilitiesStatus , inclusionConfig .Overrides ); err != nil {
434+ klog .V (4 ).Infof ("Excluding %s: %s" , ms [i ].String (), err )
435+ ms = append (ms [:i ], ms [i + 1 :]... )
436+ }
443437 }
444438 }
445439
@@ -470,20 +464,20 @@ func (o *ExtractOptions) Run(ctx context.Context) error {
470464
471465 out := o .Out
472466 if o .Directory != "" {
473- out , err = os .Create (filepath .Join (o .Directory , hdr . Name ))
467+ out , err = os .Create (filepath .Join (o .Directory , name ))
474468 if err != nil {
475- return false , errors .Wrapf (err , "error creating manifest in %s" , hdr . Name )
469+ return false , errors .Wrapf (err , "error creating manifest in %s" , name )
476470 }
477471 }
478472 if out != nil {
479473 for _ , m := range manifestsToWrite {
480474 yamlBytes , err := yaml .JSONToYAML (m .Raw )
481475 if err != nil {
482- return false , errors .Wrapf (err , "error serializing manifest in %s" , hdr . Name )
476+ return false , errors .Wrapf (err , "error serializing manifest in %s" , name )
483477 }
484478 fmt .Fprintf (out , "---\n " )
485479 if _ , err := out .Write (yamlBytes ); err != nil {
486- return false , errors .Wrapf (err , "error writing manifest in %s" , hdr . Name )
480+ return false , errors .Wrapf (err , "error writing manifest in %s" , name )
487481 }
488482 }
489483 }
@@ -493,24 +487,23 @@ func (o *ExtractOptions) Run(ctx context.Context) error {
493487
494488 fileFound := false
495489 if o .File != "" {
496- tarEntryCallbacks = append (tarEntryCallbacks , func (hdr * tar. Header , _ extract. LayerInfo , r io.Reader ) (bool , error ) {
497- if hdr . Name != o .File {
490+ manifestsCallbacks = append (manifestsCallbacks , func (name string , _ []manifest. Manifest , r io.Reader , _ []configv1. ClusterVersionCapability ) (bool , error ) {
491+ if name != o .File {
498492 return true , nil
499493 }
500494 fileFound = true
501495 _ , err := io .Copy (o .Out , r )
502496 return false , err
503497 })
504498 }
505-
506- if len (tarEntryCallbacks ) > 0 {
507- tarEntryCallbacksDone := make ([]bool , len (tarEntryCallbacks ))
508- opts .TarEntryCallback = func (hdr * tar.Header , layer extract.LayerInfo , r io.Reader ) (bool , error ) {
509- for i , callback := range tarEntryCallbacks {
499+ manifestsCallback := func (name string , ms []manifest.Manifest , r io.Reader , enabled []configv1.ClusterVersionCapability ) (bool , error ) {
500+ if len (manifestsCallbacks ) > 0 {
501+ tarEntryCallbacksDone := make ([]bool , len (manifestsCallbacks ))
502+ for i , callback := range manifestsCallbacks {
510503 if tarEntryCallbacksDone [i ] {
511504 continue
512505 }
513- if cont , err := callback (hdr , layer , r ); err != nil {
506+ if cont , err := callback (name , ms , r , enabled ); err != nil {
514507 return cont , err
515508 } else if ! cont {
516509 tarEntryCallbacksDone [i ] = true
@@ -525,8 +518,13 @@ func (o *ExtractOptions) Run(ctx context.Context) error {
525518
526519 return false , nil
527520 }
521+ return true , nil
528522 }
529523
524+ manifestReceiver := NewManifestReceiver (manifestsCallback , waitAll , sets .New [string ]("image-references" , "release-metadata" ), inclusionConfig )
525+ opts .TarEntryCallback = manifestReceiver .TarEntryCallback
526+ opts .TarEntryCallbackDoneCallback = manifestReceiver .TarEntryCallbackDoneCallback
527+
530528 if err := opts .Run (); err != nil {
531529 return err
532530 }
@@ -553,8 +551,8 @@ func (o *ExtractOptions) Run(ctx context.Context) error {
553551
554552 // Only output manifest errors if manifests were being extracted.
555553 // Do not return an error so current operation, e.g. mirroring, continues.
556- if o .ExtractManifests && len (manifestErrs ) > 0 {
557- fmt .Fprintf (o .ErrOut , "Errors: %s\n " , errorList (manifestErrs ))
554+ if o .ExtractManifests && len (manifestReceiver . ManifestErrs ) > 0 {
555+ fmt .Fprintf (o .ErrOut , "Errors: %s\n " , errorList (manifestReceiver . ManifestErrs ))
558556 }
559557
560558 return nil
0 commit comments