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

🐛 ROSA: Fix version gate Ack for rosa hcp y-stream version upgrade #5166

Merged
merged 1 commit into from
Oct 24, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,19 @@ spec:
version:
description: OpenShift semantic version, for example "4.14.5".
type: string
versionGate:
default: WaitForAcknowledge
description: |-
VersionGate requires acknowledgment when upgrading ROSA-HCP y-stream versions (e.g., from 4.15 to 4.16).
Default is WaitForAcknowledge.
WaitForAcknowledge: If acknowledgment is required, the upgrade will not proceed until VersionGate is set to Acknowledge or AlwaysAcknowledge.
Acknowledge: If acknowledgment is required, apply it for the upgrade. After upgrade is done set the version gate to WaitForAcknowledge.
AlwaysAcknowledge: If acknowledgment is required, apply it and proceed with the upgrade.
enum:
- Acknowledge
- WaitForAcknowledge
- AlwaysAcknowledge
type: string
workerRoleARN:
description: WorkerRoleARN is an AWS IAM role that will be attached
to worker instances.
Expand All @@ -801,11 +814,17 @@ spec:
- subnets
- supportRoleARN
- version
- versionGate
- workerRoleARN
type: object
status:
description: RosaControlPlaneStatus defines the observed state of ROSAControlPlane.
properties:
availableUpgrades:
description: Available upgrades for the ROSA hosted control plane.
items:
type: string
type: array
conditions:
description: Conditions specifies the conditions for the managed control
plane
Expand Down
27 changes: 27 additions & 0 deletions controlplane/rosa/api/v1beta2/rosacontrolplane_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ const (
Private RosaEndpointAccessType = "Private"
)

// VersionGateAckType specifies the version gate acknowledgement.
type VersionGateAckType string

const (
// Acknowledge if acknowledgment is required and proceed with the upgrade.
Acknowledge VersionGateAckType = "Acknowledge"

// WaitForAcknowledge if acknowledgment is required, wait not to proceed with the upgrade.
WaitForAcknowledge VersionGateAckType = "WaitForAcknowledge"

// AlwaysAcknowledge always acknowledg if required and proceed with the upgrade.
AlwaysAcknowledge VersionGateAckType = "AlwaysAcknowledge"
)

