Skip to content

service resource

Description

ServiceResource 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:81

Example usage:

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

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

optional(list(object))
optional(
  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

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

placement-constraints

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

placement-strategy

optional(list(object))
optional(
  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

optional(map(string))

force-delete

optional(boolean)

Input Constraints

Launch type rules

launch-type and capacity-provider-strategy are mutually exclusive.

Rule logic
Require
input.launch-type == null
|| !(@core.length(input.capacity-provider-strategy ?? []) >= 1)

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 >= 0
&& 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
@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 >= 0
&& @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 >= 0
&& @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 >= 0
&& @each.value.container-port <= 65536

Placement constraints rules

placement-constraints allows at most 10 entries.

Rule logic
Require
@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
@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