provider/aws: Update ECS task_definition and service
Updates ECS task_definition documentation, and schema validation functions to match the AWS API documentation. Updates ECS service documentation, and schema validation functions match the AWS API documentation.
This commit is contained in:
parent
570af34f0f
commit
5276496e6d
|
@ -117,11 +117,12 @@ func resourceAwsEcsService() *schema.Resource {
|
||||||
"field": {
|
"field": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Required: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
"placement_constraints": {
|
"placement_constraints": {
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
@ -129,7 +130,7 @@ func resourceAwsEcsService() *schema.Resource {
|
||||||
MaxItems: 10,
|
MaxItems: 10,
|
||||||
Elem: &schema.Resource{
|
Elem: &schema.Resource{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"type": { //TODO: Add a Validation for the types
|
"type": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -137,7 +138,7 @@ func resourceAwsEcsService() *schema.Resource {
|
||||||
"expression": {
|
"expression": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Required: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -178,6 +179,11 @@ func resourceAwsEcsServiceCreate(d *schema.ResourceData, meta interface{}) error
|
||||||
var ps []*ecs.PlacementStrategy
|
var ps []*ecs.PlacementStrategy
|
||||||
for _, raw := range strategies {
|
for _, raw := range strategies {
|
||||||
p := raw.(map[string]interface{})
|
p := raw.(map[string]interface{})
|
||||||
|
t := p["type"].(string)
|
||||||
|
f := p["field"].(string)
|
||||||
|
if err := validateAwsEcsPlacementStrategy(t, f); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
ps = append(ps, &ecs.PlacementStrategy{
|
ps = append(ps, &ecs.PlacementStrategy{
|
||||||
Type: aws.String(p["type"].(string)),
|
Type: aws.String(p["type"].(string)),
|
||||||
Field: aws.String(p["field"].(string)),
|
Field: aws.String(p["field"].(string)),
|
||||||
|
@ -191,9 +197,14 @@ func resourceAwsEcsServiceCreate(d *schema.ResourceData, meta interface{}) error
|
||||||
var pc []*ecs.PlacementConstraint
|
var pc []*ecs.PlacementConstraint
|
||||||
for _, raw := range constraints {
|
for _, raw := range constraints {
|
||||||
p := raw.(map[string]interface{})
|
p := raw.(map[string]interface{})
|
||||||
|
t := p["type"].(string)
|
||||||
|
e := p["expression"].(string)
|
||||||
|
if err := validateAwsEcsPlacementConstraint(t, e); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
pc = append(pc, &ecs.PlacementConstraint{
|
pc = append(pc, &ecs.PlacementConstraint{
|
||||||
Type: aws.String(p["type"].(string)),
|
Type: aws.String(t),
|
||||||
Expression: aws.String(p["expression"].(string)),
|
Expression: aws.String(e),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
input.PlacementConstraints = pc
|
input.PlacementConstraints = pc
|
||||||
|
|
|
@ -96,7 +96,7 @@ func resourceAwsEcsTaskDefinition() *schema.Resource {
|
||||||
"expression": {
|
"expression": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Required: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -154,9 +154,14 @@ func resourceAwsEcsTaskDefinitionCreate(d *schema.ResourceData, meta interface{}
|
||||||
var pc []*ecs.TaskDefinitionPlacementConstraint
|
var pc []*ecs.TaskDefinitionPlacementConstraint
|
||||||
for _, raw := range constraints {
|
for _, raw := range constraints {
|
||||||
p := raw.(map[string]interface{})
|
p := raw.(map[string]interface{})
|
||||||
|
t := p["type"].(string)
|
||||||
|
e := p["expression"].(string)
|
||||||
|
if err := validateAwsEcsPlacementConstraint(t, e); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
pc = append(pc, &ecs.TaskDefinitionPlacementConstraint{
|
pc = append(pc, &ecs.TaskDefinitionPlacementConstraint{
|
||||||
Type: aws.String(p["type"].(string)),
|
Type: aws.String(t),
|
||||||
Expression: aws.String(p["expression"].(string)),
|
Expression: aws.String(e),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
input.PlacementConstraints = pc
|
input.PlacementConstraints = pc
|
||||||
|
|
|
@ -673,3 +673,44 @@ func validateRoute53RecordType(v interface{}, k string) (ws []string, errors []e
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validates that ECS Placement Constraints are set correctly
|
||||||
|
// Takes type, and expression as strings
|
||||||
|
func validateAwsEcsPlacementConstraint(constType, constExpr string) error {
|
||||||
|
switch constType {
|
||||||
|
case "distinctInstance":
|
||||||
|
// Expression can be nil for distinctInstance
|
||||||
|
return nil
|
||||||
|
case "memberOf":
|
||||||
|
if constExpr == "" {
|
||||||
|
return fmt.Errorf("Expression cannot be nil for 'memberOf' type")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Unknown type provided: %q", constType)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validates that an Ecs placement strategy is set correctly
|
||||||
|
// Takes type, and field as strings
|
||||||
|
func validateAwsEcsPlacementStrategy(stratType, stratField string) error {
|
||||||
|
switch stratType {
|
||||||
|
case "random":
|
||||||
|
// random does not need the field attribute set, could error, but it isn't read at the API level
|
||||||
|
return nil
|
||||||
|
case "spread":
|
||||||
|
// For the spread placement strategy, valid values are instanceId
|
||||||
|
// (or host, which has the same effect), or any platform or custom attribute
|
||||||
|
// that is applied to a container instance
|
||||||
|
// stratField is already cased to a string
|
||||||
|
return nil
|
||||||
|
case "binpack":
|
||||||
|
if stratField != "cpu" && stratField != "memory" {
|
||||||
|
return fmt.Errorf("Binpack type requires the field attribute to be either 'cpu' or 'memory'. Got: %s",
|
||||||
|
stratField)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Unknown type %s. Must be one of 'random', 'spread', or 'binpack'.", stratType)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -1043,3 +1043,87 @@ func TestValidateRoute53RecordType(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateEcsPlacementConstraint(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
constType string
|
||||||
|
constExpr string
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
constType: "distinctInstance",
|
||||||
|
constExpr: "",
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
constType: "memberOf",
|
||||||
|
constExpr: "",
|
||||||
|
Err: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
constType: "distinctInstance",
|
||||||
|
constExpr: "expression",
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
constType: "memberOf",
|
||||||
|
constExpr: "expression",
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
if err := validateAwsEcsPlacementConstraint(tc.constType, tc.constExpr); err != nil && !tc.Err {
|
||||||
|
t.Fatalf("Unexpected validation error for \"%s:%s\": %s",
|
||||||
|
tc.constType, tc.constExpr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateEcsPlacementStrategy(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
stratType string
|
||||||
|
stratField string
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
stratType: "random",
|
||||||
|
stratField: "",
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stratType: "spread",
|
||||||
|
stratField: "instanceID",
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stratType: "binpack",
|
||||||
|
stratField: "cpu",
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stratType: "binpack",
|
||||||
|
stratField: "memory",
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stratType: "binpack",
|
||||||
|
stratField: "disk",
|
||||||
|
Err: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stratType: "fakeType",
|
||||||
|
stratField: "",
|
||||||
|
Err: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
if err := validateAwsEcsPlacementStrategy(tc.stratType, tc.stratField); err != nil && !tc.Err {
|
||||||
|
t.Fatalf("Unexpected validation error for \"%s:%s\": %s",
|
||||||
|
tc.stratType, tc.stratField, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -75,11 +75,13 @@ Load balancers support the following:
|
||||||
|
|
||||||
`placement_constraints` support the following:
|
`placement_constraints` support the following:
|
||||||
|
|
||||||
* `expression` - Cluster Query Language expression to apply to the constraint.
|
* `type` - (Required) The type of constraint. The only valid values at this time are `memberOf` and `distinctInstance`.
|
||||||
|
* `expression` - (Optional) Cluster Query Language expression to apply to the constraint. Does not need to be specified
|
||||||
|
for the `distinctInstance` type.
|
||||||
For more information, see [Cluster Query Language in the Amazon EC2 Container
|
For more information, see [Cluster Query Language in the Amazon EC2 Container
|
||||||
Service Developer
|
Service Developer
|
||||||
Guide](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-query-language.html).
|
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
|
||||||
|
|
|
@ -81,6 +81,8 @@ official [Developer Guide](https://docs.aws.amazon.com/AmazonECS/latest/develope
|
||||||
* `volume` - (Optional) A volume block. See below for details about what arguments are supported.
|
* `volume` - (Optional) A volume block. See below for details about what arguments are supported.
|
||||||
* `placement_constraints` - (Optional) rules that are taken into consideration during task placement. Maximum number of
|
* `placement_constraints` - (Optional) rules that are taken into consideration during task placement. Maximum number of
|
||||||
`placement_constraints` is `10`. Defined below.
|
`placement_constraints` is `10`. Defined below.
|
||||||
|
* `placement_strategy` - (Optional) an algorithm for selecting instances for task placement or tasks for termination. Maximum
|
||||||
|
number of `placement_strategy` blocks is `5`. Defined below.
|
||||||
|
|
||||||
Volume block supports the following arguments:
|
Volume block supports the following arguments:
|
||||||
|
|
||||||
|
@ -92,11 +94,24 @@ parameter of container definition in the `mountPoints` section.
|
||||||
|
|
||||||
`placement_constraints` support the following:
|
`placement_constraints` support the following:
|
||||||
|
|
||||||
* `expression` - Cluster Query Language expression to apply to the constraint.
|
* `type` - (Required) The type of constraint. The only valid values at this time are `memberOf` or `distinctInstance`.
|
||||||
|
* `expression` - (Optional) Cluster Query Language expression to apply to the constraint. Does not need to be specified
|
||||||
|
for the `distinctInstance` type.
|
||||||
For more information, see [Cluster Query Language in the Amazon EC2 Container
|
For more information, see [Cluster Query Language in the Amazon EC2 Container
|
||||||
Service Developer
|
Service Developer
|
||||||
Guide](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-query-language.html).
|
Guide](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-query-language.html).
|
||||||
* `type` - The type of constraint. The only valid value at this time is `memberOf`
|
|
||||||
|
## placement_strategy
|
||||||
|
|
||||||
|
`placement_strategy` supports the following:
|
||||||
|
|
||||||
|
* `type` - (Required) The type of placement strategy. Must be one of: `binpack`, `random`, or `spread`
|
||||||
|
* `field` - (Optional) For the `spread` placement strategy, valid values are instanceId (or host,
|
||||||
|
which has the same effect), or any platform or custom attribute that is applied to a container instance.
|
||||||
|
For the `binpack` type, valid values are `memory` and `cpu`. For the `random` type, this attribute is not
|
||||||
|
needed. For more information, see [Placement Strategy](http://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_PlacementStrategy.html).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Attributes Reference
|
## Attributes Reference
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue