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

Bug 2075647: pkg/cli/admin/upgrade: Use PATCH instead of POST for spec updates #1111

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Prev Previous commit
Next Next commit
pkg/cli/admin/upgrade: Allow --to-lastest and --allow-not-recommended…
… together

6c8d935 (Adding the flag --allow-not-recommended to oc adm upgrade,
2021-12-01, #986) taught --to and --to-image about
--allow-not-recommended.  This commit extends that coverage to
--to-latest, allowing folks to say "I want the latest supported
update, even if that update is not currently recommended".  Probably
not the best idea to do that sort of thing, but that's generally true
of --allow-not-recommended.

To accomplish this change, I've consolidated into a single "user
requested an update" case, where we use one of the three options
(--to-latest, --to, or --to-image) to hunt for a target update, and
then centralized logic to actually apply that target.
  • Loading branch information
wking committed Apr 14, 2022
commit 27c7bdb46f4380d5cefb011c940eedb3294d3bad
80 changes: 34 additions & 46 deletions pkg/cli/admin/upgrade/upgrade.go
Expand Up @@ -194,47 +194,9 @@ func (o *Options) Run() error {
}
return nil

case o.ToLatestAvailable:
if len(cv.Status.AvailableUpdates) == 0 {
fmt.Fprintf(o.Out, "info: Cluster is already at the latest available version %s\n", cv.Status.Desired.Version)
return nil
}

if err := checkForUpgrade(cv); err != nil {
if !o.AllowUpgradeWithWarnings {
return fmt.Errorf("%s\n\nIf you want to upgrade anyway, use --allow-upgrade-with-warnings.", err)
}
fmt.Fprintf(o.ErrOut, "warning: --allow-upgrade-with-warnings is bypassing: %s", err)
}

sortReleasesBySemanticVersions(cv.Status.AvailableUpdates)

update := cv.Status.AvailableUpdates[0]
desiredUpdate := &configv1.Update{
Version: update.Version,
Image: update.Image,
}
if o.Force {
desiredUpdate.Force = true
fmt.Fprintln(o.ErrOut, "warning: --force overrides cluster verification of your supplied release image and waives any update precondition failures.")
}

cv.Spec.DesiredUpdate = desiredUpdate
_, err := o.Client.ConfigV1().ClusterVersions().Update(context.TODO(), cv, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("Unable to upgrade to latest version %s: %v", update.Version, err)
}

if len(update.Version) > 0 {
fmt.Fprintf(o.Out, "Updating to latest version %s\n", update.Version)
} else {
fmt.Fprintf(o.Out, "Updating to latest release image %s\n", update.Image)
}

return nil

case len(o.To) > 0, len(o.ToImage) > 0:
case o.ToLatestAvailable, len(o.To) > 0, len(o.ToImage) > 0:
var update *configv1.Update

if len(o.To) > 0 && o.To == cv.Status.Desired.Version {
fmt.Fprintf(o.Out, "info: Cluster is already at version %s\n", o.To)
return nil
Expand All @@ -245,7 +207,8 @@ func (o *Options) Run() error {
return nil
}

possibleUpgradeTargets := make([]string, 0, len(cv.Status.AvailableUpdates)+len(cv.Status.ConditionalUpdates))
possibleUpgradeTargets := make([]configv1.Release, 0, len(cv.Status.AvailableUpdates)+len(cv.Status.ConditionalUpdates))
recommendedConditions := make(map[string]metav1.Condition, len(cv.Status.ConditionalUpdates))

// check for recommended updates
for _, available := range cv.Status.AvailableUpdates {
Expand All @@ -258,7 +221,7 @@ func (o *Options) Run() error {
} else if err != nil {
fmt.Fprintf(o.ErrOut, "warning: unable to calculate match for the update target in available updates: %v\n", err)
}
possibleUpgradeTargets = append(possibleUpgradeTargets, available.Version)
possibleUpgradeTargets = append(possibleUpgradeTargets, available)
}

if update == nil {
Expand All @@ -282,7 +245,8 @@ func (o *Options) Run() error {
fmt.Fprintf(o.ErrOut, "warning: unable to calculate match for the update target in available conditional updates: %v\n", err)
}
if o.AllowNotRecommended {
possibleUpgradeTargets = append(possibleUpgradeTargets, upgrade.Release.Version)
possibleUpgradeTargets = append(possibleUpgradeTargets, upgrade.Release)
recommendedConditions[upgrade.Release.Image] = *c
}
}
}
Expand All @@ -297,25 +261,49 @@ func (o *Options) Run() error {
"You have used --allow-explicit-upgrade for the update to proceed anyway")
}

sortReleasesBySemanticVersions(possibleUpgradeTargets)

if o.ToLatestAvailable && len(possibleUpgradeTargets) > 0 {
update = &configv1.Update{
Version: possibleUpgradeTargets[0].Version,
Image: possibleUpgradeTargets[0].Image,
}

if c, ok := recommendedConditions[update.Image]; ok {
fmt.Fprintf(o.ErrOut, "warning: with --allow-not-recommended you have accepted the risks with %s and bypassed %s=%s %s: %s\n",
update.Version, c.Type, c.Status, c.Reason, c.Message)
}
}

if update == nil {
sort.Strings(possibleUpgradeTargets)
c := findClusterOperatorStatusCondition(cv.Status.Conditions, configv1.RetrievedUpdates)

toImageOption := "--to-image"
if o.ToImage != "" {
toImageOption = "--allow-explicit-upgrade"
}
nextStep := fmt.Sprintf("%s to continue with the update", toImageOption)
article := "the" // --to and --to-image have a specific target in mind
if o.ToLatestAvailable {
article = "an" // --to-latest does not have a specific target in mind
}
nextStep := fmt.Sprintf("%s to continue with %s update", toImageOption, article)

switch {
case c != nil && c.Status != configv1.ConditionTrue:
return fmt.Errorf("cannot refresh available updates:\n Reason: %s\n Message: %s\n\nspecify %s.", c.Reason, strings.ReplaceAll(c.Message, "\n", "\n "), nextStep)
case len(possibleUpgradeTargets) == 0 && o.AllowNotRecommended:
return fmt.Errorf("no recommended or conditional updates, specify %s or wait for new updates to be available.", nextStep)
case len(possibleUpgradeTargets) == 0 && o.ToLatestAvailable:
fmt.Fprintf(o.Out, "info: Cluster is already at the latest available version %s\n", cv.Status.Desired.Version)
return nil
case len(possibleUpgradeTargets) == 0:
return fmt.Errorf("no recommended updates, specify %s or wait for new updates to be available.", nextStep)
case len(possibleUpgradeTargets) > 0:
return fmt.Errorf("the update is not one of the possible targets: %s. specify %s.", strings.Join(possibleUpgradeTargets, ", "), nextStep)
versions := make([]string, 0, len(possibleUpgradeTargets))
for _, release := range possibleUpgradeTargets {
versions = append(versions, release.Version)
}
return fmt.Errorf("the update is not one of the possible targets: %s. specify %s.", strings.Join(versions, ", "), nextStep)
default:
return errors.New("unable to calculate a target update")
}
Expand Down