Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
306 changes: 147 additions & 159 deletions api/v1alpha1/clusterextension_types.go

Large diffs are not rendered by default.

16 changes: 10 additions & 6 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

213 changes: 107 additions & 106 deletions config/base/crd/bases/olm.operatorframework.io_clusterextensions.yaml

Large diffs are not rendered by default.

60 changes: 30 additions & 30 deletions docs/api-reference/operator-controller-api-reference.md

Large diffs are not rendered by default.

29 changes: 23 additions & 6 deletions internal/applier/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
apimachyaml "k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client"

Expand Down Expand Up @@ -56,6 +57,26 @@ type Helm struct {
Preflights []Preflight
}

// shouldSkipPreflight is a helper to determine if the preflight check is CRDUpgradeSafety AND
// if it is set to enforcement None.
func shouldSkipPreflight(ctx context.Context, preflight Preflight, ext *ocv1alpha1.ClusterExtension, state string) bool {
l := log.FromContext(ctx)
hasCRDUpgradeSafety := ext.Spec.Install.Preflight != nil && ext.Spec.Install.Preflight.CRDUpgradeSafety != nil
_, isCRDUpgradeSafetyInstance := preflight.(*crdupgradesafety.Preflight)

if hasCRDUpgradeSafety && isCRDUpgradeSafetyInstance {
if state == StateNeedsInstall || state == StateNeedsUpgrade {
l.Info("crdUpgradeSafety ", "policy", ext.Spec.Install.Preflight.CRDUpgradeSafety.Enforcement)
}
if ext.Spec.Install.Preflight.CRDUpgradeSafety.Enforcement == ocv1alpha1.CRDUpgradeSafetyEnforcementNone {
// Skip this preflight check because it is of type *crdupgradesafety.Preflight and the CRD Upgrade Safety
// policy is set to None
return true
}
}
return false
}

