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

Enhancement/eks adding service ipv4 range #15518

Merged
merged 11 commits into from
Nov 30, 2020
16 changes: 16 additions & 0 deletions aws/data_source_aws_eks_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ func dataSourceAwsEksCluster() *schema.Resource {
},
},
},
"kubernetes_network_config": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"service_ipv4_cidr": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"name": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -184,5 +196,9 @@ func dataSourceAwsEksClusterRead(d *schema.ResourceData, meta interface{}) error
return fmt.Errorf("error setting vpc_config: %s", err)
}

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

return nil
}
2 changes: 2 additions & 0 deletions aws/data_source_aws_eks_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ func TestAccAWSEksClusterDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(resourceName, "identity.#", dataSourceResourceName, "identity.#"),
resource.TestCheckResourceAttrPair(resourceName, "identity.0.oidc.#", dataSourceResourceName, "identity.0.oidc.#"),
resource.TestCheckResourceAttrPair(resourceName, "identity.0.oidc.0.issuer", dataSourceResourceName, "identity.0.oidc.0.issuer"),
resource.TestCheckResourceAttrPair(resourceName, "kubernetes_network_config.#", dataSourceResourceName, "kubernetes_network_config.#"),
resource.TestCheckResourceAttrPair(resourceName, "kubernetes_network_config.0.service_ipv4_cidr", dataSourceResourceName, "kubernetes_network_config.0.service_ipv4_cidr"),
resource.TestMatchResourceAttr(dataSourceResourceName, "platform_version", regexp.MustCompile(`^eks\.\d+$`)),
resource.TestCheckResourceAttrPair(resourceName, "role_arn", dataSourceResourceName, "role_arn"),
resource.TestCheckResourceAttrPair(resourceName, "status", dataSourceResourceName, "status"),
Expand Down
59 changes: 59 additions & 0 deletions aws/resource_aws_eks_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package aws
import (
"fmt"
"log"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -113,6 +114,28 @@ func resourceAwsEksCluster() *schema.Resource {
},
},
},

"kubernetes_network_config": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @philnichol -- apologies for the delay ! i missed to note in my previous review that we should have parity with the matching data-source now that this field has been added in the resource so if you don't mind adding a similar block in data_source_aws_eks_cluster would be greatly appreciated (as well add a line in the data-source test to check for the field against the resource i.e. using resource.TestCheckResourceAttrPair()) ! Should be a quick addition with the corresponding fields set to Computed. if you're crunched for time, we're also happy to help out 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @anGie44 , no worries at all. Happy to have a crack at the data_source, but if it takes a while I might well ask for your help since I don't want to hold people up 😄. Before making any changes I seem to be getting the following error on all datasource tests, but can't see what I'm doing wrong, any ideas? I get the same (resourceNotFound) regardless of which datasource test I run it seems.

TF_ACC=1 go test ./aws -v -count 1 -parallel 10 -run=TestAccAWSEksClusterDataSource_basic
=== RUN   TestAccAWSEksClusterDataSource_basic
=== PAUSE TestAccAWSEksClusterDataSource_basic
=== CONT  TestAccAWSEksClusterDataSource_basic
    data_source_aws_eks_cluster_test.go:18: Step 1/1 error: terraform failed: exit status 1

        stderr:

        Error: error reading EKS Cluster (tf-acc-test-gs09q): ResourceNotFoundException: No cluster found for name: tf-acc-test-gs09q.
        {
          RespMetadata: {
            StatusCode: 404,
            RequestID: "91f46140-c965-4387-bddf-9834ad7beb69"
          },
          Message_: "No cluster found for name: tf-acc-test-gs09q."
        }


--- FAIL: TestAccAWSEksClusterDataSource_basic (5.87s)
FAIL
FAIL    github.com/terraform-providers/terraform-provider-aws/aws       5.909s
FAIL

Copy link
Contributor

@anGie44 anGie44 Nov 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh which version of Terraform do you have locally @philnichol ? I've come across these type of errors when using the family of 0.13 versions. I'd recommendv.0.12.29 or 0.14+

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦 sorry I didn't try that before, works now, will aim to address this and the documentation comment shortly, thanks @anGie44 !

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no worries - i don't think we have that behavior documented unfortunately ..sounds great 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anGie44 I've pushed my changes to the data source, let me know if there are any issues. Acceptance tests ran here:

