diff --git a/integration/tests/addons/addons_test.go b/integration/tests/addons/addons_test.go index fcef9a3325..a824cb22d9 100644 --- a/integration/tests/addons/addons_test.go +++ b/integration/tests/addons/addons_test.go @@ -75,7 +75,7 @@ var _ = BeforeSuite(func() { rawClient = getRawClient(context.Background(), params.ClusterName) serverVersion, err := rawClient.ServerVersion() Expect(err).NotTo(HaveOccurred()) - Expect(serverVersion).To(HavePrefix(api.DefaultVersion)) + Expect(serverVersion).To(HavePrefix(params.Version)) }) @@ -555,7 +555,7 @@ var _ = Describe("(Integration) [EKS Addons test]", func() { cmd := params.EksctlUtilsCmd. WithArgs( "describe-addon-versions", - "--kubernetes-version", api.DefaultVersion, + "--kubernetes-version", params.Version, ) Expect(cmd).To(RunSuccessfullyWithOutputStringLines( ContainElement(ContainSubstring("vpc-cni")), @@ -569,7 +569,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.DefaultVersion), + KubernetesVersion: aws.String(params.Version), }) Expect(err).NotTo(HaveOccurred(), "error describing addon versions") By(fmt.Sprintf("fetching the configuration schema for %s", addonWithSchema)) @@ -592,7 +592,7 @@ var _ = Describe("(Integration) [EKS Addons test]", func() { cmd := params.EksctlUtilsCmd. WithArgs( "describe-addon-versions", - "--kubernetes-version", api.DefaultVersion, + "--kubernetes-version", params.Version, "--types", "networking", "--owners", "aws", "--publishers", "eks", @@ -625,7 +625,7 @@ var _ = Describe("(Integration) [EKS Addons test]", func() { cmd := params.EksctlUtilsCmd. WithArgs( "describe-addon-versions", - "--kubernetes-version", api.DefaultVersion, + "--kubernetes-version", params.Version, "--types", "networking, storage", ) Expect(cmd).To(RunSuccessfullyWithOutputStringLines( @@ -990,7 +990,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.DefaultVersion + clusterConfig.Metadata.Version = params.Version 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 0c125ebb86..ae6311f8c2 100644 --- a/integration/tests/dry_run/dry_run_test.go +++ b/integration/tests/dry_run/dry_run_test.go @@ -46,7 +46,7 @@ func TestDryRun(t *testing.T) { testutils.RegisterAndRun(t) } -const eksVersion = api.DefaultVersion +const eksVersion = api.Version1_34 const defaultClusterConfig = ` apiVersion: eksctl.io/v1alpha5 diff --git a/integration/tests/gitops/flux_test.go b/integration/tests/gitops/flux_test.go index 91d254754c..713a788cb0 100644 --- a/integration/tests/gitops/flux_test.go +++ b/integration/tests/gitops/flux_test.go @@ -66,7 +66,7 @@ var _ = Describe("Enable GitOps", func() { clusterConfig = &api.ClusterConfig{ TypeMeta: api.ClusterConfigTypeMeta(), Metadata: &api.ClusterMeta{ - Version: api.DefaultVersion, + Version: params.Version, Name: params.ClusterName, Region: params.Region, }, diff --git a/integration/tests/ipv6/ipv6_test.go b/integration/tests/ipv6/ipv6_test.go index f33a6c8ba0..81a94bf669 100644 --- a/integration/tests/ipv6/ipv6_test.go +++ b/integration/tests/ipv6/ipv6_test.go @@ -55,7 +55,7 @@ var _ = BeforeSuite(func() { clusterConfig = api.NewClusterConfig() clusterConfig.Metadata.Name = params.ClusterName - clusterConfig.Metadata.Version = api.DefaultVersion + clusterConfig.Metadata.Version = params.Version clusterConfig.Metadata.Region = params.Region clusterConfig.KubernetesNetworkConfig.IPFamily = "iPv6" clusterConfig.VPC.NAT = nil diff --git a/integration/tests/karpenter/karpenter_test.go b/integration/tests/karpenter/karpenter_test.go index 132de854c2..3a205669ef 100644 --- a/integration/tests/karpenter/karpenter_test.go +++ b/integration/tests/karpenter/karpenter_test.go @@ -81,7 +81,7 @@ var _ = Describe("(Integration) Karpenter", func() { Metadata: &api.ClusterMeta{ Name: clusterName, Region: params.Region, - Version: api.DefaultVersion, + Version: params.Version, Tags: map[string]string{ "karpenter.sh/discovery": clusterName, }, diff --git a/integration/tests/params.go b/integration/tests/params.go index 0f149f9aae..91491af4dc 100644 --- a/integration/tests/params.go +++ b/integration/tests/params.go @@ -210,7 +210,7 @@ func NewParamsWithGivenClusterName(clusterNamePrefix string, givenName string) * flag.StringVar(¶ms.EksctlPath, "eksctl.path", "../../../eksctl", "Path to eksctl") flag.StringVar(¶ms.Region, "eksctl.region", api.DefaultRegion, "Region to use for the tests") - flag.StringVar(¶ms.Version, "eksctl.version", api.DefaultVersion, "Version of Kubernetes to test") + flag.StringVar(¶ms.Version, "eksctl.version", "", "Version of Kubernetes to test (default: the EKS default version)") flag.StringVar(¶ms.TestDirectory, "eksctl.test.dir", defaultTestDirectory, "Test directory. Defaulted to: "+defaultTestDirectory) // Flags to help with the development of the integration tests flag.StringVar(¶ms.ClusterName, "eksctl.cluster", "", "Cluster name (default: generate one)") @@ -223,6 +223,9 @@ func NewParamsWithGivenClusterName(clusterNamePrefix string, givenName string) * // go1.13+ testing flags regression fix: https://github.com/golang/go/issues/31859 flag.Parse() + if params.Version == "" { + params.attemptSettingDefaultVersion() + } params.attemptSettingUserID() if params.ClusterName == "" { params.ClusterName = params.newClusterName(clusterNamePrefix, givenName) @@ -257,6 +260,26 @@ func (p *Params) LogStacksEventsOnFailureForCluster(clusterName string) bool { }) } +func (p *Params) attemptSettingDefaultVersion() { + msg := "Warning: failed to resolve the EKS default Kubernetes version, proceeding without it. Error: %v" + clusterProvider, err := eks.New(context.TODO(), &api.ProviderConfig{Region: p.Region}, nil) + if err != nil { + fmt.Fprintf(GinkgoWriter, msg, err) + return + } + cvm, err := eks.NewClusterVersionsManager(clusterProvider.AWSProvider.EKS()) + if err != nil { + fmt.Fprintf(GinkgoWriter, msg, err) + return + } + version, err := cvm.ResolveClusterVersion("") + if err != nil { + fmt.Fprintf(GinkgoWriter, msg, err) + return + } + p.Version = version +} + // attemptSettingUserID will attempt to fetch the first 4 characters of the userID running the // integration tests to be used as a prefix for cluster names. It fails silently if an error occurs func (p *Params) attemptSettingUserID() { diff --git a/integration/tests/windows/windows_test.go b/integration/tests/windows/windows_test.go index 2766e60f9c..aa071f4ee6 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.DefaultVersion + clusterConfig.Metadata.Version = params.Version clusterConfig.Metadata.Region = api.DefaultRegion clusterConfig.IAM.WithOIDC = &withOIDC diff --git a/integration/tests/windows_managed/windows_managed_test.go b/integration/tests/windows_managed/windows_managed_test.go index fa6cfc57d8..d1092f0ec8 100644 --- a/integration/tests/windows_managed/windows_managed_test.go +++ b/integration/tests/windows_managed/windows_managed_test.go @@ -43,7 +43,7 @@ func TestWindowsManaged(t *testing.T) { func makeClusterConfig() *api.ClusterConfig { clusterConfig := api.NewClusterConfig() clusterConfig.Metadata.Name = params.ClusterName - clusterConfig.Metadata.Version = api.DefaultVersion + clusterConfig.Metadata.Version = params.Version clusterConfig.Metadata.Region = params.Region return clusterConfig } diff --git a/pkg/actions/addon/create_test.go b/pkg/actions/addon/create_test.go index 078808c395..a154bceae2 100644 --- a/pkg/actions/addon/create_test.go +++ b/pkg/actions/addon/create_test.go @@ -92,7 +92,7 @@ var _ = Describe("Create", func() { RequiresIamPermissions: true, Compatibilities: []ekstypes.Compatibility{ { - ClusterVersion: aws.String(api.DefaultVersion), + ClusterVersion: aws.String(api.Version1_34), DefaultVersion: true, }, }, diff --git a/pkg/actions/addon/update_test.go b/pkg/actions/addon/update_test.go index 52a3d5a9b1..fd658e7716 100644 --- a/pkg/actions/addon/update_test.go +++ b/pkg/actions/addon/update_test.go @@ -667,7 +667,7 @@ var _ = Describe("Update", func() { }, nil).Once() mockProvider.MockEKS().On("DescribeAddonVersions", mock.Anything, &awseks.DescribeAddonVersionsInput{ AddonName: aws.String("vpc-cni"), - KubernetesVersion: aws.String(api.DefaultVersion), + KubernetesVersion: aws.String(api.Version1_34), }).Return(&awseks.DescribeAddonVersionsOutput{ Addons: []ekstypes.AddonInfo{ { @@ -741,7 +741,7 @@ var _ = Describe("Update", func() { addonManager, err := addon.New(&api.ClusterConfig{ Metadata: &api.ClusterMeta{ - Version: api.DefaultVersion, + Version: api.Version1_34, Name: clusterName, }, AddonsConfig: e.addonsConfig, diff --git a/pkg/actions/nodegroup/create_test.go b/pkg/actions/nodegroup/create_test.go index 0ad082b59f..0759d5b861 100644 --- a/pkg/actions/nodegroup/create_test.go +++ b/pkg/actions/nodegroup/create_test.go @@ -748,7 +748,7 @@ func newClusterConfig() *api.ClusterConfig { TypeMeta: api.ClusterConfigTypeMeta(), Metadata: &api.ClusterMeta{ Name: "my-cluster", - Version: api.DefaultVersion, + Version: api.Version1_34, }, Status: &api.ClusterStatus{ Endpoint: "https://localhost/", diff --git a/pkg/actions/nodegroup/upgrade_test.go b/pkg/actions/nodegroup/upgrade_test.go index f96051968c..e42172948e 100644 --- a/pkg/actions/nodegroup/upgrade_test.go +++ b/pkg/actions/nodegroup/upgrade_test.go @@ -130,7 +130,7 @@ var _ = Describe("Upgrade", func() { }}, nil) }) It("returns an error if kubernetes version is specified", func() { - options.KubernetesVersion = api.DefaultVersion + options.KubernetesVersion = api.Version1_34 err := m.Upgrade(context.Background(), options) Expect(err).To(MatchError(ContainSubstring("cannot specify kubernetes-version or release-version when using a custom AMI"))) }) diff --git a/pkg/apis/eksctl.io/v1alpha5/instance_selector_test.go b/pkg/apis/eksctl.io/v1alpha5/instance_selector_test.go index 8a21cb17ec..757a82b5e5 100644 --- a/pkg/apis/eksctl.io/v1alpha5/instance_selector_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/instance_selector_test.go @@ -14,7 +14,7 @@ var _ = Describe("Instance Selector Validation", func() { DescribeTable("Supported and unsupported field combinations", func(n *instanceSelectorCase) { cfg := NewClusterConfig() - err := SetNodeGroupDefaults(n.ng, &ClusterMeta{Name: "cluster", Version: DefaultVersion}, cfg.IsControlPlaneOnOutposts()) + err := SetNodeGroupDefaults(n.ng, &ClusterMeta{Name: "cluster", Version: Version1_34}, cfg.IsControlPlaneOnOutposts()) Expect(err).NotTo(HaveOccurred()) err = ValidateNodeGroup(0, n.ng, cfg) diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 44469091c8..8be00c3ee0 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -54,9 +54,6 @@ const ( AmazonLinux2EOLVersion = Version1_33 // EFABuiltInSupportVersion defines the minimum Kubernetes version that supports built-in EFA EFABuiltInSupportVersion = Version1_33 - //TODO: Remove this and replace with output from DescribeClusterVersions endpoint - // DefaultVersion (default) - DefaultVersion = Version1_34 ) const ( @@ -1307,10 +1304,8 @@ func ClusterConfigTypeMeta() metav1.TypeMeta { func NewClusterConfig() *ClusterConfig { cfg := &ClusterConfig{ TypeMeta: ClusterConfigTypeMeta(), - Metadata: &ClusterMeta{ - Version: DefaultVersion, - }, - IAM: NewClusterIAM(), + Metadata: &ClusterMeta{}, + IAM: NewClusterIAM(), KubernetesNetworkConfig: &KubernetesNetworkConfig{ IPFamily: DefaultIPFamily, }, diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index 391cb4c369..c0744ea827 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -881,6 +881,7 @@ var _ = Describe("ClusterConfig validation", func() { DescribeTable("AWS Local Zones", func(e localZonesEntry) { clusterConfig := api.NewClusterConfig() + clusterConfig.Metadata.Version = api.Version1_34 e.updateClusterConfig(clusterConfig) clusterConfig.LocalZones = []string{"us-west-2-lax-1a", "us-west-2-lax-1b"} @@ -1013,6 +1014,7 @@ var _ = Describe("ClusterConfig validation", func() { } DescribeTable("RemoteNetworkConfig", func(e remoteNetworkConfigEntry) { cfg := api.NewClusterConfig() + cfg.Metadata.Version = api.Version1_34 api.SetClusterConfigDefaults(cfg) api.SetClusterEndpointAccessDefaults(cfg.VPC) gatewayID := api.VPCGateway("tgw-1234") @@ -1131,6 +1133,7 @@ var _ = Describe("ClusterConfig validation", func() { BeforeEach(func() { cfg = api.NewClusterConfig() + cfg.Metadata.Version = api.Version1_34 vpc = api.NewClusterVPC(false) cfg.VPC = vpc }) diff --git a/pkg/cfn/builder/managed_nodegroup_ami_type_test.go b/pkg/cfn/builder/managed_nodegroup_ami_type_test.go index b54b71bc0e..f6ebbc3fe2 100644 --- a/pkg/cfn/builder/managed_nodegroup_ami_type_test.go +++ b/pkg/cfn/builder/managed_nodegroup_ami_type_test.go @@ -33,7 +33,7 @@ var _ = DescribeTable("Managed Nodegroup AMI type", func(e amiTypeEntry) { if e.clusterVersion != "" { clusterConfig.Metadata.Version = e.clusterVersion } else { - clusterConfig.Metadata.Version = api.DefaultVersion + clusterConfig.Metadata.Version = api.Version1_34 } err := api.SetManagedNodeGroupDefaults(e.nodeGroup, clusterConfig.Metadata, false) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/ctl/cmdutils/cmd.go b/pkg/ctl/cmdutils/cmd.go index 42e6444f56..a4eba8d318 100644 --- a/pkg/ctl/cmdutils/cmd.go +++ b/pkg/ctl/cmdutils/cmd.go @@ -44,11 +44,9 @@ func (c *Cmd) NewCtl() (*eks.ClusterProvider, error) { return nil, err } - version, err := cvm.ResolveClusterVersion(c.ClusterConfig.Metadata.Version) - if err != nil { - return nil, fmt.Errorf("resolving cluster version: %w", err) + if err := resolveClusterVersion(cvm, c.ClusterConfig.Metadata); err != nil { + return nil, err } - c.ClusterConfig.Metadata.Version = version if err := c.InitializeClusterConfig(); err != nil { return nil, err @@ -61,6 +59,18 @@ func (c *Cmd) NewCtl() (*eks.ClusterProvider, error) { return ctl, nil } +func resolveClusterVersion(cvm eks.ClusterVersionsManagerInterface, meta *api.ClusterMeta) error { + if meta.Version == "" && cvm.DefaultVersion() == "" { + return nil + } + version, err := cvm.ResolveClusterVersion(meta.Version) + if err != nil { + return fmt.Errorf("resolving cluster version: %w", err) + } + meta.Version = version + return nil +} + // InitializeClusterConfig validates and initializes the ClusterConfig. func (c *Cmd) InitializeClusterConfig() error { api.SetClusterConfigDefaults(c.ClusterConfig) diff --git a/pkg/ctl/cmdutils/cmd_test.go b/pkg/ctl/cmdutils/cmd_test.go new file mode 100644 index 0000000000..fbff53295c --- /dev/null +++ b/pkg/ctl/cmdutils/cmd_test.go @@ -0,0 +1,66 @@ +package cmdutils + +import ( + "github.com/aws/aws-sdk-go-v2/aws" + awseks "github.com/aws/aws-sdk-go-v2/service/eks" + ekstypes "github.com/aws/aws-sdk-go-v2/service/eks/types" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/stretchr/testify/mock" + + 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("resolveClusterVersion", func() { + type resolveClusterVersionEntry struct { + eksFlagsDefault bool + version string + expectedVersion string + expectedErr string + } + + DescribeTable("resolves the cluster version", func(e resolveClusterVersionEntry) { + mockProvider := mockprovider.NewMockProvider() + mockProvider.MockEKS().On("DescribeClusterVersions", mock.Anything, &awseks.DescribeClusterVersionsInput{}). + Return(&awseks.DescribeClusterVersionsOutput{ + ClusterVersions: []ekstypes.ClusterVersionInformation{ + { + ClusterVersion: aws.String(api.Version1_34), + DefaultVersion: e.eksFlagsDefault, + }, + { + ClusterVersion: aws.String(api.Version1_35), + }, + }, + }, nil) + cvm, err := eks.NewClusterVersionsManager(mockProvider.EKS()) + Expect(err).NotTo(HaveOccurred()) + + meta := &api.ClusterMeta{Version: e.version} + err = resolveClusterVersion(cvm, meta) + if e.expectedErr != "" { + Expect(err).To(MatchError(ContainSubstring(e.expectedErr))) + return + } + Expect(err).NotTo(HaveOccurred()) + Expect(meta.Version).To(Equal(e.expectedVersion)) + }, + Entry("uses the EKS default version when the version is not set", resolveClusterVersionEntry{ + eksFlagsDefault: true, + expectedVersion: api.Version1_34, + }), + Entry("leaves the version unset when EKS does not flag a default", resolveClusterVersionEntry{ + expectedVersion: "", + }), + Entry("uses the specified version when EKS does not flag a default", resolveClusterVersionEntry{ + version: api.Version1_35, + expectedVersion: api.Version1_35, + }), + Entry("fails for auto when EKS does not flag a default", resolveClusterVersionEntry{ + version: "auto", + expectedErr: "EKS did not report a default Kubernetes version", + }), + ) +}) diff --git a/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go b/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go index b7e99a7997..c775a19b62 100644 --- a/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go +++ b/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go @@ -270,6 +270,7 @@ func newClusterConfig() *api.ClusterConfig { cfg.Metadata.Name = "test-3x3-ngs" cfg.Metadata.Region = "eu-central-1" + cfg.Metadata.Version = api.Version1_34 return cfg } @@ -657,7 +658,7 @@ var expected = fmt.Sprintf(` } ] } -`, api.DefaultVersion) +`, api.Version1_34) type mockStackLister struct { nodesResult []manager.NodeGroupStack diff --git a/pkg/ctl/create/cluster.go b/pkg/ctl/create/cluster.go index c79a20b987..965b5ae927 100644 --- a/pkg/ctl/create/cluster.go +++ b/pkg/ctl/create/cluster.go @@ -101,7 +101,7 @@ func createClusterCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.C fs.BoolVar(cfg.IAM.WithOIDC, "with-oidc", false, "Enable the IAM OIDC provider") fs.StringSliceVar(¶ms.AvailabilityZones, "zones", nil, "(auto-select if unspecified)") fs.StringVarP(&cfg.UpgradePolicy.SupportType, "support-type", "", "", "Set cluster's upgradePolicy supportType") - cmdutils.AddVersionFlag(fs, cfg.Metadata, "") + cmdutils.AddVersionFlag(fs, cfg.Metadata, `defaults to the EKS default version; use "latest" for the newest supported version`) cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout) fs.BoolVarP(¶ms.InstallWindowsVPCController, "install-vpc-controllers", "", false, "Install VPC controller that's required for Windows workloads") @@ -153,6 +153,10 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params cfg := cmd.ClusterConfig meta := cmd.ClusterConfig.Metadata + if meta.Version == "" { + return errors.New("EKS did not report a default Kubernetes version; set --version or metadata.version") + } + if meta.Name != "" && api.IsInvalidNameArg(meta.Name) { return api.ErrInvalidName(meta.Name) } diff --git a/pkg/ctl/create/cluster_test.go b/pkg/ctl/create/cluster_test.go index 7c52388537..6a91997b33 100644 --- a/pkg/ctl/create/cluster_test.go +++ b/pkg/ctl/create/cluster_test.go @@ -218,6 +218,26 @@ var _ = Describe("create cluster", func() { ) }) + DescribeTable("version flag", + func(expectedVersion string, args ...string) { + commandArgs := append([]string{"cluster"}, args...) + cmd := newMockEmptyCmd(commandArgs...) + count := 0 + cmdutils.AddResourceCmd(cmdutils.NewGrouping(), cmd.parentCmd, func(cmd *cmdutils.Cmd) { + createClusterCmdWithRunFunc(cmd, func(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params *cmdutils.CreateClusterCmdParams) error { + Expect(cmd.ClusterConfig.Metadata.Version).To(Equal(expectedVersion)) + count++ + return nil + }) + }) + _, err := cmd.execute() + Expect(err).NotTo(HaveOccurred()) + Expect(count).To(Equal(1)) + }, + Entry("without version flag", ""), + Entry("with version flag", "1.33", "--version", "1.33"), + ) + type createClusterEntry struct { updateClusterConfig func(*api.ClusterConfig) updateClusterParams func(*cmdutils.CreateClusterCmdParams) @@ -265,6 +285,7 @@ var _ = Describe("create cluster", func() { clusterConfig := api.NewClusterConfig() clusterConfig.Metadata.Name = clusterName + clusterConfig.Metadata.Version = api.Version1_34 clusterConfig.AddonsConfig.DisableDefaultAddons = true clusterConfig.VPC.ClusterEndpoints = api.ClusterEndpointAccessDefaults() clusterConfig.AccessConfig.AuthenticationMode = ekstypes.AuthenticationModeApiAndConfigMap @@ -311,6 +332,13 @@ var _ = Describe("create cluster", func() { } }, + Entry("fails when the cluster version is not set", createClusterEntry{ + updateClusterConfig: func(c *api.ClusterConfig) { + c.Metadata.Version = "" + }, + expectedErr: "EKS did not report a default Kubernetes version", + }), + Entry("[Cluster with NodeGroups] fails to install device plugins", createClusterEntry{ updateClusterConfig: func(c *api.ClusterConfig) { nodeGroup := getDefaultNodeGroup() diff --git a/pkg/ctl/create/nodegroup.go b/pkg/ctl/create/nodegroup.go index 6d07027d60..9bc87cbdfe 100644 --- a/pkg/ctl/create/nodegroup.go +++ b/pkg/ctl/create/nodegroup.go @@ -149,6 +149,9 @@ func checkNodeGroupVersion(cvm eks.ClusterVersionsManagerInterface, controlPlane meta.Version = "auto" case "default": meta.Version = cvm.DefaultVersion() + if meta.Version == "" { + return fmt.Errorf("EKS did not report a default Kubernetes version; set --version or metadata.version") + } logger.Info("will use default version (%s) for new nodegroup(s)", meta.Version) case "latest": meta.Version = cvm.LatestVersion() diff --git a/pkg/ctl/create/nodegroup_test.go b/pkg/ctl/create/nodegroup_test.go index 947c9c1824..7e808e3e49 100644 --- a/pkg/ctl/create/nodegroup_test.go +++ b/pkg/ctl/create/nodegroup_test.go @@ -177,6 +177,7 @@ var _ = Describe("create nodegroup", func() { type checkNodeGroupVersionInput struct { ctl *eks.ClusterProvider meta *api.ClusterMeta + defaultVersion string expectedVersion string expectedErr string } @@ -198,6 +199,7 @@ var _ = Describe("create nodegroup", func() { return []string{"1.29", "1.30", "1.31"} } cvm.LatestVersionReturns("1.31") + cvm.DefaultVersionReturns(input.defaultVersion) err := checkNodeGroupVersion(cvm, input.ctl.ControlPlaneVersion(), input.meta) if input.expectedErr != "" { Expect(err).To(MatchError(ContainSubstring(input.expectedErr))) @@ -225,6 +227,21 @@ var _ = Describe("create nodegroup", func() { }, expectedVersion: api.Version1_31, }), + Entry("version is set to default", checkNodeGroupVersionInput{ + ctl: providerVersion1_23, + meta: &api.ClusterMeta{ + Version: "default", + }, + defaultVersion: api.Version1_30, + expectedVersion: api.Version1_30, + }), + Entry("version is set to default and EKS does not report a default", checkNodeGroupVersionInput{ + ctl: providerVersion1_23, + meta: &api.ClusterMeta{ + Version: "default", + }, + expectedErr: "EKS did not report a default Kubernetes version", + }), Entry("fails to retrieve control plane version", checkNodeGroupVersionInput{ ctl: &eks.ClusterProvider{ Status: &eks.ProviderStatus{}, diff --git a/pkg/ctl/update/cluster.go b/pkg/ctl/update/cluster.go index 9279c885e2..a5a5da5544 100644 --- a/pkg/ctl/update/cluster.go +++ b/pkg/ctl/update/cluster.go @@ -14,8 +14,6 @@ import ( func updateClusterCmd(cmd *cmdutils.Cmd) { cfg := api.NewClusterConfig() - // Reset version before loading - cfg.Metadata.Version = "" cmd.ClusterConfig = cfg cmd.SetDescription("cluster", "DEPRECATED: use 'upgrade cluster' instead. Upgrade control plane to the next version. ", diff --git a/pkg/ctl/upgrade/cluster.go b/pkg/ctl/upgrade/cluster.go index 25ac4b951a..21da974dba 100644 --- a/pkg/ctl/upgrade/cluster.go +++ b/pkg/ctl/upgrade/cluster.go @@ -24,8 +24,6 @@ func upgradeCluster(cmd *cmdutils.Cmd) { func upgradeClusterWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.Cmd) error) { cfg := api.NewClusterConfig() - // Reset version - cfg.Metadata.Version = "" cmd.ClusterConfig = cfg cmd.SetDescription("cluster", "Upgrade control plane to the next version", diff --git a/pkg/ctl/utils/migrate_to_pod_identity.go b/pkg/ctl/utils/migrate_to_pod_identity.go index 799241101b..9ed93a0379 100644 --- a/pkg/ctl/utils/migrate_to_pod_identity.go +++ b/pkg/ctl/utils/migrate_to_pod_identity.go @@ -74,6 +74,7 @@ func doMigrateToPodIdentity(cmd *cmdutils.Cmd, options podidentityassociation.Po return err } + cfg.Metadata.Version = ctl.ControlPlaneVersion() addonManager, err := addon.New(cfg, ctl.AWSProvider.EKS(), nil, false, nil, nil) if err != nil { return fmt.Errorf("initializing addon creator %w", err) diff --git a/pkg/eks/nodegroup_service_test.go b/pkg/eks/nodegroup_service_test.go index 33d08e72d8..37636e7aff 100644 --- a/pkg/eks/nodegroup_service_test.go +++ b/pkg/eks/nodegroup_service_test.go @@ -78,7 +78,7 @@ var _ = Describe("NodeGroupService", func() { Entry("[Outposts] nodeGroup.instanceType should be set to the smallest available instance type", normalizeEntry{ clusterConfig: &api.ClusterConfig{ Metadata: &api.ClusterMeta{ - Version: api.DefaultVersion, + Version: api.Version1_34, }, Outpost: &api.Outpost{ ControlPlaneOutpostARN: "arn:aws:outposts:us-west-2:1234:outpost/op-1234", @@ -122,7 +122,7 @@ var _ = Describe("NodeGroupService", func() { Entry("[Outposts] unavailable instance type should return an error", normalizeEntry{ clusterConfig: &api.ClusterConfig{ Metadata: &api.ClusterMeta{ - Version: api.DefaultVersion, + Version: api.Version1_34, }, Outpost: &api.Outpost{ ControlPlaneOutpostARN: "arn:aws:outposts:us-west-2:1234:outpost/op-1234", @@ -148,7 +148,7 @@ var _ = Describe("NodeGroupService", func() { Entry("[Outposts] available instance type should not return an error", normalizeEntry{ clusterConfig: &api.ClusterConfig{ Metadata: &api.ClusterMeta{ - Version: api.DefaultVersion, + Version: api.Version1_34, }, Outpost: &api.Outpost{ ControlPlaneOutpostARN: "arn:aws:outposts:us-west-2:1234:outpost/op-1234", @@ -183,7 +183,7 @@ var _ = Describe("NodeGroupService", func() { Entry("instance type should be set to the default instance type", normalizeEntry{ clusterConfig: &api.ClusterConfig{ Metadata: &api.ClusterMeta{ - Version: api.DefaultVersion, + Version: api.Version1_34, }, NodeGroups: []*api.NodeGroup{ { @@ -214,7 +214,7 @@ var _ = Describe("NodeGroupService", func() { Entry(`instance type should be set to "mixed" when using mixed instance types`, normalizeEntry{ clusterConfig: &api.ClusterConfig{ Metadata: &api.ClusterMeta{ - Version: api.DefaultVersion, + Version: api.Version1_34, }, NodeGroups: []*api.NodeGroup{ { @@ -237,7 +237,7 @@ var _ = Describe("NodeGroupService", func() { Entry("instance type should be left unset when instanceSelector or launchTemplate is set", normalizeEntry{ clusterConfig: &api.ClusterConfig{ Metadata: &api.ClusterMeta{ - Version: api.DefaultVersion, + Version: api.Version1_34, }, ManagedNodeGroups: []*api.ManagedNodeGroup{ { diff --git a/pkg/eks/versions_manager.go b/pkg/eks/versions_manager.go index 39e3d69eeb..7d4443a1c3 100644 --- a/pkg/eks/versions_manager.go +++ b/pkg/eks/versions_manager.go @@ -11,7 +11,6 @@ import ( 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" ) @@ -100,8 +99,7 @@ func (cvm *ClusterVersionsManager) IsDeprecatedVersion(version string) bool { } func (cvm *ClusterVersionsManager) DefaultVersion() string { - //TODO: replace with output from DescribeClusterVersions endpoint - return api.DefaultVersion + return cvm.defaultVersion } func (cvm *ClusterVersionsManager) LatestVersion() string { @@ -121,6 +119,9 @@ func (cvm *ClusterVersionsManager) ValidateVersion(version string) error { func (cvm *ClusterVersionsManager) ResolveClusterVersion(version string) (string, error) { switch version { case "auto", "": + if cvm.DefaultVersion() == "" { + return "", fmt.Errorf("EKS did not report a default Kubernetes version; set --version or metadata.version") + } return cvm.DefaultVersion(), nil case "latest": return cvm.LatestVersion(), nil diff --git a/pkg/eks/versions_manager_test.go b/pkg/eks/versions_manager_test.go index 8f843865ba..9004747c02 100644 --- a/pkg/eks/versions_manager_test.go +++ b/pkg/eks/versions_manager_test.go @@ -122,3 +122,90 @@ var _ = Describe("upgrade cluster", func() { }), ) }) + +var _ = Describe("resolve cluster version", func() { + type resolveCase struct { + eksDefaultVersion string + givenVersion string + expectedDefaultVersion string + expectedVersion string + expectedErrorText string + } + + DescribeTable("resolves the specified version", + func(c resolveCase) { + var clusterVersions []ekstypes.ClusterVersionInformation + for _, v := range []string{"1.33", "1.34", "1.35", "1.36", "1.37"} { + clusterVersions = append(clusterVersions, ekstypes.ClusterVersionInformation{ + ClusterVersion: utils.StringPtr(v), + DefaultVersion: v == c.eksDefaultVersion, + }) + } + mockProvider := mockprovider.NewMockProvider() + mockProvider.MockEKS().On("DescribeClusterVersions", mock.Anything, &awseks.DescribeClusterVersionsInput{}). + Return(&awseks.DescribeClusterVersionsOutput{ + ClusterVersions: clusterVersions, + }, nil) + + cvm, err := eks.NewClusterVersionsManager(mockProvider.EKS()) + Expect(err).NotTo(HaveOccurred()) + Expect(cvm.DefaultVersion()).To(Equal(c.expectedDefaultVersion)) + + version, err := cvm.ResolveClusterVersion(c.givenVersion) + + if c.expectedErrorText != "" { + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(c.expectedErrorText)) + } else { + Expect(err).NotTo(HaveOccurred()) + Expect(version).To(Equal(c.expectedVersion)) + } + }, + + Entry("uses the EKS default version when the version is not specified", resolveCase{ + eksDefaultVersion: "1.36", + givenVersion: "", + expectedDefaultVersion: "1.36", + expectedVersion: "1.36", + }), + + Entry("uses the EKS default version when the version is auto", resolveCase{ + eksDefaultVersion: "1.36", + givenVersion: "auto", + expectedDefaultVersion: "1.36", + expectedVersion: "1.36", + }), + + Entry("uses the latest version when the version is latest", resolveCase{ + eksDefaultVersion: "1.36", + givenVersion: "latest", + expectedDefaultVersion: "1.36", + expectedVersion: "1.37", + }), + + Entry("uses the specified version when it is supported", resolveCase{ + eksDefaultVersion: "1.36", + givenVersion: "1.33", + expectedDefaultVersion: "1.36", + expectedVersion: "1.33", + }), + + Entry("fails when the version is not specified and EKS does not flag a default", resolveCase{ + eksDefaultVersion: "", + givenVersion: "", + expectedErrorText: "EKS did not report a default Kubernetes version", + }), + + Entry("fails when the version is auto and EKS does not flag a default", resolveCase{ + eksDefaultVersion: "", + givenVersion: "auto", + expectedErrorText: "EKS did not report a default Kubernetes version", + }), + + Entry("uses the specified version when EKS does not flag a default", resolveCase{ + eksDefaultVersion: "", + givenVersion: "1.35", + expectedVersion: "1.35", + }), + ) +}) diff --git a/pkg/vpc/vpc_test.go b/pkg/vpc/vpc_test.go index 91ef208ae7..35db457729 100644 --- a/pkg/vpc/vpc_test.go +++ b/pkg/vpc/vpc_test.go @@ -827,7 +827,7 @@ var _ = Describe("VPC", func() { cfg: &api.ClusterConfig{ TypeMeta: api.ClusterConfigTypeMeta(), Metadata: &api.ClusterMeta{ - Version: api.DefaultVersion, + Version: api.Version1_34, }, IAM: &api.ClusterIAM{}, VPC: &api.ClusterVPC{ @@ -855,7 +855,7 @@ var _ = Describe("VPC", func() { cfg: &api.ClusterConfig{ TypeMeta: api.ClusterConfigTypeMeta(), Metadata: &api.ClusterMeta{ - Version: api.DefaultVersion, + Version: api.Version1_34, }, IAM: &api.ClusterIAM{}, VPC: &api.ClusterVPC{ @@ -977,7 +977,7 @@ var _ = Describe("VPC", func() { cfg: &api.ClusterConfig{ TypeMeta: api.ClusterConfigTypeMeta(), Metadata: &api.ClusterMeta{ - Version: api.DefaultVersion, + Version: api.Version1_34, }, IAM: &api.ClusterIAM{}, VPC: &api.ClusterVPC{ diff --git a/userdocs/src/getting-started.md b/userdocs/src/getting-started.md index fa46d8a8cc..beb18a8080 100644 --- a/userdocs/src/getting-started.md +++ b/userdocs/src/getting-started.md @@ -124,11 +124,11 @@ eksctl create cluster --name=cluster-1 --nodes=4 ### Supported versions -EKS supports versions `1.23` (extended), `1.24` (extended), `1.25`, `1.26`, `1.27`, `1.28`, `1.29`, **`1.30`** (default) and `1.31`. -With `eksctl` you can deploy any of the supported versions by passing `--version`. +By default, `eksctl` uses the EKS default Kubernetes version (see `eksctl utils describe-cluster-versions --default-only`). +To override it, pass `--version=`, or `--version=latest` for the newest supported version. ```sh -eksctl create cluster --version=1.28 +eksctl create cluster --version=1.35 ``` ### Config-based creation