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

F eks placement groups #28112

Merged
merged 17 commits into from
Dec 1, 2022
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
7 changes: 7 additions & 0 deletions .changelog/28112.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_eks_cluster: Add `cluster_id` attribute and `outpost_config.control_plane_placement` argument
```

```release-note:enhancement
data-source/aws_eks_cluster: Add `cluster_id` attribute
```
417 changes: 296 additions & 121 deletions internal/service/eks/cluster.go

Large diffs are not rendered by default.

51 changes: 25 additions & 26 deletions internal/service/eks/cluster_data_source.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package eks

import (
"fmt"
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
)

func DataSourceCluster() *schema.Resource {
return &schema.Resource{
Read: dataSourceClusterRead,
ReadWithoutTimeout: dataSourceClusterRead,

Schema: map[string]*schema.Schema{
"arn": {
Expand All @@ -30,6 +31,10 @@ func DataSourceCluster() *schema.Resource {
},
},
},
"cluster_id": {
Type: schema.TypeString,
Computed: true,
},
"created_at": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -168,57 +173,51 @@ func DataSourceCluster() *schema.Resource {
}
}

func dataSourceClusterRead(d *schema.ResourceData, meta interface{}) error {
func dataSourceClusterRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).EKSConn
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig

name := d.Get("name").(string)
cluster, err := FindClusterByName(conn, name)
cluster, err := FindClusterByName(ctx, conn, name)

if err != nil {
return fmt.Errorf("error reading EKS Cluster (%s): %w", name, err)
return diag.Errorf("reading EKS Cluster (%s): %s", name, err)
}

d.SetId(name)
d.Set("arn", cluster.Arn)

if err := d.Set("certificate_authority", flattenCertificate(cluster.CertificateAuthority)); err != nil {
return fmt.Errorf("error setting certificate_authority: %w", err)
return diag.Errorf("setting certificate_authority: %s", err)
}
// cluster_id is only relevant for clusters on Outposts.
if cluster.OutpostConfig != nil {
d.Set("cluster_id", cluster.Id)
}

d.Set("created_at", aws.TimeValue(cluster.CreatedAt).String())

if err := d.Set("enabled_cluster_log_types", flattenEnabledLogTypes(cluster.Logging)); err != nil {
return fmt.Errorf("error setting enabled_cluster_log_types: %w", err)
if err := d.Set("enabled_cluster_log_types", flattenLogging(cluster.Logging)); err != nil {
return diag.Errorf("setting enabled_cluster_log_types: %s", err)
}

d.Set("endpoint", cluster.Endpoint)

if err := d.Set("identity", flattenIdentity(cluster.Identity)); err != nil {
return fmt.Errorf("error setting identity: %w", err)
}

if err := d.Set("kubernetes_network_config", flattenNetworkConfig(cluster.KubernetesNetworkConfig)); err != nil {
return fmt.Errorf("error setting kubernetes_network_config: %w", err)
return diag.Errorf("setting identity: %s", err)
}

if err := d.Set("outpost_config", flattenOutpostConfig(cluster.OutpostConfig)); err != nil {
return fmt.Errorf("error setting outpost_config: %w", err)
if err := d.Set("kubernetes_network_config", flattenKubernetesNetworkConfigResponse(cluster.KubernetesNetworkConfig)); err != nil {
return diag.Errorf("setting kubernetes_network_config: %s", err)
}

d.Set("name", cluster.Name)
if err := d.Set("outpost_config", flattenOutpostConfigResponse(cluster.OutpostConfig)); err != nil {
return diag.Errorf("setting outpost_config: %s", err)
}
d.Set("platform_version", cluster.PlatformVersion)
d.Set("role_arn", cluster.RoleArn)
d.Set("status", cluster.Status)

d.Set("version", cluster.Version)

if err := d.Set("vpc_config", flattenVPCConfigResponse(cluster.ResourcesVpcConfig)); err != nil {
return fmt.Errorf("error setting vpc_config: %w", err)
return diag.Errorf("setting vpc_config: %s", err)
}

if err := d.Set("tags", KeyValueTags(cluster.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %w", err)
return diag.Errorf("setting tags: %s", err)
}

return nil
Expand Down
91 changes: 85 additions & 6 deletions internal/service/eks/cluster_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package eks_test

import (
"context"
"errors"
"fmt"
"regexp"
Expand Down Expand Up @@ -41,6 +42,7 @@ func TestAccEKSCluster_basic(t *testing.T) {
acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "eks", regexp.MustCompile(fmt.Sprintf("cluster/%s$", rName))),
resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "1"),
resource.TestCheckResourceAttrSet(resourceName, "certificate_authority.0.data"),
resource.TestCheckNoResourceAttr(resourceName, "cluster_id"),
resource.TestMatchResourceAttr(resourceName, "endpoint", regexp.MustCompile(`^https://`)),
resource.TestCheckResourceAttr(resourceName, "identity.#", "1"),
resource.TestCheckResourceAttr(resourceName, "identity.0.oidc.#", "1"),
Expand Down Expand Up @@ -620,6 +622,7 @@ func TestAccEKSCluster_Outpost_create(t *testing.T) {
Config: testAccClusterConfig_outpost(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckClusterExists(resourceName, &cluster),
resource.TestMatchResourceAttr(resourceName, "cluster_id", regexp.MustCompile(`^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$`)),
resource.TestCheckResourceAttr(resourceName, "outpost_config.#", "1"),
resource.TestCheckResourceAttr(resourceName, "outpost_config.0.control_plane_instance_type", controlPlaneInstanceType),
resource.TestCheckResourceAttr(resourceName, "outpost_config.0.outpost_arns.#", "1"),
Expand All @@ -634,20 +637,51 @@ func TestAccEKSCluster_Outpost_create(t *testing.T) {
})
}

func TestAccEKSCluster_Outpost_placement(t *testing.T) {
var cluster eks.Cluster
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_eks_cluster.test"
controlPlaneInstanceType := "m5d.large"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t); acctest.PreCheckOutpostsOutposts(t) },
ErrorCheck: acctest.ErrorCheck(t, eks.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccClusterConfig_outpostPlacement(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckClusterExists(resourceName, &cluster),
resource.TestMatchResourceAttr(resourceName, "cluster_id", regexp.MustCompile(`^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$`)),
resource.TestCheckResourceAttr(resourceName, "outpost_config.#", "1"),
resource.TestCheckResourceAttr(resourceName, "outpost_config.0.control_plane_instance_type", controlPlaneInstanceType),
resource.TestCheckResourceAttr(resourceName, "outpost_config.0.outpost_arns.#", "1"),
resource.TestCheckResourceAttr(resourceName, "outpost_config.0.control_plane_placement.#", "1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckClusterExists(resourceName string, cluster *eks.Cluster) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("Not found: %s", resourceName)
}

if rs.Primary.ID == "" {
return fmt.Errorf("No EKS Cluster ID is set")
}

conn := acctest.Provider.Meta().(*conns.AWSClient).EKSConn

output, err := tfeks.FindClusterByName(conn, rs.Primary.ID)
output, err := tfeks.FindClusterByName(context.Background(), conn, rs.Primary.ID)

if err != nil {
return err
Expand All @@ -667,7 +701,7 @@ func testAccCheckClusterDestroy(s *terraform.State) error {

conn := acctest.Provider.Meta().(*conns.AWSClient).EKSConn

_, err := tfeks.FindClusterByName(conn, rs.Primary.ID)
_, err := tfeks.FindClusterByName(context.Background(), conn, rs.Primary.ID)

if tfresource.NotFound(err) {
continue
Expand Down Expand Up @@ -1048,22 +1082,67 @@ data "aws_iam_role" "test" {
name = "AmazonEKSLocalOutpostClusterRole"
}

data "aws_outposts_outposts" "test" {}
data "aws_outposts_outpost" "test" {
id = "op-XXXXXXXX"
}

data "aws_subnets" test {
filter {
name = "outpost-arn"
values = [data.aws_outposts_outpost.test.arn]
}
}

resource "aws_eks_cluster" "test" {
name = %[1]q
role_arn = data.aws_iam_role.test.arn

outpost_config {
control_plane_instance_type = "m5d.large"
outpost_arns = [data.aws_outposts_outpost.test.arn]
}

vpc_config {
endpoint_private_access = true
endpoint_public_access = false
subnet_ids = [tolist(data.aws_subnets.test.ids)[0]]
}
}
`, rName))
}

func testAccClusterConfig_outpostPlacement(rName string) string {
return acctest.ConfigCompose(testAccClusterConfig_Base(rName), fmt.Sprintf(`
data "aws_iam_role" "test" {
name = "AmazonEKSLocalOutpostClusterRole"
}

data "aws_outposts_outpost" "test" {
id = "op-XXXXXXXX"
}

data "aws_subnets" test {
filter {
name = "outpost-arn"
values = [tolist(data.aws_outposts_outposts.test.arns)[0]]
values = [data.aws_outposts_outpost.test.arn]
}
}

resource "aws_placement_group" "test" {
name = %[1]q
strategy = "cluster"
}

resource "aws_eks_cluster" "test" {
name = %[1]q
role_arn = data.aws_iam_role.test.arn

outpost_config {
control_plane_instance_type = "m5d.large"
outpost_arns = [tolist(data.aws_outposts_outposts.test.arns)[0]]
control_plane_placement {
group_name = aws_placement_group.test.name
}
outpost_arns = [data.aws_outposts_outpost.test.arn]
}

vpc_config {
Expand Down
59 changes: 0 additions & 59 deletions internal/service/eks/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,65 +118,6 @@ func FindAddonVersionByAddonNameAndKubernetesVersion(ctx context.Context, conn *
return version, nil
}

func FindClusterByName(conn *eks.EKS, name string) (*eks.Cluster, error) {
input := &eks.DescribeClusterInput{
Name: aws.String(name),
}

output, err := conn.DescribeCluster(input)

// Sometimes the EKS API returns the ResourceNotFound error in this form:
// ClientException: No cluster found for name: tf-acc-test-0o1f8
if tfawserr.ErrCodeEquals(err, eks.ErrCodeResourceNotFoundException) || tfawserr.ErrMessageContains(err, eks.ErrCodeClientException, "No cluster found for name:") {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || output.Cluster == nil {
return nil, &resource.NotFoundError{
Message: "Empty result",
LastRequest: input,
}
}

return output.Cluster, nil
}

func FindClusterUpdateByNameAndID(conn *eks.EKS, name, id string) (*eks.Update, error) {
input := &eks.DescribeUpdateInput{
Name: aws.String(name),
UpdateId: aws.String(id),
}

output, err := conn.DescribeUpdate(input)

if tfawserr.ErrCodeEquals(err, eks.ErrCodeResourceNotFoundException) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || output.Update == nil {
return nil, &resource.NotFoundError{
Message: "Empty result",
LastRequest: input,
}
}

return output.Update, nil
}

func FindFargateProfileByClusterNameAndFargateProfileName(conn *eks.EKS, clusterName, fargateProfileName string) (*eks.FargateProfile, error) {
input := &eks.DescribeFargateProfileInput{
ClusterName: aws.String(clusterName),
Expand Down
32 changes: 0 additions & 32 deletions internal/service/eks/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,38 +41,6 @@ func statusAddonUpdate(ctx context.Context, conn *eks.EKS, clusterName, addonNam
}
}

func statusCluster(conn *eks.EKS, name string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := FindClusterByName(conn, name)

if tfresource.NotFound(err) {
return nil, "", nil
}

if err != nil {
return nil, "", err
}

return output, aws.StringValue(output.Status), nil
}
}

func statusClusterUpdate(conn *eks.EKS, name, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := FindClusterUpdateByNameAndID(conn, name, id)

if tfresource.NotFound(err) {
return nil, "", nil
}

if err != nil {
return nil, "", err
}

return output, aws.StringValue(output.Status), nil
}
}

func statusFargateProfile(conn *eks.EKS, clusterName, fargateProfileName string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := FindFargateProfileByClusterNameAndFargateProfileName(conn, clusterName, fargateProfileName)
Expand Down
Loading