$ TF_ACC=1 go test ./aws -v -count 1 -parallel 10 -run=TestAccAWSEksClusterDataSource_basic -timeout 60m
=== RUN   TestAccAWSEksClusterDataSource_basic
=== PAUSE TestAccAWSEksClusterDataSource_basic
=== CONT  TestAccAWSEksClusterDataSource_basic
--- PASS: TestAccAWSEksClusterDataSource_basic (998.81s)
PASS
ok      github.com/terraform-providers/terraform-provider-aws/aws       998.846s

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @philnichol -- test looks good on my end as well 👍 i'm running the resource acceptance tests as well in the background (I don't expect any changes)..and will comment back w/the PR approval

Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"service_ipv4_cidr": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
philnichol marked this conversation as resolved.
Show resolved Hide resolved
ValidateFunc: validation.All(
validation.IsCIDRNetwork(12, 24),
validation.StringMatch(regexp.MustCompile(`^(10|172\.(1[6-9]|2[0-9]|3[0-1])|192\.168)\..*`), "must be within 10.0.0.0/8, 172.16.0.0.0/12, or 192.168.0.0/16"),
anGie44 marked this conversation as resolved.
Show resolved Hide resolved
),
},
},
},
},

"name": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -218,6 +241,10 @@ func resourceAwsEksClusterCreate(d *schema.ResourceData, meta interface{}) error
input.Tags = keyvaluetags.New(v).IgnoreAws().EksTags()
}

if _, ok := d.GetOk("kubernetes_network_config"); ok {
input.KubernetesNetworkConfig = expandEksNetworkConfigRequest(d.Get("kubernetes_network_config").([]interface{}))
}

if v, ok := d.GetOk("version"); ok {
input.Version = aws.String(v.(string))
}
Expand Down Expand Up @@ -334,6 +361,10 @@ func resourceAwsEksClusterRead(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("error setting vpc_config: %s", err)
}

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

return nil
}

Expand Down Expand Up @@ -548,6 +579,22 @@ func expandEksVpcConfigUpdateRequest(l []interface{}) *eks.VpcConfigRequest {
return vpcConfigRequest
}

func expandEksNetworkConfigRequest(tfList []interface{}) *eks.KubernetesNetworkConfigRequest {
anGie44 marked this conversation as resolved.
Show resolved Hide resolved
tfMap, ok := tfList[0].(map[string]interface{})

if !ok {
return nil
}

apiObject := &eks.KubernetesNetworkConfigRequest{}

if v, ok := tfMap["service_ipv4_cidr"].(string); ok && v != "" {
apiObject.ServiceIpv4Cidr = aws.String(v)
}

return apiObject
}

