Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the bundle version check with latest releases #762

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 45 additions & 40 deletions certification/internal/bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,27 @@ import (
"sigs.k8s.io/yaml"
)

const ocpVerV1beta1Unsupported = "4.9"

// versionsKey is the OpenShift versions in annotations.yaml that lists the versions allowed for an operator
const versionsKey = "com.redhat.openshift.versions"

// This table signifies what the NEXT release of OpenShift will
// deprecate, not what it matches up to.
var ocpToKubeVersion = map[string]string{
"4.9": "1.22",
"4.10": "1.23",
"4.11": "1.24",
"4.12": "1.25",
"4.13": "1.26",
}

const latestReleasedVersion = "4.11"

type operatorSdk interface {
BundleValidate(context.Context, string, operatorsdk.OperatorSdkBundleValidateOptions) (*operatorsdk.OperatorSdkBundleValidateReport, error)
}

func Validate(ctx context.Context, operatorSdk operatorSdk, imagePath string) (*operatorsdk.OperatorSdkBundleValidateReport, error) {
selector := []string{"community", "operatorhub"}
selector := []string{"community", "operatorhub", "alpha-deprecated-apis"}
opts := operatorsdk.OperatorSdkBundleValidateOptions{
Selector: selector,
Verbose: true,
Expand All @@ -51,75 +61,70 @@ func Validate(ctx context.Context, operatorSdk operatorSdk, imagePath string) (*

if versions, ok := annotations[versionsKey]; ok {
// Check that the label range contains >= 4.9
if isTarget49OrGreater(versions) {
log.Debug("OpenShift 4.9 detected in annotations. Running with additional checks enabled.")
targetVersion, err := targetVersion(versions)
if err != nil {
// Could not parse the version, which probably means the annotation is invalid
return nil, fmt.Errorf("%v", err)
}
if k8sVer, ok := ocpToKubeVersion[targetVersion]; ok {
log.Debugf("OpenShift %s detected in annotations. Running with additional checks enabled.", targetVersion)
opts.OptionalValues = make(map[string]string)
opts.OptionalValues["k8s-version"] = "1.22"
opts.OptionalValues["k8s-version"] = k8sVer
}
}

return operatorSdk.BundleValidate(ctx, imagePath, opts)
}

func isTarget49OrGreater(ocpLabelIndex string) bool {
semVerOCPV1beta1Unsupported, _ := semver.ParseTolerant(ocpVerV1beta1Unsupported)
// the OCP range informed cannot allow carry on to OCP 4.9+
func targetVersion(ocpLabelIndex string) (string, error) {
beginsEqual := strings.HasPrefix(ocpLabelIndex, "=")
// It means that the OCP label is =OCP version
if beginsEqual {
version := cleanStringToGetTheVersionToParse(strings.Split(ocpLabelIndex, "=")[1])
verParsed, err := semver.ParseTolerant(version)
if err != nil {
log.Errorf("unable to parse the value (%s) on (%s)", version, ocpLabelIndex)
return false
return "", fmt.Errorf("unable to parse the value (%s) on (%s): %v", version, ocpLabelIndex, err)
}

if verParsed.GE(semVerOCPV1beta1Unsupported) {
return true
}
return false
return fmt.Sprintf("%d.%d", verParsed.Major, verParsed.Minor), nil
}

indexRange := cleanStringToGetTheVersionToParse(ocpLabelIndex)
if len(indexRange) > 1 {
// Bare version
// Bare version, so send back latest released
if !strings.Contains(indexRange, "-") {
verParsed, err := semver.ParseTolerant(indexRange)
if err != nil {
log.Error("unable to parse the version")
return false
// The passed version is not valid. We don't care what it is,
// just that it's valid.
return "", fmt.Errorf("unable to parse the version: %v", err)
}
if verParsed.GE(semVerOCPV1beta1Unsupported) {
return true

// If the specified version is greater than latestReleased, we will accept that
latestReleasedParsed, _ := semver.ParseTolerant(latestReleasedVersion)
if verParsed.GT(latestReleasedParsed) {
return fmt.Sprintf("%d.%d", verParsed.Major, verParsed.Minor), nil
}

return latestReleasedVersion, nil
}

versions := strings.Split(indexRange, "-")
version := versions[0]
if len(versions) > 1 {
version = versions[1]
// This is a normal range of 1.0-2.0
if len(versions) > 1 && versions[1] != "" {
version := versions[1]
verParsed, err := semver.ParseTolerant(version)
if err != nil {
log.Error("unable to parse the version")
return false
}

if verParsed.GE(semVerOCPV1beta1Unsupported) {
return true
return "", fmt.Errorf("unable to parse the version: %v", err)
}
return false
}

verParsed, err := semver.ParseTolerant(version)
if err != nil {
log.Error("unable to parse the version")
return false
return fmt.Sprintf("%d.%d", verParsed.Major, verParsed.Minor), nil
}

if semVerOCPV1beta1Unsupported.GE(verParsed) {
return true
}
// This is an open-ended range: v1-. This is not valid.
// So, we just fall through to the default return.
komish marked this conversation as resolved.
Show resolved Hide resolved
return "", fmt.Errorf("unable to parse the version: malformed range: %s", indexRange)
}
return false
return "", fmt.Errorf("unable to parse the version: unknown error")
}

// cleanStringToGetTheVersionToParse will remove the expected characters for
Expand Down
46 changes: 34 additions & 12 deletions certification/internal/bundle/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,19 @@ var _ = Describe("BundleValidateCheck", func() {
})
})

Context("the annotations file has a bad OpenShift version", func() {
JustBeforeEach(func() {
err := os.WriteFile(filepath.Join(imageRef.ImageFSPath, metadataDir, annotationFilename), []byte(`annotations:
com.redhat.openshift.versions: "vfoo"`), 0o644)
Expect(err).ToNot(HaveOccurred())
})
It("should fail", func() {
report, err := Validate(context.Background(), fakeEngine, imageRef.ImageFSPath)
Expect(err).To(HaveOccurred())
Expect(report).To(BeNil())
})
})

Context("getting the CSV file from the bundle", func() {
var manifestsPath string

Expand Down Expand Up @@ -258,18 +271,27 @@ var _ = Describe("BundleValidateCheck", func() {
})

DescribeTable("Image Registry validation",
func(versions string, expected bool) {
ok := isTarget49OrGreater(versions)
Expect(ok).To(Equal(expected))
func(versions string, expected string, success bool) {
version, err := targetVersion(versions)
if success {
Expect(err).ToNot(HaveOccurred())
} else {
Expect(err).To(HaveOccurred())
}
Expect(version).To(Equal(expected))
},
Entry("range 4.6 to 4.8", "v4.6-v4.8", false),
Entry("exactly 4.8", "=v4.8", false),
Entry("exactly 4.9", "=v4.9", true),
Entry("range 4.6 to 4.9", "v4.6-v4.9", true),
Entry(">= 4.8", "v4.8", true),
Entry(">= 4.9", "v4.9", true),
Entry("begins = with error", "=foo", false),
Entry("bare version with error", "vfoo", false),
Entry("range with error", "v4.6-vfoo", false),

Entry("range 4.6 to 4.8", "v4.6-v4.8", "4.8", true),
Entry("exactly 4.8", "=v4.8", "4.8", true),
Entry("exactly 4.9", "=v4.9", "4.9", true),
Entry("range 4.6 to 4.9", "v4.6-v4.9", "4.9", true),
Entry(">= 4.8", "v4.8", latestReleasedVersion, true),
Entry(">= 4.9", "v4.9", latestReleasedVersion, true),
Entry(">= 4.11", "v4.11", latestReleasedVersion, true),
Entry(">= 4.13, which is more than released", "v4.13", "4.13", true),
Entry("begins = with error", "=foo", "", false),
Entry("bare version with error", "vfoo", "", false),
Entry("range with error", "v4.6-vfoo", "", false),
Entry("open-ended range is error", "v4.11-", "", false),
)
})