diff --git a/integration/tests/instance_selector/instance_selector_test.go b/integration/tests/instance_selector/instance_selector_test.go index d113869ff6..f6168b71a3 100644 --- a/integration/tests/instance_selector/instance_selector_test.go +++ b/integration/tests/instance_selector/instance_selector_test.go @@ -9,12 +9,12 @@ import ( . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" "github.com/pkg/errors" - "github.com/weaveworks/eksctl/pkg/utils" "github.com/weaveworks/eksctl/integration/tests" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/eks" "github.com/weaveworks/eksctl/pkg/testutils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" . "github.com/onsi/ginkgo" ) @@ -58,7 +58,7 @@ var _ = Describe("(Integration) [Instance Selector test]", func() { }, Entry("non-GPU instances", func(instanceTypes []string) { for _, instanceType := range instanceTypes { - Expect(instanceType).ToNot(Satisfy(utils.IsGPUInstanceType)) + Expect(instanceType).ToNot(Satisfy(instanceutils.IsGPUInstanceType)) } }, "--instance-selector-vcpus=8", "--instance-selector-memory=32", diff --git a/pkg/actions/nodegroup/create.go b/pkg/actions/nodegroup/create.go index 57205cc409..3bd92939f6 100644 --- a/pkg/actions/nodegroup/create.go +++ b/pkg/actions/nodegroup/create.go @@ -14,7 +14,7 @@ import ( "github.com/weaveworks/eksctl/pkg/eks" "github.com/weaveworks/eksctl/pkg/kubernetes" "github.com/weaveworks/eksctl/pkg/printers" - "github.com/weaveworks/eksctl/pkg/utils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" "github.com/weaveworks/eksctl/pkg/utils/tasks" "github.com/weaveworks/eksctl/pkg/vpc" @@ -278,7 +278,7 @@ func (m *Manager) checkARMSupport(ctl *eks.ClusterProvider, clientSet kubernetes if err != nil { return err } - if api.ClusterHasInstanceType(cfg, utils.IsARMInstanceType) { + if api.ClusterHasInstanceType(cfg, instanceutils.IsARMInstanceType) { upToDate, err := defaultaddons.DoAddonsSupportMultiArch(clientSet, rawClient, kubernetesVersion, ctl.Provider.Region()) if err != nil { return err diff --git a/pkg/ami/auto_resolver.go b/pkg/ami/auto_resolver.go index 790bfa68e9..3acfeccf3d 100644 --- a/pkg/ami/auto_resolver.go +++ b/pkg/ami/auto_resolver.go @@ -6,7 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/kris-nova/logger" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/utils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" ) const ( @@ -71,7 +71,7 @@ func (r *AutoResolver) Resolve(region, version, instanceType, imageFamily string imageClasses := MakeImageSearchPatterns(version)[imageFamily] namePattern := imageClasses[ImageClassGeneral] - if utils.IsGPUInstanceType(instanceType) { + if instanceutils.IsGPUInstanceType(instanceType) { var ok bool namePattern, ok = imageClasses[ImageClassGPU] if !ok { @@ -80,7 +80,7 @@ func (r *AutoResolver) Resolve(region, version, instanceType, imageFamily string } } - if utils.IsARMInstanceType(instanceType) { + if instanceutils.IsARMInstanceType(instanceType) { var ok bool namePattern, ok = imageClasses[ImageClassARM] if !ok { diff --git a/pkg/ami/auto_resolver_test.go b/pkg/ami/auto_resolver_test.go index 8d7a6f2b19..596fb70115 100644 --- a/pkg/ami/auto_resolver_test.go +++ b/pkg/ami/auto_resolver_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/mock" . "github.com/weaveworks/eksctl/pkg/ami" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/eks" "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" ) @@ -77,7 +76,7 @@ var _ = Describe("AMI Auto Resolution", func() { BeforeEach(func() { imageState = "available" - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockDescribeImages(p, "amazon-eks-node-1.15-v*", expectedAmi, imageState, "2018-08-20T23:25:53.000Z", api.NodeImageFamilyAmazonLinux2) resolver := NewAutoResolver(p.MockEC2()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -101,7 +100,7 @@ var _ = Describe("AMI Auto Resolution", func() { imageState = "available" imageFamily = "Ubuntu1804" - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockDescribeImages(p, "ubuntu-eks/k8s_1.15/images/*18.04*", expectedAmi, imageState, "2018-08-20T23:25:53.000Z", api.NodeImageFamilyUbuntu1804) resolver := NewAutoResolver(p.MockEC2()) @@ -125,7 +124,7 @@ var _ = Describe("AMI Auto Resolution", func() { BeforeEach(func() { imageState = "pending" - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockDescribeImagesMultiple(p, "amazon-eks-node-1.15-v*", []returnAmi{}) resolver := NewAutoResolver(p.MockEC2()) @@ -150,7 +149,7 @@ var _ = Describe("AMI Auto Resolution", func() { imageState = "available" expectedAmi = "ami-5678" - _, p = createProviders() + p = mockprovider.NewMockProvider() images := []returnAmi{ { createdDate: "2018-08-20T23:25:53.000Z", @@ -193,7 +192,7 @@ var _ = Describe("AMI Auto Resolution", func() { BeforeEach(func() { imageState = "available" - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockDescribeImages(p, "amazon-eks-gpu-node-1.15-*", expectedAmi, imageState, "2018-08-20T23:25:53.000Z", api.NodeImageFamilyAmazonLinux2) resolver := NewAutoResolver(p.MockEC2()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -216,16 +215,6 @@ var _ = Describe("AMI Auto Resolution", func() { }) }) -func createProviders() (*eks.ClusterProvider, *mockprovider.MockProvider) { - p := mockprovider.NewMockProvider() - - c := &eks.ClusterProvider{ - Provider: p, - } - - return c, p -} - func addMockDescribeImages(p *mockprovider.MockProvider, expectedNamePattern string, amiID string, amiState string, createdDate string, instanceFamily string) { p.MockEC2().On("DescribeImages", mock.MatchedBy(func(input *ec2.DescribeImagesInput) bool { diff --git a/pkg/ami/ssm_resolver.go b/pkg/ami/ssm_resolver.go index 792b0d1f75..9b63352bff 100644 --- a/pkg/ami/ssm_resolver.go +++ b/pkg/ami/ssm_resolver.go @@ -10,8 +10,8 @@ import ( "github.com/kris-nova/logger" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/utils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" ) // SSMResolver resolves the AMI to the defaults for the region @@ -86,7 +86,7 @@ func MakeManagedSSMParameterName(version, imageFamily, amiType string) (string, // instanceEC2ArchName returns the name of the architecture as used by EC2 // resources. func instanceEC2ArchName(instanceType string) string { - if utils.IsARMInstanceType(instanceType) { + if instanceutils.IsARMInstanceType(instanceType) { return "arm64" } return "x86_64" @@ -94,11 +94,11 @@ func instanceEC2ArchName(instanceType string) string { func imageType(imageFamily, instanceType string) string { family := utils.ToKebabCase(imageFamily) - if utils.IsGPUInstanceType(instanceType) { + if instanceutils.IsGPUInstanceType(instanceType) { return family + "-gpu" } - if utils.IsARMInstanceType(instanceType) { + if instanceutils.IsARMInstanceType(instanceType) { return family + "-arm64" } return family diff --git a/pkg/ami/ssm_resolver_test.go b/pkg/ami/ssm_resolver_test.go index a9d745760f..6bba8b8895 100644 --- a/pkg/ami/ssm_resolver_test.go +++ b/pkg/ami/ssm_resolver_test.go @@ -42,7 +42,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and AL2 ami is available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockGetParameter(p, "/aws/service/eks/optimized-ami/1.12/amazon-linux-2/recommended/image_id", expectedAmi) resolver := NewSSMResolver(p.MockSSM()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -64,7 +64,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is NOT available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockFailedGetParameter(p, "/aws/service/eks/optimized-ami/1.12/amazon-linux-2/recommended/image_id") resolver := NewSSMResolver(p.MockSSM()) @@ -94,7 +94,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockGetParameter(p, "/aws/service/eks/optimized-ami/1.12/amazon-linux-2-gpu/recommended/image_id", expectedAmi) resolver := NewSSMResolver(p.MockSSM()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -122,7 +122,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is available", func() { BeforeEach(func() { version = "1.14" - _, p = createProviders() + p = mockprovider.NewMockProvider() }) It("should return a valid Full image for 1.14", func() { @@ -160,7 +160,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and Ubuntu family", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() }) It("should return an error", func() { @@ -180,7 +180,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockGetParameter(p, "/aws/service/bottlerocket/aws-k8s-1.15/x86_64/latest/image_id", expectedAmi) resolver := NewSSMResolver(p.MockSSM()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -201,7 +201,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is NOT available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockFailedGetParameter(p, "/aws/service/bottlerocket/aws-k8s-1.15/x86_64/latest/image_id") resolver := NewSSMResolver(p.MockSSM()) @@ -229,7 +229,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockGetParameter(p, "/aws/service/bottlerocket/aws-k8s-1.15/arm64/latest/image_id", expectedAmi) resolver := NewSSMResolver(p.MockSSM()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -250,7 +250,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is NOT available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockFailedGetParameter(p, "/aws/service/bottlerocket/aws-k8s-1.15/arm64/latest/image_id") resolver := NewSSMResolver(p.MockSSM()) @@ -278,7 +278,7 @@ var _ = Describe("AMI Auto Resolution", func() { }) }) -func addMockGetParameter(p *mockprovider.MockProvider, name string, amiID string) { +func addMockGetParameter(p *mockprovider.MockProvider, name, amiID string) { p.MockSSM().On("GetParameter", mock.MatchedBy(func(input *ssm.GetParameterInput) bool { return *input.Name == name diff --git a/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go new file mode 100644 index 0000000000..984023d3a9 --- /dev/null +++ b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go @@ -0,0 +1,91 @@ +package v1alpha5_test + +import ( + "fmt" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/gomega" + + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" +) + +var _ = Describe("GPU instance support", func() { + + type gpuInstanceEntry struct { + gpuInstanceType string + amiFamily string + + expectUnsupportedErr bool + } + + assertValidationError := func(e gpuInstanceEntry, err error) { + if e.expectUnsupportedErr { + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("GPU instance types are not supported for %s", e.amiFamily)))) + return + } + Expect(err).ToNot(HaveOccurred()) + } + + DescribeTable("managed nodegroups", func(e gpuInstanceEntry) { + mng := api.NewManagedNodeGroup() + mng.InstanceType = e.gpuInstanceType + mng.AMIFamily = e.amiFamily + mng.InstanceSelector = &api.InstanceSelector{} + assertValidationError(e, api.ValidateManagedNodeGroup(mng, 0)) + }, + Entry("AL2", gpuInstanceEntry{ + gpuInstanceType: "asdf", + amiFamily: api.NodeImageFamilyAmazonLinux2, + }), + Entry("Bottlerocket", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyBottlerocket, + gpuInstanceType: "g4dn.xlarge", + expectUnsupportedErr: true, + }), + Entry("Ubuntu2004", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyUbuntu2004, + gpuInstanceType: "g4dn.xlarge", + expectUnsupportedErr: true, + }), + ) + + DescribeTable("unmanaged nodegroups", func(e gpuInstanceEntry) { + ng := api.NewNodeGroup() + ng.InstanceType = e.gpuInstanceType + ng.AMIFamily = e.amiFamily + assertValidationError(e, api.ValidateNodeGroup(0, ng)) + + }, + Entry("AL2", gpuInstanceEntry{ + gpuInstanceType: "g4dn.xlarge", + amiFamily: api.NodeImageFamilyAmazonLinux2, + }), + Entry("Bottlerocket", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyBottlerocket, + gpuInstanceType: "g4dn.xlarge", + expectUnsupportedErr: true, + }), + Entry("Ubuntu2004", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyUbuntu2004, + gpuInstanceType: "g4dn.xlarge", + expectUnsupportedErr: true, + }), + Entry("Windows2004", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyWindowsServer2004CoreContainer, + gpuInstanceType: "p2.xlarge", + expectUnsupportedErr: true, + }), + Entry("Windows2019Core", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyWindowsServer2019CoreContainer, + gpuInstanceType: "g3.8xlarge", + expectUnsupportedErr: true, + }), + Entry("Windows2019Full", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyWindowsServer2019FullContainer, + gpuInstanceType: "p3.2xlarge", + expectUnsupportedErr: true, + }), + ) +}) diff --git a/pkg/apis/eksctl.io/v1alpha5/instance.go b/pkg/apis/eksctl.io/v1alpha5/instance.go new file mode 100644 index 0000000000..407de19633 --- /dev/null +++ b/pkg/apis/eksctl.io/v1alpha5/instance.go @@ -0,0 +1,32 @@ +package v1alpha5 + +import ( + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" +) + +// SelectInstanceType determines which instanceType is relevant for selecting an AMI +// If the nodegroup has mixed instances it will prefer a GPU instance type over a general class one +// This is to make sure that the AMI that is selected later is valid for all the types +func SelectInstanceType(np NodePool) string { + var instanceTypes []string + switch ng := np.(type) { + case *NodeGroup: + if ng.InstancesDistribution != nil { + instanceTypes = ng.InstancesDistribution.InstanceTypes + } + case *ManagedNodeGroup: + instanceTypes = ng.InstanceTypes + } + + hasMixedInstances := len(instanceTypes) > 0 + if hasMixedInstances { + for _, instanceType := range instanceTypes { + if instanceutils.IsGPUInstanceType(instanceType) { + return instanceType + } + } + return instanceTypes[0] + } + + return np.BaseNodeGroup().InstanceType +} diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 3f2260f7cc..1a9c225499 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -822,7 +822,6 @@ func NewManagedNodeGroup() *ManagedNodeGroup { SSH: &NodeGroupSSH{ Allow: Disabled(), PublicKeyName: &publicKey, - EnableSSM: Disabled(), }, IAM: &NodeGroupIAM{ WithAddonPolicies: NodeGroupIAMAddonPolicies{ diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 207f3671d4..5d2bd40cdb 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -7,6 +7,8 @@ import ( "strconv" "strings" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/arn" "github.com/kris-nova/logger" @@ -212,7 +214,8 @@ func PrivateOnly(ces *ClusterEndpoints) bool { return !*ces.PublicAccess && *ces.PrivateAccess } -func validateNodeGroupBase(ng *NodeGroupBase, path string) error { +func validateNodeGroupBase(np NodePool, path string) error { + ng := np.BaseNodeGroup() if ng.VolumeSize == nil { errCantSet := func(field string) error { return fmt.Errorf("%s.%s cannot be set without %s.volumeSize", path, field, path) @@ -279,6 +282,10 @@ func validateNodeGroupBase(ng *NodeGroupBase, path string) error { } } + if instanceutils.IsGPUInstanceType(SelectInstanceType(np)) && ng.AMIFamily != NodeImageFamilyAmazonLinux2 { + return errors.Errorf("GPU instance types are not supported for %s", ng.AMIFamily) + } + return nil } @@ -369,7 +376,7 @@ func validateNodeGroupName(name string) error { // ValidateNodeGroup checks compatible fields of a given nodegroup func ValidateNodeGroup(i int, ng *NodeGroup) error { path := fmt.Sprintf("nodeGroups[%d]", i) - if err := validateNodeGroupBase(ng.NodeGroupBase, path); err != nil { + if err := validateNodeGroupBase(ng, path); err != nil { return err } @@ -593,7 +600,7 @@ func ValidateManagedNodeGroup(ng *ManagedNodeGroup, index int) error { path := fmt.Sprintf("managedNodeGroups[%d]", index) - if err := validateNodeGroupBase(ng.NodeGroupBase, path); err != nil { + if err := validateNodeGroupBase(ng, path); err != nil { return err } diff --git a/pkg/cfn/builder/managed_nodegroup.go b/pkg/cfn/builder/managed_nodegroup.go index fe50c7f915..98c86da9f2 100644 --- a/pkg/cfn/builder/managed_nodegroup.go +++ b/pkg/cfn/builder/managed_nodegroup.go @@ -14,7 +14,7 @@ import ( api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/nodebootstrap" - "github.com/weaveworks/eksctl/pkg/utils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" "github.com/weaveworks/eksctl/pkg/vpc" ) @@ -215,7 +215,7 @@ func mapTaints(taints []api.NodeGroupTaint) ([]*gfneks.Nodegroup_Taints, error) func selectManagedInstanceType(ng *api.ManagedNodeGroup) string { if len(ng.InstanceTypes) > 0 { for _, instanceType := range ng.InstanceTypes { - if utils.IsGPUInstanceType(instanceType) { + if instanceutils.IsGPUInstanceType(instanceType) { return instanceType } } @@ -260,10 +260,10 @@ func validateLaunchTemplate(launchTemplateData *ec2.ResponseLaunchTemplateData, } func getAMIType(instanceType string) string { - if utils.IsGPUInstanceType(instanceType) { + if instanceutils.IsGPUInstanceType(instanceType) { return eks.AMITypesAl2X8664Gpu } - if utils.IsARMInstanceType(instanceType) { + if instanceutils.IsARMInstanceType(instanceType) { return eks.AMITypesAl2Arm64 } return eks.AMITypesAl2X8664 diff --git a/pkg/eks/api.go b/pkg/eks/api.go index 274d262ecc..2cfee9c18d 100644 --- a/pkg/eks/api.go +++ b/pkg/eks/api.go @@ -46,7 +46,6 @@ import ( ekscreds "github.com/weaveworks/eksctl/pkg/credentials" "github.com/weaveworks/eksctl/pkg/kubernetes" kubewrapper "github.com/weaveworks/eksctl/pkg/kubernetes" - "github.com/weaveworks/eksctl/pkg/utils" "github.com/weaveworks/eksctl/pkg/version" ) @@ -340,7 +339,7 @@ func ResolveAMI(provider api.ClusterProvider, version string, np api.NodePool) e return errors.Errorf("invalid AMI value: %q", ng.AMI) } - instanceType := SelectInstanceType(np) + instanceType := api.SelectInstanceType(np) id, err := resolver.Resolve(provider.Region(), version, instanceType, ng.AMIFamily) if err != nil { return errors.Wrap(err, "unable to determine AMI to use") @@ -352,33 +351,6 @@ func ResolveAMI(provider api.ClusterProvider, version string, np api.NodePool) e return nil } -// SelectInstanceType determines which instanceType is relevant for selecting an AMI -// If the nodegroup has mixed instances it will prefer a GPU instance type over a general class one -// This is to make sure that the AMI that is selected later is valid for all the types -func SelectInstanceType(np api.NodePool) string { - var instanceTypes []string - switch ng := np.(type) { - case *api.NodeGroup: - if ng.InstancesDistribution != nil { - instanceTypes = ng.InstancesDistribution.InstanceTypes - } - case *api.ManagedNodeGroup: - instanceTypes = ng.InstanceTypes - } - - hasMixedInstances := len(instanceTypes) > 0 - if hasMixedInstances { - for _, instanceType := range instanceTypes { - if utils.IsGPUInstanceType(instanceType) { - return instanceType - } - } - return instanceTypes[0] - } - - return np.BaseNodeGroup().InstanceType -} - func errTooFewAvailabilityZones(azs []string) error { return fmt.Errorf("only %d zones specified %v, %d are required (can be non-unique)", len(azs), azs, az.MinRequiredAvailabilityZones) } diff --git a/pkg/eks/instance_selection_test.go b/pkg/eks/instance_selection_test.go index 6ff6cf8e05..4f1677c9b3 100644 --- a/pkg/eks/instance_selection_test.go +++ b/pkg/eks/instance_selection_test.go @@ -4,7 +4,6 @@ import ( . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/eks" ) type instanceTypeCase struct { @@ -42,7 +41,7 @@ var _ = DescribeTable("Instance type selection", func(t instanceTypeCase) { } for _, np := range []api.NodePool{ng, mng} { - instanceType := eks.SelectInstanceType(np) + instanceType := api.SelectInstanceType(np) Expect(instanceType).To(Equal(t.expectedInstanceType)) } }, diff --git a/pkg/eks/tasks.go b/pkg/eks/tasks.go index b457a8b22a..48ff4d7145 100644 --- a/pkg/eks/tasks.go +++ b/pkg/eks/tasks.go @@ -19,7 +19,7 @@ import ( "github.com/weaveworks/eksctl/pkg/addons" "github.com/weaveworks/eksctl/pkg/fargate" iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" - "github.com/weaveworks/eksctl/pkg/utils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" "github.com/weaveworks/eksctl/pkg/utils/tasks" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" @@ -272,16 +272,16 @@ func (c *ClusterProvider) ClusterTasksForNodeGroups(cfg *api.ClusterConfig, inst IsSubTask: false, } var needsNvidiaButNotNeuron = func(t string) bool { - return utils.IsGPUInstanceType(t) && !utils.IsInferentiaInstanceType(t) + return instanceutils.IsGPUInstanceType(t) && !instanceutils.IsInferentiaInstanceType(t) } var haveNeuronInstanceType, haveNvidiaInstanceType, efaEnabled bool for _, ng := range cfg.NodeGroups { - haveNeuronInstanceType = haveNeuronInstanceType || api.HasInstanceType(ng, utils.IsInferentiaInstanceType) + haveNeuronInstanceType = haveNeuronInstanceType || api.HasInstanceType(ng, instanceutils.IsInferentiaInstanceType) haveNvidiaInstanceType = haveNvidiaInstanceType || api.HasInstanceType(ng, needsNvidiaButNotNeuron) efaEnabled = efaEnabled || api.IsEnabled(ng.EFAEnabled) } for _, ng := range cfg.ManagedNodeGroups { - haveNeuronInstanceType = haveNeuronInstanceType || api.HasInstanceTypeManaged(ng, utils.IsInferentiaInstanceType) + haveNeuronInstanceType = haveNeuronInstanceType || api.HasInstanceTypeManaged(ng, instanceutils.IsInferentiaInstanceType) haveNvidiaInstanceType = haveNvidiaInstanceType || api.HasInstanceTypeManaged(ng, needsNvidiaButNotNeuron) efaEnabled = efaEnabled || api.IsEnabled(ng.EFAEnabled) } diff --git a/pkg/utils/instance/instance.go b/pkg/utils/instance/instance.go new file mode 100644 index 0000000000..98e554b1ef --- /dev/null +++ b/pkg/utils/instance/instance.go @@ -0,0 +1,32 @@ +package instance + +import ( + "strings" +) + +// IsARMInstanceType returns true if the instance type is ARM architecture +func IsARMInstanceType(instanceType string) bool { + return strings.HasPrefix(instanceType, "a1") || + strings.HasPrefix(instanceType, "t4g") || + strings.HasPrefix(instanceType, "m6g") || + strings.HasPrefix(instanceType, "m6gd") || + strings.HasPrefix(instanceType, "c6g") || + strings.HasPrefix(instanceType, "c6gd") || + strings.HasPrefix(instanceType, "r6g") || + strings.HasPrefix(instanceType, "r6gd") +} + +// IsGPUInstanceType returns true if the instance type is GPU optimised +func IsGPUInstanceType(instanceType string) bool { + return strings.HasPrefix(instanceType, "p2") || + strings.HasPrefix(instanceType, "p3") || + strings.HasPrefix(instanceType, "p4") || + strings.HasPrefix(instanceType, "g3") || + strings.HasPrefix(instanceType, "g4") || + strings.HasPrefix(instanceType, "inf1") +} + +// IsInferentiaInstanceType returns true if the instance type requires AWS Neuron +func IsInferentiaInstanceType(instanceType string) bool { + return strings.HasPrefix(instanceType, "inf1") +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 1de713e33b..1ebd47c3aa 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -9,33 +9,6 @@ import ( "github.com/pkg/errors" ) -// IsARMInstanceType returns true if the instance type is ARM architecture -func IsARMInstanceType(instanceType string) bool { - return strings.HasPrefix(instanceType, "a1") || - strings.HasPrefix(instanceType, "t4g") || - strings.HasPrefix(instanceType, "m6g") || - strings.HasPrefix(instanceType, "m6gd") || - strings.HasPrefix(instanceType, "c6g") || - strings.HasPrefix(instanceType, "c6gd") || - strings.HasPrefix(instanceType, "r6g") || - strings.HasPrefix(instanceType, "r6gd") -} - -// IsGPUInstanceType returns true if the instance type is GPU optimised -func IsGPUInstanceType(instanceType string) bool { - return strings.HasPrefix(instanceType, "p2") || - strings.HasPrefix(instanceType, "p3") || - strings.HasPrefix(instanceType, "p4") || - strings.HasPrefix(instanceType, "g3") || - strings.HasPrefix(instanceType, "g4") || - strings.HasPrefix(instanceType, "inf1") -} - -// IsInferentiaInstanceType returns true if the instance type requires AWS Neuron -func IsInferentiaInstanceType(instanceType string) bool { - return strings.HasPrefix(instanceType, "inf1") -} - var matchFirstCap = regexp.MustCompile("([0-9]+|[A-Z])") // ToKebabCase turns a CamelCase string into a kebab-case string