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)
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
```
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:
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.
I've switched to Fargate CLI. It automatically updates a suitable task definition.
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.
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}```