// RosaControlPlaneSpec defines the desired state of ROSAControlPlane.
type RosaControlPlaneSpec struct { //nolint: maligned
// Cluster name must be valid DNS-1035 label, so it must consist of lower case alphanumeric
Expand Down Expand Up @@ -77,6 +91,16 @@ type RosaControlPlaneSpec struct { //nolint: maligned
// OpenShift semantic version, for example "4.14.5".
Version string `json:"version"`

// VersionGate requires acknowledgment when upgrading ROSA-HCP y-stream versions (e.g., from 4.15 to 4.16).
// Default is WaitForAcknowledge.
// WaitForAcknowledge: If acknowledgment is required, the upgrade will not proceed until VersionGate is set to Acknowledge or AlwaysAcknowledge.
// Acknowledge: If acknowledgment is required, apply it for the upgrade. After upgrade is done set the version gate to WaitForAcknowledge.
// AlwaysAcknowledge: If acknowledgment is required, apply it and proceed with the upgrade.
//
// +kubebuilder:validation:Enum=Acknowledge;WaitForAcknowledge;AlwaysAcknowledge
// +kubebuilder:default=WaitForAcknowledge
VersionGate VersionGateAckType `json:"versionGate"`

// AWS IAM roles used to perform credential requests by the openshift operators.
RolesRef AWSRolesRef `json:"rolesRef"`

Expand Down Expand Up @@ -697,6 +721,9 @@ type RosaControlPlaneStatus struct {
ConsoleURL string `json:"consoleURL,omitempty"`
// OIDCEndpointURL is the endpoint url for the managed OIDC provider.
OIDCEndpointURL string `json:"oidcEndpointURL,omitempty"`

// Available upgrades for the ROSA hosted control plane.
AvailableUpgrades []string `json:"availableUpgrades,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
5 changes: 5 additions & 0 deletions controlplane/rosa/api/v1beta2/zz_generated.deepcopy.go

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

24 changes: 22 additions & 2 deletions controlplane/rosa/controllers/rosacontrolplane_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,17 @@ func (r *ROSAControlPlaneReconciler) reconcileClusterVersion(rosaScope *scope.RO
version := rosaScope.ControlPlane.Spec.Version
if version == rosa.RawVersionID(cluster.Version()) {
conditions.MarkFalse(rosaScope.ControlPlane, rosacontrolplanev1.ROSAControlPlaneUpgradingCondition, "upgraded", clusterv1.ConditionSeverityInfo, "")

if cluster.Version() != nil {
rosaScope.ControlPlane.Status.AvailableUpgrades = cluster.Version().AvailableUpgrades()
}

// Set the version gate to WaitForAcknowledge as the previous upgrade is applied.
if rosaScope.ControlPlane.Spec.VersionGate == rosacontrolplanev1.Acknowledge {
rosaScope.ControlPlane.Spec.VersionGate = rosacontrolplanev1.WaitForAcknowledge
}

// return as there is no upgrade to schedule.
return nil
}

Expand All @@ -419,9 +430,18 @@ func (r *ROSAControlPlaneReconciler) reconcileClusterVersion(rosaScope *scope.RO
}

if scheduledUpgrade == nil {
scheduledUpgrade, err = rosa.ScheduleControlPlaneUpgrade(ocmClient, cluster, version, time.Now())
ack := (rosaScope.ControlPlane.Spec.VersionGate == rosacontrolplanev1.Acknowledge || rosaScope.ControlPlane.Spec.VersionGate == rosacontrolplanev1.AlwaysAcknowledge)
scheduledUpgrade, err = rosa.ScheduleControlPlaneUpgrade(ocmClient, cluster, version, time.Now(), ack)
if err != nil {
return fmt.Errorf("failed to schedule control plane upgrade to version %s: %w", version, err)
condition := &clusterv1.Condition{
Type: rosacontrolplanev1.ROSAControlPlaneUpgradingCondition,
Status: corev1.ConditionFalse,
Reason: "failed",
Message: fmt.Sprintf("failed to schedule upgrade to version %s: %v", version, err),
}
conditions.Set(rosaScope.ControlPlane, condition)

return err
}
}

Expand Down
25 changes: 24 additions & 1 deletion pkg/rosa/versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func CheckExistingScheduledUpgrade(client *ocm.Client, cluster *cmv1.Cluster) (*
}

// ScheduleControlPlaneUpgrade schedules a new control plane upgrade to the specified version at the specified time.
func ScheduleControlPlaneUpgrade(client *ocm.Client, cluster *cmv1.Cluster, version string, nextRun time.Time) (*cmv1.ControlPlaneUpgradePolicy, error) {
func ScheduleControlPlaneUpgrade(client *ocm.Client, cluster *cmv1.Cluster, version string, nextRun time.Time, ack bool) (*cmv1.ControlPlaneUpgradePolicy, error) {
// earliestNextRun is set to at least 5 min from now by the OCM API.
// Set our next run request to something slightly longer than 5min to make sure we account for the latency between when we send this
// request and when the server processes it.
Expand All @@ -41,10 +41,32 @@ func ScheduleControlPlaneUpgrade(client *ocm.Client, cluster *cmv1.Cluster, vers
ScheduleType(cmv1.ScheduleTypeManual).
Version(version).
NextRun(nextRun).
EnableMinorVersionUpgrades(true).
Build()
if err != nil {
return nil, err
}

versionGates, err := client.GetMissingGateAgreementsHypershift(cluster.ID(), upgradePolicy)
if err != nil {
return nil, err
}

if !ack && len(versionGates) > 0 {
errMess := "version gate acknowledgement required"
for id := range versionGates {
errMess = fmt.Sprintf(errMess+"\nid:%s\n %s\n %s\n %s\n", versionGates[id].ID(), versionGates[id].Description(), versionGates[id].DocumentationURL(), versionGates[id].WarningMessage())
}

return nil, fmt.Errorf("%s", errMess)
}

for id := range versionGates {
if err = client.AckVersionGate(cluster.ID(), versionGates[id].ID()); err != nil {
return nil, err
}
}

return client.ScheduleHypershiftControlPlaneUpgrade(cluster.ID(), upgradePolicy)
}

Expand All @@ -64,6 +86,7 @@ func ScheduleNodePoolUpgrade(client *ocm.Client, clusterID string, nodePool *cmv
ScheduleType(cmv1.ScheduleTypeManual).
Version(version).
NextRun(nextRun).
EnableMinorVersionUpgrades(true).
Build()
if err != nil {
return nil, err
Expand Down