Skip to content

Commit

Permalink
Add functionality to increment control plane version
Browse files Browse the repository at this point in the history
  • Loading branch information
errordeveloper committed Mar 5, 2019
1 parent 926ea1a commit e896995
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 4 deletions.
63 changes: 59 additions & 4 deletions pkg/ctl/update/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ import (
"github.com/weaveworks/eksctl/pkg/printers"
)

var updateClusterDryRun = true
var (
updateClusterDryRun = true
updateClusterWait = true
)

func updateClusterCmd(g *cmdutils.Grouping) *cobra.Command {
p := &api.ProviderConfig{}
cfg := api.NewClusterConfig()

// cfg.Metadata.Version = "next"

cmd := &cobra.Command{
Use: "cluster",
Short: "Update cluster",
Expand All @@ -37,8 +42,9 @@ func updateClusterCmd(g *cmdutils.Grouping) *cobra.Command {
group.InFlagSet("General", func(fs *pflag.FlagSet) {
fs.StringVarP(&cfg.Metadata.Name, "name", "n", "", "EKS cluster name (required)")
cmdutils.AddRegionFlag(fs, p)
cmdutils.AddVersionFlag(fs, cfg.Metadata, "")
// cmdutils.AddVersionFlag(fs, cfg.Metadata, `"next" and "latest" can be used to automatically increment version by one, or force latest`)
fs.BoolVar(&updateClusterDryRun, "dry-run", updateClusterDryRun, "do not apply any change, only show what resources would be added")
cmdutils.AddWaitFlag(&updateClusterWait, fs, "all update operations to complete")
})

cmdutils.AddCommonFlagsForAWS(group, p, false)
Expand All @@ -62,6 +68,11 @@ func doUpdateClusterCmd(p *api.ProviderConfig, cfg *api.ClusterConfig, nameArg s

ctl := eks.New(p, cfg)

if !ctl.IsSupportedRegion() {
return cmdutils.ErrUnsupportedRegion(p)
}
logger.Info("using region %s", cfg.Metadata.Region)

printer := printers.NewJSONPrinter()

if err := api.Register(); err != nil {
Expand All @@ -72,6 +83,25 @@ func doUpdateClusterCmd(p *api.ProviderConfig, cfg *api.ClusterConfig, nameArg s
return err
}

if err := ctl.GetCredentials(cfg); err != nil {
return errors.Wrapf(err, "getting credentials for cluster %q", cfg.Metadata.Name)
}

currentVersion := ctl.ControlPlaneVersion()
// determine next version based on what's currently deployed
switch currentVersion {
case "":
return fmt.Errorf("unable to get control plane version")
case api.Version1_10:
cfg.Metadata.Version = api.Version1_11
case api.LatestVersion:
cfg.Metadata.Version = api.LatestVersion
default:
// version of control is not known to us, maybe we are just too old...
return fmt.Errorf("control plane version version %q is known to this version of eksctl, try to upgrade eksctl first", currentVersion)
}
versionUpdateRequired := cfg.Metadata.Version != currentVersion

if err := ctl.GetClusterVPC(cfg); err != nil {
return errors.Wrapf(err, "getting VPC configuration for cluster %q", cfg.Metadata.Name)
}
Expand All @@ -82,7 +112,7 @@ func doUpdateClusterCmd(p *api.ProviderConfig, cfg *api.ClusterConfig, nameArg s

stackManager := ctl.NewStackManager(cfg)

updateRequired, err := stackManager.AppendNewClusterStackResource(updateClusterDryRun)
stackUpdateRequired, err := stackManager.AppendNewClusterStackResource(updateClusterDryRun)
if err != nil {
return err
}
Expand All @@ -91,7 +121,32 @@ func doUpdateClusterCmd(p *api.ProviderConfig, cfg *api.ClusterConfig, nameArg s
logger.Critical("failed checking nodegroups", err.Error())
}

if updateClusterDryRun && updateRequired {
if versionUpdateRequired {
msg := func(verb string) {
logger.Info("cluster %q control plane %s upgraded from current version %q to %q", cfg.Metadata.Name, verb, currentVersion, cfg.Metadata.Version)
}
msgNodeGroupsAndAddons := "you will need to follow the upgrade procedure for all of nodegroups and add-ons"
if updateClusterDryRun {
msg("can be")
} else {
msg("will be")
if updateClusterWait {
if err := ctl.UpdateClusterVersionBlocking(cfg); err != nil {
return err
}
logger.Success("cluster %q control plan e has been upgraded to version %q", cfg.Metadata.Name, cfg.Metadata.Version)
logger.Info(msgNodeGroupsAndAddons)
} else {
if _, err := ctl.UpdateClusterVersion(cfg); err != nil {
return err
}
logger.Success("a version update operation has been requested for cluster %q", cfg.Metadata.Name)
logger.Info("once it has been updated, %s", cfg.Metadata.Name, msgNodeGroupsAndAddons)
}
}
}

if updateClusterDryRun && (stackUpdateRequired || versionUpdateRequired) {
logger.Warning("no changes were applied, run again with '--dry-run=false' to apply the changes")
}

Expand Down
47 changes: 47 additions & 0 deletions pkg/eks/eks.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import (
"github.com/kris-nova/logger"
"github.com/pkg/errors"

"github.com/aws/aws-sdk-go/aws/request"
awseks "github.com/aws/aws-sdk-go/service/eks"

"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/kubernetes"

api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha4"
"github.com/weaveworks/eksctl/pkg/printers"
"github.com/weaveworks/eksctl/pkg/utils/waiters"
"github.com/weaveworks/eksctl/pkg/vpc"
)

Expand Down Expand Up @@ -261,6 +263,51 @@ func (c *ClusterProvider) WaitForControlPlane(id *api.ClusterMeta, clientSet *ku
}
}

// UpdateClusterVersion calls eks.UpdateClusterVersion and updates to cfg.Metadata.Version,
// it will return update ID along with an error (if it occurrs)
func (c *ClusterProvider) UpdateClusterVersion(cfg *api.ClusterConfig) (string, error) {
input := &awseks.UpdateClusterVersionInput{
Name: &cfg.Metadata.Name,
Version: &cfg.Metadata.Version,
}
output, err := c.Provider.EKS().UpdateClusterVersion(input)
if err != nil {
return "", err
}
return *output.Update.Id, nil
}

// UpdateClusterVersionBlocking calls UpdateClusterVersion and blocks until update
// operation is successful
func (c *ClusterProvider) UpdateClusterVersionBlocking(cfg *api.ClusterConfig) error {
id, err := c.UpdateClusterVersion(cfg)
if err != nil {
return err
}

newRequest := func() *request.Request {
input := &awseks.DescribeUpdateInput{
Name: &cfg.Metadata.Name,
UpdateId: &id,
}
req, _ := c.Provider.EKS().DescribeUpdateRequest(input)
return req
}

msg := fmt.Sprintf("waiting for control plane %q version update", cfg.Metadata.Name)

acceptors := waiters.MakeAcceptors(
"Update.Status",
awseks.UpdateStatusSuccessful,
[]string{
awseks.UpdateStatusCancelled,
awseks.UpdateStatusFailed,
},
)

return waiters.Wait(cfg.Metadata.Name, msg, acceptors, newRequest, c.Provider.WaitTimeout(), nil)
}

func addSummaryTableColumns(printer *printers.TablePrinter) {
printer.AddColumn("NAME", func(c *awseks.Cluster) string {
return *c.Name
Expand Down

0 comments on commit e896995

Please sign in to comment.