diff --git a/.changelog/13938.txt b/.changelog/13938.txt new file mode 100644 index 00000000000..410820390f1 --- /dev/null +++ b/.changelog/13938.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_eks_node_group: Add `node_group_name_prefix` argument +``` \ No newline at end of file diff --git a/aws/internal/service/eks/id.go b/aws/internal/service/eks/id.go new file mode 100644 index 00000000000..67651b3c435 --- /dev/null +++ b/aws/internal/service/eks/id.go @@ -0,0 +1,25 @@ +package eks + +import ( + "fmt" + "strings" +) + +const nodeGroupResourceIDSeparator = ":" + +func NodeGroupCreateResourceID(clusterName, nodeGroupName string) string { + parts := []string{clusterName, nodeGroupName} + id := strings.Join(parts, nodeGroupResourceIDSeparator) + + return id +} + +func NodeGroupParseResourceID(id string) (string, string, error) { + parts := strings.Split(id, nodeGroupResourceIDSeparator) + + if len(parts) == 2 && parts[0] != "" && parts[1] != "" { + return parts[0], parts[1], nil + } + + return "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected cluster-name%[2]snode-group-name", id, nodeGroupResourceIDSeparator) +} diff --git a/aws/resource_aws_eks_node_group.go b/aws/resource_aws_eks_node_group.go index 09d3a3258cb..7f4f9b7c62f 100644 --- a/aws/resource_aws_eks_node_group.go +++ b/aws/resource_aws_eks_node_group.go @@ -12,6 +12,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/naming" + tfeks "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/eks" ) func resourceAwsEksNodeGroup() *schema.Resource { @@ -35,15 +37,11 @@ func resourceAwsEksNodeGroup() *schema.Resource { Schema: map[string]*schema.Schema{ "ami_type": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - eks.AMITypesAl2X8664, - eks.AMITypesAl2X8664Gpu, - eks.AMITypesAl2Arm64, - }, false), + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(eks.AMITypes_Values(), false), }, "arn": { Type: schema.TypeString, @@ -115,10 +113,18 @@ func resourceAwsEksNodeGroup() *schema.Resource { }, }, "node_group_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.NoZeroValues, + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: []string{"node_group_name_prefix"}, + }, + "node_group_name_prefix": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: []string{"node_group_name"}, }, "node_role_arn": { Type: schema.TypeString, @@ -226,9 +232,9 @@ func resourceAwsEksNodeGroupCreate(d *schema.ResourceData, meta interface{}) err conn := meta.(*AWSClient).eksconn defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig tags := defaultTagsConfig.MergeTags(keyvaluetags.New(d.Get("tags").(map[string]interface{}))) - clusterName := d.Get("cluster_name").(string) - nodeGroupName := d.Get("node_group_name").(string) + clusterName := d.Get("cluster_name").(string) + nodeGroupName := naming.Generate(d.Get("node_group_name").(string), d.Get("node_group_name_prefix").(string)) input := &eks.CreateNodegroupInput{ ClientRequestToken: aws.String(resource.UniqueId()), ClusterName: aws.String(clusterName), @@ -283,13 +289,11 @@ func resourceAwsEksNodeGroupCreate(d *schema.ResourceData, meta interface{}) err _, err := conn.CreateNodegroup(input) - id := resourceAwsEksNodeGroupCreateId(clusterName, nodeGroupName) - if err != nil { - return fmt.Errorf("error creating EKS Node Group (%s): %s", id, err) + return fmt.Errorf("error creating EKS Node Group (%s/%s): %w", clusterName, nodeGroupName, err) } - d.SetId(id) + d.SetId(tfeks.NodeGroupCreateResourceID(clusterName, nodeGroupName)) stateConf := resource.StateChangeConf{ Pending: []string{eks.NodegroupStatusCreating}, @@ -299,7 +303,7 @@ func resourceAwsEksNodeGroupCreate(d *schema.ResourceData, meta interface{}) err } if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf("error waiting for EKS Node Group (%s) creation: %s", d.Id(), err) + return fmt.Errorf("error waiting for EKS Node Group (%s) creation: %w", d.Id(), err) } return resourceAwsEksNodeGroupRead(d, meta) @@ -310,7 +314,8 @@ func resourceAwsEksNodeGroupRead(d *schema.ResourceData, meta interface{}) error defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig - clusterName, nodeGroupName, err := resourceAwsEksNodeGroupParseId(d.Id()) + clusterName, nodeGroupName, err := tfeks.NodeGroupParseResourceID(d.Id()) + if err != nil { return err } @@ -329,7 +334,7 @@ func resourceAwsEksNodeGroupRead(d *schema.ResourceData, meta interface{}) error } if err != nil { - return fmt.Errorf("error reading EKS Node Group (%s): %s", d.Id(), err) + return fmt.Errorf("error reading EKS Node Group (%s): %w", d.Id(), err) } nodeGroup := output.Nodegroup @@ -346,37 +351,38 @@ func resourceAwsEksNodeGroupRead(d *schema.ResourceData, meta interface{}) error d.Set("disk_size", nodeGroup.DiskSize) if err := d.Set("instance_types", aws.StringValueSlice(nodeGroup.InstanceTypes)); err != nil { - return fmt.Errorf("error setting instance_types: %s", err) + return fmt.Errorf("error setting instance_types: %w", err) } if err := d.Set("labels", aws.StringValueMap(nodeGroup.Labels)); err != nil { - return fmt.Errorf("error setting labels: %s", err) + return fmt.Errorf("error setting labels: %w", err) } if err := d.Set("launch_template", flattenEksLaunchTemplateSpecification(nodeGroup.LaunchTemplate)); err != nil { - return fmt.Errorf("error setting launch_template: %s", err) + return fmt.Errorf("error setting launch_template: %w", err) } d.Set("node_group_name", nodeGroup.NodegroupName) + d.Set("node_group_name_prefix", naming.NamePrefixFromName(aws.StringValue(nodeGroup.NodegroupName))) d.Set("node_role_arn", nodeGroup.NodeRole) d.Set("release_version", nodeGroup.ReleaseVersion) if err := d.Set("remote_access", flattenEksRemoteAccessConfig(nodeGroup.RemoteAccess)); err != nil { - return fmt.Errorf("error setting remote_access: %s", err) + return fmt.Errorf("error setting remote_access: %w", err) } if err := d.Set("resources", flattenEksNodeGroupResources(nodeGroup.Resources)); err != nil { - return fmt.Errorf("error setting resources: %s", err) + return fmt.Errorf("error setting resources: %w", err) } if err := d.Set("scaling_config", flattenEksNodeGroupScalingConfig(nodeGroup.ScalingConfig)); err != nil { - return fmt.Errorf("error setting scaling_config: %s", err) + return fmt.Errorf("error setting scaling_config: %w", err) } d.Set("status", nodeGroup.Status) if err := d.Set("subnet_ids", aws.StringValueSlice(nodeGroup.Subnets)); err != nil { - return fmt.Errorf("error setting subnets: %s", err) + return fmt.Errorf("error setting subnets: %w", err) } tags := keyvaluetags.EksKeyValueTags(nodeGroup.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig) @@ -398,7 +404,8 @@ func resourceAwsEksNodeGroupRead(d *schema.ResourceData, meta interface{}) error func resourceAwsEksNodeGroupUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).eksconn - clusterName, nodeGroupName, err := resourceAwsEksNodeGroupParseId(d.Id()) + clusterName, nodeGroupName, err := tfeks.NodeGroupParseResourceID(d.Id()) + if err != nil { return err } @@ -420,7 +427,7 @@ func resourceAwsEksNodeGroupUpdate(d *schema.ResourceData, meta interface{}) err output, err := conn.UpdateNodegroupConfig(input) if err != nil { - return fmt.Errorf("error updating EKS Node Group (%s) config: %s", d.Id(), err) + return fmt.Errorf("error updating EKS Node Group (%s) config: %w", d.Id(), err) } if output == nil || output.Update == nil || output.Update.Id == nil { @@ -431,7 +438,7 @@ func resourceAwsEksNodeGroupUpdate(d *schema.ResourceData, meta interface{}) err err = waitForEksNodeGroupUpdate(conn, clusterName, nodeGroupName, updateID, d.Timeout(schema.TimeoutUpdate)) if err != nil { - return fmt.Errorf("error waiting for EKS Node Group (%s) config update (%s): %s", d.Id(), updateID, err) + return fmt.Errorf("error waiting for EKS Node Group (%s) config update (%s): %w", d.Id(), updateID, err) } } @@ -474,7 +481,7 @@ func resourceAwsEksNodeGroupUpdate(d *schema.ResourceData, meta interface{}) err output, err := conn.UpdateNodegroupVersion(input) if err != nil { - return fmt.Errorf("error updating EKS Node Group (%s) version: %s", d.Id(), err) + return fmt.Errorf("error updating EKS Node Group (%s) version: %w", d.Id(), err) } if output == nil || output.Update == nil || output.Update.Id == nil { @@ -485,14 +492,14 @@ func resourceAwsEksNodeGroupUpdate(d *schema.ResourceData, meta interface{}) err err = waitForEksNodeGroupUpdate(conn, clusterName, nodeGroupName, updateID, d.Timeout(schema.TimeoutUpdate)) if err != nil { - return fmt.Errorf("error waiting for EKS Node Group (%s) version update (%s): %s", d.Id(), updateID, err) + return fmt.Errorf("error waiting for EKS Node Group (%s) version update (%s): %w", d.Id(), updateID, err) } } if d.HasChange("tags_all") { o, n := d.GetChange("tags_all") if err := keyvaluetags.EksUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { - return fmt.Errorf("error updating tags: %s", err) + return fmt.Errorf("error updating tags: %w", err) } } @@ -502,7 +509,8 @@ func resourceAwsEksNodeGroupUpdate(d *schema.ResourceData, meta interface{}) err func resourceAwsEksNodeGroupDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).eksconn - clusterName, nodeGroupName, err := resourceAwsEksNodeGroupParseId(d.Id()) + clusterName, nodeGroupName, err := tfeks.NodeGroupParseResourceID(d.Id()) + if err != nil { return err } @@ -519,11 +527,11 @@ func resourceAwsEksNodeGroupDelete(d *schema.ResourceData, meta interface{}) err } if err != nil { - return fmt.Errorf("error deleting EKS Node Group (%s): %s", d.Id(), err) + return fmt.Errorf("error deleting EKS Node Group (%s): %w", d.Id(), err) } if err := waitForEksNodeGroupDeletion(conn, clusterName, nodeGroupName, d.Timeout(schema.TimeoutDelete)); err != nil { - return fmt.Errorf("error waiting for EKS Node Group (%s) deletion: %s", d.Id(), err) + return fmt.Errorf("error waiting for EKS Node Group (%s) deletion: %w", d.Id(), err) } return nil @@ -718,7 +726,7 @@ func refreshEksNodeGroupStatus(conn *eks.EKS, clusterName string, nodeGroupName nodeGroup := output.Nodegroup if nodeGroup == nil { - return nodeGroup, "", fmt.Errorf("EKS Node Group (%s) missing", resourceAwsEksNodeGroupCreateId(clusterName, nodeGroupName)) + return nodeGroup, "", fmt.Errorf("EKS Node Group (%s) missing", tfeks.NodeGroupCreateResourceID(clusterName, nodeGroupName)) } status := aws.StringValue(nodeGroup.Status) @@ -727,7 +735,7 @@ func refreshEksNodeGroupStatus(conn *eks.EKS, clusterName string, nodeGroupName // unexpected state 'CREATE_FAILED', wanted target 'ACTIVE'. last error: %!s() if status == eks.NodegroupStatusCreateFailed || status == eks.NodegroupStatusDeleteFailed { if nodeGroup.Health == nil || len(nodeGroup.Health.Issues) == 0 || nodeGroup.Health.Issues[0] == nil { - return nodeGroup, status, fmt.Errorf("unable to find additional information about %s status, check EKS Node Group (%s) health", status, resourceAwsEksNodeGroupCreateId(clusterName, nodeGroupName)) + return nodeGroup, status, fmt.Errorf("unable to find additional information about %s status, check EKS Node Group (%s) health", status, tfeks.NodeGroupCreateResourceID(clusterName, nodeGroupName)) } issue := nodeGroup.Health.Issues[0] @@ -754,7 +762,7 @@ func refreshEksNodeGroupUpdateStatus(conn *eks.EKS, clusterName string, nodeGrou } if output == nil || output.Update == nil { - return nil, "", fmt.Errorf("EKS Node Group (%s) update (%s) missing", resourceAwsEksNodeGroupCreateId(clusterName, nodeGroupName), updateID) + return nil, "", fmt.Errorf("EKS Node Group (%s) update (%s) missing", tfeks.NodeGroupCreateResourceID(clusterName, nodeGroupName), updateID) } return output.Update, aws.StringValue(output.Update.Status), nil @@ -812,19 +820,3 @@ func waitForEksNodeGroupUpdate(conn *eks.EKS, clusterName, nodeGroupName string, return fmt.Errorf("EKS Node Group (%s) update (%s) status (%s) not successful: Errors:\n%s", clusterName, updateID, aws.StringValue(update.Status), strings.Join(detailedErrors, "\n")) } - -func resourceAwsEksNodeGroupParseId(id string) (string, string, error) { - // inverse of resourceAwsEksNodeGroupCreateId() - parts := strings.Split(id, ":") - - if len(parts) != 2 { - return "", "", fmt.Errorf("unexpected format of ID (%s), expected cluster-name:node-group-name", id) - } - - return parts[0], parts[1], nil -} - -func resourceAwsEksNodeGroupCreateId(clusterName, nodeGroupName string) string { - // inverse of resourceAwsEksNodeGroupParseId() - return fmt.Sprintf("%s:%s", clusterName, nodeGroupName) -} diff --git a/aws/resource_aws_eks_node_group_test.go b/aws/resource_aws_eks_node_group_test.go index 8d92adcb211..b381cba9598 100644 --- a/aws/resource_aws_eks_node_group_test.go +++ b/aws/resource_aws_eks_node_group_test.go @@ -13,6 +13,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/naming" + tfeks "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/eks" ) func init() { @@ -53,7 +55,7 @@ func testSweepEksNodeGroups(region string) error { d.Set("cluster_name", clusterName) d.Set("node_group_name", nodeGroupName) - d.SetId(resourceAwsEksNodeGroupCreateId(clusterName, nodeGroupName)) + d.SetId(tfeks.NodeGroupCreateResourceID(clusterName, nodeGroupName)) sweepResources = append(sweepResources, NewTestSweepResource(r, d, client)) } @@ -111,6 +113,7 @@ func TestAccAWSEksNodeGroup_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "instance_types.#", "1"), resource.TestCheckResourceAttr(resourceName, "labels.%", "0"), resource.TestCheckResourceAttr(resourceName, "node_group_name", rName), + resource.TestCheckResourceAttr(resourceName, "node_group_name_prefix", ""), resource.TestCheckResourceAttrPair(resourceName, "node_role_arn", iamRoleResourceName, "arn"), resource.TestMatchResourceAttr(resourceName, "release_version", regexp.MustCompile(`^\d+\.\d+\.\d+-\d{8}$`)), resource.TestCheckResourceAttr(resourceName, "remote_access.#", "0"), @@ -135,6 +138,62 @@ func TestAccAWSEksNodeGroup_basic(t *testing.T) { }) } +func TestAccAWSEksNodeGroup_Name_Generated(t *testing.T) { + var nodeGroup 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) }, + ErrorCheck: testAccErrorCheck(t, eks.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSEksNodeGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSEksNodeGroupConfigNodeGroupNameGenerated(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSEksNodeGroupExists(resourceName, &nodeGroup), + naming.TestCheckResourceAttrNameGenerated(resourceName, "node_group_name"), + resource.TestCheckResourceAttr(resourceName, "node_group_name_prefix", "terraform-"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSEksNodeGroup_NamePrefix(t *testing.T) { + var nodeGroup 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) }, + ErrorCheck: testAccErrorCheck(t, eks.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSEksNodeGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSEksNodeGroupConfigNodeGroupNamePrefix(rName, "tf-acc-test-prefix-"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSEksNodeGroupExists(resourceName, &nodeGroup), + naming.TestCheckResourceAttrNameFromPrefix(resourceName, "node_group_name", "tf-acc-test-prefix-"), + resource.TestCheckResourceAttr(resourceName, "node_group_name_prefix", "tf-acc-test-prefix-"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAWSEksNodeGroup_disappears(t *testing.T) { var nodeGroup eks.Nodegroup rName := acctest.RandomWithPrefix("tf-acc-test") @@ -811,7 +870,7 @@ func testAccCheckAWSEksNodeGroupExists(resourceName string, nodeGroup *eks.Nodeg return fmt.Errorf("No EKS Node Group ID is set") } - clusterName, nodeGroupName, err := resourceAwsEksNodeGroupParseId(rs.Primary.ID) + clusterName, nodeGroupName, err := tfeks.NodeGroupParseResourceID(rs.Primary.ID) if err != nil { return err } @@ -855,7 +914,7 @@ func testAccCheckAWSEksNodeGroupDestroy(s *terraform.State) error { continue } - clusterName, nodeGroupName, err := resourceAwsEksNodeGroupParseId(rs.Primary.ID) + clusterName, nodeGroupName, err := tfeks.NodeGroupParseResourceID(rs.Primary.ID) if err != nil { return err } @@ -994,13 +1053,17 @@ resource "aws_vpc" "test" { enable_dns_support = true tags = { - Name = "tf-acc-test-eks-node-group" + Name = %[1]q "kubernetes.io/cluster/%[1]s" = "shared" } } resource "aws_internet_gateway" "test" { vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } resource "aws_route_table" "test" { @@ -1010,6 +1073,10 @@ resource "aws_route_table" "test" { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.test.id } + + tags = { + Name = %[1]q + } } resource "aws_main_route_table_association" "test" { @@ -1034,6 +1101,10 @@ resource "aws_security_group" "test" { protocol = -1 to_port = 0 } + + tags = { + Name = %[1]q + } } resource "aws_subnet" "test" { @@ -1045,7 +1116,7 @@ resource "aws_subnet" "test" { vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-test-eks-node-group" + Name = %[1]q "kubernetes.io/cluster/%[1]s" = "shared" } } @@ -1094,7 +1165,7 @@ resource "aws_eks_cluster" "test" { } func testAccAWSEksNodeGroupConfigNodeGroupName(rName string) string { - return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` resource "aws_eks_node_group" "test" { cluster_name = aws_eks_cluster.test.name node_group_name = %[1]q @@ -1113,11 +1184,56 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName) +`, rName)) +} + +func testAccAWSEksNodeGroupConfigNodeGroupNameGenerated(rName string) string { + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), ` +resource "aws_eks_node_group" "test" { + cluster_name = aws_eks_cluster.test.name + 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, + ] +} +`) +} + +func testAccAWSEksNodeGroupConfigNodeGroupNamePrefix(rName, namePrefix string) string { + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` +resource "aws_eks_node_group" "test" { + cluster_name = aws_eks_cluster.test.name + node_group_name_prefix = %[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", + ] +} +`, namePrefix)) } func testAccAWSEksNodeGroupConfigAmiType(rName, amiType string) string { - return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` resource "aws_eks_node_group" "test" { ami_type = %[2]q cluster_name = aws_eks_cluster.test.name @@ -1137,11 +1253,11 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName, amiType) +`, rName, amiType)) } func testAccAWSEksNodeGroupConfigCapacityType(rName, capacityType string) string { - return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` resource "aws_eks_node_group" "test" { capacity_type = %[2]q cluster_name = aws_eks_cluster.test.name @@ -1161,11 +1277,11 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName, capacityType) +`, rName, capacityType)) } func testAccAWSEksNodeGroupConfigDiskSize(rName string, diskSize int) string { - return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` resource "aws_eks_node_group" "test" { cluster_name = aws_eks_cluster.test.name disk_size = %[2]d @@ -1185,11 +1301,11 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName, diskSize) +`, rName, diskSize)) } func testAccAWSEksNodeGroupConfigForceUpdateVersion(rName, version string) string { - return testAccAWSEksNodeGroupConfigBaseVersion(rName, version) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBaseVersion(rName, version), fmt.Sprintf(` resource "aws_eks_node_group" "test" { cluster_name = aws_eks_cluster.test.name force_update_version = true @@ -1210,7 +1326,7 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName) +`, rName)) } func testAccAWSEksNodeGroupConfigInstanceTypesMultiple(rName string) string { @@ -1282,7 +1398,7 @@ resource "aws_eks_node_group" "test" { } func testAccAWSEksNodeGroupConfigLabels1(rName, labelKey1, labelValue1 string) string { - return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` resource "aws_eks_node_group" "test" { cluster_name = aws_eks_cluster.test.name node_group_name = %[1]q @@ -1305,11 +1421,11 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName, labelKey1, labelValue1) +`, rName, labelKey1, labelValue1)) } func testAccAWSEksNodeGroupConfigLabels2(rName, labelKey1, labelValue1, labelKey2, labelValue2 string) string { - return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` resource "aws_eks_node_group" "test" { cluster_name = aws_eks_cluster.test.name node_group_name = %[1]q @@ -1333,7 +1449,7 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName, labelKey1, labelValue1, labelKey2, labelValue2) +`, rName, labelKey1, labelValue1, labelKey2, labelValue2)) } func testAccAWSEksNodeGroupConfigLaunchTemplateId1(rName string) string { @@ -1613,7 +1729,7 @@ resource "aws_eks_node_group" "test" { } func testAccAWSEksNodeGroupConfigReleaseVersion(rName string, version string) string { - return testAccAWSEksNodeGroupConfigBaseVersion(rName, version) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBaseVersion(rName, version), fmt.Sprintf(` data "aws_ssm_parameter" "test" { name = "/aws/service/eks/optimized-ami/${aws_eks_cluster.test.version}/amazon-linux-2/recommended/release_version" } @@ -1638,11 +1754,11 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName) +`, rName)) } func testAccAWSEksNodeGroupConfigRemoteAccessEc2SshKey(rName string) string { - return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` resource "aws_key_pair" "test" { key_name = %[1]q public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8giupGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKVHO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwWdhXmXSrbX8ZbabVohBK41 example@example.com" @@ -1670,11 +1786,11 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName) +`, rName)) } func testAccAWSEksNodeGroupConfigRemoteAccessSourceSecurityGroupIds1(rName string) string { - return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` resource "aws_key_pair" "test" { key_name = %[1]q public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8giupGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKVHO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwWdhXmXSrbX8ZbabVohBK41 example@example.com" @@ -1703,11 +1819,11 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName) +`, rName)) } func testAccAWSEksNodeGroupConfigScalingConfigSizes(rName string, desiredSize, maxSize, minSize int) string { - return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` resource "aws_eks_node_group" "test" { cluster_name = aws_eks_cluster.test.name node_group_name = %[1]q @@ -1726,11 +1842,11 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName, desiredSize, maxSize, minSize) +`, rName, desiredSize, maxSize, minSize)) } func testAccAWSEksNodeGroupConfigTags1(rName, tagKey1, tagValue1 string) string { - return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` resource "aws_eks_node_group" "test" { cluster_name = aws_eks_cluster.test.name node_group_name = %[1]q @@ -1753,11 +1869,11 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName, tagKey1, tagValue1) +`, rName, tagKey1, tagValue1)) } func testAccAWSEksNodeGroupConfigTags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { - return testAccAWSEksNodeGroupConfigBase(rName) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBase(rName), fmt.Sprintf(` resource "aws_eks_node_group" "test" { cluster_name = aws_eks_cluster.test.name node_group_name = %[1]q @@ -1781,11 +1897,11 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +`, rName, tagKey1, tagValue1, tagKey2, tagValue2)) } func testAccAWSEksNodeGroupConfigVersion(rName, version string) string { - return testAccAWSEksNodeGroupConfigBaseVersion(rName, version) + fmt.Sprintf(` + return composeConfig(testAccAWSEksNodeGroupConfigBaseVersion(rName, version), fmt.Sprintf(` resource "aws_eks_node_group" "test" { cluster_name = aws_eks_cluster.test.name node_group_name = %[1]q @@ -1805,5 +1921,5 @@ resource "aws_eks_node_group" "test" { aws_iam_role_policy_attachment.node-AmazonEC2ContainerRegistryReadOnly, ] } -`, rName) +`, rName)) } diff --git a/website/docs/r/eks_node_group.html.markdown b/website/docs/r/eks_node_group.html.markdown index 2c17aed57fd..e021880b5c8 100644 --- a/website/docs/r/eks_node_group.html.markdown +++ b/website/docs/r/eks_node_group.html.markdown @@ -116,20 +116,21 @@ resource "aws_subnet" "example" { The following arguments are required: * `cluster_name` – (Required) Name of the EKS Cluster. Must be between 1-100 characters in length. Must begin with an alphanumeric character, and must only contain alphanumeric characters, dashes and underscores (`^[0-9A-Za-z][A-Za-z0-9\-_]+$`). -* `node_group_name` – (Required) Name of the EKS Node Group. * `node_role_arn` – (Required) Amazon Resource Name (ARN) of the IAM Role that provides permissions for the EKS Node Group. * `scaling_config` - (Required) Configuration block with scaling settings. Detailed below. * `subnet_ids` – (Required) Identifiers of EC2 Subnets to associate with the EKS Node Group. These subnets must have the following resource tag: `kubernetes.io/cluster/CLUSTER_NAME` (where `CLUSTER_NAME` is replaced with the name of the EKS Cluster). 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. +* `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`, `CUSTOM`. Terraform will only perform drift detection if a configuration value is provided. * `capacity_type` - (Optional) Type of capacity associated with the EKS Node Group. Valid values: `ON_DEMAND`, `SPOT`. Terraform will only perform drift detection if a configuration value is provided. * `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) 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. +* `node_group_name` – (Optional) Name of the EKS Node Group. If omitted, Terraform will assign a random, unique name. Conflicts with `node_group_name_prefix`. +* `node_group_name_prefix` – (Optional) Creates a unique name beginning with the specified prefix. Conflicts with `node_group_name`. * `release_version` – (Optional) AMI version of the EKS Node Group. Defaults to latest version for Kubernetes version. * `remote_access` - (Optional) Configuration block with remote access settings. Detailed below. * `tags` - (Optional) Key-value map of resource tags. If configured with a provider [`default_tags` configuration block](https://www.terraform.io/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.