Skip to content

Commit

Permalink
Switch the bundle validate to use the API
Browse files Browse the repository at this point in the history
This uses the validators directly, but still has the same usage
semantics, for the most part.

Signed-off-by: Brad P. Crochet <brad@redhat.com>
  • Loading branch information
bcrochet authored and acornett21 committed Sep 6, 2022
1 parent 7555dc9 commit 5159bc1
Show file tree
Hide file tree
Showing 25 changed files with 1,610 additions and 277 deletions.
4 changes: 2 additions & 2 deletions certification/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ func initializeChecks(ctx context.Context, p policy.Policy, cfg certification.Co
return []certification.Check{
operatorpol.NewScorecardBasicSpecCheck(operatorsdk.New(cfg.ScorecardImage(), exec.Command), cfg.Namespace(), cfg.ServiceAccount(), cfg.Kubeconfig(), cfg.ScorecardWaitTime()),
operatorpol.NewScorecardOlmSuiteCheck(operatorsdk.New(cfg.ScorecardImage(), exec.Command), cfg.Namespace(), cfg.ServiceAccount(), cfg.Kubeconfig(), cfg.ScorecardWaitTime()),
operatorpol.NewDeployableByOlmCheck(operatorsdk.New(cfg.ScorecardImage(), exec.Command), cfg.IndexImage(), cfg.DockerConfig(), cfg.Channel()),
operatorpol.NewValidateOperatorBundleCheck(operatorsdk.New(cfg.ScorecardImage(), exec.Command)),
operatorpol.NewDeployableByOlmCheck(cfg.IndexImage(), cfg.DockerConfig(), cfg.Channel()),
operatorpol.NewValidateOperatorBundleCheck(),
operatorpol.NewCertifiedImagesCheck(pyxis.NewPyxisClient(
certification.DefaultPyxisHost,
"",
Expand Down
46 changes: 29 additions & 17 deletions certification/internal/bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import (
"path/filepath"
"strings"

"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/operatorsdk"

"github.com/blang/semver"
"github.com/operator-framework/api/pkg/manifests"
"github.com/operator-framework/api/pkg/validation"
olmvalidation "github.com/redhat-openshift-ecosystem/ocp-olm-catalog-validator/pkg/validation"
log "github.com/sirupsen/logrus"
rbacv1 "k8s.io/api/rbac/v1"
"sigs.k8s.io/yaml"
Expand All @@ -29,21 +29,22 @@ var ocpToKubeVersion = map[string]string{

const latestReleasedVersion = "4.11"

type operatorSdk interface {
BundleValidate(context.Context, string, operatorsdk.OperatorSdkBundleValidateOptions) (*operatorsdk.OperatorSdkBundleValidateReport, error)
}
func Validate(ctx context.Context, imagePath string) (*Report, error) {
log.Trace("reading annotations file from the bundle")
log.Debug("image extraction directory is ", imagePath)

func Validate(ctx context.Context, operatorSdk operatorSdk, imagePath string) (*operatorsdk.OperatorSdkBundleValidateReport, error) {
selector := []string{"community", "operatorhub", "alpha-deprecated-apis"}
opts := operatorsdk.OperatorSdkBundleValidateOptions{
Selector: selector,
Verbose: true,
ContainerEngine: "none",
OutputFormat: "json-alpha1",
bundle, err := manifests.GetBundleFromDir(imagePath)
if err != nil {
return nil, fmt.Errorf("could not load bundle from path: %s: %v", imagePath, err)
}
validators := validation.DefaultBundleValidators.WithValidators(
validation.AlphaDeprecatedAPIsValidator,
validation.OperatorHubValidator,
olmvalidation.OpenShiftValidator,
)

objs := bundle.ObjectsToValidate()

log.Trace("reading annotations file from the bundle")
log.Debug("image extraction directory is ", imagePath)
// retrieve the operator metadata from bundle image
annotationsFileName := filepath.Join(imagePath, "metadata", "annotations.yaml")
annotationsFile, err := os.Open(annotationsFileName)
Expand All @@ -55,6 +56,7 @@ func Validate(ctx context.Context, operatorSdk operatorSdk, imagePath string) (*
return nil, fmt.Errorf("unable to get annotations.yaml from the bundle: %v", err)
}

optionalValues := make(map[string]string)
if annotations.OpenshiftVersions != "" {
// Check that the label range contains >= 4.9
targetVersion, err := targetVersion(annotations.OpenshiftVersions)
Expand All @@ -64,12 +66,22 @@ func Validate(ctx context.Context, operatorSdk operatorSdk, imagePath string) (*
}
if k8sVer, found := ocpToKubeVersion[targetVersion]; found {
log.Debugf("OpenShift %s detected in annotations. Running with additional checks enabled.", targetVersion)
opts.OptionalValues = make(map[string]string)
opts.OptionalValues["k8s-version"] = k8sVer
optionalValues = make(map[string]string)
optionalValues["k8s-version"] = k8sVer
}
}
objs = append(objs, optionalValues)

results := validators.Validate(objs...)
passed := true
for _, v := range results {
if v.HasError() {
passed = false
break
}
}

return operatorSdk.BundleValidate(ctx, imagePath, opts)
return &Report{Results: results, Passed: passed}, nil
}

func targetVersion(ocpLabelIndex string) (string, error) {
Expand Down
12 changes: 0 additions & 12 deletions certification/internal/bundle/bundle_suite_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package bundle

import (
"context"
"errors"
"testing"

"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/operatorsdk"

. "github.com/onsi/ginkgo/v2/dsl/core"
. "github.com/onsi/gomega"
)
Expand All @@ -16,15 +13,6 @@ func TestBundle(t *testing.T) {
RunSpecs(t, "Bundle Utils Suite")
}

type FakeOperatorSdk struct {
OperatorSdkReport operatorsdk.OperatorSdkScorecardReport
OperatorSdkBVReport operatorsdk.OperatorSdkBundleValidateReport
}

func (f FakeOperatorSdk) BundleValidate(ctx context.Context, image string, opts operatorsdk.OperatorSdkBundleValidateOptions) (*operatorsdk.OperatorSdkBundleValidateReport, error) {
return &f.OperatorSdkBVReport, nil
}

// In order to test some negative paths, this io.Reader will just throw an error
type errReader int

Expand Down
84 changes: 18 additions & 66 deletions certification/internal/bundle/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,95 +3,55 @@ package bundle
import (
"bytes"
"context"
"os"
"path/filepath"

"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/ginkgo/v2/dsl/core"
. "github.com/onsi/ginkgo/v2/dsl/table"
. "github.com/onsi/gomega"
)

var _ = Describe("BundleValidateCheck", func() {
const (
manifestsDir = "manifests"
metadataDir = "metadata"
annotationFilename = "annotations.yaml"
annotations = `annotations:
com.redhat.openshift.versions: "v4.6-v4.9"
operators.operatorframework.io.bundle.package.v1: testPackage
operators.operatorframework.io.bundle.channel.default.v1: testChannel
`
)

Describe("Bundle validation", func() {
var (
imageRef certification.ImageReference
fakeEngine operatorSdk
)

BeforeEach(func() {
// mock bundle directory
tmpDir, err := os.MkdirTemp("", "bundle-metadata-*")
Expect(err).ToNot(HaveOccurred())

err = os.Mkdir(filepath.Join(tmpDir, metadataDir), 0o755)
Expect(err).ToNot(HaveOccurred())

err = os.Mkdir(filepath.Join(tmpDir, manifestsDir), 0o755)
Expect(err).ToNot(HaveOccurred())

err = os.WriteFile(filepath.Join(tmpDir, metadataDir, annotationFilename), []byte(annotations), 0o644)
Expect(err).ToNot(HaveOccurred())

imageRef.ImageFSPath = tmpDir
fakeEngine = FakeOperatorSdk{}
})

AfterEach(func() {
err := os.RemoveAll(imageRef.ImageFSPath)
Expect(err).ToNot(HaveOccurred())
})

Context("the annotations file is valid", func() {
It("should pass", func() {
report, err := Validate(context.Background(), fakeEngine, imageRef.ImageFSPath)
imageRef := certification.ImageReference{
ImageFSPath: "./testdata/valid_bundle",
}
report, err := Validate(context.Background(), imageRef.ImageFSPath)
Expect(err).ToNot(HaveOccurred())
Expect(report).ToNot(BeNil())
})
})

Context("the annotations file does not exist", func() {
JustBeforeEach(func() {
err := os.Remove(filepath.Join(imageRef.ImageFSPath, metadataDir, annotationFilename))
Expect(err).ToNot(HaveOccurred())
})
It("should error", func() {
report, err := Validate(context.Background(), fakeEngine, imageRef.ImageFSPath)
imageRef := certification.ImageReference{
ImageFSPath: "./testdata/no_annotations_file",
}
report, err := Validate(context.Background(), imageRef.ImageFSPath)
Expect(err).To(HaveOccurred())
Expect(report).To(BeNil())
})
})

Context("the annotations file is malformed", func() {
JustBeforeEach(func() {
err := os.WriteFile(filepath.Join(imageRef.ImageFSPath, metadataDir, annotationFilename), []byte("badAnnotations"), 0o644)
Expect(err).ToNot(HaveOccurred())
})
It("should error", func() {
report, err := Validate(context.Background(), fakeEngine, imageRef.ImageFSPath)
imageRef := certification.ImageReference{
ImageFSPath: "./testdata/malformed_annotations_file",
}
report, err := Validate(context.Background(), imageRef.ImageFSPath)
Expect(err).To(HaveOccurred())
Expect(report).To(BeNil())
})
})

Context("the annotations file is valid but has no annotations", func() {
JustBeforeEach(func() {
err := os.WriteFile(filepath.Join(imageRef.ImageFSPath, metadataDir, annotationFilename), []byte("annotations:"), 0o644)
Expect(err).ToNot(HaveOccurred())
})
It("should fail gracefully", func() {
report, err := Validate(context.Background(), fakeEngine, imageRef.ImageFSPath)
imageRef := certification.ImageReference{
ImageFSPath: "./testdata/invalid_bundle",
}
report, err := Validate(context.Background(), imageRef.ImageFSPath)
Expect(err).ToNot(HaveOccurred())
Expect(report).ToNot(BeNil())
})
Expand All @@ -101,14 +61,6 @@ var _ = Describe("BundleValidateCheck", func() {
Describe("While ensuring that container util is working", func() {
// tests: extractAnnotationsBytes
Context("with an annotations yaml data read from disk", func() {
Context("with the correct format", func() {
It("should properly marshal to a map[string]string", func() {
annotations, err := LoadAnnotations(context.TODO(), bytes.NewReader([]byte(annotations)))
Expect(err).ToNot(HaveOccurred())
Expect(annotations.DefaultChannelName).To(Equal("testChannel"))
})
})

Context("containing no data read in from the yaml file", func() {
data := []byte{}

Expand Down
Empty file.
Loading

0 comments on commit 5159bc1

Please sign in to comment.