describe-task-definitionで取得したJSONはそのままではregister-task-definitionで登録できないお話

もこ@札幌オフィスです。

AWS CLI, SDKでdescribe-task-definitionを利用してJSONを取得して、register-task-definitionをする機会が増えてきましたので、ハマりポイントをご紹介します。

そのままやってみる

describe-task-definition で取得した結果は下記のようになっています。

$ aws ecs describe-task-definition --task-definition example_task_1:1 > taskdefinition.json
$ cat taskdefinition.json
{
    "taskDefinition": {
        "status": "ACTIVE", 
        "networkMode": "awsvpc", 
        "family": "example_task_1", 
        "placementConstraints": [], 
        "requiresAttributes": [
            {
                "name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
            }, 
            {
                "name": "ecs.capability.execution-role-awslogs"
            }, 
            {
                "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
            }, 
            {
                "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
            }, 
            {
                "name": "ecs.capability.task-eni"
            }
        ], 
        "cpu": "1024", 
        "executionRoleArn": "arn:aws:iam::xxxxxxxxxxxx:role/ecsTaskExecutionRole", 
        "compatibilities": [
            "EC2", 
            "FARGATE"
        ], 
        "volumes": [], 
        "memory": "2048", 
        "requiresCompatibilities": [
            "FARGATE"
        ], 
        "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:xxxxxxxxxxxx:task-definition/example_task_1:1", 
        "containerDefinitions": [
            {
                "environment": [], 
                "name": "nginx-container", 
                "mountPoints": [], 
                "image": "nginx", 
                "cpu": 0, 
                "portMappings": [
                    {
                        "protocol": "tcp", 
                        "containerPort": 80, 
                        "hostPort": 80
                    }
                ], 
                "logConfiguration": {
                    "logDriver": "awslogs", 
                    "options": {
                        "awslogs-region": "us-west-2", 
                        "awslogs-stream-prefix": "fargate-task-1", 
                        "awslogs-group": "ecs-log-streaming"
                    }
                }, 
                "memory": 128, 
                "essential": true, 
                "volumesFrom": []
            }
        ], 
        "revision": 1
    }
}

そのまま register-task-definition でこのJSONを流し込んでみましょう。

$ aws ecs register-task-definition --cli-input-json fileb://taskdefinition.json

Parameter validation failed:
Missing required parameter in input: "family"
Missing required parameter in input: "containerDefinitions"
Unknown parameter in input: "taskDefinition", must be one of: family, taskRoleArn, executionRoleArn, networkMode, containerDefinitions, volumes, placementConstraints, requiresCompatibilities, cpu, memory, tags, pidMode, ipcMode, proxyConfiguration

エラーになってしまいました。

ドキュメントを読む

なぜこのようなエラーが出たのでしょうか、ドキュメントを読んでみましょう。

https://docs.aws.amazon.com/cli/latest/reference/ecs/register-task-definition.html

ドキュメントの JSON Syntax: にJSONのSyntaxが書かれていました。 describe-task-definitionで取ってきた物をそのまま流す事はそもそもできなさそうです。

[
  {
    "name": "string",
    "image": "string",
    "repositoryCredentials": {
      "credentialsParameter": "string"
    },
    "cpu": integer,
    "memory": integer,
    "memoryReservation": integer,
    "links": ["string", ...],
    "portMappings": [
      {
        "containerPort": integer,
        "hostPort": integer,
        "protocol": "tcp"|"udp"
      }
      ...長いので略

register-task-definitionで流れるようにJSONを書き換える

ドキュメントのSyntaxに合わせるように、JSONを書き換えてみましょう。

まずは一番上の taskDefinition からです。

{
  "taskDefinition": {
      "status": "ACTIVE",
      "networkMode": "awsvpc",
      "family": "example_task_1",
      "placementConstraints": [],
      "requiresAttributes": [
      ...長いので略

となっていたところを、taskDefinitionを削除し、下記のようなJSONにしました。

{
      "status": "ACTIVE",
      "networkMode": "awsvpc",
      "family": "example_task_1",
      "placementConstraints": [],
      "requiresAttributes": [
      ...長いので略

この状態で流してみましょう。

$ aws ecs register-task-definition --cli-input-json fileb://taskdefinition.json

status, compatibilities, taskDefinitionArn, requiresAttributes, revision が余計なパラメーターになっている事が確認できたので、削除してみます。

最終的な差分は下記のようになりました。

このJSONを流してみます

$  aws ecs register-task-definition --cli-input-json fileb://taskdefinition.json
{
    "taskDefinition": {
        "status": "ACTIVE", 
        "networkMode": "awsvpc", 
        "family": "example_task_1",
        ...長いので省略

特にエラーの出力もなく、正常に既存のタスク定義から登録できたことを確認できます!

まとめ

既存のタスク定義をdescribe-task-definitionで取得して、register-task-definitionで登録するには、 taskDefinition の中身を取り出して、 status, compatibilities, taskDefinitionArn, requiresAttributes, revision を削除することで、登録する事ができます!

誰かのお役に立てれば幸いです。