diff --git a/aws/resource_aws_ecs_service.go b/aws/resource_aws_ecs_service.go index 22f8eb94550..3c151589d95 100644 --- a/aws/resource_aws_ecs_service.go +++ b/aws/resource_aws_ecs_service.go @@ -133,6 +133,11 @@ func resourceAwsEcsService() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, + "assign_public_ip": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, }, }, }, @@ -410,9 +415,14 @@ func flattenEcsNetworkConfigration(nc *ecs.NetworkConfiguration) []interface{} { if nc == nil { return nil } + result := make(map[string]interface{}) result["security_groups"] = schema.NewSet(schema.HashString, flattenStringList(nc.AwsvpcConfiguration.SecurityGroups)) result["subnets"] = schema.NewSet(schema.HashString, flattenStringList(nc.AwsvpcConfiguration.Subnets)) + result["assign_public_ip"] = "true" + if *nc.AwsvpcConfiguration.AssignPublicIp == ecs.AssignPublicIpDisabled { + result["assign_public_ip"] = "false" + } return []interface{}{result} } @@ -426,6 +436,13 @@ func expandEcsNetworkConfigration(nc []interface{}) *ecs.NetworkConfiguration { awsVpcConfig.SecurityGroups = expandStringSet(val.(*schema.Set)) } awsVpcConfig.Subnets = expandStringSet(raw["subnets"].(*schema.Set)) + if val, ok := raw["assign_public_ip"].(bool); ok { + awsVpcConfig.AssignPublicIp = aws.String(ecs.AssignPublicIpDisabled) + if val { + awsVpcConfig.AssignPublicIp = aws.String(ecs.AssignPublicIpEnabled) + } + } + return &ecs.NetworkConfiguration{AwsvpcConfiguration: awsVpcConfig} } @@ -495,9 +512,8 @@ func resourceAwsEcsServiceUpdate(d *schema.ResourceData, meta interface{}) error } } - if d.HasChange("network_configration") { - input.NetworkConfiguration = expandEcsNetworkConfigration(d.Get("network_configuration").([]interface{})) - } + //d.HasChange("network_configration") is not working, so explicity calling method. + input.NetworkConfiguration = expandEcsNetworkConfigration(d.Get("network_configuration").([]interface{})) // Retry due to IAM & ECS eventual consistency err := resource.Retry(2*time.Minute, func() *resource.RetryError { diff --git a/aws/resource_aws_ecs_service_test.go b/aws/resource_aws_ecs_service_test.go index d513bbe5566..89496b4368e 100644 --- a/aws/resource_aws_ecs_service_test.go +++ b/aws/resource_aws_ecs_service_test.go @@ -486,7 +486,7 @@ func TestAccAWSEcsService_withLaunchTypeFargate(t *testing.T) { }) } -func TestAccAWSEcsService_withNetworkConfiguration(t *testing.T) { +func TestAccAWSEcsService_withNetworkConfigurationAssignPublicIp(t *testing.T) { rString := acctest.RandString(8) sg1Name := fmt.Sprintf("tf-acc-sg-1-svc-w-nc-%s", rString) @@ -501,7 +501,31 @@ func TestAccAWSEcsService_withNetworkConfiguration(t *testing.T) { CheckDestroy: testAccCheckAWSEcsServiceDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSEcsServiceWithNetworkConfigration(sg1Name, sg2Name, clusterName, tdName, svcName), + Config: testAccAWSEcsServiceWithNetworkConfigration(sg1Name, sg2Name, clusterName, tdName, svcName, "true"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSEcsServiceExists("aws_ecs_service.main"), + ), + }, + }, + }) +} + +func TestAccAWSEcsService_withNetworkConfigurationDoNotAssignPublicIp(t *testing.T) { + rString := acctest.RandString(8) + + sg1Name := fmt.Sprintf("tf-acc-sg-1-svc-w-nc-%s", rString) + sg2Name := fmt.Sprintf("tf-acc-sg-2-svc-w-nc-%s", rString) + clusterName := fmt.Sprintf("tf-acc-cluster-svc-w-nc-%s", rString) + tdName := fmt.Sprintf("tf-acc-td-svc-w-nc-%s", rString) + svcName := fmt.Sprintf("tf-acc-svc-w-nc-%s", rString) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSEcsServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSEcsServiceWithNetworkConfigration(sg1Name, sg2Name, clusterName, tdName, svcName, "false"), Check: resource.ComposeTestCheckFunc( testAccCheckAWSEcsServiceExists("aws_ecs_service.main"), ), @@ -1448,7 +1472,7 @@ resource "aws_ecs_service" "with_alb" { `, clusterName, tdName, roleName, policyName, tgName, lbName, svcName) } -func testAccAWSEcsServiceWithNetworkConfigration(sg1Name, sg2Name, clusterName, tdName, svcName string) string { +func testAccAWSEcsServiceWithNetworkConfigration(sg1Name, sg2Name, clusterName, tdName, svcName, assignPublicIp string) string { return fmt.Sprintf(` data "aws_availability_zones" "available" {} @@ -1517,7 +1541,8 @@ resource "aws_ecs_service" "main" { network_configuration { security_groups = ["${aws_security_group.allow_all_a.id}", "${aws_security_group.allow_all_b.id}"] subnets = ["${aws_subnet.main.*.id}"] + assign_public_ip = %s } } -`, sg1Name, sg2Name, clusterName, tdName, svcName) +`, sg1Name, sg2Name, clusterName, tdName, svcName, assignPublicIp) } diff --git a/aws/resource_aws_lb_listener.go b/aws/resource_aws_lb_listener.go index ec99fa366f4..f96e6e6aa00 100644 --- a/aws/resource_aws_lb_listener.go +++ b/aws/resource_aws_lb_listener.go @@ -34,7 +34,6 @@ func resourceAwsLbListener() *schema.Resource { "load_balancer_arn": { Type: schema.TypeString, Required: true, - ForceNew: true, }, "port": { diff --git a/examples/networking/region/numbering.tf b/examples/networking/region/numbering.tf deleted file mode 120000 index 49f7617b054..00000000000 --- a/examples/networking/region/numbering.tf +++ /dev/null @@ -1 +0,0 @@ -../numbering/variables.tf \ No newline at end of file diff --git a/examples/networking/subnet/numbering.tf b/examples/networking/subnet/numbering.tf deleted file mode 120000 index 49f7617b054..00000000000 --- a/examples/networking/subnet/numbering.tf +++ /dev/null @@ -1 +0,0 @@ -../numbering/variables.tf \ No newline at end of file diff --git a/website/docs/r/ecs_service.html.markdown b/website/docs/r/ecs_service.html.markdown index 3a4cbe07dc4..a427f15e2e7 100644 --- a/website/docs/r/ecs_service.html.markdown +++ b/website/docs/r/ecs_service.html.markdown @@ -102,6 +102,7 @@ Guide](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-query * `subnets` - (Required) The subnets associated with the task or service. * `security_groups` - (Optional) The security groups associated with the task or service. If you do not specify a security group, the default security group for the VPC is used. +* `assign_public_ip` - (Optional) Valid values are "true" or "false". Will assign a public IP address to the ENI. Default value is "false". For more information, see [Task Networking](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-networking.html) ## Attributes Reference