func expandEksLoggingTypes(vEnabledLogTypes *schema.Set) *eks.Logging {
vEksLogTypes := []interface{}{}
for _, eksLogType := range eks.LogType_Values() {
Expand Down Expand Up @@ -671,6 +718,18 @@ func flattenEksEnabledLogTypes(logging *eks.Logging) *schema.Set {
return flattenStringSet(enabledLogTypes)
}

func flattenEksNetworkConfig(apiObject *eks.KubernetesNetworkConfigResponse) []interface{} {
if apiObject == nil {
return nil
}

tfMap := map[string]interface{}{
"service_ipv4_cidr": aws.StringValue(apiObject.ServiceIpv4Cidr),
}

return []interface{}{tfMap}
}

func refreshEksClusterStatus(conn *eks.EKS, clusterName string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := conn.DescribeCluster(&eks.DescribeClusterInput{
Expand Down
93 changes: 93 additions & 0 deletions aws/resource_aws_eks_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ func TestAccAWSEksCluster_basic(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "identity.0.oidc.#", "1"),
resource.TestMatchResourceAttr(resourceName, "identity.0.oidc.0.issuer", regexp.MustCompile(`^https://`)),
resource.TestCheckResourceAttr(resourceName, "name", rName),
resource.TestCheckResourceAttr(resourceName, "kubernetes_network_config.#", "1"),
resource.TestCheckResourceAttrSet(resourceName, "kubernetes_network_config.0.service_ipv4_cidr"),
resource.TestMatchResourceAttr(resourceName, "platform_version", regexp.MustCompile(`^eks\.\d+$`)),
resource.TestCheckResourceAttrPair(resourceName, "role_arn", "aws_iam_role.test", "arn"),
resource.TestCheckResourceAttr(resourceName, "status", eks.ClusterStatusActive),
Expand Down Expand Up @@ -424,6 +426,68 @@ func TestAccAWSEksCluster_VpcConfig_PublicAccessCidrs(t *testing.T) {
})
}

func TestAccAWSEksCluster_NetworkConfig_ServiceIpv4Cidr(t *testing.T) {
philnichol marked this conversation as resolved.
Show resolved Hide resolved
var cluster1, cluster2 eks.Cluster

rName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(5))
resourceName := "aws_eks_cluster.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSEks(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEksClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEksClusterConfig_NetworkConfig_ServiceIpv4Cidr(rName, `"10.0.0.0/11"`),
ExpectError: regexp.MustCompile(`expected .* to contain a network Value with between`),
},
{
Config: testAccAWSEksClusterConfig_NetworkConfig_ServiceIpv4Cidr(rName, `"10.0.0.0/25"`),
ExpectError: regexp.MustCompile(`expected .* to contain a network Value with between`),
},
{
Config: testAccAWSEksClusterConfig_NetworkConfig_ServiceIpv4Cidr(rName, `"9.0.0.0/16"`),
ExpectError: regexp.MustCompile(`must be within`),
},
{
Config: testAccAWSEksClusterConfig_NetworkConfig_ServiceIpv4Cidr(rName, `"172.14.0.0/24"`),
ExpectError: regexp.MustCompile(`must be within`),
},
{
Config: testAccAWSEksClusterConfig_NetworkConfig_ServiceIpv4Cidr(rName, `"192.167.0.0/24"`),
ExpectError: regexp.MustCompile(`must be within`),
},
{
Config: testAccAWSEksClusterConfig_NetworkConfig_ServiceIpv4Cidr(rName, `"192.168.0.0/24"`),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEksClusterExists(resourceName, &cluster1),
resource.TestCheckResourceAttr(resourceName, "kubernetes_network_config.#", "1"),
resource.TestCheckResourceAttr(resourceName, "kubernetes_network_config.0.service_ipv4_cidr", "192.168.0.0/24"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAWSEksClusterConfig_NetworkConfig_ServiceIpv4Cidr(rName, `"192.168.0.0/24"`),
PlanOnly: true,
ExpectNonEmptyPlan: false,
},
{
Config: testAccAWSEksClusterConfig_NetworkConfig_ServiceIpv4Cidr(rName, `"192.168.1.0/24"`),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEksClusterExists(resourceName, &cluster2),
testAccCheckAWSEksClusterRecreated(&cluster1, &cluster2),
resource.TestCheckResourceAttr(resourceName, "kubernetes_network_config.#", "1"),
resource.TestCheckResourceAttr(resourceName, "kubernetes_network_config.0.service_ipv4_cidr", "192.168.1.0/24"),
),
},
},
})
}

func testAccCheckAWSEksClusterExists(resourceName string, cluster *eks.Cluster) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resourceName]
Expand Down Expand Up @@ -491,6 +555,16 @@ func testAccCheckAWSEksClusterDestroy(s *terraform.State) error {
return nil
}

func testAccCheckAWSEksClusterRecreated(i, j *eks.Cluster) resource.TestCheckFunc {
return func(s *terraform.State) error {
if aws.TimeValue(i.CreatedAt) == aws.TimeValue(j.CreatedAt) {
return errors.New("EKS Cluster was not recreated")
}

return nil
}
}