func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.ClusterExtension, objectLabels map[string]string, storageLabels map[string]string) ([]client.Object, string, error) {
chrt, err := convert.RegistryV1ToHelmChart(ctx, contentFS, ext.Spec.Install.Namespace, []string{corev1.NamespaceAll})
if err != nil {
Expand All @@ -78,12 +99,8 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.Clust
}

for _, preflight := range h.Preflights {
if ext.Spec.Install.Preflight != nil && ext.Spec.Install.Preflight.CRDUpgradeSafety != nil {
if _, ok := preflight.(*crdupgradesafety.Preflight); ok && ext.Spec.Install.Preflight.CRDUpgradeSafety.Policy == ocv1alpha1.CRDUpgradeSafetyPolicyDisabled {
// Skip this preflight check because it is of type *crdupgradesafety.Preflight and the CRD Upgrade Safety
// preflight check has been disabled
continue
}
if shouldSkipPreflight(ctx, preflight, ext, state) {
continue
}
switch state {
case StateNeedsInstall:
Expand Down
24 changes: 21 additions & 3 deletions internal/conditionsets/conditionsets.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,27 @@ limitations under the License.

package conditionsets

import (
"github.com/operator-framework/operator-controller/api/v1alpha1"
)

// ConditionTypes is the full set of ClusterExtension condition Types.
// ConditionReasons is the full set of ClusterExtension condition Reasons.
//
// NOTE: These are populated by init() in api/v1alpha1/clusterextension_types.go
var ConditionTypes []string
var ConditionReasons []string
// NOTE: unit tests in clusterextension_types_test will enforce completeness.
var ConditionTypes = []string{
v1alpha1.TypeInstalled,
v1alpha1.TypeDeprecated,
v1alpha1.TypePackageDeprecated,
v1alpha1.TypeChannelDeprecated,
v1alpha1.TypeBundleDeprecated,
v1alpha1.TypeProgressing,
}

var ConditionReasons = []string{
v1alpha1.ReasonSucceeded,
v1alpha1.ReasonDeprecated,
v1alpha1.ReasonFailed,
v1alpha1.ReasonBlocked,
v1alpha1.ReasonRetrying,
}
10 changes: 5 additions & 5 deletions internal/controllers/clusterextension_admission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func TestClusterExtensionSourceConfig(t *testing.T) {

func TestClusterExtensionAdmissionPackageName(t *testing.T) {
tooLongError := "spec.source.catalog.packageName: Too long: may not be longer than 253"
regexMismatchError := "spec.source.catalog.packageName in body should match"
regexMismatchError := "packageName must be a valid DNS1123 subdomain"

testCases := []struct {
name string
Expand Down Expand Up @@ -136,7 +136,7 @@ func TestClusterExtensionAdmissionPackageName(t *testing.T) {

func TestClusterExtensionAdmissionVersion(t *testing.T) {
tooLongError := "spec.source.catalog.version: Too long: may not be longer than 64"
regexMismatchError := "spec.source.catalog.version in body should match"
regexMismatchError := "invalid version expression"

testCases := []struct {
name string
Expand Down Expand Up @@ -236,7 +236,7 @@ func TestClusterExtensionAdmissionVersion(t *testing.T) {

func TestClusterExtensionAdmissionChannel(t *testing.T) {
tooLongError := "spec.source.catalog.channels[0]: Too long: may not be longer than 253"
regexMismatchError := "spec.source.catalog.channels[0] in body should match"
regexMismatchError := "channels entries must be valid DNS1123 subdomains"

testCases := []struct {
name string
Expand Down Expand Up @@ -293,7 +293,7 @@ func TestClusterExtensionAdmissionChannel(t *testing.T) {

func TestClusterExtensionAdmissionInstallNamespace(t *testing.T) {
tooLongError := "spec.install.namespace: Too long: may not be longer than 63"
regexMismatchError := "spec.install.namespace in body should match"
regexMismatchError := "namespace must be a valid DNS1123 label"

testCases := []struct {
name string
Expand Down Expand Up @@ -348,7 +348,7 @@ func TestClusterExtensionAdmissionInstallNamespace(t *testing.T) {

func TestClusterExtensionAdmissionServiceAccount(t *testing.T) {
tooLongError := "spec.install.serviceAccount.name: Too long: may not be longer than 253"
regexMismatchError := "spec.install.serviceAccount.name in body should match"
regexMismatchError := "name must be a valid DNS1123 subdomain"

testCases := []struct {
name string
Expand Down
2 changes: 1 addition & 1 deletion internal/controllers/clusterextension_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,7 @@ func TestClusterExtensionInstallationSucceeds(t *testing.T) {
t.Log("By checking the expected progressing conditions")
progressingCond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1alpha1.TypeProgressing)
require.NotNil(t, progressingCond)
require.Equal(t, metav1.ConditionFalse, progressingCond.Status)
require.Equal(t, metav1.ConditionTrue, progressingCond.Status)
require.Equal(t, ocv1alpha1.ReasonSucceeded, progressingCond.Reason)

require.NoError(t, cl.DeleteAllOf(ctx, &ocv1alpha1.ClusterExtension{}))
Expand Down
3 changes: 1 addition & 2 deletions internal/controllers/common_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,13 @@ func setInstallStatus(ext *ocv1alpha1.ClusterExtension, installStatus *ocv1alpha
func setStatusProgressing(ext *ocv1alpha1.ClusterExtension, err error) {
progressingCond := metav1.Condition{
Type: ocv1alpha1.TypeProgressing,
Status: metav1.ConditionFalse,
Status: metav1.ConditionTrue,
Reason: ocv1alpha1.ReasonSucceeded,
Message: "desired state reached",
ObservedGeneration: ext.GetGeneration(),
}

if err != nil {
progressingCond.Status = metav1.ConditionTrue
progressingCond.Reason = ocv1alpha1.ReasonRetrying
progressingCond.Message = err.Error()
}
Expand Down
4 changes: 2 additions & 2 deletions internal/controllers/common_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ func TestSetStatusProgressing(t *testing.T) {
expected metav1.Condition
}{
{
name: "non-nil ClusterExtension, nil error, Progressing condition has status False with reason Success",
name: "non-nil ClusterExtension, nil error, Progressing condition has status True with reason Success",
err: nil,
clusterExtension: &ocv1alpha1.ClusterExtension{},
expected: metav1.Condition{
Type: ocv1alpha1.TypeProgressing,
Status: metav1.ConditionFalse,
Status: metav1.ConditionTrue,
Reason: ocv1alpha1.ReasonSucceeded,
Message: "desired state reached",
},
Expand Down
19 changes: 12 additions & 7 deletions internal/resolve/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,18 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1alpha1.ClusterEx
versionRange := ext.Spec.Source.Catalog.Version
channels := ext.Spec.Source.Catalog.Channels

selector, err := metav1.LabelSelectorAsSelector(&ext.Spec.Source.Catalog.Selector)
if err != nil {
return nil, nil, nil, fmt.Errorf("desired catalog selector is invalid: %w", err)
}
// A nothing (empty) seletor selects everything
if selector == labels.Nothing() {
selector = labels.Everything()
// unless overridden, default to selecting all bundles
var selector = labels.Everything()
var err error
if ext.Spec.Source.Catalog != nil {
selector, err = metav1.LabelSelectorAsSelector(ext.Spec.Source.Catalog.Selector)
if err != nil {
return nil, nil, nil, fmt.Errorf("desired catalog selector is invalid: %w", err)
}
// A nothing (empty) selector selects everything
if selector == labels.Nothing() {
selector = labels.Everything()
}
}

var versionRangeConstraints *mmsemver.Constraints
Expand Down
14 changes: 9 additions & 5 deletions internal/resolve/catalog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ func TestInvalidClusterExtensionCatalogMatchExpressions(t *testing.T) {
Source: ocv1alpha1.SourceConfig{
Catalog: &ocv1alpha1.CatalogSource{
PackageName: "foo",
Selector: metav1.LabelSelector{
Selector: &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "name",
Expand Down Expand Up @@ -802,7 +802,7 @@ func TestInvalidClusterExtensionCatalogMatchLabelsName(t *testing.T) {
Source: ocv1alpha1.SourceConfig{
Catalog: &ocv1alpha1.CatalogSource{
PackageName: "foo",
Selector: metav1.LabelSelector{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"": "value"},
},
},
Expand All @@ -828,7 +828,7 @@ func TestInvalidClusterExtensionCatalogMatchLabelsValue(t *testing.T) {
Source: ocv1alpha1.SourceConfig{
Catalog: &ocv1alpha1.CatalogSource{
PackageName: "foo",
Selector: metav1.LabelSelector{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"name": "&value"},
},
},
Expand All @@ -852,7 +852,9 @@ func TestClusterExtensionMatchLabel(t *testing.T) {
}
r := CatalogResolver{WalkCatalogsFunc: w.WalkCatalogs}
ce := buildFooClusterExtension(pkgName, []string{}, "", ocv1alpha1.UpgradeConstraintPolicyCatalogProvided)
ce.Spec.Source.Catalog.Selector.MatchLabels = map[string]string{"olm.operatorframework.io/metadata.name": "b"}
ce.Spec.Source.Catalog.Selector = &metav1.LabelSelector{
MatchLabels: map[string]string{"olm.operatorframework.io/metadata.name": "b"},
}

_, _, _, err := r.Resolve(context.Background(), ce, nil)
require.NoError(t, err)
Expand All @@ -871,7 +873,9 @@ func TestClusterExtensionNoMatchLabel(t *testing.T) {
}
r := CatalogResolver{WalkCatalogsFunc: w.WalkCatalogs}
ce := buildFooClusterExtension(pkgName, []string{}, "", ocv1alpha1.UpgradeConstraintPolicyCatalogProvided)
ce.Spec.Source.Catalog.Selector.MatchLabels = map[string]string{"olm.operatorframework.io/metadata.name": "a"}
ce.Spec.Source.Catalog.Selector = &metav1.LabelSelector{
MatchLabels: map[string]string{"olm.operatorframework.io/metadata.name": "a"},
}

_, _, _, err := r.Resolve(context.Background(), ce, nil)
require.Error(t, err)
Expand Down
10 changes: 5 additions & 5 deletions test/e2e/cluster_extension_install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ func TestClusterExtensionInstallRegistry(t *testing.T) {
SourceType: "Catalog",
Catalog: &ocv1alpha1.CatalogSource{
PackageName: tc.packageName,
Selector: metav1.LabelSelector{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"olm.operatorframework.io/metadata.name": extensionCatalog.Name},
},
},
Expand Down Expand Up @@ -580,7 +580,7 @@ func TestClusterExtensionInstallReResolvesWhenCatalogIsPatched(t *testing.T) {
SourceType: "Catalog",
Catalog: &ocv1alpha1.CatalogSource{
PackageName: "prometheus",
Selector: metav1.LabelSelector{
Selector: &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "olm.operatorframework.io/metadata.name",
Expand Down Expand Up @@ -669,7 +669,7 @@ func TestClusterExtensionInstallReResolvesWhenNewCatalog(t *testing.T) {
SourceType: "Catalog",
Catalog: &ocv1alpha1.CatalogSource{
PackageName: "prometheus",
Selector: metav1.LabelSelector{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"olm.operatorframework.io/metadata.name": extensionCatalog.Name},
},
},
Expand Down Expand Up @@ -732,7 +732,7 @@ func TestClusterExtensionInstallReResolvesWhenManagedContentChanged(t *testing.T
SourceType: "Catalog",
Catalog: &ocv1alpha1.CatalogSource{
PackageName: "prometheus",
Selector: metav1.LabelSelector{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"olm.operatorframework.io/metadata.name": extensionCatalog.Name},
},
},
Expand Down Expand Up @@ -797,7 +797,7 @@ func TestClusterExtensionRecoversFromInitialInstallFailedWhenFailureFixed(t *tes
SourceType: "Catalog",
Catalog: &ocv1alpha1.CatalogSource{
PackageName: "prometheus",
Selector: metav1.LabelSelector{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"olm.operatorframework.io/metadata.name": extensionCatalog.Name},
},
},
Expand Down
Loading