diff --git a/go.mod b/go.mod index df35716b97..184fd2e77c 100644 --- a/go.mod +++ b/go.mod @@ -14,19 +14,19 @@ require ( github.com/aws/aws-sdk-go-v2 v1.32.8 github.com/aws/aws-sdk-go-v2/config v1.28.9 github.com/aws/aws-sdk-go-v2/credentials v1.17.50 - github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.3 - github.com/aws/aws-sdk-go-v2/service/cloudformation v1.56.4 - github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.46.5 - github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.45.2 + github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.5 + github.com/aws/aws-sdk-go-v2/service/cloudformation v1.56.5 + github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.46.7 + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.45.4 github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.48.4 github.com/aws/aws-sdk-go-v2/service/ec2 v1.166.0 - github.com/aws/aws-sdk-go-v2/service/eks v1.56.1 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.28.9 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.4 - github.com/aws/aws-sdk-go-v2/service/iam v1.38.3 + github.com/aws/aws-sdk-go-v2/service/eks v1.56.3 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.28.10 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.5 + github.com/aws/aws-sdk-go-v2/service/iam v1.38.5 github.com/aws/aws-sdk-go-v2/service/kms v1.27.5 github.com/aws/aws-sdk-go-v2/service/outposts v1.48.1 - github.com/aws/aws-sdk-go-v2/service/ssm v1.56.3 + github.com/aws/aws-sdk-go-v2/service/ssm v1.56.5 github.com/aws/aws-sdk-go-v2/service/sts v1.33.5 github.com/aws/smithy-go v1.22.1 github.com/awslabs/amazon-eks-ami/nodeadm v0.0.0-20240508073157-fbfa1bc129f5 diff --git a/go.sum b/go.sum index e22fa335f8..fa5558c6a7 100644 --- a/go.sum +++ b/go.sum @@ -736,24 +736,50 @@ github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvK github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.3 h1:1QljimH+yYwrCPgmF2S/vnIE/sBEBS0IdZIvE5+bRJY= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.3/go.mod h1:t5bdAowh8MWq51TuDmltU+wtxMl/VaegNwSBaznkUYc= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.4 h1:w4Tdy9sQlJdcF5dZ9H5uRxradA9Mi2Hp4eOHQmxUJhA= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.4/go.mod h1:6klY3glv/b/phmA0CUj38SWNBior8rKtVvAJrAXljis= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.5 h1:cLKnOycNGGGV75XIk2dv5kjYLnxV4XIWVPtQfSa2qd8= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.5/go.mod h1:6klY3glv/b/phmA0CUj38SWNBior8rKtVvAJrAXljis= github.com/aws/aws-sdk-go-v2/service/cloudformation v1.56.4 h1:uH6So7Ee+2JQf+TKbfifXKUDNN0JfaJ6CgJ6Bh/u1sc= github.com/aws/aws-sdk-go-v2/service/cloudformation v1.56.4/go.mod h1:GdDLBO8SzD4wvQ6fhqU1QCmvG1waj1MPHL4cBtuSgdQ= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.56.5 h1:B9a36cMvleRcLb38hgtb7q39LlKEJFcKsA0qBy+4Xgs= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.56.5/go.mod h1:GdDLBO8SzD4wvQ6fhqU1QCmvG1waj1MPHL4cBtuSgdQ= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.46.5 h1:+fSJTvw91AyBSgS7iaPlSe0NVwa1DJqb6F6GClah+0s= github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.46.5/go.mod h1:2lQF0aEQAXkUf/Td7RqGIuylJlJO6wSv/onvNdShVyA= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.46.6 h1:fMIPTKNUEtU0JCBtKEDH0mvhyDBYZ6dEgqpBOYB5hOU= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.46.6/go.mod h1:a2KI7mJ3kF1AdkW4Cyu0fl/6G9H+x7J7KD7BZdvLwYg= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.46.7 h1:DBhLX1P+nwIXO6xyDqLpdHoGRKAHSM1b5BECVCSNO5s= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.46.7/go.mod h1:a2KI7mJ3kF1AdkW4Cyu0fl/6G9H+x7J7KD7BZdvLwYg= github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.45.2 h1:9zwK03mlPPGzTaiLh1AJS6IhOAWDYnVXfZTwdyBhQtg= github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.45.2/go.mod h1:u8Bi6DG9tLOVIS9MNqtE3vh9T6I/U/8RBpYvy/VyMjc= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.45.3 h1:va7zt8/kkg5zR0TX2r7wCXssdZ4+blRxbsA6IS9XXYI= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.45.3/go.mod h1:CijDCaRp5sH8QM0LqImyzy5roG8cOtgp2Abj0V/4luk= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.45.4 h1:20qw4O1b41McWMulR1q2ZPtUjZTE78iiR54PmlmD8DE= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.45.4/go.mod h1:CijDCaRp5sH8QM0LqImyzy5roG8cOtgp2Abj0V/4luk= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.48.4 h1:78+PSLTY1QcbesyoPKAnYRG+jFhcuZr17pGAQVxDTWw= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.48.4/go.mod h1:vPpQlrSaeqEX2s/iM5eqaSFUxVtBrpZFP9SOd25AZuY= github.com/aws/aws-sdk-go-v2/service/ec2 v1.166.0 h1:FDZVMxzXB13cRmHs3t3tH9gme8GhvmjsQXeXFI37OHU= github.com/aws/aws-sdk-go-v2/service/ec2 v1.166.0/go.mod h1:Wv7N3iFOKVsZNIaw9MOBUmwCkX6VMmQQRFhMrHtNGno= github.com/aws/aws-sdk-go-v2/service/eks v1.56.1 h1:TbZoGON9WoQSDC86lTA+eDCXTCqJElgM4TTiqdVcSG4= github.com/aws/aws-sdk-go-v2/service/eks v1.56.1/go.mod h1:kNUWaiotRWCnfQlprrxSMg8ALqbZyA9xLCwKXuLumSk= +github.com/aws/aws-sdk-go-v2/service/eks v1.56.2 h1:NXxglcZhHubtK2SgqavDGkbArM4NYI7QvLr+FpOL3Oo= +github.com/aws/aws-sdk-go-v2/service/eks v1.56.2/go.mod h1:KkH+D6VJmtIVGD9KTxB9yZu4hQP7s9kxWn8lLb7tmVg= +github.com/aws/aws-sdk-go-v2/service/eks v1.56.3 h1:FqupDsZsAzlLzjZwAUJ24PA1H/P0r/O0G7u5O0Iq4T0= +github.com/aws/aws-sdk-go-v2/service/eks v1.56.3/go.mod h1:KkH+D6VJmtIVGD9KTxB9yZu4hQP7s9kxWn8lLb7tmVg= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.28.9 h1:phUmuRbBmJKpPBbGx34uZJuV1PPg4u0/RMzIecVVR0E= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.28.9/go.mod h1:EH2+vt500M2IewoiYVo4rP0gfRhIXzh6BDFZ5KbidUI= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.28.10 h1:/0EH8MuNQp2bDORevPdEgQkipyCzYGh1uSKkl9Aw1Wo= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.28.10/go.mod h1:EH2+vt500M2IewoiYVo4rP0gfRhIXzh6BDFZ5KbidUI= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.4 h1:tC9S2BkqlMWP3N2t4UasxIhIJSNY5g7EINjz94VK+3U= github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.4/go.mod h1:OhWF5Dd6Ge4VW/RcFQKOO0eEv1JInQJoo6/tkCjlvrM= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.5 h1:oEpZAvjZqy4CkpC5WApi1JBVXxxCdPWbOSB2sOaDHD4= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.5/go.mod h1:OhWF5Dd6Ge4VW/RcFQKOO0eEv1JInQJoo6/tkCjlvrM= github.com/aws/aws-sdk-go-v2/service/iam v1.38.3 h1:2sFIoFzU1IEL9epJWubJm9Dhrn45aTNEJuwsesaCGnk= github.com/aws/aws-sdk-go-v2/service/iam v1.38.3/go.mod h1:KzlNINwfr/47tKkEhgk0r10/OZq3rjtyWy0txL3lM+I= +github.com/aws/aws-sdk-go-v2/service/iam v1.38.4 h1:440YtmP8Cn6Qp7WHYfvz2/Xzmu1v1Vox/FJnzUDDQGM= +github.com/aws/aws-sdk-go-v2/service/iam v1.38.4/go.mod h1:oXqc4hmGhZpj06Zu8z+ahXhdbjq4Uw8pjN9flty0Ync= +github.com/aws/aws-sdk-go-v2/service/iam v1.38.5 h1:DzMv18mXANjE3nwkTHvXW7TIBIqhKJbKu/pHR6HQfAo= +github.com/aws/aws-sdk-go-v2/service/iam v1.38.5/go.mod h1:oXqc4hmGhZpj06Zu8z+ahXhdbjq4Uw8pjN9flty0Ync= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.8 h1:cWno7lefSH6Pp+mSznagKCgfDGeZRin66UvYUqAkyeA= @@ -766,6 +792,10 @@ github.com/aws/aws-sdk-go-v2/service/pricing v1.17.0 h1:RQOMvPwte2H4ZqsiZmrla1cr github.com/aws/aws-sdk-go-v2/service/pricing v1.17.0/go.mod h1:LJyh9figH3ZpSiVjR5umzbl6V3EpQdZR4Se1ayoUtfI= github.com/aws/aws-sdk-go-v2/service/ssm v1.56.3 h1:QMx9lj524IOWjI1IpmcXSkHaazGBzTPgBmECzbppF5s= github.com/aws/aws-sdk-go-v2/service/ssm v1.56.3/go.mod h1:RKWoqC9FlgMCkrfVOtgfqfwdaUIaq8H93UAt4xNaR0A= +github.com/aws/aws-sdk-go-v2/service/ssm v1.56.4 h1:oXh/PjaKtStu7RkaUtuKX6+h/OxXriMa9WyQQhylKG0= +github.com/aws/aws-sdk-go-v2/service/ssm v1.56.4/go.mod h1:IiHGbiFg4wVdEKrvFi/zxVZbjfEpgSe21N9RwyQFXCU= +github.com/aws/aws-sdk-go-v2/service/ssm v1.56.5 h1:ZQorDO4+5xcNiQKvkg5cGVDPgtwnjglmDBCPRoEM6oU= +github.com/aws/aws-sdk-go-v2/service/ssm v1.56.5/go.mod h1:IiHGbiFg4wVdEKrvFi/zxVZbjfEpgSe21N9RwyQFXCU= github.com/aws/aws-sdk-go-v2/service/sso v1.24.9 h1:YqtxripbjWb2QLyzRK9pByfEDvgg95gpC2AyDq4hFE8= github.com/aws/aws-sdk-go-v2/service/sso v1.24.9/go.mod h1:lV8iQpg6OLOfBnqbGMBKYjilBlf633qwHnBEiMSPoHY= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.8 h1:6dBT1Lz8fK11m22R+AqfRsFn8320K0T5DTGxxOQBSMw= diff --git a/integration/tests/addons/addons_test.go b/integration/tests/addons/addons_test.go index 4a5dee7933..ae446cc9e4 100644 --- a/integration/tests/addons/addons_test.go +++ b/integration/tests/addons/addons_test.go @@ -72,7 +72,7 @@ var _ = BeforeSuite(func() { rawClient = getRawClient(context.Background(), params.ClusterName) serverVersion, err := rawClient.ServerVersion() Expect(err).NotTo(HaveOccurred()) - Expect(serverVersion).To(HavePrefix(api.LatestVersion)) + Expect(serverVersion).To(HavePrefix(api.DefaultVersion)) }) @@ -445,7 +445,7 @@ var _ = Describe("(Integration) [EKS Addons test]", func() { cmd := params.EksctlUtilsCmd. WithArgs( "describe-addon-versions", - "--kubernetes-version", api.LatestVersion, + "--kubernetes-version", api.DefaultVersion, ) Expect(cmd).To(RunSuccessfullyWithOutputStringLines( ContainElement(ContainSubstring("vpc-cni")), @@ -459,7 +459,7 @@ var _ = Describe("(Integration) [EKS Addons test]", func() { By(fmt.Sprintf("listing available addon versions for %s", addonWithSchema)) output, err := eksAPI.DescribeAddonVersions(context.Background(), &awseks.DescribeAddonVersionsInput{ AddonName: aws.String(addonWithSchema), - KubernetesVersion: aws.String(api.LatestVersion), + KubernetesVersion: aws.String(api.DefaultVersion), }) Expect(err).NotTo(HaveOccurred(), "error describing addon versions") By(fmt.Sprintf("fetching the configuration schema for %s", addonWithSchema)) @@ -482,7 +482,7 @@ var _ = Describe("(Integration) [EKS Addons test]", func() { cmd := params.EksctlUtilsCmd. WithArgs( "describe-addon-versions", - "--kubernetes-version", api.LatestVersion, + "--kubernetes-version", api.DefaultVersion, "--types", "networking", "--owners", "aws", "--publishers", "eks", @@ -498,7 +498,7 @@ var _ = Describe("(Integration) [EKS Addons test]", func() { cmd := params.EksctlUtilsCmd. WithArgs( "describe-addon-versions", - "--kubernetes-version", api.LatestVersion, + "--kubernetes-version", api.DefaultVersion, "--types", "networking, storage", ) Expect(cmd).To(RunSuccessfullyWithOutputStringLines( @@ -860,7 +860,7 @@ func getRawClient(ctx context.Context, clusterName string) *kubewrapper.RawClien func getInitialClusterConfig() *api.ClusterConfig { clusterConfig := api.NewClusterConfig() clusterConfig.Metadata.Name = params.ClusterName - clusterConfig.Metadata.Version = api.LatestVersion + clusterConfig.Metadata.Version = api.DefaultVersion clusterConfig.Metadata.Region = params.Region clusterConfig.IAM.WithOIDC = api.Enabled() clusterConfig.Addons = []*api.Addon{ diff --git a/integration/tests/dry_run/dry_run_test.go b/integration/tests/dry_run/dry_run_test.go index 794ee64e54..08da0f7247 100644 --- a/integration/tests/dry_run/dry_run_test.go +++ b/integration/tests/dry_run/dry_run_test.go @@ -47,7 +47,7 @@ func TestDryRun(t *testing.T) { testutils.RegisterAndRun(t) } -const eksVersion = api.LatestVersion +const eksVersion = api.DefaultVersion const defaultClusterConfig = ` apiVersion: eksctl.io/v1alpha5 diff --git a/integration/tests/ipv6/ipv6_test.go b/integration/tests/ipv6/ipv6_test.go index b40dd082fa..ce181aebdc 100644 --- a/integration/tests/ipv6/ipv6_test.go +++ b/integration/tests/ipv6/ipv6_test.go @@ -56,7 +56,7 @@ var _ = BeforeSuite(func() { clusterConfig = api.NewClusterConfig() clusterConfig.Metadata.Name = params.ClusterName - clusterConfig.Metadata.Version = api.LatestVersion + clusterConfig.Metadata.Version = api.DefaultVersion clusterConfig.Metadata.Region = params.Region clusterConfig.KubernetesNetworkConfig.IPFamily = "iPv6" clusterConfig.VPC.NAT = nil diff --git a/integration/tests/unowned_cluster/unowned_cluster_test.go b/integration/tests/unowned_cluster/unowned_cluster_test.go index 3c5e209283..4ef8a00889 100644 --- a/integration/tests/unowned_cluster/unowned_cluster_test.go +++ b/integration/tests/unowned_cluster/unowned_cluster_test.go @@ -59,7 +59,13 @@ var _ = BeforeSuite(func() { mng2 = "mng-2" stackName = fmt.Sprintf("eksctl-%s", params.ClusterName) - version, upgradeVersion = clusterutils.GetCurrentAndNextVersionsForUpgrade(params.Version) + clusterProvider, err := eks.New(context.Background(), &api.ProviderConfig{Region: params.Region}, cfg) + Expect(err).NotTo(HaveOccurred()) + + cvm, err := eks.NewClusterVersionsManager(clusterProvider.AWSProvider.EKS()) + Expect(err).NotTo(HaveOccurred()) + + version, upgradeVersion = clusterutils.GetCurrentAndNextVersionsForUpgrade(cvm, params.Version) cfg = &api.ClusterConfig{ TypeMeta: api.ClusterConfigTypeMeta(), @@ -71,8 +77,6 @@ var _ = BeforeSuite(func() { } if !params.SkipCreate { - clusterProvider, err := eks.New(context.Background(), &api.ProviderConfig{Region: params.Region}, cfg) - Expect(err).NotTo(HaveOccurred()) ctl = clusterProvider.AWSProvider ctx := context.Background() cfg.VPC = createClusterWithNodeGroup(ctx, params.ClusterName, stackName, mng1, version, ctl) diff --git a/integration/tests/update/update_cluster_test.go b/integration/tests/update/update_cluster_test.go index 7f91146d91..469b705322 100644 --- a/integration/tests/update/update_cluster_test.go +++ b/integration/tests/update/update_cluster_test.go @@ -94,7 +94,20 @@ var _ = BeforeSuite(func() { fmt.Fprintf(GinkgoWriter, "Using kubeconfig: %s\n", params.KubeconfigPath) - eksVersion, nextEKSVersion = clusterutils.GetCurrentAndNextVersionsForUpgrade(params.Version) + cfg := &api.ClusterConfig{ + Metadata: &api.ClusterMeta{ + Name: params.ClusterName, + Region: params.Region, + }, + } + var err error + clusterProvider, err = eks.New(context.Background(), &api.ProviderConfig{Region: params.Region}, cfg) + Expect(err).NotTo(HaveOccurred()) + + cvm, err := eks.NewClusterVersionsManager(clusterProvider.AWSProvider.EKS()) + Expect(err).NotTo(HaveOccurred()) + + eksVersion, nextEKSVersion = clusterutils.GetCurrentAndNextVersionsForUpgrade(cvm, params.Version) clusterConfig := api.NewClusterConfig() clusterConfig.Metadata.Name = defaultCluster @@ -141,8 +154,7 @@ var _ = BeforeSuite(func() { WithStdin(clusterutils.Reader(clusterConfig)) Expect(cmd).To(RunSuccessfully()) - var err error - clusterProvider, err = newClusterProvider(context.Background()) + err = clusterProvider.RefreshClusterStatus(context.Background(), cfg) Expect(err).NotTo(HaveOccurred()) }) @@ -327,23 +339,6 @@ var _ = AfterSuite(func() { os.RemoveAll(params.TestDirectory) }) -func newClusterProvider(ctx context.Context) (*eks.ClusterProvider, error) { - cfg := &api.ClusterConfig{ - Metadata: &api.ClusterMeta{ - Name: params.ClusterName, - Region: params.Region, - }, - } - ctl, err := eks.New(ctx, &api.ProviderConfig{Region: params.Region}, cfg) - if err != nil { - return nil, err - } - if err := ctl.RefreshClusterStatus(ctx, cfg); err != nil { - return nil, err - } - return ctl, nil -} - func defaultClusterConfig() *api.ClusterConfig { return &api.ClusterConfig{ Metadata: &api.ClusterMeta{ diff --git a/integration/tests/windows/windows_test.go b/integration/tests/windows/windows_test.go index eabc1cfe84..2766e60f9c 100644 --- a/integration/tests/windows/windows_test.go +++ b/integration/tests/windows/windows_test.go @@ -42,7 +42,7 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { By("creating a new cluster with Windows nodegroups") clusterConfig := api.NewClusterConfig() clusterConfig.Metadata.Name = clusterName - clusterConfig.Metadata.Version = api.LatestVersion + clusterConfig.Metadata.Version = api.DefaultVersion clusterConfig.Metadata.Region = api.DefaultRegion clusterConfig.IAM.WithOIDC = &withOIDC diff --git a/integration/utilities/cluster/cluster.go b/integration/utilities/cluster/cluster.go index 4ba9fe3c9f..c872c034e2 100644 --- a/integration/utilities/cluster/cluster.go +++ b/integration/utilities/cluster/cluster.go @@ -35,14 +35,14 @@ func ParseClusterConfig(clusterName, region, filename string) *api.ClusterConfig return clusterConfig } -func GetCurrentAndNextVersionsForUpgrade(testVersion string) (currentVersion, nextVersion string) { - supportedVersions := api.SupportedVersions() +func GetCurrentAndNextVersionsForUpgrade(cvm eks.ClusterVersionsManagerInterface, testVersion string) (currentVersion, nextVersion string) { + supportedVersions := cvm.SupportedVersions() if len(supportedVersions) < 2 { Fail("Upgrade test requires at least two supported EKS versions") } // if latest version is used, fetch previous version to upgrade from - if testVersion == api.LatestVersion { + if testVersion == cvm.LatestVersion() { previousVersionIndex := slices.Index(supportedVersions, testVersion) - 1 currentVersion = supportedVersions[previousVersionIndex] nextVersion = testVersion diff --git a/pkg/actions/addon/update_test.go b/pkg/actions/addon/update_test.go index 27287bd8fa..b65b880f8b 100644 --- a/pkg/actions/addon/update_test.go +++ b/pkg/actions/addon/update_test.go @@ -562,7 +562,7 @@ var _ = Describe("Update", func() { }, nil).Once() mockProvider.MockEKS().On("DescribeAddonVersions", mock.Anything, &awseks.DescribeAddonVersionsInput{ AddonName: aws.String("vpc-cni"), - KubernetesVersion: aws.String(api.LatestVersion), + KubernetesVersion: aws.String(api.DefaultVersion), }).Return(&awseks.DescribeAddonVersionsOutput{ Addons: []ekstypes.AddonInfo{ { @@ -636,7 +636,7 @@ var _ = Describe("Update", func() { addonManager, err := addon.New(&api.ClusterConfig{ Metadata: &api.ClusterMeta{ - Version: api.LatestVersion, + Version: api.Version1_30, Name: clusterName, }, AddonsConfig: e.addonsConfig, diff --git a/pkg/actions/cluster/upgrade.go b/pkg/actions/cluster/upgrade.go index f8fbb4fe6b..1742c5bdde 100644 --- a/pkg/actions/cluster/upgrade.go +++ b/pkg/actions/cluster/upgrade.go @@ -2,8 +2,6 @@ package cluster import ( "context" - "errors" - "fmt" "github.com/weaveworks/eksctl/pkg/printers" @@ -12,12 +10,17 @@ 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) { - currentVersion := ctl.ControlPlaneVersion() - versionUpdateRequired, err := requiresVersionUpgrade(cfg.Metadata, currentVersion) + cvm, err := eks.NewClusterVersionsManager(ctl.AWSProvider.EKS()) + if err != nil { + return false, err + } + + upgradeVersion, err := cvm.ResolveUpgradeVersion( + /* desiredVersion */ cfg.Metadata.Version, + /* currentVersion */ ctl.ControlPlaneVersion()) if err != nil { return false, err } @@ -27,10 +30,11 @@ func upgrade(ctx context.Context, cfg *api.ClusterConfig, ctl *eks.ClusterProvid return false, err } - if versionUpdateRequired { + if upgradeVersion != "" { 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, currentVersion, cfg.Metadata.Version) + cmdutils.LogIntendedAction(dryRun, "upgrade cluster %q control plane from current version %q to %q", cfg.Metadata.Name, ctl.ControlPlaneVersion(), cfg.Metadata.Version) if !dryRun { + cfg.Metadata.Version = upgradeVersion if err := ctl.UpdateClusterVersionBlocking(ctx, cfg); err != nil { return false, err } @@ -40,103 +44,5 @@ func upgrade(ctx context.Context, cfg *api.ClusterConfig, ctl *eks.ClusterProvid } else { logger.Info("no cluster version update required") } - return versionUpdateRequired, nil -} - -func requiresVersionUpgrade(clusterMeta *api.ClusterMeta, currentEKSVersion string) (bool, error) { - nextVersion, err := getNextVersion(currentEKSVersion) - if err != nil { - return false, err - } - - // If the version was not specified default to the next Kubernetes version and assume the user intended to upgrade if possible - // also support "auto" as version (see #2461) - if clusterMeta.Version == "" || clusterMeta.Version == "auto" { - if api.IsSupportedVersion(nextVersion) { - clusterMeta.Version = nextVersion - return true, nil - } - - // There is no new version, stay in the current one - clusterMeta.Version = currentEKSVersion - return false, nil - } - - if c, err := utils.CompareVersions(clusterMeta.Version, currentEKSVersion); err != nil { - return false, fmt.Errorf("couldn't compare versions for upgrade: %w", err) - } else if c < 0 { - return false, fmt.Errorf("cannot upgrade to a lower version. Found given target version %q, current cluster version %q", clusterMeta.Version, currentEKSVersion) - } - - if api.IsDeprecatedVersion(clusterMeta.Version) { - return false, fmt.Errorf("control plane version %q has been deprecated", clusterMeta.Version) - } - - if !api.IsSupportedVersion(clusterMeta.Version) { - return false, fmt.Errorf("control plane version %q is not known to this version of eksctl, try to upgrade eksctl first", clusterMeta.Version) - } - - if clusterMeta.Version == currentEKSVersion { - return false, nil - } - - if clusterMeta.Version == nextVersion { - return true, nil - } - - return false, fmt.Errorf( - "upgrading more than one version at a time is not supported. Found upgrade from %q to %q. Please upgrade to %q first", - currentEKSVersion, - clusterMeta.Version, - nextVersion) -} - -func getNextVersion(currentVersion string) (string, error) { - switch currentVersion { - case "": - return "", errors.New("unable to get control plane version") - case api.Version1_12: - return api.Version1_13, nil - case api.Version1_13: - return api.Version1_14, nil - case api.Version1_14: - return api.Version1_15, nil - case api.Version1_15: - return api.Version1_16, nil - case api.Version1_16: - return api.Version1_17, nil - case api.Version1_17: - return api.Version1_18, nil - case api.Version1_18: - return api.Version1_19, nil - case api.Version1_19: - return api.Version1_20, nil - case api.Version1_20: - return api.Version1_21, nil - case api.Version1_21: - return api.Version1_22, nil - case api.Version1_22: - return api.Version1_23, nil - case api.Version1_23: - return api.Version1_24, nil - case api.Version1_24: - return api.Version1_25, nil - case api.Version1_25: - return api.Version1_26, nil - case api.Version1_26: - return api.Version1_27, nil - case api.Version1_27: - return api.Version1_28, nil - case api.Version1_28: - return api.Version1_29, nil - case api.Version1_29: - return api.Version1_30, nil - case api.Version1_30: - return api.Version1_31, nil - case api.Version1_31: - return api.Version1_32, nil - default: - // version of control plane is not known to us, maybe we are just too old... - return "", fmt.Errorf("control plane version %q is not known to this version of eksctl, try to upgrade eksctl first", currentVersion) - } + return upgradeVersion != "", nil } diff --git a/pkg/actions/cluster/upgrade_test.go b/pkg/actions/cluster/upgrade_test.go index 50cac69a2e..916b1b53b9 100644 --- a/pkg/actions/cluster/upgrade_test.go +++ b/pkg/actions/cluster/upgrade_test.go @@ -1,94 +1 @@ package cluster - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" -) - -var _ = Describe("upgrade cluster", func() { - type upgradeCase struct { - givenVersion string - eksVersion string - expectedUpgradeVersion string - expectedUpgrade bool - expectedErrorText string - } - - DescribeTable("checks the specified version", - func(c upgradeCase) { - clusterMeta := api.ClusterMeta{ - Version: c.givenVersion, - } - result, err := requiresVersionUpgrade(&clusterMeta, c.eksVersion) - - if c.expectedErrorText != "" { - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring(c.expectedErrorText)) - } else { - Expect(clusterMeta.Version).To(Equal(c.expectedUpgradeVersion)) - Expect(result).To(Equal(c.expectedUpgrade)) - } - }, - - Entry("upgrades by default when the version is not specified", upgradeCase{ - givenVersion: "", - eksVersion: "1.23", - expectedUpgradeVersion: "1.24", - expectedUpgrade: true, - }), - - Entry("upgrades by default when the version is auto", upgradeCase{ - givenVersion: "auto", - eksVersion: "1.23", - expectedUpgradeVersion: "1.24", - expectedUpgrade: true, - }), - - Entry("does not upgrade or fail when the cluster is already in the last version", upgradeCase{ - givenVersion: "", - eksVersion: api.LatestVersion, - expectedUpgradeVersion: api.LatestVersion, - expectedUpgrade: false, - }), - - Entry("upgrades to the next version when specified", upgradeCase{ - givenVersion: "1.23", - eksVersion: "1.22", - expectedUpgradeVersion: "1.23", - expectedUpgrade: true, - }), - - Entry("does not upgrade when the current version is specified", upgradeCase{ - givenVersion: "1.15", - eksVersion: "1.15", - expectedUpgradeVersion: "1.15", - expectedUpgrade: false, - }), - - Entry("fails when the upgrade jumps more than one kubernetes version", upgradeCase{ - givenVersion: "1.23", - eksVersion: "1.21", - expectedErrorText: "upgrading more than one version at a time is not supported", - }), - - Entry("fails when the given version is lower than the current one", upgradeCase{ - givenVersion: "1.14", - eksVersion: "1.15", - expectedErrorText: "cannot upgrade to a lower version. Found given target version \"1.14\", current cluster version \"1.15\"", - }), - - Entry("fails when the version is deprecated", upgradeCase{ - givenVersion: "1.12", - eksVersion: "1.12", - expectedErrorText: "control plane version \"1.12\" has been deprecated", - }), - - Entry("fails when the version is still not supported", upgradeCase{ - givenVersion: "1.32", - eksVersion: api.LatestVersion, - expectedErrorText: "control plane version \"1.32\" is not known to this version of eksctl", - }), - ) -}) diff --git a/pkg/actions/nodegroup/upgrade_test.go b/pkg/actions/nodegroup/upgrade_test.go index bc258a7ba1..f96051968c 100644 --- a/pkg/actions/nodegroup/upgrade_test.go +++ b/pkg/actions/nodegroup/upgrade_test.go @@ -29,7 +29,7 @@ import ( ) var _ = Describe("Upgrade", func() { - supportedVersions := api.SupportedVersions() + supportedVersions := []string{api.Version1_30, api.Version1_31} if len(supportedVersions) < 2 { Fail("Upgrade test requires at least two supported EKS versions") } diff --git a/pkg/addons/default/coredns.go b/pkg/addons/default/coredns.go index cc90cf2ba5..9af2767219 100644 --- a/pkg/addons/default/coredns.go +++ b/pkg/addons/default/coredns.go @@ -4,6 +4,7 @@ import ( "context" "embed" "fmt" + "regexp" "strings" "github.com/kris-nova/logger" @@ -15,7 +16,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/weaveworks/eksctl/pkg/addons" - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/fargate/coredns" "github.com/weaveworks/eksctl/pkg/kubernetes" @@ -127,14 +127,26 @@ func loadAssetCoreDNS(controlPlaneVersion string) (*metav1.List, error) { return nil, errors.New("CoreDNS is not supported on Kubernetes 1.10") } - for _, version := range api.SupportedVersions() { - if strings.HasPrefix(controlPlaneVersion, version+".") { - manifest, err := coreDNSDir.ReadFile(fmt.Sprintf("assets/%s-%s.json", CoreDNS, version)) - if err != nil { - return nil, err - } - return newList(manifest) - } + version, err := resolveK8sVersionPrefix(controlPlaneVersion) + if err != nil { + return nil, err + } + + manifest, err := coreDNSDir.ReadFile(fmt.Sprintf("assets/%s-%s.json", CoreDNS, version)) + if err != nil { + return nil, err + } + + return newList(manifest) +} + +func resolveK8sVersionPrefix(controlPlaneVersion string) (string, error) { + // Regular expression to match Kubernetes version prefixes + re := regexp.MustCompile(`^(\d+\.\d+)`) + // Find the first match + matches := re.FindStringSubmatch(controlPlaneVersion) + if len(matches) > 1 { + return matches[1], nil } - return nil, errors.New("unsupported Kubernetes version") + return "", fmt.Errorf("could not resolve Kubernetes version from control plane version %q", controlPlaneVersion) } diff --git a/pkg/addons/default/scripts/update_coredns_assets.go b/pkg/addons/default/scripts/update_coredns_assets.go index f382a3e7ec..2ab618c214 100644 --- a/pkg/addons/default/scripts/update_coredns_assets.go +++ b/pkg/addons/default/scripts/update_coredns_assets.go @@ -26,7 +26,12 @@ func main() { log.Fatalf("failed to create the AWS provider: %v", err) } - for _, kubernetesVersion := range api.SupportedVersions() { + cvm, err := eks.NewClusterVersionsManager(clusterProvider.AWSProvider.EKS()) + if err != nil { + log.Fatal(err) + } + + for _, kubernetesVersion := range cvm.SupportedVersions() { latestVersion := getLatestVersion(ctx, clusterProvider, kubernetesVersion) if latestVersion == "" { continue diff --git a/pkg/ami/ssm_resolver_test.go b/pkg/ami/ssm_resolver_test.go index 156194deab..c969b0d4de 100644 --- a/pkg/ami/ssm_resolver_test.go +++ b/pkg/ami/ssm_resolver_test.go @@ -718,7 +718,7 @@ var _ = Describe("AMI Auto Resolution", func() { amiType == ekstypes.AMITypesAl2023X8664Nvidia || amiType == ekstypes.AMITypesAl2023X8664Neuron { continue } - ssmParameterName := MakeManagedSSMParameterName(api.LatestVersion, amiType) + ssmParameterName := MakeManagedSSMParameterName(api.Version1_31, amiType) Expect(ssmParameterName).NotTo(BeEmpty(), "expected to generate SSM parameter name for AMI type %s", amiType) } }) diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index 88388ec0ad..bdc0add36b 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -820,20 +820,8 @@ }, "version": { "type": "string", - "description": "Valid variants are: `\"1.23\"`, `\"1.24\"`, `\"1.25\"`, `\"1.26\"`, `\"1.27\"`, `\"1.28\"`, `\"1.29\"`, `\"1.30\"` (default), `\"1.31\"`.", - "x-intellij-html-description": "Valid variants are: "1.23", "1.24", "1.25", "1.26", "1.27", "1.28", "1.29", "1.30" (default), "1.31".", - "default": "1.30", - "enum": [ - "1.23", - "1.24", - "1.25", - "1.26", - "1.27", - "1.28", - "1.29", - "1.30", - "1.31" - ] + "description": "use `./eksctl utils describe-cluster-versions` to get the list of supported versions", + "x-intellij-html-description": "use ./eksctl utils describe-cluster-versions to get the list of supported versions" } }, "preferredOrder": [ diff --git a/pkg/apis/eksctl.io/v1alpha5/defaults_test.go b/pkg/apis/eksctl.io/v1alpha5/defaults_test.go index b015b0a39e..a68d4d3b28 100644 --- a/pkg/apis/eksctl.io/v1alpha5/defaults_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/defaults_test.go @@ -302,7 +302,7 @@ var _ = Describe("ClusterConfig validation", func() { testNodeGroup := NodeGroup{ NodeGroupBase: &NodeGroupBase{}, } - SetNodeGroupDefaults(&testNodeGroup, &ClusterMeta{Version: Version1_24}, false) + SetNodeGroupDefaults(&testNodeGroup, &ClusterMeta{Version: DockershimDeprecationVersion}, false) Expect(*testNodeGroup.ContainerRuntime).To(Equal(ContainerRuntimeContainerD)) }) }) diff --git a/pkg/apis/eksctl.io/v1alpha5/outposts_validation_test.go b/pkg/apis/eksctl.io/v1alpha5/outposts_validation_test.go index eb8df07ab7..5f276e2ea1 100644 --- a/pkg/apis/eksctl.io/v1alpha5/outposts_validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/outposts_validation_test.go @@ -21,7 +21,7 @@ var _ = Describe("Outposts validation", func() { DescribeTable("unsupported ClusterConfig features", func(oe outpostsEntry) { clusterConfig := api.NewClusterConfig() - clusterConfig.Metadata.Version = api.LatestVersion + clusterConfig.Metadata.Version = api.Version1_31 clusterConfig.Outpost = &api.Outpost{ ControlPlaneOutpostARN: "arn:aws:outposts:us-west-2:1234:outpost/op-1234", } @@ -188,7 +188,7 @@ var _ = Describe("Outposts validation", func() { DescribeTable("support for node AMI families", func(amiFamily string, shouldFail bool) { clusterConfig := api.NewClusterConfig() - clusterConfig.Metadata.Version = api.LatestVersion + clusterConfig.Metadata.Version = api.Version1_31 clusterConfig.Outpost = &api.Outpost{ ControlPlaneOutpostARN: "arn:aws:outposts:us-west-2:1234:outpost/op-1234", } diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 7f51006a36..92eb503aae 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -16,90 +16,40 @@ import ( v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" "github.com/aws/aws-sdk-go-v2/service/sts" - + "github.com/weaveworks/eksctl/pkg/awsapi" + "github.com/weaveworks/eksctl/pkg/utils/taints" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - - "github.com/weaveworks/eksctl/pkg/awsapi" - "github.com/weaveworks/eksctl/pkg/utils/taints" ) -// Values for `KubernetesVersion` -// All valid values should go in this block const ( - Version1_23 = "1.23" - - Version1_24 = "1.24" - - Version1_25 = "1.25" - - Version1_26 = "1.26" - - Version1_27 = "1.27" - - Version1_28 = "1.28" - - Version1_29 = "1.29" - - Version1_30 = "1.30" - - Version1_31 = "1.31" - + Version1_10 = "1.10" + Version1_11 = "1.11" + Version1_12 = "1.12" + Version1_13 = "1.13" + Version1_14 = "1.14" + Version1_15 = "1.15" + Version1_16 = "1.16" + Version1_17 = "1.17" + Version1_18 = "1.18" + Version1_19 = "1.19" + Version1_20 = "1.20" + Version1_21 = "1.21" + Version1_22 = "1.22" + Version1_23 = "1.23" + Version1_24 = "1.24" + Version1_25 = "1.25" + Version1_26 = "1.26" + Version1_27 = "1.27" + Version1_28 = "1.28" + Version1_29 = "1.29" + Version1_30 = "1.30" + Version1_31 = "1.31" + DockershimDeprecationVersion = Version1_24 + //TODO: Remove this and replace with output from DescribeClusterVersions endpoint // DefaultVersion (default) DefaultVersion = Version1_30 - - LatestVersion = Version1_31 - - DockershimDeprecationVersion = Version1_24 -) - -// No longer supported versions -const ( - // Version1_10 represents Kubernetes version 1.10.x - Version1_10 = "1.10" - - // Version1_11 represents Kubernetes version 1.11.x - Version1_11 = "1.11" - - // Version1_12 represents Kubernetes version 1.12.x - Version1_12 = "1.12" - - // Version1_13 represents Kubernetes version 1.13.x - Version1_13 = "1.13" - - // Version1_14 represents Kubernetes version 1.14.x - Version1_14 = "1.14" - - // Version1_15 represents Kubernetes version 1.15.x - Version1_15 = "1.15" - - // Version1_16 represents Kubernetes version 1.16.x - Version1_16 = "1.16" - - // Version1_17 represents Kubernetes version 1.17.x - Version1_17 = "1.17" - - // Version1_18 represents Kubernetes version 1.18.x - Version1_18 = "1.18" - - // Version1_19 represents Kubernetes version 1.19.x - Version1_19 = "1.19" - - // Version1_20 represents Kubernetes version 1.20.x - Version1_20 = "1.20" - - // Version1_21 represents Kubernetes version 1.21.x - Version1_21 = "1.21" - - // Version1_22 represents Kubernetes version 1.22.x - Version1_22 = "1.22" -) - -// Not yet supported versions -const ( - // Version1_32 represents Kubernetes version 1.32.x - Version1_32 = "1.32" ) const ( @@ -559,62 +509,6 @@ func SupportedRegions() []string { } } -// DeprecatedVersions are the versions of Kubernetes that EKS used to support -// but no longer does. See also: -// https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html -func DeprecatedVersions() []string { - return []string{ - Version1_10, - Version1_11, - Version1_12, - Version1_13, - Version1_14, - Version1_15, - Version1_16, - Version1_17, - Version1_18, - Version1_19, - Version1_20, - Version1_21, - Version1_22, - } -} - -// IsDeprecatedVersion returns true if the given Kubernetes version has been deprecated in EKS -func IsDeprecatedVersion(version string) bool { - for _, v := range DeprecatedVersions() { - if version == v { - return true - } - } - return false -} - -// SupportedVersions are the versions of Kubernetes that EKS supports -func SupportedVersions() []string { - return []string{ - Version1_23, - Version1_24, - Version1_25, - Version1_26, - Version1_27, - Version1_28, - Version1_29, - Version1_30, - Version1_31, - } -} - -// IsSupportedVersion returns true if the given Kubernetes version is supported by eksctl and EKS -func IsSupportedVersion(version string) bool { - for _, v := range SupportedVersions() { - if version == v { - return true - } - } - return false -} - // SupportedNodeVolumeTypes are the volume types that can be used for a node root volume func SupportedNodeVolumeTypes() []string { return []string{ @@ -717,7 +611,7 @@ type ClusterMeta struct { // the AWS region hosting this cluster // +required Region string `json:"region"` - // Valid variants are `KubernetesVersion` constants + // Version use `./eksctl utils describe-cluster-versions` to get the list of supported versions // +optional Version string `json:"version,omitempty"` // Tags are used to tag AWS resources created by eksctl diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index eb5e4bd542..00acd0d53b 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -316,17 +316,6 @@ func ValidateClusterConfig(cfg *ClusterConfig) error { return nil } -// ValidateClusterVersion validates the cluster version. -func ValidateClusterVersion(clusterConfig *ClusterConfig) error { - if clusterVersion := clusterConfig.Metadata.Version; clusterVersion != "" && clusterVersion != DefaultVersion && !IsSupportedVersion(clusterVersion) { - if IsDeprecatedVersion(clusterVersion) { - return fmt.Errorf("invalid version, %s is no longer supported, supported values: %s\nsee also: https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html", clusterVersion, strings.Join(SupportedVersions(), ", ")) - } - return fmt.Errorf("invalid version, supported values: %s", strings.Join(SupportedVersions(), ", ")) - } - return nil -} - func validateKarpenterConfig(cfg *ClusterConfig) error { if cfg.Karpenter == nil { return nil @@ -996,7 +985,7 @@ func ValidateNodeGroup(i int, ng *NodeGroup, cfg *ClusterConfig) error { return err } if *ng.ContainerRuntime != ContainerRuntimeContainerD && isDockershimDeprecated { - return fmt.Errorf("only %s is supported for container runtime, starting with EKS version %s", ContainerRuntimeContainerD, Version1_24) + return fmt.Errorf("only %s is supported for container runtime, starting with EKS version %s", ContainerRuntimeContainerD, DockershimDeprecationVersion) } } if ng.OverrideBootstrapCommand != nil { diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index 8b981c77d3..45c2a1876f 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -132,7 +132,7 @@ var _ = Describe("ClusterConfig validation", func() { It("should reject docker runtime if version is 1.24 or greater", func() { cfg := api.NewClusterConfig() - cfg.Metadata.Version = api.Version1_24 + cfg.Metadata.Version = api.DockershimDeprecationVersion ng0 := cfg.NewNodeGroup() ng0.Name = "node-group" ng0.ContainerRuntime = aws.String(api.ContainerRuntimeDockerD) @@ -140,7 +140,7 @@ var _ = Describe("ClusterConfig validation", func() { Expect(err).NotTo(HaveOccurred()) err = api.ValidateNodeGroup(0, ng0, cfg) Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("only %s is supported for container runtime, starting with EKS version %s", api.ContainerRuntimeContainerD, api.Version1_24)))) + Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("only %s is supported for container runtime, starting with EKS version %s", api.ContainerRuntimeContainerD, api.DockershimDeprecationVersion)))) }) It("containerd cannot be set together with overrideBootstrapCommand", func() { @@ -1429,7 +1429,7 @@ var _ = Describe("ClusterConfig validation", func() { Context("extraIPv6CIDRs", func() { It("validates cidrs", func() { cfg.KubernetesNetworkConfig.IPFamily = api.IPV6Family - cfg.Metadata.Version = api.LatestVersion + cfg.Metadata.Version = api.Version1_31 cfg.Addons = append(cfg.Addons, &api.Addon{Name: api.KubeProxyAddon}, &api.Addon{Name: api.CoreDNSAddon}, @@ -1447,7 +1447,7 @@ var _ = Describe("ClusterConfig validation", func() { When("extraIPv6CIDRs has an invalid cidr", func() { It("returns an error", func() { cfg.VPC.ExtraIPv6CIDRs = []string{"not-a-cidr"} - cfg.Metadata.Version = api.LatestVersion + cfg.Metadata.Version = api.Version1_31 cfg.Addons = append(cfg.Addons, &api.Addon{Name: api.KubeProxyAddon}, &api.Addon{Name: api.CoreDNSAddon}, @@ -1469,7 +1469,7 @@ var _ = Describe("ClusterConfig validation", func() { When("when ipv4 is configured", func() { It("returns an error", func() { cfg.KubernetesNetworkConfig.IPFamily = api.IPV4Family - cfg.Metadata.Version = api.LatestVersion + cfg.Metadata.Version = api.Version1_31 cfg.Addons = append(cfg.Addons, &api.Addon{Name: api.KubeProxyAddon}, &api.Addon{Name: api.CoreDNSAddon}, diff --git a/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go b/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go index 80f5aabd88..5b6287bf1d 100644 --- a/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go +++ b/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go @@ -1385,6 +1385,11 @@ func (in *ManagedNodeGroup) DeepCopyInto(out *ManagedNodeGroup) { *out = new(LaunchTemplate) (*in).DeepCopyInto(*out) } + if in.NodeRepairConfig != nil { + in, out := &in.NodeRepairConfig, &out.NodeRepairConfig + *out = new(NodeGroupNodeRepairConfig) + (*in).DeepCopyInto(*out) + } return } @@ -1862,6 +1867,27 @@ func (in *NodeGroupInstancesDistribution) DeepCopy() *NodeGroupInstancesDistribu return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeGroupNodeRepairConfig) DeepCopyInto(out *NodeGroupNodeRepairConfig) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeGroupNodeRepairConfig. +func (in *NodeGroupNodeRepairConfig) DeepCopy() *NodeGroupNodeRepairConfig { + if in == nil { + return nil + } + out := new(NodeGroupNodeRepairConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeGroupSGs) DeepCopyInto(out *NodeGroupSGs) { *out = *in diff --git a/pkg/ctl/cmdutils/cmd.go b/pkg/ctl/cmdutils/cmd.go index 42335b1cfb..640ae34c1f 100644 --- a/pkg/ctl/cmdutils/cmd.go +++ b/pkg/ctl/cmdutils/cmd.go @@ -34,11 +34,23 @@ type Cmd struct { // instance of eks.ClusterProvider, it may return an error if configuration // is invalid or region is not supported func (c *Cmd) NewCtl() (*eks.ClusterProvider, error) { - if err := c.InitializeClusterConfig(); err != nil { + ctl, err := eks.New(context.TODO(), &c.ProviderConfig, c.ClusterConfig) + if err != nil { return nil, err } - ctl, err := eks.New(context.TODO(), &c.ProviderConfig, c.ClusterConfig) + + cvm, err := eks.NewClusterVersionsManager(ctl.AWSProvider.EKS()) + if err != nil { + return nil, err + } + + version, err := cvm.ResolveClusterVersion(c.ClusterConfig.Metadata.Version) if err != nil { + return nil, fmt.Errorf("resolving cluster version: %w", err) + } + c.ClusterConfig.Metadata.Version = version + + if err := c.InitializeClusterConfig(); err != nil { return nil, err } @@ -84,13 +96,13 @@ func (c *Cmd) InitializeClusterConfig() error { // NewProviderForExistingCluster is a wrapper for NewCtl that also validates that the cluster exists and is not a // registered/connected cluster. func (c *Cmd) NewProviderForExistingCluster(ctx context.Context) (*eks.ClusterProvider, error) { - return c.NewProviderForExistingClusterHelper(ctx, func(ctl *eks.ClusterProvider, meta *api.ClusterMeta) error { + return c.NewProviderForExistingClusterHelper(ctx, func(cvm eks.ClusterVersionsManagerInterface, controlPlaneVersion string, meta *api.ClusterMeta) error { return nil }) } // NewProviderForExistingClusterHelper allows formating cluster K8s version to a standard value before doing nodegroup validations and initializations -func (c *Cmd) NewProviderForExistingClusterHelper(ctx context.Context, standardizeClusterVersionFormat func(ctl *eks.ClusterProvider, meta *api.ClusterMeta) error) (*eks.ClusterProvider, error) { +func (c *Cmd) NewProviderForExistingClusterHelper(ctx context.Context, standardizeClusterVersionFormat func(cvm eks.ClusterVersionsManagerInterface, controlPlaneVersion string, meta *api.ClusterMeta) error) (*eks.ClusterProvider, error) { clusterProvider, err := eks.New(ctx, &c.ProviderConfig, c.ClusterConfig) if err != nil { return nil, fmt.Errorf("could not create cluster provider from options: %w", err) @@ -102,7 +114,12 @@ func (c *Cmd) NewProviderForExistingClusterHelper(ctx context.Context, standardi return nil, err } - if err := standardizeClusterVersionFormat(clusterProvider, c.ClusterConfig.Metadata); err != nil { + cvm, err := eks.NewClusterVersionsManager(clusterProvider.AWSProvider.EKS()) + if err != nil { + return nil, err + } + + if err := standardizeClusterVersionFormat(cvm, clusterProvider.ControlPlaneVersion(), c.ClusterConfig.Metadata); err != nil { return nil, err } diff --git a/pkg/ctl/cmdutils/cmdutils.go b/pkg/ctl/cmdutils/cmdutils.go index 047d7c486b..f7ad7496f3 100644 --- a/pkg/ctl/cmdutils/cmdutils.go +++ b/pkg/ctl/cmdutils/cmdutils.go @@ -167,7 +167,7 @@ func AddRegionFlag(fs *pflag.FlagSet, p *api.ProviderConfig) { // AddVersionFlag adds common --version flag func AddVersionFlag(fs *pflag.FlagSet, meta *api.ClusterMeta, extraUsageInfo string) { - usage := fmt.Sprintf("Kubernetes version (valid options: %s)", strings.Join(api.SupportedVersions(), ", ")) + usage := "Kubernetes version" if extraUsageInfo != "" { usage = fmt.Sprintf("%s [%s]", usage, extraUsageInfo) } diff --git a/pkg/ctl/create/cluster.go b/pkg/ctl/create/cluster.go index 2f85f1ba3f..c929b32eff 100644 --- a/pkg/ctl/create/cluster.go +++ b/pkg/ctl/create/cluster.go @@ -21,7 +21,6 @@ import ( clientcmdlatest "k8s.io/client-go/tools/clientcmd/api/latest" "github.com/aws/amazon-ec2-instance-selector/v2/pkg/selector" - "github.com/weaveworks/eksctl/pkg/accessentry" accessentryactions "github.com/weaveworks/eksctl/pkg/actions/accessentry" "github.com/weaveworks/eksctl/pkg/actions/addon" @@ -72,23 +71,6 @@ func createClusterCmd(cmd *cmdutils.Cmd) { }) } -func checkClusterVersion(cfg *api.ClusterConfig) error { - switch cfg.Metadata.Version { - case "auto": - cfg.Metadata.Version = api.DefaultVersion - case "latest": - cfg.Metadata.Version = api.LatestVersion - } - - if err := api.ValidateClusterVersion(cfg); err != nil { - return err - } - if cfg.Metadata.Version == "" { - cfg.Metadata.Version = api.DefaultVersion - } - return nil -} - func createClusterCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params *cmdutils.CreateClusterCmdParams) error) { cfg := api.NewClusterConfig() ng := api.NewNodeGroup() @@ -104,10 +86,6 @@ func createClusterCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.C if err := cmdutils.NewCreateClusterLoader(cmd, ngFilter, ng, params).Load(); err != nil { return err } - err := checkClusterVersion(cmd.ClusterConfig) - if err != nil { - return err - } return runFunc(cmd, ngFilter, params) } diff --git a/pkg/ctl/create/cluster_test.go b/pkg/ctl/create/cluster_test.go index f876004ca4..af719b1d91 100644 --- a/pkg/ctl/create/cluster_test.go +++ b/pkg/ctl/create/cluster_test.go @@ -215,14 +215,6 @@ var _ = Describe("create cluster", func() { args: []string{"cluster", "--invalid", "dummy"}, error: "unknown flag: --invalid", }), - Entry("with enableSsm disabled", invalidParamsCase{ - args: []string{"--name=test", "--enable-ssm=false"}, - error: "SSM agent is now built into EKS AMIs and cannot be disabled", - }), - Entry("with node zones without zones", invalidParamsCase{ - args: []string{"--zones=zone1,zone2", "--node-zones=zone3"}, - error: "validation for --zones and --node-zones failed: node-zones [zone3] must be a subset of zones [zone1 zone2]; \"zone3\" was not found in zones", - }), ) }) diff --git a/pkg/ctl/create/nodegroup.go b/pkg/ctl/create/nodegroup.go index cf1c86f0ce..e0669774f5 100644 --- a/pkg/ctl/create/nodegroup.go +++ b/pkg/ctl/create/nodegroup.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "io" - "strings" "github.com/aws/amazon-ec2-instance-selector/v2/pkg/selector" @@ -134,35 +133,32 @@ func createNodeGroupCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc runFn) { cmdutils.AddCommonFlagsForAWS(cmd, &cmd.ProviderConfig, true) } -func checkNodeGroupVersion(ctl *eks.ClusterProvider, meta *api.ClusterMeta) error { +func checkNodeGroupVersion(cvm eks.ClusterVersionsManagerInterface, controlPlaneVersion string, meta *api.ClusterMeta) error { switch meta.Version { case "auto": break case "": meta.Version = "auto" case "default": - meta.Version = api.DefaultVersion + meta.Version = cvm.DefaultVersion() logger.Info("will use default version (%s) for new nodegroup(s)", meta.Version) case "latest": - meta.Version = api.LatestVersion + meta.Version = cvm.LatestVersion() logger.Info("will use latest version (%s) for new nodegroup(s)", meta.Version) default: - if !api.IsSupportedVersion(meta.Version) { - if api.IsDeprecatedVersion(meta.Version) { - return fmt.Errorf("invalid version, %s is no longer supported, supported values: auto, default, latest, %s\nsee also: https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html", meta.Version, strings.Join(api.SupportedVersions(), ", ")) - } - return fmt.Errorf("invalid version %s, supported values: auto, default, latest, %s", meta.Version, strings.Join(api.SupportedVersions(), ", ")) + if err := cvm.ValidateVersion(meta.Version); err != nil { + return err } } - if v := ctl.ControlPlaneVersion(); v == "" { + if controlPlaneVersion == "" { return fmt.Errorf("unable to get control plane version") } else if meta.Version == "auto" { - meta.Version = v + meta.Version = controlPlaneVersion logger.Info("will use version %s for new nodegroup(s) based on control plane version", meta.Version) - } else if meta.Version != v { + } else if meta.Version != controlPlaneVersion { hint := "--version=auto" - logger.Warning("will use version %s for new nodegroup(s), while control plane version is %s; to automatically inherit the version use %q", meta.Version, v, hint) + logger.Warning("will use version %s for new nodegroup(s), while control plane version is %s; to automatically inherit the version use %q", meta.Version, controlPlaneVersion, hint) } return nil diff --git a/pkg/ctl/create/nodegroup_test.go b/pkg/ctl/create/nodegroup_test.go index 23f11a8ba2..947c9c1824 100644 --- a/pkg/ctl/create/nodegroup_test.go +++ b/pkg/ctl/create/nodegroup_test.go @@ -1,9 +1,6 @@ package create import ( - "fmt" - "strings" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/eks/types" . "github.com/onsi/ginkgo/v2" @@ -12,6 +9,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/eks/fakes" ) var _ = Describe("create nodegroup", func() { @@ -195,7 +193,12 @@ var _ = Describe("create nodegroup", func() { DescribeTable("checkNodeGroupVersion", func(input checkNodeGroupVersionInput) { - err := checkNodeGroupVersion(input.ctl, input.meta) + cvm := &fakes.FakeClusterVersionsManagerInterface{} + cvm.SupportedVersionsStub = func() []string { + return []string{"1.29", "1.30", "1.31"} + } + cvm.LatestVersionReturns("1.31") + err := checkNodeGroupVersion(cvm, input.ctl.ControlPlaneVersion(), input.meta) if input.expectedErr != "" { Expect(err).To(MatchError(ContainSubstring(input.expectedErr))) return @@ -220,19 +223,7 @@ var _ = Describe("create nodegroup", func() { meta: &api.ClusterMeta{ Version: "latest", }, - expectedVersion: api.LatestVersion, - }), - Entry("version is set to deprecated version", checkNodeGroupVersionInput{ - meta: &api.ClusterMeta{ - Version: api.Version1_15, - }, - expectedErr: fmt.Sprintf("invalid version, %s is no longer supported", api.Version1_15), - }), - Entry("version is set to unsupported version", checkNodeGroupVersionInput{ - meta: &api.ClusterMeta{ - Version: "100", - }, - expectedErr: fmt.Sprintf("invalid version 100, supported values: auto, default, latest, %s", strings.Join(api.SupportedVersions(), ", ")), + expectedVersion: api.Version1_31, }), Entry("fails to retrieve control plane version", checkNodeGroupVersionInput{ ctl: &eks.ClusterProvider{ diff --git a/pkg/ctl/utils/describe_cluster_versions.go b/pkg/ctl/utils/describe_cluster_versions.go new file mode 100644 index 0000000000..785ba6f569 --- /dev/null +++ b/pkg/ctl/utils/describe_cluster_versions.go @@ -0,0 +1,82 @@ +package utils + +import ( + "context" + "fmt" + "os" + + "github.com/aws/aws-sdk-go-v2/service/eks" + "github.com/aws/aws-sdk-go-v2/service/eks/types" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" + "github.com/weaveworks/eksctl/pkg/printers" +) + +func describeClusterVersionsCmd(cmd *cmdutils.Cmd) { + cmd.ClusterConfig = api.NewClusterConfig() + cmd.SetDescription("describe-cluster-versions", "Describe Supported Kubernetes Versions", "") + + var clusterVersions []string + var defaultOnly, include bool + var clusterTypes, status string + + cmd.FlagSetGroup.InFlagSet("Versions", func(fs *pflag.FlagSet) { + fs.StringVar(&clusterTypes, "cluster-types", "", "(optional) Specify the cluster type(s) to filter results. Valid options: eks, eks-local-outposts. Example: --cluster-types \"eks\"") + fs.StringSliceVar(&clusterVersions, "cluster-versions", []string{}, "(optional) Filter results by specific Kubernetes versions. Accepts multiple comma-separated values. Example: --cluster-versions \"1.31,1.30\"") + fs.BoolVar(&include, "include-all", false, "(optional) When set, includes unsupported versions in the results. Default: false") + fs.StringVar(&status, "status", "", "(optional) Filter results by support plan status. Valid options: EXTENDED_SUPPORT, STANDARD_SUPPORT") + fs.BoolVar(&defaultOnly, "default-only", false, "(optional) When set, returns only the default version for the specified cluster type(s). Default: false") + cmdutils.AddClusterFlag(fs, cmd.ClusterConfig.Metadata) + }) + + cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) { + cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) + cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) + cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout) + }) + cmdutils.AddCommonFlagsForAWS(cmd, &cmd.ProviderConfig, false) + + cmd.CobraCommand.RunE = func(_ *cobra.Command, args []string) error { + cmd.NameArg = cmdutils.GetNameArg(args) + return describeClusterVersions(cmd, clusterTypes, clusterVersions, include, defaultOnly, status) + } + +} + +func describeClusterVersions(cmd *cmdutils.Cmd, clusterTypes string, clusterVersions []string, include, defaultOnly bool, status string) error { + clusterProvider, err := cmd.NewCtl() + if err != nil { + return err + } + + ctx := context.TODO() + + versions, err := clusterProvider.AWSProvider.EKS().DescribeClusterVersions( + ctx, + &eks.DescribeClusterVersionsInput{ + ClusterType: &clusterTypes, + ClusterVersions: clusterVersions, + IncludeAll: &include, + DefaultOnly: &defaultOnly, + Status: types.ClusterVersionStatus(status), + }, + ) + + if err != nil { + return err + } + + jsonPrinter := printers.NewJSONPrinter() + printerErr := jsonPrinter.PrintObj(struct { + ClusterVersions []types.ClusterVersionInformation `json:"clusterVersions"` + }{ + ClusterVersions: versions.ClusterVersions, + }, os.Stdout) + if printerErr != nil { + fmt.Printf("Error printing JSON: %v\n", printerErr) + } + + return nil +} diff --git a/pkg/ctl/utils/utils.go b/pkg/ctl/utils/utils.go index 17c21b9bed..9f7c08fcb9 100644 --- a/pkg/ctl/utils/utils.go +++ b/pkg/ctl/utils/utils.go @@ -2,7 +2,6 @@ package utils import ( "github.com/spf13/cobra" - "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" ) @@ -26,6 +25,7 @@ func Command(flagGrouping *cmdutils.FlagGrouping) *cobra.Command { cmdutils.AddResourceCmd(flagGrouping, verbCmd, enableSecretsEncryptionCmd) cmdutils.AddResourceCmd(flagGrouping, verbCmd, schemaCmd) cmdutils.AddResourceCmd(flagGrouping, verbCmd, nodeGroupHealthCmd) + cmdutils.AddResourceCmd(flagGrouping, verbCmd, describeClusterVersionsCmd) cmdutils.AddResourceCmd(flagGrouping, verbCmd, describeAddonVersionsCmd) cmdutils.AddResourceCmd(flagGrouping, verbCmd, describeAddonConfigurationCmd) cmdutils.AddResourceCmd(flagGrouping, verbCmd, migrateToPodIdentityCmd) diff --git a/pkg/eks/fakes/fake_cluster_versions_manager.go b/pkg/eks/fakes/fake_cluster_versions_manager.go new file mode 100644 index 0000000000..b3a9aa6505 --- /dev/null +++ b/pkg/eks/fakes/fake_cluster_versions_manager.go @@ -0,0 +1,614 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package fakes + +import ( + "sync" + + "github.com/weaveworks/eksctl/pkg/eks" +) + +type FakeClusterVersionsManagerInterface struct { + DefaultVersionStub func() string + defaultVersionMutex sync.RWMutex + defaultVersionArgsForCall []struct { + } + defaultVersionReturns struct { + result1 string + } + defaultVersionReturnsOnCall map[int]struct { + result1 string + } + IsDeprecatedVersionStub func(string) bool + isDeprecatedVersionMutex sync.RWMutex + isDeprecatedVersionArgsForCall []struct { + arg1 string + } + isDeprecatedVersionReturns struct { + result1 bool + } + isDeprecatedVersionReturnsOnCall map[int]struct { + result1 bool + } + IsSupportedVersionStub func(string) bool + isSupportedVersionMutex sync.RWMutex + isSupportedVersionArgsForCall []struct { + arg1 string + } + isSupportedVersionReturns struct { + result1 bool + } + isSupportedVersionReturnsOnCall map[int]struct { + result1 bool + } + LatestVersionStub func() string + latestVersionMutex sync.RWMutex + latestVersionArgsForCall []struct { + } + latestVersionReturns struct { + result1 string + } + latestVersionReturnsOnCall map[int]struct { + result1 string + } + ResolveClusterVersionStub func(string) (string, error) + resolveClusterVersionMutex sync.RWMutex + resolveClusterVersionArgsForCall []struct { + arg1 string + } + resolveClusterVersionReturns struct { + result1 string + result2 error + } + resolveClusterVersionReturnsOnCall map[int]struct { + result1 string + result2 error + } + ResolveUpgradeVersionStub func(string, string) (string, error) + resolveUpgradeVersionMutex sync.RWMutex + resolveUpgradeVersionArgsForCall []struct { + arg1 string + arg2 string + } + resolveUpgradeVersionReturns struct { + result1 string + result2 error + } + resolveUpgradeVersionReturnsOnCall map[int]struct { + result1 string + result2 error + } + SupportedVersionsStub func() []string + supportedVersionsMutex sync.RWMutex + supportedVersionsArgsForCall []struct { + } + supportedVersionsReturns struct { + result1 []string + } + supportedVersionsReturnsOnCall map[int]struct { + result1 []string + } + ValidateVersionStub func(string) error + validateVersionMutex sync.RWMutex + validateVersionArgsForCall []struct { + arg1 string + } + validateVersionReturns struct { + result1 error + } + validateVersionReturnsOnCall map[int]struct { + result1 error + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeClusterVersionsManagerInterface) DefaultVersion() string { + fake.defaultVersionMutex.Lock() + ret, specificReturn := fake.defaultVersionReturnsOnCall[len(fake.defaultVersionArgsForCall)] + fake.defaultVersionArgsForCall = append(fake.defaultVersionArgsForCall, struct { + }{}) + stub := fake.DefaultVersionStub + fakeReturns := fake.defaultVersionReturns + fake.recordInvocation("DefaultVersion", []interface{}{}) + fake.defaultVersionMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeClusterVersionsManagerInterface) DefaultVersionCallCount() int { + fake.defaultVersionMutex.RLock() + defer fake.defaultVersionMutex.RUnlock() + return len(fake.defaultVersionArgsForCall) +} + +func (fake *FakeClusterVersionsManagerInterface) DefaultVersionCalls(stub func() string) { + fake.defaultVersionMutex.Lock() + defer fake.defaultVersionMutex.Unlock() + fake.DefaultVersionStub = stub +} + +func (fake *FakeClusterVersionsManagerInterface) DefaultVersionReturns(result1 string) { + fake.defaultVersionMutex.Lock() + defer fake.defaultVersionMutex.Unlock() + fake.DefaultVersionStub = nil + fake.defaultVersionReturns = struct { + result1 string + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) DefaultVersionReturnsOnCall(i int, result1 string) { + fake.defaultVersionMutex.Lock() + defer fake.defaultVersionMutex.Unlock() + fake.DefaultVersionStub = nil + if fake.defaultVersionReturnsOnCall == nil { + fake.defaultVersionReturnsOnCall = make(map[int]struct { + result1 string + }) + } + fake.defaultVersionReturnsOnCall[i] = struct { + result1 string + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) IsDeprecatedVersion(arg1 string) bool { + fake.isDeprecatedVersionMutex.Lock() + ret, specificReturn := fake.isDeprecatedVersionReturnsOnCall[len(fake.isDeprecatedVersionArgsForCall)] + fake.isDeprecatedVersionArgsForCall = append(fake.isDeprecatedVersionArgsForCall, struct { + arg1 string + }{arg1}) + stub := fake.IsDeprecatedVersionStub + fakeReturns := fake.isDeprecatedVersionReturns + fake.recordInvocation("IsDeprecatedVersion", []interface{}{arg1}) + fake.isDeprecatedVersionMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeClusterVersionsManagerInterface) IsDeprecatedVersionCallCount() int { + fake.isDeprecatedVersionMutex.RLock() + defer fake.isDeprecatedVersionMutex.RUnlock() + return len(fake.isDeprecatedVersionArgsForCall) +} + +func (fake *FakeClusterVersionsManagerInterface) IsDeprecatedVersionCalls(stub func(string) bool) { + fake.isDeprecatedVersionMutex.Lock() + defer fake.isDeprecatedVersionMutex.Unlock() + fake.IsDeprecatedVersionStub = stub +} + +func (fake *FakeClusterVersionsManagerInterface) IsDeprecatedVersionArgsForCall(i int) string { + fake.isDeprecatedVersionMutex.RLock() + defer fake.isDeprecatedVersionMutex.RUnlock() + argsForCall := fake.isDeprecatedVersionArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *FakeClusterVersionsManagerInterface) IsDeprecatedVersionReturns(result1 bool) { + fake.isDeprecatedVersionMutex.Lock() + defer fake.isDeprecatedVersionMutex.Unlock() + fake.IsDeprecatedVersionStub = nil + fake.isDeprecatedVersionReturns = struct { + result1 bool + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) IsDeprecatedVersionReturnsOnCall(i int, result1 bool) { + fake.isDeprecatedVersionMutex.Lock() + defer fake.isDeprecatedVersionMutex.Unlock() + fake.IsDeprecatedVersionStub = nil + if fake.isDeprecatedVersionReturnsOnCall == nil { + fake.isDeprecatedVersionReturnsOnCall = make(map[int]struct { + result1 bool + }) + } + fake.isDeprecatedVersionReturnsOnCall[i] = struct { + result1 bool + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) IsSupportedVersion(arg1 string) bool { + fake.isSupportedVersionMutex.Lock() + ret, specificReturn := fake.isSupportedVersionReturnsOnCall[len(fake.isSupportedVersionArgsForCall)] + fake.isSupportedVersionArgsForCall = append(fake.isSupportedVersionArgsForCall, struct { + arg1 string + }{arg1}) + stub := fake.IsSupportedVersionStub + fakeReturns := fake.isSupportedVersionReturns + fake.recordInvocation("IsSupportedVersion", []interface{}{arg1}) + fake.isSupportedVersionMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeClusterVersionsManagerInterface) IsSupportedVersionCallCount() int { + fake.isSupportedVersionMutex.RLock() + defer fake.isSupportedVersionMutex.RUnlock() + return len(fake.isSupportedVersionArgsForCall) +} + +func (fake *FakeClusterVersionsManagerInterface) IsSupportedVersionCalls(stub func(string) bool) { + fake.isSupportedVersionMutex.Lock() + defer fake.isSupportedVersionMutex.Unlock() + fake.IsSupportedVersionStub = stub +} + +func (fake *FakeClusterVersionsManagerInterface) IsSupportedVersionArgsForCall(i int) string { + fake.isSupportedVersionMutex.RLock() + defer fake.isSupportedVersionMutex.RUnlock() + argsForCall := fake.isSupportedVersionArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *FakeClusterVersionsManagerInterface) IsSupportedVersionReturns(result1 bool) { + fake.isSupportedVersionMutex.Lock() + defer fake.isSupportedVersionMutex.Unlock() + fake.IsSupportedVersionStub = nil + fake.isSupportedVersionReturns = struct { + result1 bool + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) IsSupportedVersionReturnsOnCall(i int, result1 bool) { + fake.isSupportedVersionMutex.Lock() + defer fake.isSupportedVersionMutex.Unlock() + fake.IsSupportedVersionStub = nil + if fake.isSupportedVersionReturnsOnCall == nil { + fake.isSupportedVersionReturnsOnCall = make(map[int]struct { + result1 bool + }) + } + fake.isSupportedVersionReturnsOnCall[i] = struct { + result1 bool + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) LatestVersion() string { + fake.latestVersionMutex.Lock() + ret, specificReturn := fake.latestVersionReturnsOnCall[len(fake.latestVersionArgsForCall)] + fake.latestVersionArgsForCall = append(fake.latestVersionArgsForCall, struct { + }{}) + stub := fake.LatestVersionStub + fakeReturns := fake.latestVersionReturns + fake.recordInvocation("LatestVersion", []interface{}{}) + fake.latestVersionMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeClusterVersionsManagerInterface) LatestVersionCallCount() int { + fake.latestVersionMutex.RLock() + defer fake.latestVersionMutex.RUnlock() + return len(fake.latestVersionArgsForCall) +} + +func (fake *FakeClusterVersionsManagerInterface) LatestVersionCalls(stub func() string) { + fake.latestVersionMutex.Lock() + defer fake.latestVersionMutex.Unlock() + fake.LatestVersionStub = stub +} + +func (fake *FakeClusterVersionsManagerInterface) LatestVersionReturns(result1 string) { + fake.latestVersionMutex.Lock() + defer fake.latestVersionMutex.Unlock() + fake.LatestVersionStub = nil + fake.latestVersionReturns = struct { + result1 string + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) LatestVersionReturnsOnCall(i int, result1 string) { + fake.latestVersionMutex.Lock() + defer fake.latestVersionMutex.Unlock() + fake.LatestVersionStub = nil + if fake.latestVersionReturnsOnCall == nil { + fake.latestVersionReturnsOnCall = make(map[int]struct { + result1 string + }) + } + fake.latestVersionReturnsOnCall[i] = struct { + result1 string + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveClusterVersion(arg1 string) (string, error) { + fake.resolveClusterVersionMutex.Lock() + ret, specificReturn := fake.resolveClusterVersionReturnsOnCall[len(fake.resolveClusterVersionArgsForCall)] + fake.resolveClusterVersionArgsForCall = append(fake.resolveClusterVersionArgsForCall, struct { + arg1 string + }{arg1}) + stub := fake.ResolveClusterVersionStub + fakeReturns := fake.resolveClusterVersionReturns + fake.recordInvocation("ResolveClusterVersion", []interface{}{arg1}) + fake.resolveClusterVersionMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveClusterVersionCallCount() int { + fake.resolveClusterVersionMutex.RLock() + defer fake.resolveClusterVersionMutex.RUnlock() + return len(fake.resolveClusterVersionArgsForCall) +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveClusterVersionCalls(stub func(string) (string, error)) { + fake.resolveClusterVersionMutex.Lock() + defer fake.resolveClusterVersionMutex.Unlock() + fake.ResolveClusterVersionStub = stub +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveClusterVersionArgsForCall(i int) string { + fake.resolveClusterVersionMutex.RLock() + defer fake.resolveClusterVersionMutex.RUnlock() + argsForCall := fake.resolveClusterVersionArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveClusterVersionReturns(result1 string, result2 error) { + fake.resolveClusterVersionMutex.Lock() + defer fake.resolveClusterVersionMutex.Unlock() + fake.ResolveClusterVersionStub = nil + fake.resolveClusterVersionReturns = struct { + result1 string + result2 error + }{result1, result2} +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveClusterVersionReturnsOnCall(i int, result1 string, result2 error) { + fake.resolveClusterVersionMutex.Lock() + defer fake.resolveClusterVersionMutex.Unlock() + fake.ResolveClusterVersionStub = nil + if fake.resolveClusterVersionReturnsOnCall == nil { + fake.resolveClusterVersionReturnsOnCall = make(map[int]struct { + result1 string + result2 error + }) + } + fake.resolveClusterVersionReturnsOnCall[i] = struct { + result1 string + result2 error + }{result1, result2} +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveUpgradeVersion(arg1 string, arg2 string) (string, error) { + fake.resolveUpgradeVersionMutex.Lock() + ret, specificReturn := fake.resolveUpgradeVersionReturnsOnCall[len(fake.resolveUpgradeVersionArgsForCall)] + fake.resolveUpgradeVersionArgsForCall = append(fake.resolveUpgradeVersionArgsForCall, struct { + arg1 string + arg2 string + }{arg1, arg2}) + stub := fake.ResolveUpgradeVersionStub + fakeReturns := fake.resolveUpgradeVersionReturns + fake.recordInvocation("ResolveUpgradeVersion", []interface{}{arg1, arg2}) + fake.resolveUpgradeVersionMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveUpgradeVersionCallCount() int { + fake.resolveUpgradeVersionMutex.RLock() + defer fake.resolveUpgradeVersionMutex.RUnlock() + return len(fake.resolveUpgradeVersionArgsForCall) +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveUpgradeVersionCalls(stub func(string, string) (string, error)) { + fake.resolveUpgradeVersionMutex.Lock() + defer fake.resolveUpgradeVersionMutex.Unlock() + fake.ResolveUpgradeVersionStub = stub +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveUpgradeVersionArgsForCall(i int) (string, string) { + fake.resolveUpgradeVersionMutex.RLock() + defer fake.resolveUpgradeVersionMutex.RUnlock() + argsForCall := fake.resolveUpgradeVersionArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveUpgradeVersionReturns(result1 string, result2 error) { + fake.resolveUpgradeVersionMutex.Lock() + defer fake.resolveUpgradeVersionMutex.Unlock() + fake.ResolveUpgradeVersionStub = nil + fake.resolveUpgradeVersionReturns = struct { + result1 string + result2 error + }{result1, result2} +} + +func (fake *FakeClusterVersionsManagerInterface) ResolveUpgradeVersionReturnsOnCall(i int, result1 string, result2 error) { + fake.resolveUpgradeVersionMutex.Lock() + defer fake.resolveUpgradeVersionMutex.Unlock() + fake.ResolveUpgradeVersionStub = nil + if fake.resolveUpgradeVersionReturnsOnCall == nil { + fake.resolveUpgradeVersionReturnsOnCall = make(map[int]struct { + result1 string + result2 error + }) + } + fake.resolveUpgradeVersionReturnsOnCall[i] = struct { + result1 string + result2 error + }{result1, result2} +} + +func (fake *FakeClusterVersionsManagerInterface) SupportedVersions() []string { + fake.supportedVersionsMutex.Lock() + ret, specificReturn := fake.supportedVersionsReturnsOnCall[len(fake.supportedVersionsArgsForCall)] + fake.supportedVersionsArgsForCall = append(fake.supportedVersionsArgsForCall, struct { + }{}) + stub := fake.SupportedVersionsStub + fakeReturns := fake.supportedVersionsReturns + fake.recordInvocation("SupportedVersions", []interface{}{}) + fake.supportedVersionsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeClusterVersionsManagerInterface) SupportedVersionsCallCount() int { + fake.supportedVersionsMutex.RLock() + defer fake.supportedVersionsMutex.RUnlock() + return len(fake.supportedVersionsArgsForCall) +} + +func (fake *FakeClusterVersionsManagerInterface) SupportedVersionsCalls(stub func() []string) { + fake.supportedVersionsMutex.Lock() + defer fake.supportedVersionsMutex.Unlock() + fake.SupportedVersionsStub = stub +} + +func (fake *FakeClusterVersionsManagerInterface) SupportedVersionsReturns(result1 []string) { + fake.supportedVersionsMutex.Lock() + defer fake.supportedVersionsMutex.Unlock() + fake.SupportedVersionsStub = nil + fake.supportedVersionsReturns = struct { + result1 []string + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) SupportedVersionsReturnsOnCall(i int, result1 []string) { + fake.supportedVersionsMutex.Lock() + defer fake.supportedVersionsMutex.Unlock() + fake.SupportedVersionsStub = nil + if fake.supportedVersionsReturnsOnCall == nil { + fake.supportedVersionsReturnsOnCall = make(map[int]struct { + result1 []string + }) + } + fake.supportedVersionsReturnsOnCall[i] = struct { + result1 []string + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) ValidateVersion(arg1 string) error { + fake.validateVersionMutex.Lock() + ret, specificReturn := fake.validateVersionReturnsOnCall[len(fake.validateVersionArgsForCall)] + fake.validateVersionArgsForCall = append(fake.validateVersionArgsForCall, struct { + arg1 string + }{arg1}) + stub := fake.ValidateVersionStub + fakeReturns := fake.validateVersionReturns + fake.recordInvocation("ValidateVersion", []interface{}{arg1}) + fake.validateVersionMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeClusterVersionsManagerInterface) ValidateVersionCallCount() int { + fake.validateVersionMutex.RLock() + defer fake.validateVersionMutex.RUnlock() + return len(fake.validateVersionArgsForCall) +} + +func (fake *FakeClusterVersionsManagerInterface) ValidateVersionCalls(stub func(string) error) { + fake.validateVersionMutex.Lock() + defer fake.validateVersionMutex.Unlock() + fake.ValidateVersionStub = stub +} + +func (fake *FakeClusterVersionsManagerInterface) ValidateVersionArgsForCall(i int) string { + fake.validateVersionMutex.RLock() + defer fake.validateVersionMutex.RUnlock() + argsForCall := fake.validateVersionArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *FakeClusterVersionsManagerInterface) ValidateVersionReturns(result1 error) { + fake.validateVersionMutex.Lock() + defer fake.validateVersionMutex.Unlock() + fake.ValidateVersionStub = nil + fake.validateVersionReturns = struct { + result1 error + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) ValidateVersionReturnsOnCall(i int, result1 error) { + fake.validateVersionMutex.Lock() + defer fake.validateVersionMutex.Unlock() + fake.ValidateVersionStub = nil + if fake.validateVersionReturnsOnCall == nil { + fake.validateVersionReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.validateVersionReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakeClusterVersionsManagerInterface) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.defaultVersionMutex.RLock() + defer fake.defaultVersionMutex.RUnlock() + fake.isDeprecatedVersionMutex.RLock() + defer fake.isDeprecatedVersionMutex.RUnlock() + fake.isSupportedVersionMutex.RLock() + defer fake.isSupportedVersionMutex.RUnlock() + fake.latestVersionMutex.RLock() + defer fake.latestVersionMutex.RUnlock() + fake.resolveClusterVersionMutex.RLock() + defer fake.resolveClusterVersionMutex.RUnlock() + fake.resolveUpgradeVersionMutex.RLock() + defer fake.resolveUpgradeVersionMutex.RUnlock() + fake.supportedVersionsMutex.RLock() + defer fake.supportedVersionsMutex.RUnlock() + fake.validateVersionMutex.RLock() + defer fake.validateVersionMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeClusterVersionsManagerInterface) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ eks.ClusterVersionsManagerInterface = new(FakeClusterVersionsManagerInterface) diff --git a/pkg/eks/versions_manager.go b/pkg/eks/versions_manager.go new file mode 100644 index 0000000000..5690836933 --- /dev/null +++ b/pkg/eks/versions_manager.go @@ -0,0 +1,241 @@ +package eks + +import ( + "context" + "fmt" + "slices" + "sort" + "strconv" + "strings" + + awseks "github.com/aws/aws-sdk-go-v2/service/eks" + "github.com/kris-nova/logger" + + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/awsapi" + "github.com/weaveworks/eksctl/pkg/utils" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate +//counterfeiter:generate -o fakes/fake_cluster_versions_manager.go . ClusterVersionsManagerInterface +type ClusterVersionsManagerInterface interface { + DefaultVersion() string + LatestVersion() string + SupportedVersions() []string + IsSupportedVersion(string) bool + IsDeprecatedVersion(string) bool + ValidateVersion(string) error + ResolveClusterVersion(string) (string, error) + ResolveUpgradeVersion(string, string) (string, error) +} + +type ClusterVersionsManager struct { + eksAPI awsapi.EKS + versionsInfo +} + +type versionsInfo struct { + supportedVersions []string + deprecatedVersions []string + defaultVersion, latestVersion, oldestVersion string +} + +func NewClusterVersionsManager(eksAPI awsapi.EKS) (ClusterVersionsManagerInterface, error) { + cvm := &ClusterVersionsManager{ + eksAPI: eksAPI, + } + output, err := cvm.eksAPI.DescribeClusterVersions(context.TODO(), &awseks.DescribeClusterVersionsInput{}) + if err != nil { + return nil, fmt.Errorf("describing cluster versions: %w", err) + } + + // build a list of supported versions, + for _, version := range output.ClusterVersions { + if version.Status != "UNSUPPORTED" { + cvm.supportedVersions = append(cvm.supportedVersions, *version.ClusterVersion) + } + if version.DefaultVersion { + cvm.defaultVersion = *version.ClusterVersion + } + } + + // resolve oldest and latest versions + sortVersions(cvm.supportedVersions) + cvm.oldestVersion = cvm.supportedVersions[0] + cvm.latestVersion = cvm.supportedVersions[len(cvm.supportedVersions)-1] + + // build a list of deprecated versions + cvm.deprecatedVersions, err = resolveDeprecatedVersions(cvm.oldestVersion) + if err != nil { + return nil, fmt.Errorf("resolving deprecated EKS versions: %w", err) + } + + return cvm, nil +} + +func (cvm *ClusterVersionsManager) SupportedVersions() []string { + return cvm.supportedVersions +} + +func (cvm *ClusterVersionsManager) IsSupportedVersion(version string) bool { + for _, v := range cvm.SupportedVersions() { + if version == v { + return true + } + } + return false +} + +func (cvm *ClusterVersionsManager) DeprecatedVersions() []string { + return cvm.deprecatedVersions +} + +func (cvm *ClusterVersionsManager) IsDeprecatedVersion(version string) bool { + for _, v := range cvm.DeprecatedVersions() { + if version == v { + return true + } + } + return false +} + +func (cvm *ClusterVersionsManager) DefaultVersion() string { + //TODO: replace with output from DescribeClusterVersions endpoint + return api.DefaultVersion +} + +func (cvm *ClusterVersionsManager) LatestVersion() string { + return cvm.latestVersion +} + +func (cvm *ClusterVersionsManager) ValidateVersion(version string) error { + if !cvm.IsSupportedVersion(version) { + if cvm.IsDeprecatedVersion(version) { + return fmt.Errorf("invalid version, %s is no longer supported, supported values: %s\nsee also: https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html", version, strings.Join(cvm.supportedVersions, ", ")) + } + return fmt.Errorf("invalid version, supported values: %s", strings.Join(cvm.supportedVersions, ", ")) + } + return nil +} + +func (cvm *ClusterVersionsManager) ResolveClusterVersion(version string) (string, error) { + switch version { + case "auto", "": + return cvm.DefaultVersion(), nil + case "latest": + return cvm.LatestVersion(), nil + default: + if err := cvm.ValidateVersion(version); err != nil { + return "", err + } + return version, nil + } +} + +func (cvm *ClusterVersionsManager) ResolveUpgradeVersion(desiredVersion string, currentVersion string) (string, error) { + // Resolve next version + var nextVersion string + switch { + case currentVersion == "": + return "", fmt.Errorf("couldn't resolve control plane version") + case cvm.IsDeprecatedVersion(currentVersion): + return "", fmt.Errorf("control plane version %q has been deprecated", currentVersion) + case !cvm.IsSupportedVersion(currentVersion): + return "", fmt.Errorf("control plane version %q is not supported", currentVersion) + default: + i := slices.Index(cvm.supportedVersions, currentVersion) + if i == len(cvm.supportedVersions)-1 { + logger.Info("control plane is already on latest version %q", currentVersion) + return "", nil + } + nextVersion = cvm.supportedVersions[i+1] + } + + // If the version was not specified, default to the next Kubernetes version, and assume the user intended to upgrade if possible. + // Also support "auto" as version (see #2461) + if desiredVersion == "" || desiredVersion == "auto" { + if cvm.IsSupportedVersion(nextVersion) { + return nextVersion, nil + } + // There is no new version, stay in the current one + return "", nil + } + + if c, err := utils.CompareVersions(desiredVersion, currentVersion); err != nil { + return "", fmt.Errorf("couldn't compare versions for upgrade: %w", err) + } else if c < 0 { + return "", fmt.Errorf("cannot upgrade to a lower version. Found given target version %q, current cluster version %q", desiredVersion, currentVersion) + } + + if cvm.IsDeprecatedVersion(desiredVersion) { + return "", fmt.Errorf("control plane version %q has been deprecated", desiredVersion) + } + + if !cvm.IsSupportedVersion(desiredVersion) { + return "", fmt.Errorf("control plane version %q is not supported", desiredVersion) + } + + if desiredVersion == currentVersion { + return "", nil + } + + if desiredVersion == nextVersion { + return desiredVersion, nil + } + + return "", fmt.Errorf( + "upgrading more than one version at a time is not supported. Found upgrade from %q to %q. Please upgrade to %q first", + currentVersion, + desiredVersion, + nextVersion) +} + +func resolveDeprecatedVersions(currentVersion string) ([]string, error) { + parts := strings.Split(currentVersion, ".") + if len(parts) != 2 { + return nil, fmt.Errorf("invalid version format: %s", currentVersion) + } + + major, err := strconv.Atoi(parts[0]) + if err != nil { + return nil, fmt.Errorf("invalid major version in: %s", currentVersion) + } + + minor, err := strconv.Atoi(parts[1]) + if err != nil { + return nil, fmt.Errorf("invalid minor version in: %s", currentVersion) + } + + var versions []string + for m := major; m >= 1; m-- { + startMinor := minor + if m < major { + startMinor = 99 + } + + for n := startMinor - 1; n >= 0; n-- { + versions = append(versions, fmt.Sprintf("%d.%d", m, n)) + } + } + return versions, nil +} + +func sortVersions(versions []string) []string { + sort.Slice(versions, func(i, j int) bool { + v1Parts := strings.Split(versions[i], ".") + v2Parts := strings.Split(versions[j], ".") + + v1Major, _ := strconv.Atoi(v1Parts[0]) + v1Minor, _ := strconv.Atoi(v1Parts[1]) + + v2Major, _ := strconv.Atoi(v2Parts[0]) + v2Minor, _ := strconv.Atoi(v2Parts[1]) + + // Compare major versions first, then minor versions + if v1Major != v2Major { + return v1Major < v2Major + } + return v1Minor < v2Minor + }) + return versions +} diff --git a/pkg/eks/versions_manager_test.go b/pkg/eks/versions_manager_test.go new file mode 100644 index 0000000000..c42dcaa9dd --- /dev/null +++ b/pkg/eks/versions_manager_test.go @@ -0,0 +1,120 @@ +package eks_test + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/stretchr/testify/mock" + + awseks "github.com/aws/aws-sdk-go-v2/service/eks" + ekstypes "github.com/aws/aws-sdk-go-v2/service/eks/types" + "github.com/aws/aws-sdk-go/aws" + + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/eks" + "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" +) + +var _ = Describe("upgrade cluster", func() { + type upgradeCase struct { + givenVersion string + eksVersion string + expectedUpgradeVersion string + expectedErrorText string + } + + DescribeTable("checks the specified version", + func(c upgradeCase) { + mockProvider := mockprovider.NewMockProvider() + mockProvider.MockEKS().On("DescribeClusterVersions", mock.Anything, &awseks.DescribeClusterVersionsInput{}). + Return(&awseks.DescribeClusterVersionsOutput{ + ClusterVersions: []ekstypes.ClusterVersionInformation{ + { + ClusterVersion: aws.String(api.Version1_27), + }, + { + ClusterVersion: aws.String(api.Version1_28), + }, + { + ClusterVersion: aws.String(api.Version1_29), + }, + { + ClusterVersion: aws.String(api.Version1_30), + }, + { + ClusterVersion: aws.String(api.Version1_31), + DefaultVersion: true, + }, + }, + }, nil) + + cvm, err := eks.NewClusterVersionsManager(mockProvider.EKS()) + Expect(err).NotTo(HaveOccurred()) + + upgradeVersion, err := cvm.ResolveUpgradeVersion(c.givenVersion, c.eksVersion) + + if c.expectedErrorText != "" { + if c.expectedErrorText != "cannot upgrade to a lower version" { + } else { + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(c.expectedErrorText)) + } + } else { + Expect(upgradeVersion).To(Equal(c.expectedUpgradeVersion)) + } + }, + + Entry("upgrades by default when the version is not specified", upgradeCase{ + givenVersion: "", + eksVersion: api.Version1_27, + expectedUpgradeVersion: api.Version1_28, + }), + + Entry("upgrades by default when the version is auto", upgradeCase{ + givenVersion: "auto", + eksVersion: api.Version1_27, + expectedUpgradeVersion: api.Version1_28, + }), + + Entry("does not upgrade or fail when the cluster is already in the last version", upgradeCase{ + givenVersion: "", + eksVersion: api.Version1_31, + expectedUpgradeVersion: "", + }), + + Entry("upgrades to the next version when specified", upgradeCase{ + givenVersion: api.Version1_28, + eksVersion: api.Version1_27, + expectedUpgradeVersion: api.Version1_28, + }), + + Entry("does not upgrade when the current version is specified", upgradeCase{ + givenVersion: api.Version1_30, + eksVersion: api.Version1_30, + expectedUpgradeVersion: "", + }), + + Entry("fails when the upgrade jumps more than one kubernetes version", upgradeCase{ + givenVersion: api.Version1_31, + eksVersion: api.Version1_29, + expectedErrorText: "upgrading more than one version at a time is not supported", + }), + + Entry("fails when the given version is lower than the current one", upgradeCase{ + givenVersion: api.Version1_29, + eksVersion: api.Version1_30, + expectedErrorText: "cannot upgrade to a lower version", + }), + + Entry("fails when the version is deprecated", upgradeCase{ + givenVersion: api.Version1_12, + eksVersion: api.Version1_12, + expectedErrorText: "control plane version \"1.12\" has been deprecated", + }), + + Entry("fails when the version is not supported", upgradeCase{ + givenVersion: "1.50", + eksVersion: api.Version1_31, + expectedErrorText: "control plane version \"1.50\" is not supported", + }), + ) +}) diff --git a/pkg/version/version.go b/pkg/version/version.go index 2224eb1fe4..bcce7f0e16 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -4,18 +4,15 @@ import ( "encoding/json" "fmt" "strings" - - "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" ) //go:generate go run ./release_generate.go // Info holds version information type Info struct { - Version string - PreReleaseID string - Metadata BuildMetadata - EKSServerSupportedVersions []string + Version string + PreReleaseID string + Metadata BuildMetadata } // BuildMetadata contains the semver build metadata: @@ -34,7 +31,6 @@ func GetVersionInfo() Info { GitCommit: gitCommit, BuildDate: buildDate, }, - EKSServerSupportedVersions: v1alpha5.SupportedVersions(), } } diff --git a/pkg/version/version_test.go b/pkg/version/version_test.go index 2913dcb6dd..8398e0d33c 100644 --- a/pkg/version/version_test.go +++ b/pkg/version/version_test.go @@ -3,7 +3,6 @@ package version import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" ) var _ = Describe("release tests", func() { @@ -20,10 +19,9 @@ var _ = Describe("release tests", func() { Expect(v).To(Equal("0.5.0")) Expect(info).To(Equal(Info{ - Version: "0.5.0", - PreReleaseID: "", - Metadata: BuildMetadata{}, - EKSServerSupportedVersions: v1alpha5.SupportedVersions(), + Version: "0.5.0", + PreReleaseID: "", + Metadata: BuildMetadata{}, })) }) @@ -44,7 +42,6 @@ var _ = Describe("release tests", func() { GitCommit: "abc123", BuildDate: "today", }, - EKSServerSupportedVersions: v1alpha5.SupportedVersions(), })) }) @@ -64,7 +61,6 @@ var _ = Describe("release tests", func() { GitCommit: "abc123", BuildDate: "today", }, - EKSServerSupportedVersions: v1alpha5.SupportedVersions(), })) }) @@ -84,7 +80,6 @@ var _ = Describe("release tests", func() { GitCommit: "abc1234", BuildDate: "2020-01-15T14:03:46Z", }, - EKSServerSupportedVersions: v1alpha5.SupportedVersions(), })) }) @@ -96,10 +91,9 @@ var _ = Describe("release tests", func() { Expect(v).To(Equal("0.5.0-dev")) Expect(info).To(Equal(Info{ - Version: "0.5.0", - PreReleaseID: "dev", - Metadata: BuildMetadata{}, - EKSServerSupportedVersions: v1alpha5.SupportedVersions(), + Version: "0.5.0", + PreReleaseID: "dev", + Metadata: BuildMetadata{}, })) })