From 70d7e5a70a160768b612a0d0db2820fb24259958 Mon Sep 17 00:00:00 2001 From: Clare Liguori Date: Mon, 13 Jan 2020 12:11:48 -0800 Subject: [PATCH] Fix: Ignore task definition fields that are Describe outputs, but not Register inputs Fixes #22 --- dist/index.js | 25 ++++++++++++++++++++++++- index.js | 25 ++++++++++++++++++++++++- index.test.js | 14 ++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index e3fe57b4f..4a09f653b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -137,6 +137,15 @@ const CODE_DEPLOY_MAX_WAIT_MINUTES = 360; // 6 hours const CODE_DEPLOY_MIN_WAIT_MINUTES = 30; const CODE_DEPLOY_WAIT_DEFAULT_DELAY_SEC = 15; +// Attributes that are returned by DescribeTaskDefinition, but are not valid RegisterTaskDefinition inputs +const IGNORED_TASK_DEFINITION_ATTRIBUTES = [ + 'compatibilities', + 'taskDefinitionArn', + 'requiresAttributes', + 'revision', + 'status' +]; + // Deploy to a service that uses the 'ECS' deployment controller async function updateEcsService(ecs, clusterName, service, taskDefArn, waitForService) { core.debug('Updating the service'); @@ -191,6 +200,20 @@ function cleanNullKeys(obj) { return JSON.parse(JSON.stringify(obj, undefinedOrNullReplacer)); } +function removeIgnoredAttributes(taskDef) { + for (var attribute of IGNORED_TASK_DEFINITION_ATTRIBUTES) { + if (taskDef[attribute]) { + core.warning(`Ignoring property '${attribute}' in the task definition file. ` + + 'This property is returned by the Amazon ECS DescribeTaskDefinition API and may be shown in the ECS console, ' + + 'but it is not a valid field when registering a new task definition. ' + + 'This field can be safely removed from your task definition file.'); + delete taskDef[attribute]; + } + } + + return taskDef; +} + // Deploy to a service that uses the 'CODE_DEPLOY' deployment controller async function createCodeDeployDeployment(codedeploy, clusterName, service, taskDefArn, waitForService) { core.debug('Updating AppSpec file with new task definition ARN'); @@ -292,7 +315,7 @@ async function run() { taskDefinitionFile : path.join(process.env.GITHUB_WORKSPACE, taskDefinitionFile); const fileContents = fs.readFileSync(taskDefPath, 'utf8'); - const taskDefContents = cleanNullKeys(yaml.parse(fileContents)); + const taskDefContents = removeIgnoredAttributes(cleanNullKeys(yaml.parse(fileContents))); const registerResponse = await ecs.registerTaskDefinition(taskDefContents).promise(); const taskDefArn = registerResponse.taskDefinition.taskDefinitionArn; core.setOutput('task-definition-arn', taskDefArn); diff --git a/index.js b/index.js index 9a793684d..2a4e78f0a 100644 --- a/index.js +++ b/index.js @@ -10,6 +10,15 @@ const CODE_DEPLOY_MAX_WAIT_MINUTES = 360; // 6 hours const CODE_DEPLOY_MIN_WAIT_MINUTES = 30; const CODE_DEPLOY_WAIT_DEFAULT_DELAY_SEC = 15; +// Attributes that are returned by DescribeTaskDefinition, but are not valid RegisterTaskDefinition inputs +const IGNORED_TASK_DEFINITION_ATTRIBUTES = [ + 'compatibilities', + 'taskDefinitionArn', + 'requiresAttributes', + 'revision', + 'status' +]; + // Deploy to a service that uses the 'ECS' deployment controller async function updateEcsService(ecs, clusterName, service, taskDefArn, waitForService) { core.debug('Updating the service'); @@ -64,6 +73,20 @@ function cleanNullKeys(obj) { return JSON.parse(JSON.stringify(obj, undefinedOrNullReplacer)); } +function removeIgnoredAttributes(taskDef) { + for (var attribute of IGNORED_TASK_DEFINITION_ATTRIBUTES) { + if (taskDef[attribute]) { + core.warning(`Ignoring property '${attribute}' in the task definition file. ` + + 'This property is returned by the Amazon ECS DescribeTaskDefinition API and may be shown in the ECS console, ' + + 'but it is not a valid field when registering a new task definition. ' + + 'This field can be safely removed from your task definition file.'); + delete taskDef[attribute]; + } + } + + return taskDef; +} + // Deploy to a service that uses the 'CODE_DEPLOY' deployment controller async function createCodeDeployDeployment(codedeploy, clusterName, service, taskDefArn, waitForService) { core.debug('Updating AppSpec file with new task definition ARN'); @@ -165,7 +188,7 @@ async function run() { taskDefinitionFile : path.join(process.env.GITHUB_WORKSPACE, taskDefinitionFile); const fileContents = fs.readFileSync(taskDefPath, 'utf8'); - const taskDefContents = cleanNullKeys(yaml.parse(fileContents)); + const taskDefContents = removeIgnoredAttributes(cleanNullKeys(yaml.parse(fileContents))); const registerResponse = await ecs.registerTaskDefinition(taskDefContents).promise(); const taskDefArn = registerResponse.taskDefinition.taskDefinitionArn; core.setOutput('task-definition-arn', taskDefArn); diff --git a/index.test.js b/index.test.js index 98a0c7f9f..642474246 100644 --- a/index.test.js +++ b/index.test.js @@ -170,6 +170,20 @@ describe('Deploy to ECS', () => { expect(mockEcsRegisterTaskDef).toHaveBeenNthCalledWith(1, { family: 'task-def-family'}); }); + test('cleans invalid keys out of the task definition contents', async () => { + fs.readFileSync.mockImplementation((pathInput, encoding) => { + if (encoding != 'utf8') { + throw new Error(`Wrong encoding ${encoding}`); + } + + return '{ "compatibilities": ["EC2"], "taskDefinitionArn": "arn:aws...:task-def-family:1", "family": "task-def-family", "revision": 1, "status": "ACTIVE" }'; + }); + + await run(); + expect(core.setFailed).toHaveBeenCalledTimes(0); + expect(mockEcsRegisterTaskDef).toHaveBeenNthCalledWith(1, { family: 'task-def-family'}); + }); + test('registers the task definition contents and creates a CodeDeploy deployment', async () => { core.getInput = jest .fn()