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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions integration/tests/instance_selector/instance_selector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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",
Expand Down
4 changes: 2 additions & 2 deletions pkg/actions/nodegroup/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions pkg/ami/auto_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
21 changes: 5 additions & 16 deletions pkg/ami/auto_resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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)
Expand All @@ -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())
Expand All @@ -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())
Expand All @@ -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",
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand Down
8 changes: 4 additions & 4 deletions pkg/ami/ssm_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -86,19 +86,19 @@ 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"
}

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
Expand Down
20 changes: 10 additions & 10 deletions pkg/ami/ssm_resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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())
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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() {
Expand All @@ -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)
Expand All @@ -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())
Expand Down Expand Up @@ -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)
Expand All @@ -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())
Expand Down Expand Up @@ -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
Expand Down
91 changes: 91 additions & 0 deletions pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go
Original file line number Diff line number Diff line change
@@ -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,
}),
)
})
32 changes: 32 additions & 0 deletions pkg/apis/eksctl.io/v1alpha5/instance.go
Original file line number Diff line number Diff line change
@@ -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
}
1 change: 0 additions & 1 deletion pkg/apis/eksctl.io/v1alpha5/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,6 @@ func NewManagedNodeGroup() *ManagedNodeGroup {
SSH: &NodeGroupSSH{
Allow: Disabled(),
PublicKeyName: &publicKey,
EnableSSM: Disabled(),
},
IAM: &NodeGroupIAM{
WithAddonPolicies: NodeGroupIAMAddonPolicies{
Expand Down
Loading