Skip to content

Commit

Permalink
Require extra flag when updating cluster with downgraded kops version
Browse files Browse the repository at this point in the history
  • Loading branch information
johngmyers committed Jun 14, 2020
1 parent d6f03b3 commit 23c5843
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 13 deletions.
17 changes: 10 additions & 7 deletions cmd/kops/update_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ var (
)

type UpdateClusterOptions struct {
Yes bool
Target string
Models string
OutDir string
SSHPublicKey string
RunTasksOptions fi.RunTasksOptions
CreateKubecfg bool
Yes bool
Target string
Models string
OutDir string
SSHPublicKey string
RunTasksOptions fi.RunTasksOptions
CreateKubecfg bool
AllowKopsDowngrade bool

Phase string

Expand Down Expand Up @@ -116,6 +117,7 @@ func NewCmdUpdateCluster(f *util.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringVar(&options.SSHPublicKey, "ssh-public-key", options.SSHPublicKey, "SSH public key to use (deprecated: use kops create secret instead)")
cmd.Flags().StringVar(&options.OutDir, "out", options.OutDir, "Path to write any local output")
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.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"))
Expand Down Expand Up @@ -262,6 +264,7 @@ func RunUpdateCluster(ctx context.Context, f *util.Factory, clusterName string,
Clientset: clientset,
Cluster: cluster,
DryRun: isDryrun,
AllowKopsDowngrade: c.AllowKopsDowngrade,
InstanceGroups: instanceGroups,
RunTasksOptions: &c.RunTasksOptions,
Models: strings.Split(c.Models, ","),
Expand Down
1 change: 1 addition & 0 deletions docs/cli/kops_update_cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ kops update cluster [flags]
### Options

```
--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 (default true)
-h, --help help for cluster
--lifecycle-overrides strings comma separated list of phase overrides, example: SecurityGroups=Ignore,InternetGateway=ExistsAndWarnIfChanges
Expand Down
3 changes: 3 additions & 0 deletions docs/releases/1.19-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

* Clusters using the Amazon VPC CNI provider now perform an `ec2.DescribeInstanceTypes` call at instance launch time. In large clusters or AWS accounts this may lead to API throttling which could delay node readiness. If this becomes a problem please open a GitHub issue.

* 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.
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/kops/registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ const (
PathCluster = "config"
// Path for completed cluster spec in the state store
PathClusterCompleted = "cluster.spec"
// PathKopsVersion is the path for the version of kops last used to apply the cluster.
PathKopsVersionApplied = "kops-version-applied.txt"
)

func ConfigBase(c *api.Cluster) (vfs.Path, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/client/simple/vfsclientset/clientset.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func DeleteAllClusterState(basePath vfs.Path) error {
continue
}

if relativePath == "config" || relativePath == "cluster.spec" {
if relativePath == "config" || relativePath == "cluster.spec" || relativePath == "kops-version-applied.txt" {
continue
}
if strings.HasPrefix(relativePath, "addons/") {
Expand Down
1 change: 1 addition & 0 deletions upup/pkg/fi/cloudup/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,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/registry:go_default_library",
"//pkg/apis/kops/util:go_default_library",
Expand Down
47 changes: 42 additions & 5 deletions upup/pkg/fi/cloudup/apply_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package cloudup

import (
"bytes"
"context"
"fmt"
"net/url"
Expand All @@ -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"
Expand Down Expand Up @@ -126,6 +128,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

Expand Down Expand Up @@ -234,6 +239,34 @@ 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 {
kopsVersionApplied, err := configBase.Join(registry.PathKopsVersionApplied).ReadFile()
if err == nil {
version, err := semver.Parse(strings.TrimSpace(string(kopsVersionApplied)))
if err != nil {
return fmt.Errorf("error parsing last kops version applied: %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", kopsVersionApplied)
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 that last used to apply cluster")
}
} else if err != os.ErrNotExist {
return fmt.Errorf("error reading last kops version applied: %v", err)
}
}

cloud, err := BuildCloud(cluster)
if err != nil {
return err
Expand All @@ -255,11 +288,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
Expand Down Expand Up @@ -876,6 +904,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.PathKopsVersionApplied).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)
Expand Down

0 comments on commit 23c5843

Please sign in to comment.