Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resource/aws_eks_node_group: Add capacity_type argument and support multiple instance_types #16510

Merged
merged 1 commit into from
Dec 1, 2020
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
15 changes: 12 additions & 3 deletions aws/resource_aws_eks_node_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ func resourceAwsEksNodeGroup() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"capacity_type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: eks.CapacityTypesOnDemand,
ValidateFunc: validation.StringInSlice(eks.CapacityTypes_Values(), false),
},
"cluster_name": {
Type: schema.TypeString,
Required: true,
Expand All @@ -68,9 +75,6 @@ func resourceAwsEksNodeGroup() *schema.Resource {
Optional: true,
Computed: true,
ForceNew: true,
// Multiple instance types returns an API error currently:
// InvalidParameterException: Instance type list not valid, only one instance type is supported!
MaxItems: 1,
Elem: &schema.Schema{Type: schema.TypeString},
},
"labels": {
Expand Down Expand Up @@ -232,6 +236,10 @@ func resourceAwsEksNodeGroupCreate(d *schema.ResourceData, meta interface{}) err
input.AmiType = aws.String(v.(string))
}

if v, ok := d.GetOk("capacity_type"); ok {
input.CapacityType = aws.String(v.(string))
}

if v, ok := d.GetOk("disk_size"); ok {
input.DiskSize = aws.Int64(int64(v.(int)))
}
Expand Down Expand Up @@ -327,6 +335,7 @@ func resourceAwsEksNodeGroupRead(d *schema.ResourceData, meta interface{}) error

d.Set("ami_type", nodeGroup.AmiType)
d.Set("arn", nodeGroup.NodegroupArn)
d.Set("capacity_type", nodeGroup.CapacityType)
d.Set("cluster_name", nodeGroup.ClusterName)
d.Set("disk_size", nodeGroup.DiskSize)

Expand Down
134 changes: 128 additions & 6 deletions aws/resource_aws_eks_node_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ func TestAccAWSEksNodeGroup_basic(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "ami_type", eks.AMITypesAl2X8664),
testAccMatchResourceAttrRegionalARN(resourceName, "arn", "eks", regexp.MustCompile(fmt.Sprintf("nodegroup/%[1]s/%[1]s/.+", rName))),
resource.TestCheckResourceAttrPair(resourceName, "cluster_name", eksClusterResourceName, "name"),
resource.TestCheckResourceAttr(resourceName, "capacity_type", eks.CapacityTypesOnDemand),
resource.TestCheckResourceAttr(resourceName, "disk_size", "20"),
resource.TestCheckResourceAttr(resourceName, "instance_types.#", "1"),
resource.TestCheckResourceAttr(resourceName, "labels.%", "0"),
Expand Down Expand Up @@ -179,6 +180,32 @@ func TestAccAWSEksNodeGroup_AmiType(t *testing.T) {
})
}

