-
Notifications
You must be signed in to change notification settings - Fork 1.4k
✨clusterctl: add upgrade plan cmd #2178
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
Copyright 2019 The Kubernetes Authors. | ||
Copyright 2020 The Kubernetes Authors. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
|
@@ -16,4 +16,135 @@ limitations under the License. | |
|
||
package cmd | ||
|
||
// TODO: upgrade command | ||
import ( | ||
"fmt" | ||
"os" | ||
"sort" | ||
"text/tabwriter" | ||
|
||
"github.com/spf13/cobra" | ||
"sigs.k8s.io/cluster-api/cmd/clusterctl/pkg/client" | ||
) | ||
|
||
var upgradeCmd = &cobra.Command{ | ||
Use: "upgrade", | ||
Short: "Upgrades Cluster API providers in a management cluster", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return cmd.Help() | ||
}, | ||
} | ||
|
||
type upgradePlanOptions struct { | ||
kubeconfig string | ||
} | ||
|
||
var up = &upgradePlanOptions{} | ||
|
||
var upgradePlanCmd = &cobra.Command{ | ||
Use: "plan", | ||
Short: "Provide a list of recommended target versions for upgrading Cluster API providers in a management cluster", | ||
Long: LongDesc(` | ||
The upgrade plan command provides a list of recommended target versions for upgrading Cluster API providers in a management cluster. | ||
|
||
The providers are grouped into management groups, each one defining a set of providers that should be supporting the same cluster API version | ||
in order to guarantee the proper functioning of the management cluster. | ||
|
||
Then, for each provider in a management group, the following upgrade options are provided: | ||
- The latest patch release for the current Cluster API version. | ||
- The latest patch release for the next Cluster API version, if available.`), | ||
|
||
Example: Examples(` | ||
# Gets the recommended target versions for upgrading Cluster API providers. | ||
clusterctl upgrade plan`), | ||
|
||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return runUpgradePlan() | ||
}, | ||
} | ||
|
||
func init() { | ||
upgradePlanCmd.Flags().StringVarP(&up.kubeconfig, "kubeconfig", "", "", "Path to the kubeconfig file to use for accessing the management cluster. If empty, default rules for kubeconfig discovery will be used") | ||
|
||
upgradeCmd.AddCommand(upgradePlanCmd) | ||
|
||
RootCmd.AddCommand(upgradeCmd) | ||
} | ||
|
||
func runUpgradePlan() error { | ||
c, err := client.New(cfgFile) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
//TODO: switch to klog as soon as https://github.com/kubernetes-sigs/cluster-api/pull/2150 merge | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems we can switch now? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately no, because we switched to the global logger approach and this is not yet merged. Waiting for #2191 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since 2191 is blocked on this PR, we can create an issue to track this work or I'm assuming @fabriziopandini will be submitting a PR to refactor the upgrade cmd to use the global logger. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. He's going to update 2191 after this goes in |
||
fmt.Println("Checking new release availability...") | ||
upgradePlans, err := c.PlanUpgrade(client.PlanUpgradeOptions{ | ||
Kubeconfig: up.kubeconfig, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// ensure upgrade plans are sorted consistently (by CoreProvider.Namespace, ClusterAPIVersion). | ||
sortUpgradePlans(upgradePlans) | ||
|
||
if len(upgradePlans) == 0 { | ||
fmt.Println("There are no management groups in the cluster. Please use clusterctl init to initialize a Cluster API management cluster.") | ||
return nil | ||
} | ||
|
||
for _, plan := range upgradePlans { | ||
// ensure provider are sorted consistently (by Type, Name, Namespace). | ||
sortUpgradeItems(plan) | ||
|
||
upgradeAvailable := false | ||
|
||
fmt.Println("") | ||
fmt.Printf("Management group: %s/%s, latest release available for the %s Cluster API version:\n", plan.CoreProvider.Namespace, plan.CoreProvider.Name, plan.ClusterAPIVersion) | ||
fmt.Println("") | ||
w := tabwriter.NewWriter(os.Stdout, 10, 4, 3, ' ', 0) | ||
fmt.Fprintln(w, "NAME\tNAMESPACE\tTYPE\tCURRENT VERSION\tNEXT VERSION") | ||
for _, upgradeItem := range plan.Providers { | ||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", upgradeItem.Provider.Name, upgradeItem.Provider.Namespace, upgradeItem.Provider.Type, upgradeItem.Provider.Version, prettifyTargetVersion(upgradeItem.NextVersion)) | ||
if upgradeItem.NextVersion != "" { | ||
upgradeAvailable = true | ||
} | ||
} | ||
w.Flush() | ||
fmt.Println("") | ||
|
||
if upgradeAvailable { | ||
fmt.Println("You can now apply the upgrade by executing the following command:") | ||
fmt.Println("") | ||
fmt.Println(fmt.Sprintf(" upgrade apply --management-group %s/%s --cluster-api-version %s", plan.CoreProvider.Namespace, plan.CoreProvider.Name, plan.ClusterAPIVersion)) | ||
} else { | ||
fmt.Println("You are already up to date!") | ||
} | ||
fmt.Println("") | ||
|
||
} | ||
|
||
return nil | ||
} | ||
|
||
func sortUpgradeItems(plan client.UpgradePlan) { | ||
sort.Slice(plan.Providers, func(i, j int) bool { | ||
return plan.Providers[i].Provider.Type < plan.Providers[j].Provider.Type || | ||
(plan.Providers[i].Provider.Type == plan.Providers[j].Provider.Type && plan.Providers[i].Provider.Name < plan.Providers[j].Provider.Name) || | ||
(plan.Providers[i].Provider.Type == plan.Providers[j].Provider.Type && plan.Providers[i].Provider.Name == plan.Providers[j].Provider.Name && plan.Providers[i].Provider.Namespace < plan.Providers[j].Provider.Namespace) | ||
}) | ||
} | ||
|
||
func sortUpgradePlans(upgradePlans []client.UpgradePlan) { | ||
sort.Slice(upgradePlans, func(i, j int) bool { | ||
return upgradePlans[i].CoreProvider.Namespace < upgradePlans[j].CoreProvider.Namespace || | ||
(upgradePlans[i].CoreProvider.Namespace == upgradePlans[j].CoreProvider.Namespace && upgradePlans[i].ClusterAPIVersion < upgradePlans[j].ClusterAPIVersion) | ||
}) | ||
} | ||
|
||
func prettifyTargetVersion(version string) string { | ||
if version == "" { | ||
return "Already up to date" | ||
} | ||
return version | ||
} |
Uh oh!
There was an error while loading. Please reload this page.