provider/aws: Add support for placement_constraint to aws_ecs_service (#11242)
``` % make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSEcsServiceWithPlacementConstraints' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/01/17 18:25:27 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSEcsServiceWithPlacementConstraints -timeout 120m === RUN TestAccAWSEcsServiceWithPlacementConstraints --- PASS: TestAccAWSEcsServiceWithPlacementConstraints (113.18s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 113.208s ``` //cc @catsby
This commit is contained in:
parent
104d043a01
commit
36b6384956
|
@ -26,73 +26,73 @@ func resourceAwsEcsService() *schema.Resource {
|
||||||
Delete: resourceAwsEcsServiceDelete,
|
Delete: resourceAwsEcsServiceDelete,
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"name": &schema.Schema{
|
"name": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"cluster": &schema.Schema{
|
"cluster": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"task_definition": &schema.Schema{
|
"task_definition": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"desired_count": &schema.Schema{
|
"desired_count": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"iam_role": &schema.Schema{
|
"iam_role": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"deployment_maximum_percent": &schema.Schema{
|
"deployment_maximum_percent": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: 200,
|
Default: 200,
|
||||||
},
|
},
|
||||||
|
|
||||||
"deployment_minimum_healthy_percent": &schema.Schema{
|
"deployment_minimum_healthy_percent": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: 100,
|
Default: 100,
|
||||||
},
|
},
|
||||||
|
|
||||||
"load_balancer": &schema.Schema{
|
"load_balancer": {
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
MaxItems: 1,
|
MaxItems: 1,
|
||||||
Elem: &schema.Resource{
|
Elem: &schema.Resource{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"elb_name": &schema.Schema{
|
"elb_name": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"target_group_arn": &schema.Schema{
|
"target_group_arn": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"container_name": &schema.Schema{
|
"container_name": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"container_port": &schema.Schema{
|
"container_port": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
|
@ -102,19 +102,39 @@ func resourceAwsEcsService() *schema.Resource {
|
||||||
Set: resourceAwsEcsLoadBalancerHash,
|
Set: resourceAwsEcsLoadBalancerHash,
|
||||||
},
|
},
|
||||||
|
|
||||||
"placement_strategy": &schema.Schema{
|
"placement_strategy": {
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
MaxItems: 5,
|
MaxItems: 5,
|
||||||
Elem: &schema.Resource{
|
Elem: &schema.Resource{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"type": &schema.Schema{
|
"type": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
"field": &schema.Schema{
|
"field": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
ForceNew: true,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"placement_constraints": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
MaxItems: 10,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"type": { //TODO: Add a Validation for the types
|
||||||
|
Type: schema.TypeString,
|
||||||
|
ForceNew: true,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"expression": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -166,6 +186,19 @@ func resourceAwsEcsServiceCreate(d *schema.ResourceData, meta interface{}) error
|
||||||
input.PlacementStrategy = ps
|
input.PlacementStrategy = ps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constraints := d.Get("placement_constraints").(*schema.Set).List()
|
||||||
|
if len(constraints) > 0 {
|
||||||
|
var pc []*ecs.PlacementConstraint
|
||||||
|
for _, raw := range constraints {
|
||||||
|
p := raw.(map[string]interface{})
|
||||||
|
pc = append(pc, &ecs.PlacementConstraint{
|
||||||
|
Type: aws.String(p["type"].(string)),
|
||||||
|
Expression: aws.String(p["expression"].(string)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
input.PlacementConstraints = pc
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Creating ECS service: %s", input)
|
log.Printf("[DEBUG] Creating ECS service: %s", input)
|
||||||
|
|
||||||
// Retry due to AWS IAM policy eventual consistency
|
// Retry due to AWS IAM policy eventual consistency
|
||||||
|
@ -277,10 +310,27 @@ func resourceAwsEcsServiceRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
if err := d.Set("placement_strategy", flattenPlacementStrategy(service.PlacementStrategy)); err != nil {
|
if err := d.Set("placement_strategy", flattenPlacementStrategy(service.PlacementStrategy)); err != nil {
|
||||||
log.Printf("[ERR] Error setting placement_strategy for (%s): %s", d.Id(), err)
|
log.Printf("[ERR] Error setting placement_strategy for (%s): %s", d.Id(), err)
|
||||||
}
|
}
|
||||||
|
if err := d.Set("placement_constraints", flattenServicePlacementConstraints(service.PlacementConstraints)); err != nil {
|
||||||
|
log.Printf("[ERR] Error setting placement_constraints for (%s): %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func flattenServicePlacementConstraints(pcs []*ecs.PlacementConstraint) []map[string]interface{} {
|
||||||
|
if len(pcs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
results := make([]map[string]interface{}, 0)
|
||||||
|
for _, pc := range pcs {
|
||||||
|
c := make(map[string]interface{})
|
||||||
|
c["type"] = *pc.Type
|
||||||
|
c["expression"] = *pc.Expression
|
||||||
|
results = append(results, c)
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
func flattenPlacementStrategy(pss []*ecs.PlacementStrategy) []map[string]interface{} {
|
func flattenPlacementStrategy(pss []*ecs.PlacementStrategy) []map[string]interface{} {
|
||||||
if len(pss) == 0 {
|
if len(pss) == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -13,52 +13,52 @@ import (
|
||||||
|
|
||||||
func TestParseTaskDefinition(t *testing.T) {
|
func TestParseTaskDefinition(t *testing.T) {
|
||||||
cases := map[string]map[string]interface{}{
|
cases := map[string]map[string]interface{}{
|
||||||
"invalid": map[string]interface{}{
|
"invalid": {
|
||||||
"family": "",
|
"family": "",
|
||||||
"revision": "",
|
"revision": "",
|
||||||
"isValid": false,
|
"isValid": false,
|
||||||
},
|
},
|
||||||
"invalidWithColon:": map[string]interface{}{
|
"invalidWithColon:": {
|
||||||
"family": "",
|
"family": "",
|
||||||
"revision": "",
|
"revision": "",
|
||||||
"isValid": false,
|
"isValid": false,
|
||||||
},
|
},
|
||||||
"1234": map[string]interface{}{
|
"1234": {
|
||||||
"family": "",
|
"family": "",
|
||||||
"revision": "",
|
"revision": "",
|
||||||
"isValid": false,
|
"isValid": false,
|
||||||
},
|
},
|
||||||
"invalid:aaa": map[string]interface{}{
|
"invalid:aaa": {
|
||||||
"family": "",
|
"family": "",
|
||||||
"revision": "",
|
"revision": "",
|
||||||
"isValid": false,
|
"isValid": false,
|
||||||
},
|
},
|
||||||
"invalid=family:1": map[string]interface{}{
|
"invalid=family:1": {
|
||||||
"family": "",
|
"family": "",
|
||||||
"revision": "",
|
"revision": "",
|
||||||
"isValid": false,
|
"isValid": false,
|
||||||
},
|
},
|
||||||
"invalid:name:1": map[string]interface{}{
|
"invalid:name:1": {
|
||||||
"family": "",
|
"family": "",
|
||||||
"revision": "",
|
"revision": "",
|
||||||
"isValid": false,
|
"isValid": false,
|
||||||
},
|
},
|
||||||
"valid:1": map[string]interface{}{
|
"valid:1": {
|
||||||
"family": "valid",
|
"family": "valid",
|
||||||
"revision": "1",
|
"revision": "1",
|
||||||
"isValid": true,
|
"isValid": true,
|
||||||
},
|
},
|
||||||
"abc12-def:54": map[string]interface{}{
|
"abc12-def:54": {
|
||||||
"family": "abc12-def",
|
"family": "abc12-def",
|
||||||
"revision": "54",
|
"revision": "54",
|
||||||
"isValid": true,
|
"isValid": true,
|
||||||
},
|
},
|
||||||
"lorem_ip-sum:123": map[string]interface{}{
|
"lorem_ip-sum:123": {
|
||||||
"family": "lorem_ip-sum",
|
"family": "lorem_ip-sum",
|
||||||
"revision": "123",
|
"revision": "123",
|
||||||
"isValid": true,
|
"isValid": true,
|
||||||
},
|
},
|
||||||
"lorem-ipsum:1": map[string]interface{}{
|
"lorem-ipsum:1": {
|
||||||
"family": "lorem-ipsum",
|
"family": "lorem-ipsum",
|
||||||
"revision": "1",
|
"revision": "1",
|
||||||
"isValid": true,
|
"isValid": true,
|
||||||
|
@ -89,14 +89,14 @@ func TestAccAWSEcsServiceWithARN(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsService,
|
Config: testAccAWSEcsService,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsServiceModified,
|
Config: testAccAWSEcsServiceModified,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
|
||||||
|
@ -112,14 +112,14 @@ func TestAccAWSEcsServiceWithFamilyAndRevision(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsServiceWithFamilyAndRevision,
|
Config: testAccAWSEcsServiceWithFamilyAndRevision,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.jenkins"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.jenkins"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsServiceWithFamilyAndRevisionModified,
|
Config: testAccAWSEcsServiceWithFamilyAndRevisionModified,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.jenkins"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.jenkins"),
|
||||||
|
@ -141,7 +141,7 @@ func TestAccAWSEcsServiceWithRenamedCluster(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsServiceWithRenamedCluster,
|
Config: testAccAWSEcsServiceWithRenamedCluster,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.ghost"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.ghost"),
|
||||||
|
@ -150,7 +150,7 @@ func TestAccAWSEcsServiceWithRenamedCluster(t *testing.T) {
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsServiceWithRenamedClusterModified,
|
Config: testAccAWSEcsServiceWithRenamedClusterModified,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.ghost"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.ghost"),
|
||||||
|
@ -168,7 +168,7 @@ func TestAccAWSEcsService_withIamRole(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsService_withIamRole,
|
Config: testAccAWSEcsService_withIamRole,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.ghost"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.ghost"),
|
||||||
|
@ -184,7 +184,7 @@ func TestAccAWSEcsService_withDeploymentValues(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsServiceWithDeploymentValues,
|
Config: testAccAWSEcsServiceWithDeploymentValues,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
|
||||||
|
@ -205,13 +205,13 @@ func TestAccAWSEcsService_withLbChanges(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsService_withLbChanges,
|
Config: testAccAWSEcsService_withLbChanges,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.with_lb_changes"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.with_lb_changes"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsService_withLbChanges_modified,
|
Config: testAccAWSEcsService_withLbChanges_modified,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.with_lb_changes"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.with_lb_changes"),
|
||||||
|
@ -229,7 +229,7 @@ func TestAccAWSEcsService_withEcsClusterName(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsServiceWithEcsClusterName,
|
Config: testAccAWSEcsServiceWithEcsClusterName,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.jenkins"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.jenkins"),
|
||||||
|
@ -247,7 +247,7 @@ func TestAccAWSEcsService_withAlb(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsServiceWithAlb,
|
Config: testAccAWSEcsServiceWithAlb,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.with_alb"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.with_alb"),
|
||||||
|
@ -263,14 +263,14 @@ func TestAccAWSEcsServiceWithPlacementStrategy(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsService,
|
Config: testAccAWSEcsService,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
|
||||||
resource.TestCheckResourceAttr("aws_ecs_service.mongo", "placement_strategy.#", "0"),
|
resource.TestCheckResourceAttr("aws_ecs_service.mongo", "placement_strategy.#", "0"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsServiceWithPlacementStrategy,
|
Config: testAccAWSEcsServiceWithPlacementStrategy,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
|
||||||
|
@ -281,6 +281,23 @@ func TestAccAWSEcsServiceWithPlacementStrategy(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccAWSEcsServiceWithPlacementConstraints(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccAWSEcsServiceWithPlacementConstraint,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo"),
|
||||||
|
resource.TestCheckResourceAttr("aws_ecs_service.mongo", "placement_constraints.#", "1"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckAWSEcsServiceDestroy(s *terraform.State) error {
|
func testAccCheckAWSEcsServiceDestroy(s *terraform.State) error {
|
||||||
conn := testAccProvider.Meta().(*AWSClient).ecsconn
|
conn := testAccProvider.Meta().(*AWSClient).ecsconn
|
||||||
|
|
||||||
|
@ -416,6 +433,38 @@ resource "aws_ecs_service" "mongo" {
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var testAccAWSEcsServiceWithPlacementConstraint = `
|
||||||
|
resource "aws_ecs_cluster" "default" {
|
||||||
|
name = "terraformecstest21"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_ecs_task_definition" "mongo" {
|
||||||
|
family = "mongodb"
|
||||||
|
container_definitions = <<DEFINITION
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"cpu": 128,
|
||||||
|
"essential": true,
|
||||||
|
"image": "mongo:latest",
|
||||||
|
"memory": 128,
|
||||||
|
"name": "mongodb"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
DEFINITION
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_ecs_service" "mongo" {
|
||||||
|
name = "mongodb"
|
||||||
|
cluster = "${aws_ecs_cluster.default.id}"
|
||||||
|
task_definition = "${aws_ecs_task_definition.mongo.arn}"
|
||||||
|
desired_count = 1
|
||||||
|
placement_constraints {
|
||||||
|
type = "memberOf"
|
||||||
|
expression = "attribute:ecs.availability-zone in [us-west-2a, us-west-2b]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
var testAccAWSEcsService_withIamRole = `
|
var testAccAWSEcsService_withIamRole = `
|
||||||
resource "aws_ecs_cluster" "main" {
|
resource "aws_ecs_cluster" "main" {
|
||||||
name = "terraformecstest11"
|
name = "terraformecstest11"
|
||||||
|
|
|
@ -21,23 +21,23 @@ func resourceAwsEcsTaskDefinition() *schema.Resource {
|
||||||
Delete: resourceAwsEcsTaskDefinitionDelete,
|
Delete: resourceAwsEcsTaskDefinitionDelete,
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"arn": &schema.Schema{
|
"arn": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"family": &schema.Schema{
|
"family": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"revision": &schema.Schema{
|
"revision": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"container_definitions": &schema.Schema{
|
"container_definitions": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
|
@ -47,13 +47,13 @@ func resourceAwsEcsTaskDefinition() *schema.Resource {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
"task_role_arn": &schema.Schema{
|
"task_role_arn": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"network_mode": &schema.Schema{
|
"network_mode": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
|
@ -61,18 +61,18 @@ func resourceAwsEcsTaskDefinition() *schema.Resource {
|
||||||
ValidateFunc: validateAwsEcsTaskDefinitionNetworkMode,
|
ValidateFunc: validateAwsEcsTaskDefinitionNetworkMode,
|
||||||
},
|
},
|
||||||
|
|
||||||
"volume": &schema.Schema{
|
"volume": {
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Elem: &schema.Resource{
|
Elem: &schema.Resource{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"name": &schema.Schema{
|
"name": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"host_path": &schema.Schema{
|
"host_path": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
|
@ -81,19 +81,19 @@ func resourceAwsEcsTaskDefinition() *schema.Resource {
|
||||||
Set: resourceAwsEcsTaskDefinitionVolumeHash,
|
Set: resourceAwsEcsTaskDefinitionVolumeHash,
|
||||||
},
|
},
|
||||||
|
|
||||||
"placement_constraints": &schema.Schema{
|
"placement_constraints": {
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
MaxItems: 10,
|
MaxItems: 10,
|
||||||
Elem: &schema.Resource{
|
Elem: &schema.Resource{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"type": &schema.Schema{
|
"type": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
"expression": &schema.Schema{
|
"expression": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -108,9 +108,9 @@ func resourceAwsEcsTaskDefinition() *schema.Resource {
|
||||||
func validateAwsEcsTaskDefinitionNetworkMode(v interface{}, k string) (ws []string, errors []error) {
|
func validateAwsEcsTaskDefinitionNetworkMode(v interface{}, k string) (ws []string, errors []error) {
|
||||||
value := strings.ToLower(v.(string))
|
value := strings.ToLower(v.(string))
|
||||||
validTypes := map[string]struct{}{
|
validTypes := map[string]struct{}{
|
||||||
"bridge": struct{}{},
|
"bridge": {},
|
||||||
"host": struct{}{},
|
"host": {},
|
||||||
"none": struct{}{},
|
"none": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := validTypes[value]; !ok {
|
if _, ok := validTypes[value]; !ok {
|
||||||
|
|
|
@ -17,13 +17,13 @@ func TestAccAWSEcsTaskDefinition_basic(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsTaskDefinition,
|
Config: testAccAWSEcsTaskDefinition,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.jenkins", &def),
|
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.jenkins", &def),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsTaskDefinitionModified,
|
Config: testAccAWSEcsTaskDefinitionModified,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.jenkins", &def),
|
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.jenkins", &def),
|
||||||
|
@ -41,7 +41,7 @@ func TestAccAWSEcsTaskDefinition_withScratchVolume(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsTaskDefinitionWithScratchVolume,
|
Config: testAccAWSEcsTaskDefinitionWithScratchVolume,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.sleep", &def),
|
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.sleep", &def),
|
||||||
|
@ -59,14 +59,14 @@ func TestAccAWSEcsTaskDefinition_withEcsService(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsTaskDefinitionWithEcsService,
|
Config: testAccAWSEcsTaskDefinitionWithEcsService,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.sleep", &def),
|
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.sleep", &def),
|
||||||
testAccCheckAWSEcsServiceExists("aws_ecs_service.sleep-svc"),
|
testAccCheckAWSEcsServiceExists("aws_ecs_service.sleep-svc"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsTaskDefinitionWithEcsServiceModified,
|
Config: testAccAWSEcsTaskDefinitionWithEcsServiceModified,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.sleep", &def),
|
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.sleep", &def),
|
||||||
|
@ -84,7 +84,7 @@ func TestAccAWSEcsTaskDefinition_withTaskRoleArn(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsTaskDefinitionWithTaskRoleArn,
|
Config: testAccAWSEcsTaskDefinitionWithTaskRoleArn,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.sleep", &def),
|
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.sleep", &def),
|
||||||
|
@ -101,7 +101,7 @@ func TestAccAWSEcsTaskDefinition_withNetworkMode(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsTaskDefinitionWithNetworkMode,
|
Config: testAccAWSEcsTaskDefinitionWithNetworkMode,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.sleep", &def),
|
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.sleep", &def),
|
||||||
|
@ -120,7 +120,7 @@ func TestAccAWSEcsTaskDefinition_constraint(t *testing.T) {
|
||||||
Providers: testAccProviders,
|
Providers: testAccProviders,
|
||||||
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
CheckDestroy: testAccCheckAWSEcsTaskDefinitionDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
{
|
||||||
Config: testAccAWSEcsTaskDefinition_constraint,
|
Config: testAccAWSEcsTaskDefinition_constraint,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.jenkins", &def),
|
testAccCheckAWSEcsTaskDefinitionExists("aws_ecs_task_definition.jenkins", &def),
|
||||||
|
|
|
@ -35,6 +35,11 @@ resource "aws_ecs_service" "mongo" {
|
||||||
container_name = "mongo"
|
container_name = "mongo"
|
||||||
container_port = 8080
|
container_port = 8080
|
||||||
}
|
}
|
||||||
|
|
||||||
|
placement_constraints {
|
||||||
|
type = "memberOf"
|
||||||
|
expression = "attribute:ecs.availability-zone in [us-west-2a, us-west-2b]"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -54,6 +59,8 @@ into consideration during task placement. The maximum number of
|
||||||
`placement_strategy` blocks is `5`. See [the related docs](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-strategies.html) for
|
`placement_strategy` blocks is `5`. See [the related docs](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-strategies.html) for
|
||||||
details on attributes.
|
details on attributes.
|
||||||
* `load_balancer` - (Optional) A load balancer block. Load balancers documented below.
|
* `load_balancer` - (Optional) A load balancer block. Load balancers documented below.
|
||||||
|
* `placement_constraints` - (Optional) rules that are taken into consideration during task placement. Maximum number of
|
||||||
|
`placement_constraints` is `10`. Defined below.
|
||||||
|
|
||||||
-> **Note:** As a result of an AWS limitation, a single `load_balancer` can be attached to the ECS service at most. See [related docs](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-load-balancing.html#load-balancing-concepts).
|
-> **Note:** As a result of an AWS limitation, a single `load_balancer` can be attached to the ECS service at most. See [related docs](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-load-balancing.html#load-balancing-concepts).
|
||||||
|
|
||||||
|
@ -64,6 +71,16 @@ Load balancers support the following:
|
||||||
* `container_name` - (Required) The name of the container to associate with the load balancer (as it appears in a container definition).
|
* `container_name` - (Required) The name of the container to associate with the load balancer (as it appears in a container definition).
|
||||||
* `container_port` - (Required) The port on the container to associate with the load balancer.
|
* `container_port` - (Required) The port on the container to associate with the load balancer.
|
||||||
|
|
||||||
|
## placement_constraints
|
||||||
|
|
||||||
|
`placement_constraints` support the following:
|
||||||
|
|
||||||
|
* `expression` - Cluster Query Language expression to apply to the constraint.
|
||||||
|
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).
|
||||||
|
* `type` - The type of constraint. The only valid values at this time are `memberOf` and `distinctInstance`.
|
||||||
|
|
||||||
|
|
||||||
## Attributes Reference
|
## Attributes Reference
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue