Skip to content

Commit

Permalink
Merge pull request #28112 from skyscrapr/f-eks-placement-groups
Browse files Browse the repository at this point in the history
F eks placement groups
  • Loading branch information
ewbankkit authored Dec 1, 2022
2 parents ea7c041 + fd39dc8 commit 40efd3f
Show file tree
Hide file tree
Showing 10 changed files with 423 additions and 329 deletions.
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

0 comments on commit 40efd3f

Please sign in to comment.