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

Add aws_ecs_task_definition.proxy_configuration #8780

Merged
merged 7 commits into from
Jun 20, 2019
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
87 changes: 86 additions & 1 deletion aws/resource_aws_ecs_task_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,37 @@ func resourceAwsEcsTaskDefinition() *schema.Resource {
}, false),
},

"proxy_configuration": {
bflad marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"container_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"properties": {
Type: schema.TypeMap,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
ForceNew: true,
},
"type": {
bflad marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeString,
Default: ecs.ProxyConfigurationTypeAppmesh,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
ecs.ProxyConfigurationTypeAppmesh,
}, false),
},
},
},
},

"tags": tagsSchema(),
},
}
Expand Down Expand Up @@ -321,6 +352,34 @@ func resourceAwsEcsTaskDefinitionCreate(d *schema.ResourceData, meta interface{}
input.RequiresCompatibilities = expandStringList(v.(*schema.Set).List())
}

proxyConfigs := d.Get("proxy_configuration").([]interface{})
if len(proxyConfigs) > 0 {
proxyConfig := proxyConfigs[0]
configMap := proxyConfig.(map[string]interface{})

containerName := configMap["container_name"].(string)
proxyType := configMap["type"].(string)

rawProperties := configMap["properties"].(map[string]interface{})

properties := make([]*ecs.KeyValuePair, len(rawProperties))
i := 0
for name, value := range rawProperties {
properties[i] = &ecs.KeyValuePair{
Name: aws.String(name),
Value: aws.String(value.(string)),
}
i++
}

var ecsProxyConfig ecs.ProxyConfiguration
ecsProxyConfig.ContainerName = aws.String(containerName)
ecsProxyConfig.Type = aws.String(proxyType)
ecsProxyConfig.Properties = properties

input.ProxyConfiguration = &ecsProxyConfig
}

log.Printf("[DEBUG] Registering ECS task definition: %s", input)
out, err := conn.RegisterTaskDefinition(&input)
if err != nil {
Expand Down Expand Up @@ -393,7 +452,11 @@ func resourceAwsEcsTaskDefinitionRead(d *schema.ResourceData, meta interface{})
}

if err := d.Set("requires_compatibilities", flattenStringList(taskDefinition.RequiresCompatibilities)); err != nil {
return err
return fmt.Errorf("error setting requires_compatibilities: %s", err)
}

if err := d.Set("proxy_configuration", flattenProxyConfiguration(taskDefinition.ProxyConfiguration)); err != nil {
return fmt.Errorf("error setting proxy_configuration: %s", err)
}

return nil
Expand All @@ -413,6 +476,28 @@ func flattenPlacementConstraints(pcs []*ecs.TaskDefinitionPlacementConstraint) [
return results
}

func flattenProxyConfiguration(pc *ecs.ProxyConfiguration) []map[string]interface{} {
if pc == nil {
return nil
}

meshProperties := make(map[string]string)
if pc.Properties != nil {
for _, prop := range pc.Properties {
meshProperties[aws.StringValue(prop.Name)] = aws.StringValue(prop.Value)
}
}

config := make(map[string]interface{})
config["container_name"] = aws.StringValue(pc.ContainerName)
config["type"] = aws.StringValue(pc.Type)
config["properties"] = meshProperties

return []map[string]interface{}{
config,
}
}

func resourceAwsEcsTaskDefinitionUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn

Expand Down
136 changes: 135 additions & 1 deletion aws/resource_aws_ecs_task_definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,141 @@ func TestAccAWSEcsTaskDefinition_Tags(t *testing.T) {
})
}

func TestAccAWSEcsTaskDefinition_ProxyConfiguration(t *testing.T) {
var taskDefinition ecs.TaskDefinition
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_ecs_task_definition.test"

containerName := "web"
proxyType := "APPMESH"
ignoredUid := "1337"
ignoredGid := "999"
appPorts := "80"
proxyIngressPort := "15000"
proxyEgressPort := "15001"
egressIgnoredPorts := "5500"
egressIgnoredIPs := "169.254.170.2,169.254.169.254"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEcsTaskDefinitionConfigProxyConfiguration(rName, containerName, proxyType, ignoredUid, ignoredGid, appPorts, proxyIngressPort, proxyEgressPort, egressIgnoredPorts, egressIgnoredIPs),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsTaskDefinitionExists(resourceName, &taskDefinition),
testAccCheckAWSEcsTaskDefinitionProxyConfiguration(&taskDefinition, containerName, proxyType, ignoredUid, ignoredGid, appPorts, proxyIngressPort, proxyEgressPort, egressIgnoredPorts, egressIgnoredIPs),
),
},
SebastianC marked this conversation as resolved.
Show resolved Hide resolved
{
ResourceName: resourceName,
ImportState: true,
ImportStateIdFunc: testAccAWSEcsTaskDefinitionImportStateIdFunc(resourceName),
ImportStateVerify: true,
},
},
})
}

func testAccAWSEcsTaskDefinitionConfigProxyConfiguration(rName string, containerName string, proxyType string,
ignoredUid string, ignoredGid string, appPorts string, proxyIngressPort string, proxyEgressPort string,
egressIgnoredPorts string, egressIgnoredIPs string) string {

return fmt.Sprintf(`
resource "aws_ecs_cluster" "test" {
name = %q
}

resource "aws_ecs_task_definition" "test" {
family = %q
network_mode = "awsvpc"

proxy_configuration {
type = %q
container_name = %q
properties = {
IgnoredUID = %q
IgnoredGID = %q
AppPorts = %q
ProxyIngressPort = %q
ProxyEgressPort = %q
EgressIgnoredPorts = %q
EgressIgnoredIPs = %q
}
}

container_definitions = <<DEFINITION
[
{
"cpu": 128,
"essential": true,
"image": "nginx:latest",
"memory": 128,
"name": %q
}
]
DEFINITION

}
`, rName, rName, proxyType, containerName, ignoredUid, ignoredGid, appPorts, proxyIngressPort, proxyEgressPort, egressIgnoredPorts, egressIgnoredIPs, containerName)
}

func testAccCheckAWSEcsTaskDefinitionProxyConfiguration(after *ecs.TaskDefinition, containerName string, proxyType string,
ignoredUid string, ignoredGid string, appPorts string, proxyIngressPort string, proxyEgressPort string,
egressIgnoredPorts string, egressIgnoredIPs string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if *after.ProxyConfiguration.Type != proxyType {
return fmt.Errorf("Expected (%s) ProxyConfiguration.Type, got (%s)", proxyType, *after.ProxyConfiguration.Type)
}

if *after.ProxyConfiguration.ContainerName != containerName {
return fmt.Errorf("Expected (%s) ProxyConfiguration.ContainerName, got (%s)", containerName, *after.ProxyConfiguration.ContainerName)
}

properties := after.ProxyConfiguration.Properties
expectedProperties := []string{"IgnoredUID", "IgnoredGID", "AppPorts", "ProxyIngressPort", "ProxyEgressPort", "EgressIgnoredPorts", "EgressIgnoredIPs"}
if len(properties) != len(expectedProperties) {
return fmt.Errorf("Expected (%d) ProxyConfiguration.Property count, got (%d)", len(expectedProperties), len(properties))
}

propertyLookups := make(map[string]string)
for _, property := range properties {
propertyLookups[*property.Name] = *property.Value
}

if propertyLookups["IgnoredUID"] != ignoredUid {
return fmt.Errorf("Expected (%s) ProxyConfiguration.Properties.IgnoredUID, got (%s)", ignoredUid, propertyLookups["IgnoredUID"])
}

if propertyLookups["IgnoredGID"] != ignoredGid {
return fmt.Errorf("Expected (%s) ProxyConfiguration.Properties.IgnoredGID, got (%s)", ignoredGid, propertyLookups["IgnoredGID"])
}

if propertyLookups["AppPorts"] != appPorts {
return fmt.Errorf("Expected (%s) ProxyConfiguration.Properties.AppPorts, got (%s)", appPorts, propertyLookups["AppPorts"])
}

if propertyLookups["ProxyIngressPort"] != proxyIngressPort {
return fmt.Errorf("Expected (%s) ProxyConfiguration.Properties.ProxyIngressPort, got (%s)", proxyIngressPort, propertyLookups["ProxyIngressPort"])
}

if propertyLookups["ProxyEgressPort"] != proxyEgressPort {
return fmt.Errorf("Expected (%s) ProxyConfiguration.Properties.ProxyEgressPort, got (%s)", proxyEgressPort, propertyLookups["ProxyEgressPort"])
}

if propertyLookups["EgressIgnoredPorts"] != egressIgnoredPorts {
return fmt.Errorf("Expected (%s) ProxyConfiguration.Properties.EgressIgnoredPorts, got (%s)", egressIgnoredPorts, propertyLookups["EgressIgnoredPorts"])
}

if propertyLookups["EgressIgnoredIPs"] != egressIgnoredIPs {
return fmt.Errorf("Expected (%s) ProxyConfiguration.Properties.EgressIgnoredIPs, got (%s)", egressIgnoredIPs, propertyLookups["EgressIgnoredIPs"])
}

return nil
}
}

