Skip to content

Commit

Permalink
Introduce UpgradeStrategy field to OperatorGroups (#235)
Browse files Browse the repository at this point in the history
This commit introduces the upgradeStrategy field to the operatorGroup
type. The upgradeStrategy field defines OLM behavior when upgrading
operators in the namespace. Two upgrade strategies are currently
supported, "Default" and "TechPreviewUnsafeFailForward".

The "Default" strategy mimics existing behavior.

The "TechPreviewUnsafeFailForward" strategy allows users to recover
from failed installPlans or failed clusterServiceVersions, it should
be noted that these upgrades are unsafe and can lead to unpredictable
behavior and potentially dataloss.

Upstream-repository: api
Upstream-commit: 33310d6154f344da5494c788451bd34cdf54711c
  • Loading branch information
awgreene authored and Per Goncalves da Silva committed Apr 14, 2022
1 parent 98c34f2 commit d895574
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 2 deletions.
9 changes: 9 additions & 0 deletions manifests/0000_50_olm_00-operatorgroups.crd.yaml
Expand Up @@ -39,6 +39,8 @@ spec:
spec:
description: OperatorGroupSpec is the spec for an OperatorGroup resource.
type: object
default:
upgradeStrategy: Default
properties:
selector:
description: Selector selects the OperatorGroup's target namespaces.
Expand Down Expand Up @@ -82,6 +84,13 @@ spec:
items:
type: string
x-kubernetes-list-type: set
upgradeStrategy:
description: "UpgradeStrategy defines the upgrade strategy for operators in the namespace. There are currently two supported upgrade strategies: \n Default: OLM will only allow clusterServiceVersions to move to the replacing phase from the succeeded phase. This effectively means that OLM will not allow operators to move to the next version if an installation or upgrade has failed. \n TechPreviewUnsafeFailForward: OLM will allow clusterServiceVersions to move to the replacing phase from the succeeded phase or from the failed phase. Additionally, OLM will generate new installPlans when a subscription references a failed installPlan and the catalog has been updated with a new upgrade for the existing set of operators. \n WARNING: The TechPreviewUnsafeFailForward upgrade strategy is unsafe and may result in unexpected behavior or unrecoverable data loss unless you have deep understanding of the set of operators being managed in the namespace."
type: string
default: Default
enum:
- Default
- TechPreviewUnsafeFailForward
status:
description: OperatorGroupStatus is the status for an OperatorGroupResource.
type: object
Expand Down
9 changes: 9 additions & 0 deletions staging/api/crds/operators.coreos.com_operatorgroups.yaml
Expand Up @@ -37,6 +37,8 @@ spec:
spec:
description: OperatorGroupSpec is the spec for an OperatorGroup resource.
type: object
default:
upgradeStrategy: Default
properties:
selector:
description: Selector selects the OperatorGroup's target namespaces.
Expand Down Expand Up @@ -80,6 +82,13 @@ spec:
items:
type: string
x-kubernetes-list-type: set
upgradeStrategy:
description: "UpgradeStrategy defines the upgrade strategy for operators in the namespace. There are currently two supported upgrade strategies: \n Default: OLM will only allow clusterServiceVersions to move to the replacing phase from the succeeded phase. This effectively means that OLM will not allow operators to move to the next version if an installation or upgrade has failed. \n TechPreviewUnsafeFailForward: OLM will allow clusterServiceVersions to move to the replacing phase from the succeeded phase or from the failed phase. Additionally, OLM will generate new installPlans when a subscription references a failed installPlan and the catalog has been updated with a new upgrade for the existing set of operators. \n WARNING: The TechPreviewUnsafeFailForward upgrade strategy is unsafe and may result in unexpected behavior or unrecoverable data loss unless you have deep understanding of the set of operators being managed in the namespace."
type: string
default: Default
enum:
- Default
- TechPreviewUnsafeFailForward
status:
description: OperatorGroupStatus is the status for an OperatorGroupResource.
type: object
Expand Down
2 changes: 1 addition & 1 deletion staging/api/crds/zz_defs.go

Large diffs are not rendered by default.

70 changes: 70 additions & 0 deletions staging/api/pkg/operators/v1/operatorgroup_test.go
@@ -0,0 +1,70 @@
package v1

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestUpgradeStrategy(t *testing.T) {
tests := []struct {
description string
og *OperatorGroup
expected UpgradeStrategy
}{
{
description: "NoSpec",
og: &OperatorGroup{},
expected: UpgradeStrategyDefault,
},
{
description: "NoUpgradeStrategy",
og: &OperatorGroup{
Spec: OperatorGroupSpec{},
},
expected: UpgradeStrategyDefault,
},
{
description: "NoUpgradeStrategy",
og: &OperatorGroup{
Spec: OperatorGroupSpec{
UpgradeStrategy: "",
},
},
expected: UpgradeStrategyDefault,
},
{
description: "NonSupportedUpgradeStrategy",
og: &OperatorGroup{
Spec: OperatorGroupSpec{
UpgradeStrategy: "foo",
},
},
expected: UpgradeStrategyDefault,
},
{
description: "DefaultUpgradeStrategy",
og: &OperatorGroup{
Spec: OperatorGroupSpec{
UpgradeStrategy: "Default",
},
},
expected: UpgradeStrategyDefault,
},
{
description: "UnsafeFailForwardUpgradeStrategy",
og: &OperatorGroup{
Spec: OperatorGroupSpec{
UpgradeStrategy: "TechPreviewUnsafeFailForward",
},
},
expected: UpgradeStrategyUnsafeFailForward,
},
}

for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
require.EqualValues(t, tt.expected, tt.og.UpgradeStrategy())
})
}
}
56 changes: 56 additions & 0 deletions staging/api/pkg/operators/v1/operatorgroup_types.go
Expand Up @@ -24,8 +24,29 @@ const (
MutlipleOperatorGroupCondition = "MultipleOperatorGroup"
MultipleOperatorGroupsReason = "MultipleOperatorGroupsFound"
OperatorGroupServiceAccountReason = "ServiceAccountNotFound"

// UpgradeStrategyDefault configures OLM such that it will only allow
// clusterServiceVersions to move to the replacing phase to the succeeded
// phase. This effectively means that OLM will not allow operators to move
// to the next version if an installation or upgrade has failed.
UpgradeStrategyDefault UpgradeStrategy = "Default"

// UpgradeStrategyUnsafeFailForward configures OLM such that it will allow
// clusterServiceVersions to move to the replacing phase from the succeeded
// phase or from the failed phase. Additionally, OLM will generate new
// installPlans when a subscription references a failed installPlan and the
// catalog has been updated with a new upgrade for the existing set of
// operators.
//
// WARNING: The UpgradeStrategyUnsafeFailForward upgrade strategy is unsafe
// and may result in unexpected behavior or unrecoverable data loss unless
// you have deep understanding of the set of operators being managed in the
// namespace.
UpgradeStrategyUnsafeFailForward UpgradeStrategy = "TechPreviewUnsafeFailForward"
)