func testAccCheckAWSEksClusterNotRecreated(i, j *eks.Cluster) resource.TestCheckFunc {
return func(s *terraform.State) error {
if aws.TimeValue(i.CreatedAt) != aws.TimeValue(j.CreatedAt) {
Expand Down Expand Up @@ -779,3 +853,22 @@ resource "aws_eks_cluster" "test" {
}
`, testAccAWSEksClusterConfig_Base(rName), rName, publicAccessCidr)
}

func testAccAWSEksClusterConfig_NetworkConfig_ServiceIpv4Cidr(rName string, serviceIpv4Cidr string) string {
return composeConfig(testAccAWSEksClusterConfig_Base(rName), fmt.Sprintf(`
resource "aws_eks_cluster" "test" {
name = %q
role_arn = aws_iam_role.test.arn

vpc_config {
subnet_ids = aws_subnet.test[*].id
}

kubernetes_network_config {
service_ipv4_cidr = %s
}

depends_on = [aws_iam_role_policy_attachment.test-AmazonEKSClusterPolicy]
}
`, rName, serviceIpv4Cidr))
}
2 changes: 2 additions & 0 deletions website/docs/d/eks_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ output "identity-oidc-issuer" {
* `identity` - Nested attribute containing identity provider information for your cluster. Only available on Kubernetes version 1.13 and 1.14 clusters created or upgraded on or after September 3, 2019. For an example using this information to enable IAM Roles for Service Accounts, see the [`aws_eks_cluster` resource documentation](/docs/providers/aws/r/eks_cluster.html).
* `oidc` - Nested attribute containing [OpenID Connect](https://openid.net/connect/) identity provider information for the cluster.
* `issuer` - Issuer URL for the OpenID Connect identity provider.
* `kubernetes_network_config` - Nested list containing Kubernetes Network Configuration.
* `service_ipv4_cidr` - The CIDR block to assign Kubernetes service IP addresses from.
* `platform_version` - The platform version for the cluster.
* `role_arn` - The Amazon Resource Name (ARN) of the IAM role that provides permissions for the Kubernetes control plane to make calls to AWS API operations on your behalf.
* `status` - The status of the EKS cluster. One of `CREATING`, `ACTIVE`, `DELETING`, `FAILED`.
Expand Down
13 changes: 13 additions & 0 deletions website/docs/r/eks_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ The following arguments are supported:
* `vpc_config` - (Required) Nested argument for the VPC associated with your cluster. Amazon EKS VPC resources have specific requirements to work properly with Kubernetes. For more information, see [Cluster VPC Considerations](https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html) and [Cluster Security Group Considerations](https://docs.aws.amazon.com/eks/latest/userguide/sec-group-reqs.html) in the Amazon EKS User Guide. Configuration detailed below.
* `enabled_cluster_log_types` - (Optional) A list of the desired control plane logging to enable. For more information, see [Amazon EKS Control Plane Logging](https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html)
* `encryption_config` - (Optional) Configuration block with encryption configuration for the cluster. Only available on Kubernetes 1.13 and above clusters created after March 6, 2020. Detailed below.
* `kubernetes_network_config` - (Optional) Configuration block with kubernetes network configuration for the cluster. Detailed below. If removed, Terraform will only perform drift detection if a configuration value is provided.
* `tags` - (Optional) Key-value map of resource tags.
* `version` – (Optional) Desired Kubernetes master version. If you do not specify a value, the latest available version at resource creation is used and no upgrades will occur except those automatically triggered by EKS. The value must be configured and increased to upgrade the version when desired. Downgrades are not supported by EKS.

Expand All @@ -180,6 +181,18 @@ The following arguments are supported in the `provider` configuration block:
* `security_group_ids` – (Optional) List of security group IDs for the cross-account elastic network interfaces that Amazon EKS creates to use to allow communication between your worker nodes and the Kubernetes control plane.
* `subnet_ids` – (Required) List of subnet IDs. Must be in at least two different availability zones. Amazon EKS creates cross-account elastic network interfaces in these subnets to allow communication between your worker nodes and the Kubernetes control plane.

### kubernetes_network_config

The following arguments are supported in the `kubernetes_network_config` configuration block:

* `service_ipv4_cidr` - (Optional) The CIDR block to assign Kubernetes service IP addresses from. If you don't specify a block, Kubernetes assigns addresses from either the 10.100.0.0/16 or 172.20.0.0/16 CIDR blocks. We recommend that you specify a block that does not overlap with resources in other networks that are peered or connected to your VPC. You can only specify a custom CIDR block when you create a cluster, changing this value will force a new cluster to be created. The block must meet the following requirements:

* Within one of the following private IP address blocks: 10.0.0.0/8, 172.16.0.0.0/12, or 192.168.0.0/16.

* Doesn't overlap with any CIDR block assigned to the VPC that you selected for VPC.

* Between /24 and /12.

## Attributes Reference

In addition to all arguments above, the following attributes are exported:
Expand Down