Skip to content

Commit 00efef1

Browse files
committed
Support EKS upgrade policy
1 parent a99e314 commit 00efef1

File tree

8 files changed

+182
-0
lines changed

8 files changed

+182
-0
lines changed

config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3136,6 +3136,17 @@ spec:
31363136
- iam-authenticator
31373137
- aws-cli
31383138
type: string
3139+
upgradePolicy:
3140+
description: |-
3141+
The support policy to use for the cluster.
3142+
Extended support indicates that the cluster will not be automatically upgraded
3143+
when it leaves the standard support period, and will enter extended support.
3144+
Clusters in extended support have higher costs.
3145+
The default value is extended. Use standard to disable extended support.
3146+
enum:
3147+
- extended
3148+
- standard
3149+
type: string
31393150
version:
31403151
description: |-
31413152
Version defines the desired Kubernetes version. If no version number

controlplane/eks/api/v1beta1/conversion.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ func (r *AWSManagedControlPlane) ConvertTo(dstRaw conversion.Hub) error {
4646
dst.Spec.RolePermissionsBoundary = restored.Spec.RolePermissionsBoundary
4747
dst.Status.Version = restored.Status.Version
4848
dst.Spec.BootstrapSelfManagedAddons = restored.Spec.BootstrapSelfManagedAddons
49+
dst.Spec.UpgradePolicy = restored.Spec.UpgradePolicy
4950
return nil
5051
}
5152

controlplane/eks/api/v1beta1/zz_generated.conversion.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,15 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned
209209

210210
// KubeProxy defines managed attributes of the kube-proxy daemonset
211211
KubeProxy KubeProxy `json:"kubeProxy,omitempty"`
212+
213+
// The support policy to use for the cluster.
214+
// Extended support indicates that the cluster will not be automatically upgraded
215+
// when it leaves the standard support period, and will enter extended support.
216+
// Clusters in extended support have higher costs.
217+
// The default value is extended. Use standard to disable extended support.
218+
// +kubebuilder:validation:Enum=extended;standard
219+
// +optional
220+
UpgradePolicy *UpgradePolicy `json:"upgradePolicy,omitempty"`
212221
}
213222

214223
// KubeProxy specifies how the kube-proxy daemonset is managed.

controlplane/eks/api/v1beta2/types.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,24 @@ type AddonIssue struct {
212212
ResourceIDs []string `json:"resourceIds,omitempty"`
213213
}
214214