type UpgradeStrategy string

// OperatorGroupSpec is the spec for an OperatorGroup resource.
type OperatorGroupSpec struct {
// Selector selects the OperatorGroup's target namespaces.
Expand All @@ -45,6 +66,29 @@ type OperatorGroupSpec struct {
// Static tells OLM not to update the OperatorGroup's providedAPIs annotation
// +optional
StaticProvidedAPIs bool `json:"staticProvidedAPIs,omitempty"`

// UpgradeStrategy defines the upgrade strategy for operators in the namespace.
// There are currently two supported upgrade strategies:
//
// Default: OLM will only allow clusterServiceVersions to move to the replacing
// phase from the succeeded phase. This effectively means that OLM will not
// allow operators to move to the next version if an installation or upgrade
// has failed.
//
// TechPreviewUnsafeFailForward: OLM will allow clusterServiceVersions to move to the
// replacing phase from the succeeded phase or from the failed phase.
// Additionally, OLM will generate new installPlans when a subscription references
// a failed installPlan and the catalog has been updated with a new upgrade for
// the existing set of operators.
//
// WARNING: The TechPreviewUnsafeFailForward upgrade strategy is unsafe and may result
// in unexpected behavior or unrecoverable data loss unless you have deep
// understanding of the set of operators being managed in the namespace.
//
// +kubebuilder:validation:Enum=Default;TechPreviewUnsafeFailForward
// +kubebuilder:default=Default
// +optional
UpgradeStrategy UpgradeStrategy `json:"upgradeStrategy,omitempty"`
}

// OperatorGroupStatus is the status for an OperatorGroupResource.
Expand Down Expand Up @@ -76,6 +120,7 @@ type OperatorGroup struct {
metav1.ObjectMeta `json:"metadata"`

// +optional
// +kubebuilder:default={upgradeStrategy:Default}
Spec OperatorGroupSpec `json:"spec"`
Status OperatorGroupStatus `json:"status,omitempty"`
}
Expand All @@ -98,6 +143,17 @@ func (o *OperatorGroup) BuildTargetNamespaces() string {
return strings.Join(ns, ",")
}

// UpgradeStrategy returns the UpgradeStrategy specified or the default value otherwise.
func (o *OperatorGroup) UpgradeStrategy() UpgradeStrategy {
strategyName := o.Spec.UpgradeStrategy
switch {
case strategyName == UpgradeStrategyUnsafeFailForward:
return strategyName
default:
return UpgradeStrategyDefault
}
}

// IsServiceAccountSpecified returns true if the spec has a service account name specified.
func (o *OperatorGroup) IsServiceAccountSpecified() bool {
if o.Spec.ServiceAccountName == "" {
Expand Down

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

0 comments on commit d895574

Please sign in to comment.