Require extra flag when updating cluster with downgraded kops version

This commit is contained in:
John Gardiner Myers 2020-06-14 14:43:36 -07:00
parent 6f3c067e5e
commit 3201cc4dd8
7 changed files with 59 additions and 11 deletions

View File

@ -59,11 +59,12 @@ var (
)
type UpdateClusterOptions struct {
Yes bool
Target string
OutDir string
SSHPublicKey string
RunTasksOptions fi.RunTasksOptions
Yes bool
Target string
OutDir string
SSHPublicKey string
RunTasksOptions fi.RunTasksOptions
AllowKopsDowngrade bool
CreateKubecfg bool
admin bool
@ -117,6 +118,7 @@ func NewCmdUpdateCluster(f *util.Factory, out io.Writer) *cobra.Command {
cmd.Flags().BoolVar(&options.CreateKubecfg, "create-kube-config", options.CreateKubecfg, "Will control automatically creating the kube config file on your local filesystem")
cmd.Flags().BoolVar(&options.admin, "admin", options.admin, "Also export the admin user. Implies --create-kube-config")
cmd.Flags().StringVar(&options.user, "user", options.user, "Existing user to add to the cluster context. Implies --create-kube-config")
cmd.Flags().BoolVar(&options.AllowKopsDowngrade, "allow-kops-downgrade", options.AllowKopsDowngrade, "Allow an older version of kops to update the cluster than last used")
cmd.Flags().StringVar(&options.Phase, "phase", options.Phase, "Subset of tasks to run: "+strings.Join(cloudup.Phases.List(), ", "))
cmd.Flags().StringSliceVar(&options.LifecycleOverrides, "lifecycle-overrides", options.LifecycleOverrides, "comma separated list of phase overrides, example: SecurityGroups=Ignore,InternetGateway=ExistsAndWarnIfChanges")
viper.BindPFlag("lifecycle-overrides", cmd.Flags().Lookup("lifecycle-overrides"))
@ -259,6 +261,7 @@ func RunUpdateCluster(ctx context.Context, f *util.Factory, clusterName string,
Clientset: clientset,
Cluster: cluster,
DryRun: isDryrun,
AllowKopsDowngrade: c.AllowKopsDowngrade,
RunTasksOptions: &c.RunTasksOptions,
OutDir: c.OutDir,
Phase: phase,

View File

@ -26,6 +26,7 @@ kops update cluster [flags]
```
--admin Also export the admin user. Implies --create-kube-config
--allow-kops-downgrade Allow an older version of kops to update the cluster than last used
--create-kube-config Will control automatically creating the kube config file on your local filesystem
-h, --help help for cluster
--lifecycle-overrides strings comma separated list of phase overrides, example: SecurityGroups=Ignore,InternetGateway=ExistsAndWarnIfChanges

View File

@ -22,6 +22,9 @@ Similarly, `kops export kubecfg` will also require passing either the `--admin`
* New clusters running Cilium will have enabled BPF NodePort by default if kubernetes version is 1.12 or newer.
* The `kops update cluster` command will now refuse to run on a cluster that
has been updated by a newer version of kops unless it is given the `--allow-kops-downgrade` flag.
# Breaking changes
* Support for Kubernetes 1.9 and 1.10 has been removed.

View File

@ -29,6 +29,8 @@ const (
PathCluster = "config"
// Path for completed cluster spec in the state store
PathClusterCompleted = "cluster.spec"
// PathKopsVersionUpdated is the path for the version of kops last used to apply the cluster.
PathKopsVersionUpdated = "kops-version.txt"
)
func ConfigBase(c *api.Cluster) (vfs.Path, error) {

View File

@ -139,7 +139,7 @@ func DeleteAllClusterState(basePath vfs.Path) error {
continue
}
if relativePath == "config" || relativePath == "cluster.spec" {
if relativePath == "config" || relativePath == "cluster.spec" || relativePath == registry.PathKopsVersionUpdated {
continue
}
if strings.HasPrefix(relativePath, "addons/") {

View File

@ -31,6 +31,7 @@ go_library(
"//dnsprovider/pkg/dnsprovider:go_default_library",
"//dnsprovider/pkg/dnsprovider/providers/aws/route53:go_default_library",
"//dnsprovider/pkg/dnsprovider/rrstype:go_default_library",
"//pkg/acls:go_default_library",
"//pkg/apis/kops:go_default_library",
"//pkg/apis/kops/model:go_default_library",
"//pkg/apis/kops/registry:go_default_library",

View File

@ -17,6 +17,7 @@ limitations under the License.
package cloudup
import (
"bytes"
"context"
"fmt"
"net/url"
@ -28,6 +29,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog"
kopsbase "k8s.io/kops"
"k8s.io/kops/pkg/acls"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/registry"
"k8s.io/kops/pkg/apis/kops/util"
@ -112,6 +114,9 @@ type ApplyClusterCmd struct {
// DryRun is true if this is only a dry run
DryRun bool
// AllowKopsDowngrade permits applying with a kops version older than what was last used to apply to the cluster.
AllowKopsDowngrade bool
// RunTasksOptions defines parameters for task execution, e.g. retry interval
RunTasksOptions *fi.RunTasksOptions
@ -229,6 +234,35 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error {
cluster := c.Cluster
configBase, err := vfs.Context.BuildVfsPath(cluster.Spec.ConfigBase)
if err != nil {
return fmt.Errorf("error parsing config base %q: %v", cluster.Spec.ConfigBase, err)
}
if !c.AllowKopsDowngrade {
kopsVersionUpdatedBytes, err := configBase.Join(registry.PathKopsVersionUpdated).ReadFile()
if err == nil {
kopsVersionUpdated := strings.TrimSpace(string(kopsVersionUpdatedBytes))
version, err := semver.Parse(kopsVersionUpdated)
if err != nil {
return fmt.Errorf("error parsing last kops version updated: %v", err)
}
if version.GT(semver.MustParse(kopsbase.Version)) {
fmt.Printf("\n")
fmt.Printf("%s\n", starline)
fmt.Printf("\n")
fmt.Printf("The cluster was last updated by kops version %s\n", kopsVersionUpdated)
fmt.Printf("To permit updating by the older version %s, run with the --allow-kops-downgrade flag\n", kopsbase.Version)
fmt.Printf("\n")
fmt.Printf("%s\n", starline)
fmt.Printf("\n")
return fmt.Errorf("kops version older than last used to update the cluster")
}
} else if err != os.ErrNotExist {
return fmt.Errorf("error reading last kops version used to update: %v", err)
}
}
cloud, err := BuildCloud(cluster)
if err != nil {
return err
@ -250,11 +284,6 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error {
l.Init()
l.Cluster = c.Cluster
configBase, err := vfs.Context.BuildVfsPath(cluster.Spec.ConfigBase)
if err != nil {
return fmt.Errorf("error parsing config base %q: %v", cluster.Spec.ConfigBase, err)
}
keyStore, err := c.Clientset.KeyStore(cluster)
if err != nil {
return err
@ -743,6 +772,15 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error {
c.Target = target
if !dryRun {
acl, err := acls.GetACL(configBase, cluster)
if err != nil {
return err
}
err = configBase.Join(registry.PathKopsVersionUpdated).WriteFile(bytes.NewReader([]byte(kopsbase.Version)), acl)
if err != nil {
return fmt.Errorf("error writing kops version: %v", err)
}
err = registry.WriteConfigDeprecated(cluster, configBase.Join(registry.PathClusterCompleted), c.Cluster)
if err != nil {
return fmt.Errorf("error writing completed cluster spec: %v", err)