215+
// UpgradePolicy defines the support policy to use for the cluster.
216+
type UpgradePolicy string
217+
218+
var (
219+
// UpgradePolicyExtended indicates that the cluster will not be automatically upgraded
220+
// when it leaves the standard support period, and will enter extended support.
221+
// Clusters in extended support have higher costs.
222+
UpgradePolicyExtended = UpgradePolicy("extended")
223+
224+
// UpgradePolicyStandard indicates that the cluster will be automatically upgraded
225+
// when it leaves the standard support period.
226+
UpgradePolicyStandard = UpgradePolicy("standard")
227+
)
228+
229+
func (e UpgradePolicy) String() string {
230+
return string(e)
231+
}
232+
215233
const (
216234
// SecurityGroupCluster is the security group for communication between EKS
217235
// control plane and managed node groups.

controlplane/eks/api/v1beta2/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/cloud/services/eks/cluster.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"fmt"
2222
"net"
23+
"strings"
2324
"time"
2425

2526
"github.com/aws/aws-sdk-go-v2/aws"
@@ -460,6 +461,14 @@ func (s *Service) createCluster(ctx context.Context, eksClusterName string) (*ek
460461
eksVersion = &v
461462
}
462463

464+
var upgradePolicy *ekstypes.UpgradePolicyRequest
465+
466+
if s.scope.ControlPlane.Spec.UpgradePolicy != nil {
467+
upgradePolicy = &ekstypes.UpgradePolicyRequest{
468+
SupportType: convertUpgradePolicy(*s.scope.ControlPlane.Spec.UpgradePolicy),
469+
}
470+
}
471+
463472
bootstrapAddon := s.scope.BootstrapSelfManagedAddons()
464473
input := &eks.CreateClusterInput{
465474
Name: aws.String(eksClusterName),
@@ -471,6 +480,7 @@ func (s *Service) createCluster(ctx context.Context, eksClusterName string) (*ek
471480
Tags: tags,
472481
KubernetesNetworkConfig: netConfig,
473482
BootstrapSelfManagedAddons: bootstrapAddon,
483+
UpgradePolicy: upgradePolicy,
474484
}
475485

476486
var out *eks.CreateClusterOutput
@@ -526,6 +536,12 @@ func (s *Service) reconcileClusterConfig(ctx context.Context, cluster *ekstypes.
526536
input.ResourcesVpcConfig = updateVpcConfig
527537
}
528538

539+
updateUpgradePolicy := s.reconcileUpgradePolicy(cluster.UpgradePolicy)
540+
if updateUpgradePolicy != nil {
541+
needsUpdate = true
542+
input.UpgradePolicy = updateUpgradePolicy
543+
}
544+
529545
if needsUpdate {
530546
if err := wait.WaitForWithRetryable(wait.NewBackoff(), func() (bool, error) {
531547
if _, err := s.EKSClient.UpdateClusterConfig(ctx, input); err != nil {
@@ -719,6 +735,31 @@ func (s *Service) reconcileClusterVersion(ctx context.Context, cluster *ekstypes
719735
return nil
720736
}
721737

738+
func (s *Service) reconcileUpgradePolicy(upgradePolicy *ekstypes.UpgradePolicyResponse) *ekstypes.UpgradePolicyRequest {
739+
s.Info("reconciling upgrade policy")
740+
741+
if upgradePolicy == nil {
742+
s.Debug("cannot get cluster upgrade policy, no action")
743+
return nil
744+
}
745+
746+
clusterUpgradePolicy := upgradePolicy.SupportType
747+
748+
if s.scope.ControlPlane.Spec.UpgradePolicy == nil {
749+
s.Debug("upgrade policy not given, no action")
750+
return nil
751+
}
752+
753+
if strings.ToLower(string(clusterUpgradePolicy)) == s.scope.ControlPlane.Spec.UpgradePolicy.String() {
754+
s.Debug("upgrade policy unchanged, no action")
755+
return nil
756+
}
757+
758+
return &ekstypes.UpgradePolicyRequest{
759+
SupportType: convertUpgradePolicy(*s.scope.ControlPlane.Spec.UpgradePolicy),
760+
}
761+
}
762+
722763
func (s *Service) describeEKSCluster(ctx context.Context, eksClusterName string) (*ekstypes.Cluster, error) {
723764
input := &eks.DescribeClusterInput{
724765
Name: aws.String(eksClusterName),
@@ -867,3 +908,10 @@ func clusterUpdatingStateRetryable(ctx context.Context, input *eks.DescribeClust
867908
}
868909
return true, nil
869910
}
911+
912+
func convertUpgradePolicy(input ekscontrolplanev1.UpgradePolicy) ekstypes.SupportType {
913+
if input == ekscontrolplanev1.UpgradePolicyStandard {
914+
return ekstypes.SupportTypeStandard
915+
}
916+
return ekstypes.SupportTypeExtended
917+
}

pkg/cloud/services/eks/cluster_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ func TestCreateCluster(t *testing.T) {
534534
RoleName: tc.role,
535535
NetworkSpec: infrav1.NetworkSpec{Subnets: tc.subnets},
536536
BootstrapSelfManagedAddons: false,
537+
UpgradePolicy: &ekscontrolplanev1.UpgradePolicyStandard,
537538
},
538539
},
539540
})
@@ -556,6 +557,9 @@ func TestCreateCluster(t *testing.T) {
556557
Tags: tc.tags,
557558
Version: version,
558559
BootstrapSelfManagedAddons: aws.Bool(false),
560+
UpgradePolicy: &ekstypes.UpgradePolicyRequest{
561+
SupportType: ekstypes.SupportTypeStandard,
562+
},
559563
}).Return(&eks.CreateClusterOutput{}, nil)
560564
}
561565
s := NewService(scope)
@@ -687,6 +691,91 @@ func TestReconcileEKSEncryptionConfig(t *testing.T) {
687691
}
688692
}
689693

694+
func TestReconcileUpgradePolicy(t *testing.T) {
695+
clusterName := "default.cluster"
696+
tests := []struct {
697+
name string
698+
oldUpgradePolicy *ekstypes.UpgradePolicyResponse
699+
newUpgradePolicy *ekscontrolplanev1.UpgradePolicy
700+
expect *ekstypes.UpgradePolicyRequest
701+
expectError bool
702+
}{
703+
{
704+
name: "no update necessary - no upgrade policy specified",
705+
oldUpgradePolicy: &ekstypes.UpgradePolicyResponse{
706+
SupportType: ekstypes.SupportTypeStandard,
707+
},
708+
expect: nil,
709+
expectError: false,
710+
},
711+
{
712+
name: "no update necessary - cannot get cluster upgrade policy",
713+
newUpgradePolicy: &ekscontrolplanev1.UpgradePolicyStandard,
714+
expect: nil,
715+
expectError: false,
716+
},
717+
{
718+
name: "no update necessary - upgrade policy unchanged",
719+
oldUpgradePolicy: &ekstypes.UpgradePolicyResponse{
720+
SupportType: ekstypes.SupportTypeStandard,
721+
},
722+
newUpgradePolicy: &ekscontrolplanev1.UpgradePolicyStandard,
723+
expect: nil,
724+
expectError: false,
725+
},
726+
{
727+
name: "needs update",
728+
oldUpgradePolicy: &ekstypes.UpgradePolicyResponse{
729+
SupportType: ekstypes.SupportTypeStandard,
730+
},
731+
newUpgradePolicy: &ekscontrolplanev1.UpgradePolicyExtended,
732+
expect: &ekstypes.UpgradePolicyRequest{
733+
SupportType: ekstypes.SupportTypeExtended,
734+
},
735+
expectError: false,
736+
},
737+
}
738+
739+
for _, tc := range tests {
740+
t.Run(tc.name, func(t *testing.T) {
741+
g := NewWithT(t)
742+
743+
mockControl := gomock.NewController(t)
744+
defer mockControl.Finish()
745+
746+
scheme := runtime.NewScheme()
747+
_ = infrav1.AddToScheme(scheme)
748+
_ = ekscontrolplanev1.AddToScheme(scheme)
749+
client := fake.NewClientBuilder().WithScheme(scheme).Build()
750+
scope, err := scope.NewManagedControlPlaneScope(scope.ManagedControlPlaneScopeParams{
751+
Client: client,
752+
Cluster: &clusterv1.Cluster{
753+
ObjectMeta: metav1.ObjectMeta{
754+
Namespace: "ns",
755+
Name: clusterName,
756+
},
757+
},
758+
ControlPlane: &ekscontrolplanev1.AWSManagedControlPlane{
759+
Spec: ekscontrolplanev1.AWSManagedControlPlaneSpec{
760+
Version: aws.String("1.16"),
761+
UpgradePolicy: tc.newUpgradePolicy,
762+
},
763+
},
764+
})
765+
g.Expect(err).To(BeNil())
766+
767+
s := NewService(scope)
768+
769+
upgradePolicyRequest := s.reconcileUpgradePolicy(tc.oldUpgradePolicy)
770+
if tc.expectError {
771+
g.Expect(err).To(HaveOccurred())
772+
return
773+
}
774+
g.Expect(upgradePolicyRequest).To(Equal(tc.expect))
775+
})
776+
}
777+
}
778+
690779
func TestCreateIPv6Cluster(t *testing.T) {
691780
g := NewWithT(t)
692781

0 commit comments

Comments
 (0)