Skip to content

aws.ecs-service resource

Description

Service manages an ECS service. The cluster, name, scheduling strategy, and launch type are fixed at create time, so changing any of them replaces the service; every other input is reconciled in place by a single UpdateService call sent only when something it covers changed, and tags by the tag calls. Deleting drains a REPLICA service to zero desired tasks, then deletes it and waits for it to leave the ACTIVE status.

Name is required and the cluster is optional: when cluster is unset the account's default cluster is used. The task definition is required and may be a family, family:revision, or full ARN; a bare family resolves to the latest ACTIVE revision only when the service is created or that input changes, so referencing the ecs-task-definition resource's arn output is what redeploys the service as revisions are registered.

Desired-count applies only to REPLICA services, riding as 0 when unset at create; on update it is sent only when this input changed, so a value an autoscaling policy moved stays untouched by unrelated applies, and a removed desired-count leaves the running count as is. Setting health-check-grace-period-seconds requires at least one load-balancers entry, a rule checked in Create and Update. Force-delete applies only at delete time: it skips the drain and forces deletion of a service still running tasks.

Service Connect, managed volume configurations, deployment controllers other than the ECS rolling controller, deployment alarms, service registries, VPC Lattice configurations, and classic load balancer names are not modeled.

Source: internal/service/ecs/service_rsrc.go:82

Example usage:

imports: {
  aws: 'github.com/cloudboss/unobin-library-aws'
}

resources: {
  example: aws.ecs-service {
    # Set input fields here.
  }
}

Inputs

name

string

required

cluster

optional(string)

task-definition

string

required

desired-count

optional(integer)

launch-type

optional(string)

scheduling-strategy

optional(string)

capacity-provider-strategy

list(object)
list(
  object({
    capacity-provider: string
    base: optional(integer)
    weight: optional(integer)
  })
)

deployment-configuration

optional(object)
optional(
  object({
    maximum-percent: optional(integer)
    minimum-healthy-percent: optional(integer)
    deployment-circuit-breaker: optional(
      object({
        enable: boolean
        rollback: boolean
      })
    )
  })
)

network-configuration

optional(object)
optional(
  object({
    subnets: list(string)
    security-groups: optional(list(string))
    assign-public-ip: optional(string)
  })
)

load-balancers

list(object)
list(
  object({
    container-name: string
    container-port: integer
    target-group-arn: string
  })
)

placement-constraints

list(object)
list(
  object({
    type: string
    expression: optional(string)
  })
)

placement-strategy

list(object)
list(
  object({
    type: string
    field: optional(string)
  })
)

platform-version

optional(string)

propagate-tags

optional(string)

availability-zone-rebalancing

optional(string)

enable-ecs-managed-tags

optional(boolean)

enable-execute-command

optional(boolean)

health-check-grace-period-seconds

optional(integer)

tags

map(string)

force-delete

optional(boolean)

Input Constraints

Field combinations

At most one of launch-type or capacity-provider-strategy.

Launch type rules

launch-type must be EC2, FARGATE, or EXTERNAL.

Rule logic
When
input.launch-type != null
Require
input.launch-type == 'EC2'
|| input.launch-type == 'FARGATE'
|| input.launch-type == 'EXTERNAL'

Scheduling strategy rules

scheduling-strategy must be REPLICA or DAEMON.

Rule logic
When
input.scheduling-strategy != null
Require
input.scheduling-strategy == 'REPLICA'
|| input.scheduling-strategy == 'DAEMON'

Propagate tags rules

propagate-tags must be SERVICE, TASK_DEFINITION, or NONE.

Rule logic
When
input.propagate-tags != null
Require
input.propagate-tags == 'SERVICE'
|| input.propagate-tags == 'TASK_DEFINITION'
|| input.propagate-tags == 'NONE'

Availability zone rebalancing rules

availability-zone-rebalancing must be ENABLED or DISABLED.

Rule logic
When
input.availability-zone-rebalancing != null
Require
input.availability-zone-rebalancing == 'ENABLED'
|| input.availability-zone-rebalancing == 'DISABLED'

Health check grace period seconds rules

health-check-grace-period-seconds must be between 0 and 2147483647.

Rule logic
When
input.health-check-grace-period-seconds != null
Require
(input.health-check-grace-period-seconds == null || input.health-check-grace-period-seconds >= 0)
&& (input.health-check-grace-period-seconds == null || input.health-check-grace-period-seconds <= 2147483647)

Network configuration rules

network-configuration subnets must not be empty.

Rule logic
When
input.network-configuration != null
Require
input.network-configuration.subnets != null
&& @core.length(input.network-configuration.subnets) >= 1

assign-public-ip must be ENABLED or DISABLED.

Rule logic
When
input.network-configuration.assign-public-ip != null
Require
input.network-configuration.assign-public-ip == 'ENABLED'
|| input.network-configuration.assign-public-ip == 'DISABLED'

Capacity provider strategy rules

base must be between 0 and 100000.

Rule logic
For each
input.capacity-provider-strategy
When
@each.value.base != null
Require
(@each.value.base == null || @each.value.base >= 0)
&& (@each.value.base == null || @each.value.base <= 100000)

weight must be between 0 and 1000.

Rule logic
For each
input.capacity-provider-strategy
When
@each.value.weight != null
Require
(@each.value.weight == null || @each.value.weight >= 0)
&& (@each.value.weight == null || @each.value.weight <= 1000)

Load balancers rules

container-port must be between 0 and 65536.

Rule logic
For each
input.load-balancers
Require
(@each.value.container-port == null || @each.value.container-port >= 0)
&& (@each.value.container-port == null || @each.value.container-port <= 65536)

Placement constraints rules

placement-constraints allows at most 10 entries.

Rule logic
Require
input.placement-constraints == null
|| @core.length(input.placement-constraints) <= 10

type must be distinctInstance or memberOf.

Rule logic
For each
input.placement-constraints
Require
@each.value.type == 'distinctInstance'
|| @each.value.type == 'memberOf'

a memberOf placement constraint requires an expression.

Rule logic
For each
input.placement-constraints
When
@each.value.type == 'memberOf'
Require
@each.value.expression != null

a distinctInstance placement constraint takes no expression.

Rule logic
For each
input.placement-constraints
When
@each.value.type == 'distinctInstance'
Require
@each.value.expression == null

Placement strategy rules

placement-strategy allows at most 5 entries.

Rule logic
Require
input.placement-strategy == null
|| @core.length(input.placement-strategy) <= 5

type must be random, spread, or binpack.

Rule logic
For each
input.placement-strategy
Require
@each.value.type == 'random'
|| @each.value.type == 'spread'
|| @each.value.type == 'binpack'

a random placement strategy must omit field.

Rule logic
For each
input.placement-strategy
When
@each.value.type == 'random'
Require
@each.value.field == null

a binpack placement strategy field must be cpu or memory.

Rule logic
For each
input.placement-strategy
When
@each.value.type == 'binpack'
Require
@each.value.field == 'cpu'
|| @each.value.field == 'memory'

Outputs

arn

string

cluster-arn

string