Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.73.0
github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.60.2
github.com/aws/aws-sdk-go-v2/service/ec2 v1.302.0
github.com/aws/aws-sdk-go-v2/service/eks v1.87.0
github.com/aws/aws-sdk-go-v2/service/eks v1.88.0
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.25
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.54.12
github.com/aws/aws-sdk-go-v2/service/iam v1.53.10
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.60.2 h1:pZxE29WA
github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.60.2/go.mod h1:nbe4Nf/HOY+e54Dl+yjv04scYTGTC+4ZthbfOuPTXQs=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.302.0 h1:7c0jQaj+QKYUo3pgtEm9fQIePJH6QJA3bVKIgCCLdvM=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.302.0/go.mod h1:Y95W0Hm6FYLPa6o0hbnJ+sWgmdc4ifcLFjGkdobWVhY=
github.com/aws/aws-sdk-go-v2/service/eks v1.87.0 h1:bftLltXNWmNr9ed3CaQnVlzNPTNTFdHguNhIsZF6DxM=
github.com/aws/aws-sdk-go-v2/service/eks v1.87.0/go.mod h1:rbIASs+SfCDUXx2EdfMkNpDGptlW8hvMZ9AawRiUBqE=
github.com/aws/aws-sdk-go-v2/service/eks v1.88.0 h1:dP/bd/5AG73UJGXyZh6gQSafVS9T+mBQgIULtJvzEnE=
github.com/aws/aws-sdk-go-v2/service/eks v1.88.0/go.mod h1:rbIASs+SfCDUXx2EdfMkNpDGptlW8hvMZ9AawRiUBqE=
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.25 h1:VzmoYPRbNSUqk3pA04ZyGZUg52yfX259XXRqwr1lns4=
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.33.25/go.mod h1:r7chQGimOmFs4oqawhO+i+o3ez2l69rzAco5KTb7bjY=
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.54.12 h1:TJXv7kZjdXA2maPDaJFFEQPBrPmvPtMybN3qYDOpJ4Y=
Expand Down
15 changes: 13 additions & 2 deletions pkg/actions/cluster/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5"
"github.com/weaveworks/eksctl/pkg/ctl/cmdutils"
"github.com/weaveworks/eksctl/pkg/eks"
"github.com/weaveworks/eksctl/pkg/utils"
)

func upgrade(ctx context.Context, cfg *api.ClusterConfig, ctl *eks.ClusterProvider, dryRun bool) (bool, error) {
Expand All @@ -31,14 +32,24 @@ func upgrade(ctx context.Context, cfg *api.ClusterConfig, ctl *eks.ClusterProvid
}

if upgradeVersion != "" {
currentVersion := ctl.ControlPlaneVersion()
// A resolved target lower than the current version is a rollback (downgrade);
// use direction-aware wording so the logs don't say "upgrade" for a downgrade.
action, pastAction := "upgrade", "upgraded"
if c, err := utils.CompareVersions(upgradeVersion, currentVersion); err != nil {
return false, err
} else if c < 0 {
action, pastAction = "roll back", "rolled back"
}

msgNodeGroupsAndAddons := "you will need to follow the upgrade procedure for all of nodegroups and add-ons"
cmdutils.LogIntendedAction(dryRun, "upgrade cluster %q control plane from current version %q to %q", cfg.Metadata.Name, ctl.ControlPlaneVersion(), upgradeVersion)
cmdutils.LogIntendedAction(dryRun, "%s cluster %q control plane from current version %q to %q", action, cfg.Metadata.Name, currentVersion, upgradeVersion)
if !dryRun {
cfg.Metadata.Version = upgradeVersion
if err := ctl.UpdateClusterVersionBlocking(ctx, cfg); err != nil {
return false, err
}
logger.Success("cluster %q control plane has been upgraded to version %q", cfg.Metadata.Name, cfg.Metadata.Version)
logger.Success("cluster %q control plane has been %s to version %q", cfg.Metadata.Name, pastAction, cfg.Metadata.Version)
logger.Info(msgNodeGroupsAndAddons)
}
} else {
Expand Down
21 changes: 21 additions & 0 deletions pkg/apis/eksctl.io/v1alpha5/assets/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,11 @@
"description": "the AWS region hosting this cluster",
"x-intellij-html-description": "the AWS region hosting this cluster"
},
"rollbackConfig": {
"$ref": "#/definitions/RollbackConfig",
"description": "configures the automatic rollback behaviour when updating the cluster version (including downgrades).",
"x-intellij-html-description": "configures the automatic rollback behaviour when updating the cluster version (including downgrades)."
},
"tags": {
"additionalProperties": {
"type": "string"
Expand All @@ -1092,6 +1097,7 @@
"region",
"version",
"forceUpdateVersion",
"rollbackConfig",
"tags",
"annotations"
],
Expand Down Expand Up @@ -3053,6 +3059,21 @@
],
"additionalProperties": false
},
"RollbackConfig": {
"properties": {
"timeoutMinutes": {
"type": "integer",
"description": "length of time in minutes to wait before cancelling the update. The timeout is a minimum-bound: cancellation occurs no sooner than the time specified, but can occur shortly thereafter. Valid values are between 120 (2 hours) and 10080 (7 days). When unset, EKS defaults to 720 (12 hours).",
"x-intellij-html-description": "length of time in minutes to wait before cancelling the update. The timeout is a minimum-bound: cancellation occurs no sooner than the time specified, but can occur shortly thereafter. Valid values are between 120 (2 hours) and 10080 (7 days). When unset, EKS defaults to 720 (12 hours)."
}
},
"preferredOrder": [
"timeoutMinutes"
],
"additionalProperties": false,
"description": "holds the rollback configuration used when updating the cluster version. EKS waits for the configured timeout before automatically cancelling an in-progress cluster version update.",
"x-intellij-html-description": "holds the rollback configuration used when updating the cluster version. EKS waits for the configured timeout before automatically cancelling an in-progress cluster version update."
},
"SSOIdentity": {
"required": [
"id",
Expand Down
17 changes: 17 additions & 0 deletions pkg/apis/eksctl.io/v1alpha5/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,10 @@ type ClusterMeta struct {
// When updating cluster version, provide the force flag to override upgrade-blocking insights
// +optional
ForceUpdateVersion *bool `json:"forceUpdateVersion,omitempty"`
// RollbackConfig configures the automatic rollback behaviour when updating
// the cluster version (including downgrades).
// +optional
RollbackConfig *RollbackConfig `json:"rollbackConfig,omitempty"`
// Tags are used to tag AWS resources created by eksctl
// +optional
Tags map[string]string `json:"tags,omitempty"`
Expand All @@ -727,6 +731,19 @@ type UpgradePolicy struct {
SupportType string `json:"supportType,omitempty"`
}

// RollbackConfig holds the rollback configuration used when updating the
// cluster version. EKS waits for the configured timeout before automatically
// cancelling an in-progress cluster version update.
type RollbackConfig struct {
// TimeoutMinutes is the length of time in minutes to wait before cancelling
// the update. The timeout is a minimum-bound: cancellation occurs no sooner
// than the time specified, but can occur shortly thereafter. Valid values
// are between 120 (2 hours) and 10080 (7 days). When unset, EKS defaults to
// 720 (12 hours).
// +optional
TimeoutMinutes *int `json:"timeoutMinutes,omitempty"`
}

// KubernetesNetworkConfig contains cluster networking options
type KubernetesNetworkConfig struct {
// Valid variants are `IPFamily` constants
Expand Down
23 changes: 23 additions & 0 deletions pkg/apis/eksctl.io/v1alpha5/validation.go

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could consider adding validations around the rest of pre-requisites for version rollback https://docs.aws.amazon.com/eks/latest/userguide/rollback-cluster.html

Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,23 @@ func validateSupportType(supportType string) error {
return nil
}

// RollbackTimeoutMinutesMin and RollbackTimeoutMinutesMax are the inclusive
// bounds EKS accepts for metadata.rollbackConfig.timeoutMinutes.
const (
RollbackTimeoutMinutesMin = 120
RollbackTimeoutMinutesMax = 10080
)

func validateRollbackConfig(rollbackConfig *RollbackConfig) error {
if rollbackConfig == nil || rollbackConfig.TimeoutMinutes == nil {
return nil
}
if timeout := *rollbackConfig.TimeoutMinutes; timeout < RollbackTimeoutMinutesMin || timeout > RollbackTimeoutMinutesMax {
return fmt.Errorf("metadata.rollbackConfig.timeoutMinutes must be between %d and %d, got %d", RollbackTimeoutMinutesMin, RollbackTimeoutMinutesMax, timeout)
}
return nil
}

// ValidateClusterConfig checks compatible fields of a given ClusterConfig
func ValidateClusterConfig(cfg *ClusterConfig) error {
if cfg.UpgradePolicy != nil {
Expand All @@ -192,6 +209,12 @@ func ValidateClusterConfig(cfg *ClusterConfig) error {
}
}

if cfg.Metadata != nil {
if err := validateRollbackConfig(cfg.Metadata.RollbackConfig); err != nil {
return err
}
}

if IsDisabled(cfg.IAM.WithOIDC) && len(cfg.IAM.ServiceAccounts) > 0 {
return fmt.Errorf("iam.withOIDC must be enabled explicitly for iam.serviceAccounts to be created")
}
Expand Down
36 changes: 36 additions & 0 deletions pkg/apis/eksctl.io/v1alpha5/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,42 @@ var _ = Describe("ClusterConfig validation", func() {
})
})

Describe("metadata.rollbackConfig validation", func() {
var cfg *api.ClusterConfig

BeforeEach(func() {
cfg = api.NewClusterConfig()
})

It("accepts a missing rollbackConfig", func() {
Expect(api.ValidateClusterConfig(cfg)).To(Succeed())
})

It("accepts a rollbackConfig without a timeout", func() {
cfg.Metadata.RollbackConfig = &api.RollbackConfig{}
Expect(api.ValidateClusterConfig(cfg)).To(Succeed())
})

DescribeTable("timeoutMinutes bounds",
func(timeoutMinutes int, expectValid bool) {
cfg.Metadata.RollbackConfig = &api.RollbackConfig{
TimeoutMinutes: aws.Int(timeoutMinutes),
}
err := api.ValidateClusterConfig(cfg)
if expectValid {
Expect(err).NotTo(HaveOccurred())
} else {
Expect(err).To(MatchError(ContainSubstring("metadata.rollbackConfig.timeoutMinutes must be between 120 and 10080")))
}
},
Entry("rejects below the minimum", 119, false),
Entry("accepts the minimum", 120, true),
Entry("accepts a value within range", 720, true),
Entry("accepts the maximum", 10080, true),
Entry("rejects above the maximum", 10081, false),
)
})

Describe("nodeGroups[*].name validation", func() {
var (
cfg *api.ClusterConfig
Expand Down
26 changes: 26 additions & 0 deletions pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions pkg/awsapi/eks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

74 changes: 74 additions & 0 deletions pkg/eks/mocksv2/EKS.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions pkg/eks/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,14 @@ func (c *ClusterProvider) UpdateClusterVersion(ctx context.Context, cfg *api.Clu
if cfg.Metadata.ForceUpdateVersion != nil {
input.Force = *cfg.Metadata.ForceUpdateVersion
}
// Only send a RollbackConfig when there is a value to set; an empty struct
// would serialize as "rollbackConfig": {}, which is redundant with omitting it
// (EKS applies its default timeout either way).
if rollbackConfig := cfg.Metadata.RollbackConfig; rollbackConfig != nil && rollbackConfig.TimeoutMinutes != nil {
input.RollbackConfig = &ekstypes.RollbackConfig{
TimeoutMinutes: aws.Int32(int32(*rollbackConfig.TimeoutMinutes)),
}
}
output, err := c.AWSProvider.EKS().UpdateClusterVersion(ctx, input)
if err != nil {
return nil, err
Expand Down
Loading
Loading