func testAccCheckEcsTaskDefinitionRecreated(t *testing.T,
before, after *ecs.TaskDefinition) resource.TestCheckFunc {
return func(s *terraform.State) error {
Expand Down Expand Up @@ -585,7 +720,6 @@ func testAccCheckAWSEcsTaskDefinitionExists(name string, def *ecs.TaskDefinition
if err != nil {
return err
}

*def = *out.TaskDefinition

return nil
Expand Down
27 changes: 27 additions & 0 deletions website/docs/r/ecs_task_definition.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,27 @@ contains only a small subset of the available parameters.
]
```

### With AppMesh Proxy

```hcl
resource "aws_ecs_task_definition" "service" {
family = "service"
container_definitions = "${file("task-definitions/service.json")}"

proxy_configuration {
type = "APPMESH"
container_name = "applicationContainerName"
properties = {
AppPorts = "8080"
EgressIgnoredIPs = "169.254.170.2,169.254.169.254"
IgnoredUID = "1337"
ProxyEgressPort = 15001
ProxyIngressPort = 15000
}
}
}
```

## Argument Reference

### Top-Level Arguments
Expand All @@ -89,6 +110,7 @@ official [Developer Guide](https://docs.aws.amazon.com/AmazonECS/latest/develope
* `cpu` - (Optional) The number of cpu units used by the task. If the `requires_compatibilities` is `FARGATE` this field is required.
* `memory` - (Optional) The amount (in MiB) of memory used by the task. If the `requires_compatibilities` is `FARGATE` this field is required.
* `requires_compatibilities` - (Optional) A set of launch types required by the task. The valid values are `EC2` and `FARGATE`.
* `proxy_configuration` - (Optional) The [proxy configuration](#proxy-configuration-arguments) details for the App Mesh proxy.
* `tags` - (Optional) Key-value mapping of resource tags

#### Volume Block Arguments
Expand Down Expand Up @@ -134,6 +156,11 @@ For more information, see [Cluster Query Language in the Amazon EC2 Container
Service Developer
Guide](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-query-language.html).

#### Proxy Configuration Arguments

* `container_name` - (Required) The name of the container that will serve as the App Mesh proxy.
* `properties` - (Required) The set of network configuration parameters to provide the Container Network Interface (CNI) plugin, specified a key-value mapping.
* `type` - (Optional) The proxy type. The default value is `APPMESH`. The only supported value is `APPMESH`.

## Attributes Reference

Expand Down