diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index 4e29ad7455..62f050c5d1 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -1211,6 +1211,11 @@ }, "InstanceSelector": { "properties": { + "allow": { + "type": "string", + "description": "List of allowed instance types to select from w/ regex syntax (Example: m[3-5]\\\\.*)", + "x-intellij-html-description": "List of allowed instance types to select from w/ regex syntax (Example: m[3-5]\\.*)" + }, "cpuArchitecture": { "type": "string", "description": "CPU Architecture of the EC2 instance type. Valid variants are: `\"x86_64\"` `\"amd64\"` `\"arm64\"`", @@ -1221,6 +1226,11 @@ "arm64" ] }, + "deny": { + "type": "string", + "description": "List of instance types which should be excluded w/ regex syntax (Example: m[1-2]\\\\.*)", + "x-intellij-html-description": "List of instance types which should be excluded w/ regex syntax (Example: m[1-2]\\.*)" + }, "gpus": { "type": "integer", "description": "specifies the number of GPUs. It can be set to 0 to select non-GPU instance types.", @@ -1241,7 +1251,9 @@ "vCPUs", "memory", "gpus", - "cpuArchitecture" + "cpuArchitecture", + "allow", + "deny" ], "additionalProperties": false, "description": "holds EC2 instance selector options", diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 71820ef56e..716c7fa164 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -2005,6 +2005,11 @@ type InstanceSelector struct { // `"amd64"` // `"arm64"` CPUArchitecture string `json:"cpuArchitecture,omitempty"` + // List of allowed instance types to select from w/ regex syntax (Example: m[3-5]\\.*) + Allow *string `json:"allow,omitempty"` + + // List of instance types which should be excluded w/ regex syntax (Example: m[1-2]\\.*) + Deny *string `json:"deny,omitempty"` } // IsZero returns true if all fields hold a zero value diff --git a/pkg/eks/instance_selector_test.go b/pkg/eks/instance_selector_test.go index 1cf684c623..bad50cc6ce 100644 --- a/pkg/eks/instance_selector_test.go +++ b/pkg/eks/instance_selector_test.go @@ -217,6 +217,52 @@ var _ = Describe("Instance Selector", func() { createFakeInstanceSelector: makeInstanceSelector("c3.large", "c4.large", "c5.large"), expectedInstanceTypes: []string{"c3.large", "c4.large", "c5.large"}, }), + + Entry("valid instance selector criteria with Allow field", instanceSelectorCase{ + nodeGroups: []api.NodePool{ + &api.NodeGroup{ + NodeGroupBase: &api.NodeGroupBase{}, + }, + &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{}, + }, + }, + instanceSelectorValue: &api.InstanceSelector{ + CPUArchitecture: "x86_64", + Allow: aws.String(`c5[a-d]+\..*`), + }, + createFakeInstanceSelector: makeInstanceSelector( + "c5a.2xlarge", + "c5d.2xlarge", + ), + expectedInstanceTypes: []string{"c5a.2xlarge", + "c5d.2xlarge"}, + clusterAZs: []string{"az1", "az2"}, + expectedAZs: []string{"az1", "az2"}, + }), + + Entry("valid instance selector criteria with Deny field", instanceSelectorCase{ + nodeGroups: []api.NodePool{ + &api.NodeGroup{ + NodeGroupBase: &api.NodeGroupBase{}, + }, + &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{}, + }, + }, + instanceSelectorValue: &api.InstanceSelector{ + CPUArchitecture: "x86_64", + Deny: aws.String(`c4.*`), + }, + createFakeInstanceSelector: makeInstanceSelector( + "c5a.2xlarge", + "c5d.2xlarge", + ), + expectedInstanceTypes: []string{"c5a.2xlarge", + "c5d.2xlarge"}, + clusterAZs: []string{"az1", "az2"}, + expectedAZs: []string{"az1", "az2"}, + }), ) }) diff --git a/pkg/eks/nodegroup_service.go b/pkg/eks/nodegroup_service.go index bfd4034ccd..b088680893 100644 --- a/pkg/eks/nodegroup_service.go +++ b/pkg/eks/nodegroup_service.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "reflect" + "regexp" "strings" "github.com/aws/amazon-ec2-instance-selector/v2/pkg/bytequantity" @@ -209,6 +210,22 @@ func (n *NodeGroupService) expandInstanceSelector(ins *api.InstanceSelector, azs filters.CPUArchitecture = (*ec2types.ArchitectureType)(aws.String(cpuArch)) + if ins.Allow != nil { + regexVal, err := regexp.Compile(*ins.Allow) + if err != nil { + return nil, errors.Wrapf(err, "invalid value %q for instanceSelector.allow", *ins.Allow) + } + filters.AllowList = regexVal + } + + if ins.Deny != nil { + regexVal, err := regexp.Compile(*ins.Deny) + if err != nil { + return nil, errors.Wrapf(err, "invalid value %q for instanceSelector.deny", *ins.Deny) + } + filters.DenyList = regexVal + } + instanceTypes, err := n.instanceSelector.Filter(context.TODO(), filters) if err != nil { return nil, errors.Wrap(err, "error querying instance types for the specified instance selector criteria")