Aws-cli: aws ecs - how to update a task definition

Created on 29 Dec 2017  ·  18Comments  ·  Source: aws/aws-cli

Is there a way to add a new revision to a ECS task definition?

In my case I want to update the container URL in my CD pipeline using the command line. Either the documentation is missing how to do that or it is only possible currently using the management console?

see https://github.com/aws/amazon-ecs-cli/issues/91 (but i am not using docker compose)

guidance

Most helpful comment

Thanks @m-radzikowski I slightly modified your solution so it also works when using git hash as image tag instead of "latest". Needs some some environmental variables to work though
```

!/bin/bash

Script to get current task definition, and based on that add new ecr image address to old template and remove attributes that are not needed, then we send new task definition, get new revision number from output and update service

set -e
ECR_IMAGE="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${IMAGE_REPO_NAME}:${CODEBUILD_RESOLVED_SOURCE_VERSION}"
TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition "$TASK_FAMILY" --region "$AWS_DEFAULT_REGION")
NEW_TASK_DEFINTIION=$(echo $TASK_DEFINITION | jq --arg IMAGE "$ECR_IMAGE" '.taskDefinition | .containerDefinitions[0].image = $IMAGE | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities)')
NEW_TASK_INFO=$(aws ecs register-task-definition --region "$AWS_DEFAULT_REGION" --cli-input-json "$NEW_TASK_DEFINTIION")
NEW_REVISION=$(echo $NEW_TASK_INFO | jq '.taskDefinition.revision')
aws ecs update-service --cluster ${ECS_CLUSTER} --service ${SERVICE_NAME} --task-definition ${TASK_FAMILY}:${NEW_REVISION}```

All 18 comments

Hmm, I'm not sure. In general, the best place for usage related questions would be on stack overflow, as mentioned in our README.

Looking over the docs though, it seems like just using register-task-definition would create a new revision. From https://docs.aws.amazon.com/cli/latest/reference/ecs/register-task-definition.html#output:

          revision -> (integer)
              The revision of the task in a particular family. The revision is
              a version number of a task definition in a family. When you reg-
              ister  a task definition for the first time, the revision is 1 ;
              each time you register a new revision of a  task  definition  in
              the  same  family,  the  revision  value always increases by one
              (even if you have deregistered previous revisions in  this  fam-
              ily).

I would give that a shot first.

thanks, sorry for the noise. I was expecting it to be a separate command consistent with others like update-service

Hello @Extrawurst I have the same issue. I was wondering if you found a solution.

hi @menocomp see @jamesls answer. just use register-task-definition and it will create a new revision if the family already exists

register-task-definition isn't a satisfactory way to accomplish a mere bump of the revision number.

register-task-definition requires the Task Definition parameters or JSON as input. Procuring that from describe-task-definition adds an additional dictionary layer _and_ fields that are invalid for use with register-task-definition.

After flattening the top-level dictionary:

$ aws ecs register-task-definition --family name --cli-input-json file:///tmp/task-definition.json

Parameter validation failed:
Unknown parameter in input: "taskDefinitionArn", must be one of: family, taskRoleArn, executionRoleArn, networkMode, containerDefinitions, volumes, placementConstraints, requiresCompatibilities, cpu, memory, tags, pidMode, ipcMode, proxyConfiguration
Unknown parameter in input: "revision", must be one of: family, taskRoleArn, executionRoleArn, networkMode, containerDefinitions, volumes, placementConstraints, requiresCompatibilities, cpu, memory, tags, pidMode, ipcMode, proxyConfiguration
Unknown parameter in input: "status", must be one of: family, taskRoleArn, executionRoleArn, networkMode, containerDefinitions, volumes, placementConstraints, requiresCompatibilities, cpu, memory, tags, pidMode, ipcMode, proxyConfiguration
Unknown parameter in input: "requiresAttributes", must be one of: family, taskRoleArn, executionRoleArn, networkMode, containerDefinitions, volumes, placementConstraints, requiresCompatibilities, cpu, memory, tags, pidMode, ipcMode, proxyConfiguration
Unknown parameter in input: "compatibilities", must be one of: family, taskRoleArn, executionRoleArn, networkMode, containerDefinitions, volumes, placementConstraints, requiresCompatibilities, cpu, memory, tags, pidMode, ipcMode, proxyConfiguration

I think this should be reopened as a feature request. Currently, CLI for ECS Task update, required for CI/CD, is not straight forward and requires additional tricks.

Flow most commonly found on the web is to call describe-task-definition, get container definition from it, change image parameter and push it back with register-task-definition --family $FAMILY --container-definitions $UPDATED_DEFINITION.

Using Fargate I came across a problem with this flow - task couldn't be updated with the same JSON, it required additional parameters, and I basically had to put all top-level values from describe-task JSON as register-task-definition parameters (like cpu, memory and so on).

So the better solution for me was to use JSON as full input for the task, but it has it own problems mentioned by @shatil. Finally I ended with script like this:

TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition "$TASK_FAMILY" --region "us-east-1")
NEW_TASK_DEFINTIION=$(echo $TASK_DEFINITION | jq --arg IMAGE "$NEW_IMAGE" '.taskDefinition | .containerDefinitions[0].image = $IMAGE | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities)')
aws ecs register-task-definition --region "us-east-1" --cli-input-json "$NEW_TASK_DEFINTIION"

Thanks @m-radzikowski I slightly modified your solution so it also works when using git hash as image tag instead of "latest". Needs some some environmental variables to work though
```

!/bin/bash

Script to get current task definition, and based on that add new ecr image address to old template and remove attributes that are not needed, then we send new task definition, get new revision number from output and update service

set -e
ECR_IMAGE="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${IMAGE_REPO_NAME}:${CODEBUILD_RESOLVED_SOURCE_VERSION}"
TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition "$TASK_FAMILY" --region "$AWS_DEFAULT_REGION")
NEW_TASK_DEFINTIION=$(echo $TASK_DEFINITION | jq --arg IMAGE "$ECR_IMAGE" '.taskDefinition | .containerDefinitions[0].image = $IMAGE | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities)')
NEW_TASK_INFO=$(aws ecs register-task-definition --region "$AWS_DEFAULT_REGION" --cli-input-json "$NEW_TASK_DEFINTIION")
NEW_REVISION=$(echo $NEW_TASK_INFO | jq '.taskDefinition.revision')
aws ecs update-service --cluster ${ECS_CLUSTER} --service ${SERVICE_NAME} --task-definition ${TASK_FAMILY}:${NEW_REVISION}```

What's the status on this? how can we create a task definition revision? I would think there would be something like:

aws ecs update-task-definition --task-definition "$task_fam" --revision "ecr/name:tag"

so yes I am looking for:

_aws ecs update-task-definition_

I checked using aws ecs help and there is no such utility:


Screen Shot 2019-08-13 at 10 31 13 AM


I created this ticket: https://github.com/aws/aws-cli/issues/4401

aws-cli support, if you don't like us to discuss just don't use github, sorry, this is still valid and should be reopened

You might not need jq:

aws describe-task-definition --task-definition myapp \
     --query 'taskDefinition.{containerDefinitions:containerDefinitions}' \
     > /tmp/task-definitions.json 

Fargate users might need long commands like this:

aws ecs register-task-definition \
    --family myapp \
    --cli-input-json file:///tmp/task.json \
    --requires-compatibilities FARGATE \
    --network-mode awsvpc \
    --cpu 1024 --memory 2048 \
    --task-role-arn <arn> --execution-role-arn <arn>

As a fargate user, I've found a hack using for ecs cli and --tags.

Whatever you put in to the version number, it'll set the revision as the next one.

ecs-cli compose --project-name PROJECT-NAME --file DOCKER_COMPOSE_FILE --ecs-params ECS_PARAMS_FILE --region REGION create --launch-type FARGATE --tags 'TaskDefinition=TASK:VERSION_NUMBER'

I've switched to Fargate CLI. It automatically updates a suitable task definition.

https://github.com/awslabs/fargatecli

I've switched to Fargate CLI. It automatically updates a suitable task definition.

https://github.com/awslabs/fargatecli

Thanks for sharing that - hadn't seen it. Look forward to checking it out.

fargatecli does not work if you have volumes defined

You might not need jq:

aws describe-task-definition --task-definition myapp \
     --query 'taskDefinition.{containerDefinitions:containerDefinitions}' \
     > /tmp/task-definitions.json 

Fargate users might need long commands like this:

aws ecs register-task-definition \
    --family myapp \
    --cli-input-json file:///tmp/task.json \
    --requires-compatibilities FARGATE \
    --network-mode awsvpc \
    --cpu 1024 --memory 2048 \
    --task-role-arn <arn> --execution-role-arn <arn>

Here is a full version that does not require JQ:

NEW_TASK_DEFINTION=\$(aws ecs describe-task-definition --task-definition {task def} 
      --query '{  containerDefinitions: taskDefinition.containerDefinitions,
                  family: taskDefinition.family,
                  taskRoleArn: taskDefinition.taskRoleArn,
                  executionRoleArn: taskDefinition.executionRoleArn,
                  networkMode: taskDefinition.networkMode,
                  volumes: taskDefinition.volumes,
                  placementConstraints: taskDefinition.placementConstraints,
                  requiresCompatibilities: taskDefinition.requiresCompatibilities,
                  cpu: taskDefinition.cpu,
                  memory: taskDefinition.memory}')

aws ecs register-task-definition --cli-input-json "$NEW_TASK_DEFINTION"

Adding to @sashokbg's answer, register-task-definition is complaining that it needs strings for the cpu and memory values. The --query command uses JMESPath syntax, which supports to_string($arg) type casting, so just wrap those two in to_string()

If you just want to update your ECS cluster to use the latest image (tag with "latest"), this should be enough:

aws ecs update-service --cluster your-cluster-name --service your-service-name --force-new-deployment

The --force-new-deployment param does the trick.

@oalagtash Thanks for the info. I'll try it.

Was this page helpful?
0 / 5 - 0 ratings