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 3 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
81 changes: 81 additions & 0 deletions aws/resource_aws_ecs_task_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,56 @@ 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.TypeSet,
SebastianC marked this conversation as resolved.
Show resolved Hide resolved
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"value": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
},
Set: func(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["value"].(string)))
return hashcode.String(buf.String())
},
},
"type": {
bflad marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
ecs.ProxyConfigurationTypeAppmesh,
}, false),
},
},
},
},

"tags": tagsSchema(),
},
}
Expand Down Expand Up @@ -321,6 +371,37 @@ 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"].(*schema.Set).List()

properties := make([]*ecs.KeyValuePair, len(rawProperties))

for i, rawProperty := range rawProperties {
propertyMap := rawProperty.(map[string]interface{})
propertyName := propertyMap["name"].(string)
propertyValue := propertyMap["value"].(string)

properties[i] = &ecs.KeyValuePair{
Name: aws.String(propertyName),
Value: aws.String(propertyValue),
}
}

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
151 changes: 150 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,156 @@ 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
},
})
}

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 = {
SebastianC marked this conversation as resolved.
Show resolved Hide resolved
type = %q
container_name = %q
properties = [
SebastianC marked this conversation as resolved.
Show resolved Hide resolved
{
name = "IgnoredUID"
value = %q
},
{
name = "IgnoredGID"
value = %q
},
{
name = "AppPorts"
value = %q
},
{
name = "ProxyIngressPort",
value = %q
},
{
name = "ProxyEgressPort",
value = %q
},
{
name = "EgressIgnoredPorts"
value = %q
},
{
name = "EgressIgnoredIPs",
value = %q
}
]
}

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

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

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 +735,6 @@ func testAccCheckAWSEcsTaskDefinitionExists(name string, def *ecs.TaskDefinition
if err != nil {
return err
}

*def = *out.TaskDefinition

return nil
Expand Down
47 changes: 47 additions & 0 deletions website/docs/r/ecs_task_definition.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,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 +135,52 @@ 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

* `type` - (Optional) The proxy type. The only supported value is `APPMESH`.
SebastianC marked this conversation as resolved.
Show resolved Hide resolved
* `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 as a list of [Proxy Configuration Properties](#proxy-configuration-property-arguments).


##### Proxy Configuration Property Arguments
* `name` - (Required) Variable name. The only supported names names are: `IgnoredUID`, `IgnoredGID`, `AppPorts`, `ProxyIngressPort`, `ProxyEgressPort`, `EgressIgnoredPorts`, `EgressIgnoredIPs`
* `value` - (Required) Variable value. Separate multiple values with a comma.


##### Example Usage:
SebastianC marked this conversation as resolved.
Show resolved Hide resolved
```hcl
resource "aws_ecs_task_definition" "service" {
family = "service"
container_definitions = "${file("task-definitions/service.json")}"

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

## Attributes Reference

Expand Down