func TestAccAWSEksNodeGroup_CapacityType_Spot(t *testing.T) {
var nodeGroup1 eks.Nodegroup
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_eks_node_group.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSEks(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEksNodeGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEksNodeGroupConfigCapacityType(rName, eks.CapacityTypesSpot),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEksNodeGroupExists(resourceName, &nodeGroup1),
resource.TestCheckResourceAttr(resourceName, "capacity_type", eks.CapacityTypesSpot),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAWSEksNodeGroup_DiskSize(t *testing.T) {
var nodeGroup1 eks.Nodegroup
rName := acctest.RandomWithPrefix("tf-acc-test")
Expand Down Expand Up @@ -239,9 +266,10 @@ func TestAccAWSEksNodeGroup_ForceUpdateVersion(t *testing.T) {
})
}

func TestAccAWSEksNodeGroup_InstanceTypes(t *testing.T) {
func TestAccAWSEksNodeGroup_InstanceTypes_Multiple(t *testing.T) {
var nodeGroup1 eks.Nodegroup
rName := acctest.RandomWithPrefix("tf-acc-test")
ec2InstanceTypeOfferingsDataSourceName := "data.aws_ec2_instance_type_offerings.available"
resourceName := "aws_eks_node_group.test"

resource.ParallelTest(t, resource.TestCase{
Expand All @@ -250,7 +278,33 @@ func TestAccAWSEksNodeGroup_InstanceTypes(t *testing.T) {
CheckDestroy: testAccCheckAWSEksNodeGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEksNodeGroupConfigInstanceTypes1(rName, "t3.large"),
Config: testAccAWSEksNodeGroupConfigInstanceTypesMultiple(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEksNodeGroupExists(resourceName, &nodeGroup1),
resource.TestCheckResourceAttrPair(resourceName, "instance_types.#", ec2InstanceTypeOfferingsDataSourceName, "instance_types.#"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAWSEksNodeGroup_InstanceTypes_Single(t *testing.T) {
var nodeGroup1 eks.Nodegroup
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_eks_node_group.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSEks(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEksNodeGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEksNodeGroupConfigInstanceTypesSingle(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEksNodeGroupExists(resourceName, &nodeGroup1),
resource.TestCheckResourceAttr(resourceName, "instance_types.#", "1"),
Expand Down Expand Up @@ -1051,6 +1105,30 @@ resource "aws_eks_node_group" "test" {
`, rName, amiType)
}

func testAccAWSEksNodeGroupConfigCapacityType(rName, capacityType string) string {
return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(`
resource "aws_eks_node_group" "test" {
capacity_type = %[2]q
cluster_name = aws_eks_cluster.test.name
node_group_name = %[1]q
node_role_arn = aws_iam_role.node.arn
subnet_ids = aws_subnet.test[*].id

scaling_config {
desired_size = 1
max_size = 1
min_size = 1
}

depends_on = [
"aws_iam_role_policy_attachment.node-AmazonEKSWorkerNodePolicy",
"aws_iam_role_policy_attachment.node-AmazonEKS_CNI_Policy",
"aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly",
]
}
`, rName, capacityType)
}

func testAccAWSEksNodeGroupConfigDiskSize(rName string, diskSize int) string {
return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(`
resource "aws_eks_node_group" "test" {
Expand Down Expand Up @@ -1100,11 +1178,55 @@ resource "aws_eks_node_group" "test" {
`, rName)
}

func testAccAWSEksNodeGroupConfigInstanceTypes1(rName, instanceType1 string) string {
return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(`
func testAccAWSEksNodeGroupConfigInstanceTypesMultiple(rName string) string {
return composeConfig(
testAccAWSEksNodeGroupConfigBase(rName),
fmt.Sprintf(`
data "aws_ec2_instance_type_offerings" "available" {
filter {
name = "instance-type"
values = ["t3.medium", "t3.large", "t2.medium", "t2.large"]
}
}

resource "aws_eks_node_group" "test" {
cluster_name = aws_eks_cluster.test.name
instance_types = data.aws_ec2_instance_type_offerings.available.instance_types
node_group_name = %[1]q
node_role_arn = aws_iam_role.node.arn
subnet_ids = aws_subnet.test[*].id

scaling_config {
desired_size = 1
max_size = 1
min_size = 1
}

depends_on = [
"aws_iam_role_policy_attachment.node-AmazonEKSWorkerNodePolicy",
"aws_iam_role_policy_attachment.node-AmazonEKS_CNI_Policy",
"aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly",
]
}
`, rName))
}

func testAccAWSEksNodeGroupConfigInstanceTypesSingle(rName string) string {
return composeConfig(
testAccAWSEksNodeGroupConfigBase(rName),
fmt.Sprintf(`
data "aws_ec2_instance_type_offering" "available" {
filter {
name = "instance-type"
values = ["t3.large", "t2.large"]
}

preferred_instance_types = ["t3.large", "t2.large"]
}

resource "aws_eks_node_group" "test" {
cluster_name = aws_eks_cluster.test.name
instance_types = [%[2]q]
instance_types = [data.aws_ec2_instance_type_offering.available.instance_type]
node_group_name = %[1]q
node_role_arn = aws_iam_role.node.arn
subnet_ids = aws_subnet.test[*].id
Expand All @@ -1121,7 +1243,7 @@ resource "aws_eks_node_group" "test" {
"aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly",
]
}
`, rName, instanceType1)
`, rName))
}

func testAccAWSEksNodeGroupConfigLabels1(rName, labelKey1, labelValue1 string) string {
Expand Down
3 changes: 2 additions & 1 deletion website/docs/r/eks_node_group.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,10 @@ The following arguments are required:
The following arguments are optional:

* `ami_type` - (Optional) Type of Amazon Machine Image (AMI) associated with the EKS Node Group. Defaults to `AL2_x86_64`. Valid values: `AL2_x86_64`, `AL2_x86_64_GPU`, `AL2_ARM_64`. Terraform will only perform drift detection if a configuration value is provided.
* `capacity_type` - (Optional) Type of capacity associated with the EKS Node Group. Defaults to `ON_DEMAND`. Valid values: `ON_DEMAND`, `SPOT`.
* `disk_size` - (Optional) Disk size in GiB for worker nodes. Defaults to `20`. Terraform will only perform drift detection if a configuration value is provided.
* `force_update_version` - (Optional) Force version update if existing pods are unable to be drained due to a pod disruption budget issue.
* `instance_types` - (Optional) Set of instance types associated with the EKS Node Group. Defaults to `["t3.medium"]`. Terraform will only perform drift detection if a configuration value is provided. Currently, the EKS API only accepts a single value in the set.
* `instance_types` - (Optional) List of instance types associated with the EKS Node Group. Defaults to `["t3.medium"]`. Terraform will only perform drift detection if a configuration value is provided.
* `labels` - (Optional) Key-value map of Kubernetes labels. Only labels that are applied with the EKS API are managed by this argument. Other Kubernetes labels applied to the EKS Node Group will not be managed.
* `launch_template` - (Optional) Configuration block with Launch Template settings. Detailed below.
* `release_version` – (Optional) AMI version of the EKS Node Group. Defaults to latest version for Kubernetes version.
Expand Down