Skip to content
Merged
4 changes: 3 additions & 1 deletion pkg/apis/upgrade/v1alpha1/upgradeconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type UpgradeConfigSpec struct {
UpgradeAt string `json:"upgradeAt"`

// +kubebuilder:validation:Minimum:=0
// The maximum grace period granted to a node whose drain is blocked by a Pod Disruption Budget, before that drain is forced. Measured in minutes. The minimum accepted value is 0 and in this case it will trigger force drain after the expectedNodeDrainTime lapsed.
// The maximum grace period granted to a node whose drain is blocked by a Pod Disruption Budget, before that drain is forced. Measured in minutes. The minimum accepted value is 0 and in this case it will trigger force drain after the expectedNodeDrainTime lapsed.
PDBForceDrainTimeout int32 `json:"PDBForceDrainTimeout"`

// +kubebuilder:validation:Enum={"OSD","ARO"}
Expand Down Expand Up @@ -127,6 +127,8 @@ const (
PostClusterHealthCheck UpgradeConditionType = "ClusterHealthyAfterUpgrade"
// SendCompletedNotification is an UpgradeConditionType
SendCompletedNotification UpgradeConditionType = "CompletedNotificationSent"
// IsClusterUpgradable is an UpgradeConditionType
IsClusterUpgradable UpgradeConditionType = "IsClusterUpgradable"
)

// UpgradePhase is a Go string type.
Expand Down
1 change: 1 addition & 0 deletions pkg/upgraders/osdupgrader.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func NewOSDUpgrader(c client.Client, cfm configmanager.ConfigManager, mc metrics
steps := []upgradesteps.UpgradeStep{
upgradesteps.Action(string(upgradev1alpha1.SendStartedNotification), ou.SendStartedNotification),
upgradesteps.Action(string(upgradev1alpha1.SendStartedNotification), ou.UpgradeDelayedCheck),
upgradesteps.Action(string(upgradev1alpha1.IsClusterUpgradable), ou.IsUpgradeable),
upgradesteps.Action(string(upgradev1alpha1.UpgradePreHealthCheck), ou.PreUpgradeHealthCheck),
upgradesteps.Action(string(upgradev1alpha1.ExtDepAvailabilityCheck), ou.ExternalDependencyAvailabilityCheck),
upgradesteps.Action(string(upgradev1alpha1.UpgradeScaleUpExtraNodes), ou.EnsureExtraUpgradeWorkers),
Expand Down
74 changes: 74 additions & 0 deletions pkg/upgraders/upgradeable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package upgraders

import (
"context"
"fmt"

"github.com/blang/semver"
"github.com/go-logr/logr"
configv1 "github.com/openshift/api/config/v1"
upgradev1alpha1 "github.com/openshift/managed-upgrade-operator/pkg/apis/upgrade/v1alpha1"
cv "github.com/openshift/managed-upgrade-operator/pkg/clusterversion"
)

func (c *clusterUpgrader) IsUpgradeable(ctx context.Context, logger logr.Logger) (bool, error) {
cV := &configv1.ClusterVersion{}
uC := &upgradev1alpha1.UpgradeConfig{}

//Check if the cluster is already upgrading -
upgradeCommenced, err := c.cvClient.HasUpgradeCommenced(c.upgradeConfig)
if err != nil {
return false, err
}
if upgradeCommenced {
logger.Info(fmt.Sprintf("Skipping upgrade step %s", upgradev1alpha1.UpgradePreHealthCheck))
Comment thread
mrbarge marked this conversation as resolved.
Outdated
return true, nil
}

// get current clusterversion
cvVersion, err := cv.GetCurrentVersion(cV)
if err != nil {
logger.Error(err, "failed to get current cluster version")
return false, err
}

parsedCvVersion, err := semver.Parse(cvVersion)
if err != nil {
logger.Error(err, fmt.Sprintf("Failed to parse current cluster version %s as semver", cvVersion))
return false, err
}

// get the desired clusterversion from upgradeconfig
ucVersion := uC.Spec.Desired.Version
if err != nil {
logger.Error(err, "failed to get current upgrade config desired version")
return false, err
}
Comment thread
mrbarge marked this conversation as resolved.

parsedUcVersion, err := semver.Parse(ucVersion)
if err != nil {
logger.Error(err, fmt.Sprintf("failed to parse upgrade config desired version %s as semver", ucVersion))
return false, err
}

// check if the clusterversion has "Upgradeable" else return true
for _, val := range cV.Status.Conditions {
if val.Type != configv1.OperatorUpgradeable {
return true, nil
}
}
Comment thread
mrbarge marked this conversation as resolved.
Outdated

for _, condition := range cV.Status.Conditions {
if condition.Type == configv1.OperatorUpgradeable && condition.Status == configv1.ConditionTrue {
return true, nil
} else if condition.Type == configv1.OperatorUpgradeable && condition.Status == configv1.ConditionFalse {
Comment thread
mrbarge marked this conversation as resolved.
Outdated
// if the upgradeable is false then we need to check the current version with upgrade version for y-stream update
if parsedUcVersion.Major >= parsedCvVersion.Major && parsedUcVersion.Minor > parsedCvVersion.Minor {
return false, err
} else if parsedUcVersion.Major >= parsedCvVersion.Major && parsedUcVersion.Minor == parsedCvVersion.Minor {
return true, nil
}
}
}
return false, nil
Comment thread
mrbarge marked this conversation as resolved.
Outdated
}
100 changes: 100 additions & 0 deletions pkg/upgraders/upgradeable_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package upgraders

import (
"context"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"github.com/go-logr/logr"
"github.com/golang/mock/gomock"
"k8s.io/apimachinery/pkg/types"
logf "sigs.k8s.io/controller-runtime/pkg/log"

upgradev1alpha1 "github.com/openshift/managed-upgrade-operator/pkg/apis/upgrade/v1alpha1"
cvMocks "github.com/openshift/managed-upgrade-operator/pkg/clusterversion/mocks"
mockDrain "github.com/openshift/managed-upgrade-operator/pkg/drain/mocks"
emMocks "github.com/openshift/managed-upgrade-operator/pkg/eventmanager/mocks"
mockMachinery "github.com/openshift/managed-upgrade-operator/pkg/machinery/mocks"
mockMaintenance "github.com/openshift/managed-upgrade-operator/pkg/maintenance/mocks"
mockMetrics "github.com/openshift/managed-upgrade-operator/pkg/metrics/mocks"
mockScaler "github.com/openshift/managed-upgrade-operator/pkg/scaler/mocks"
"github.com/openshift/managed-upgrade-operator/util/mocks"
testStructs "github.com/openshift/managed-upgrade-operator/util/mocks/structs"
)

var _ = Describe("UpgradableCheckStep", func() {
var (
logger logr.Logger
// mocks
mockKubeClient *mocks.MockClient
mockCtrl *gomock.Controller
mockMaintClient *mockMaintenance.MockMaintenance
mockScalerClient *mockScaler.MockScaler
mockMachineryClient *mockMachinery.MockMachinery
mockMetricsClient *mockMetrics.MockMetrics
mockCVClient *cvMocks.MockClusterVersion
mockDrainStrategyBuilder *mockDrain.MockNodeDrainStrategyBuilder
mockEMClient *emMocks.MockEventManager
// upgradeconfig to be used during tests
upgradeConfigName types.NamespacedName
upgradeConfig *upgradev1alpha1.UpgradeConfig

// upgrader to be used during tests
config *upgraderConfig
upgrader *osdUpgrader
)

BeforeEach(func() {
upgradeConfigName = types.NamespacedName{
Name: "test-upgradeconfig",
Namespace: "test-namespace",
}
upgradeConfig = testStructs.NewUpgradeConfigBuilder().WithNamespacedName(upgradeConfigName).GetUpgradeConfig()
mockCtrl = gomock.NewController(GinkgoT())
mockKubeClient = mocks.NewMockClient(mockCtrl)
mockMaintClient = mockMaintenance.NewMockMaintenance(mockCtrl)
mockMetricsClient = mockMetrics.NewMockMetrics(mockCtrl)
mockScalerClient = mockScaler.NewMockScaler(mockCtrl)
mockMachineryClient = mockMachinery.NewMockMachinery(mockCtrl)
mockCVClient = cvMocks.NewMockClusterVersion(mockCtrl)
mockDrainStrategyBuilder = mockDrain.NewMockNodeDrainStrategyBuilder(mockCtrl)
mockEMClient = emMocks.NewMockEventManager(mockCtrl)
logger = logf.Log.WithName("cluster upgrader test logger")
config = buildTestUpgraderConfig(90, 30, 8, 120, 30)
upgrader = &osdUpgrader{
clusterUpgrader: &clusterUpgrader{
client: mockKubeClient,
metrics: mockMetricsClient,
cvClient: mockCVClient,
notifier: mockEMClient,
config: config,
scaler: mockScalerClient,
drainstrategyBuilder: mockDrainStrategyBuilder,
maintenance: mockMaintClient,
machinery: mockMachineryClient,
upgradeConfig: upgradeConfig,
},
}
})

AfterEach(func() {
mockCtrl.Finish()
})

Context("When running the upgradable-check phase", func() {
Context("With Upgradeable flag present in csv status condition", func() {
Context("When current 'y' stream version is lower then upgrade version", func() {
It("will not perform upgrade", func() {
// gomock.InOrder(
// mockCVClient.EXPECT().HasUpgradeCommenced(gomock.Any()).Return(true, nil),
// )
result, err := upgrader.IsUpgradeable(context.TODO(), logger)
Expect(err).NotTo(HaveOccurred())
Expect(result).To(BeTrue())
})
})

})
})
})