Skip to content

Commit ad75be6

Browse files
committed
OTA-1010: extract included manifests with net-new capabilities
1 parent e3b2070 commit ad75be6

File tree

3 files changed

+211
-57
lines changed

3 files changed

+211
-57
lines changed

pkg/cli/admin/release/extract.go

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
package release
22

33
import (
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

Comments
 (0)