Skip to content

Commit

Permalink
feat: Enable AWS managed tags (#622)
Browse files Browse the repository at this point in the history
* feat: enable ecs managed tags
---------
Co-authored-by: Kishan Gajjar <[email protected]>
  • Loading branch information
guikcd authored Aug 24, 2024
1 parent 6b5f48e commit 5ae7be6
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 27 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,21 @@ The task definition file can be updated prior to deployment with the new contain
wait-for-service-stability: true
```

### Tags

To turn on [Amazon ECS-managed tags](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-using-tags.html#managed-tags) `aws:ecs:serviceName` and `aws:ecs:clusterName` for the tasks in the service or the standalone tasks by setting `enable-ecs-managed-tags`:

```yaml
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: task-definition.json
service: my-service
cluster: my-cluster
wait-for-service-stability: true
enable-ecs-managed-tags: true
```

## Credentials and Region

This action relies on the [default behavior of the AWS SDK for Javascript](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html) to determine AWS credentials and region.
Expand Down
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ inputs:
wait-for-task-stopped:
description: 'Whether to wait for the task to stop when running it outside of a service. Will default to not wait.'
required: false
enable-ecs-managed-tags:
description: "Determines whether to turn on Amazon ECS managed tags 'aws:ecs:serviceName' and 'aws:ecs:clusterName' for the tasks in the service."
required: false
outputs:
task-definition-arn:
description: 'The ARN of the registered ECS task definition'
Expand Down
16 changes: 10 additions & 6 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const IGNORED_TASK_DEFINITION_ATTRIBUTES = [
];

// Method to run a stand-alone task with desired inputs
async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
async function runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSManagedTags) {
core.info('Running task')

const waitForTask = core.getInput('wait-for-task-stopped', { required: false }) || 'false';
Expand Down Expand Up @@ -60,7 +60,8 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
containerOverrides: containerOverrides
},
launchType: launchType,
networkConfiguration: Object.keys(awsvpcConfiguration).length === 0 ? null : { awsvpcConfiguration: awsvpcConfiguration }
networkConfiguration: Object.keys(awsvpcConfiguration).length === 0 ? null : { awsvpcConfiguration: awsvpcConfiguration },
enableECSManagedTags: enableECSManagedTags
});

core.debug(`Run task response ${JSON.stringify(runTaskResponse)}`)
Expand Down Expand Up @@ -134,14 +135,15 @@ async function tasksExitCode(ecs, clusterName, taskArns) {
}

// Deploy to a service that uses the 'ECS' deployment controller
async function updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount) {
async function updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount, enableECSManagedTags) {
core.debug('Updating the service');

let params = {
cluster: clusterName,
service: service,
taskDefinition: taskDefArn,
forceNewDeployment: forceNewDeployment
forceNewDeployment: forceNewDeployment,
enableECSManagedTags: enableECSManagedTags
};

// Add the desiredCount property only if it is defined and a number.
Expand Down Expand Up @@ -397,6 +399,8 @@ async function run() {
const forceNewDeployInput = core.getInput('force-new-deployment', { required: false }) || 'false';
const forceNewDeployment = forceNewDeployInput.toLowerCase() === 'true';
const desiredCount = parseInt((core.getInput('desired-count', {required: false})));
const enableECSManagedTagsInput = core.getInput('enable-ecs-managed-tags', { required: false }) || 'false';
const enableECSManagedTags = enableECSManagedTagsInput.toLowerCase() === 'true';

// Register the task definition
core.debug('Registering the task definition');
Expand Down Expand Up @@ -424,7 +428,7 @@ async function run() {
core.debug(`shouldRunTask: ${shouldRunTask}`);
if (shouldRunTask) {
core.debug("Running ad-hoc task...");
await runTask(ecs, clusterName, taskDefArn, waitForMinutes);
await runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSManagedTags);
}

// Update the service with the new task definition
Expand All @@ -448,7 +452,7 @@ async function run() {
if (!serviceResponse.deploymentController || !serviceResponse.deploymentController.type || serviceResponse.deploymentController.type === 'ECS') {
// Service uses the 'ECS' deployment controller, so we can call UpdateService
core.debug('Updating service...');
await updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount);
await updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount, enableECSManagedTags);

} else if (serviceResponse.deploymentController.type === 'CODE_DEPLOY') {
// Service uses CodeDeploy, so we should start a CodeDeploy deployment
Expand Down
16 changes: 10 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const IGNORED_TASK_DEFINITION_ATTRIBUTES = [
];

// Method to run a stand-alone task with desired inputs
async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
async function runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSManagedTags) {
core.info('Running task')

const waitForTask = core.getInput('wait-for-task-stopped', { required: false }) || 'false';
Expand Down Expand Up @@ -54,7 +54,8 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
containerOverrides: containerOverrides
},
launchType: launchType,
networkConfiguration: Object.keys(awsvpcConfiguration).length === 0 ? null : { awsvpcConfiguration: awsvpcConfiguration }
networkConfiguration: Object.keys(awsvpcConfiguration).length === 0 ? null : { awsvpcConfiguration: awsvpcConfiguration },
enableECSManagedTags: enableECSManagedTags
});

core.debug(`Run task response ${JSON.stringify(runTaskResponse)}`)
Expand Down Expand Up @@ -128,14 +129,15 @@ async function tasksExitCode(ecs, clusterName, taskArns) {
}

// Deploy to a service that uses the 'ECS' deployment controller
async function updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount) {
async function updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount, enableECSManagedTags) {
core.debug('Updating the service');

let params = {
cluster: clusterName,
service: service,
taskDefinition: taskDefArn,
forceNewDeployment: forceNewDeployment
forceNewDeployment: forceNewDeployment,
enableECSManagedTags: enableECSManagedTags
};

// Add the desiredCount property only if it is defined and a number.
Expand Down Expand Up @@ -391,6 +393,8 @@ async function run() {
const forceNewDeployInput = core.getInput('force-new-deployment', { required: false }) || 'false';
const forceNewDeployment = forceNewDeployInput.toLowerCase() === 'true';
const desiredCount = parseInt((core.getInput('desired-count', {required: false})));
const enableECSManagedTagsInput = core.getInput('enable-ecs-managed-tags', { required: false }) || 'false';
const enableECSManagedTags = enableECSManagedTagsInput.toLowerCase() === 'true';

// Register the task definition
core.debug('Registering the task definition');
Expand Down Expand Up @@ -418,7 +422,7 @@ async function run() {
core.debug(`shouldRunTask: ${shouldRunTask}`);
if (shouldRunTask) {
core.debug("Running ad-hoc task...");
await runTask(ecs, clusterName, taskDefArn, waitForMinutes);
await runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSManagedTags);
}

// Update the service with the new task definition
Expand All @@ -442,7 +446,7 @@ async function run() {
if (!serviceResponse.deploymentController || !serviceResponse.deploymentController.type || serviceResponse.deploymentController.type === 'ECS') {
// Service uses the 'ECS' deployment controller, so we can call UpdateService
core.debug('Updating service...');
await updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount);
await updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount, enableECSManagedTags);

} else if (serviceResponse.deploymentController.type === 'CODE_DEPLOY') {
// Service uses CodeDeploy, so we should start a CodeDeploy deployment
Expand Down
49 changes: 34 additions & 15 deletions index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ describe('Deploy to ECS', () => {
cluster: 'cluster-789',
service: 'service-456',
taskDefinition: 'task:def:arn',
forceNewDeployment: false
forceNewDeployment: false,
enableECSManagedTags: false
});
expect(waitUntilServicesStable).toHaveBeenCalledTimes(0);
expect(core.info).toBeCalledWith("Deployment started. Watch this deployment's progress in the Amazon ECS console: https://fake-region.console.aws.amazon.com/ecs/v2/clusters/cluster-789/services/service-456/events?region=fake-region");
Expand Down Expand Up @@ -213,7 +214,8 @@ describe('Deploy to ECS', () => {
cluster: 'cluster-789',
service: 'service-456',
taskDefinition: 'task:def:arn',
forceNewDeployment: false
forceNewDeployment: false,
enableECSManagedTags: false
});
expect(waitUntilServicesStable).toHaveBeenCalledTimes(0);
expect(core.info).toBeCalledWith("Deployment started. Watch this deployment's progress in the Amazon ECS console: https://fake-region.console.aws.amazon.com/ecs/v2/clusters/cluster-789/services/service-456/events?region=fake-region");
Expand Down Expand Up @@ -708,6 +710,7 @@ describe('Deploy to ECS', () => {
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('') // run-task
.mockReturnValueOnce('') // desired count
.mockReturnValueOnce('') // enable-ecs-managed-tags
.mockReturnValueOnce('/hello/appspec.json') // codedeploy-appspec
.mockReturnValueOnce('MyApplication') // codedeploy-application
.mockReturnValueOnce('MyDeploymentGroup'); // codedeploy-deployment-group
Expand Down Expand Up @@ -944,7 +947,8 @@ describe('Deploy to ECS', () => {
cluster: 'cluster-789',
service: 'service-456',
taskDefinition: 'task:def:arn',
forceNewDeployment: false
forceNewDeployment: false,
enableECSManagedTags: false
});
expect(waitUntilServicesStable).toHaveBeenNthCalledWith(
1,
Expand Down Expand Up @@ -983,7 +987,8 @@ describe('Deploy to ECS', () => {
cluster: 'cluster-789',
service: 'service-456',
taskDefinition: 'task:def:arn',
forceNewDeployment: false
forceNewDeployment: false,
enableECSManagedTags: false
});
expect(waitUntilServicesStable).toHaveBeenNthCalledWith(
1,
Expand Down Expand Up @@ -1022,7 +1027,8 @@ describe('Deploy to ECS', () => {
cluster: 'cluster-789',
service: 'service-456',
taskDefinition: 'task:def:arn',
forceNewDeployment: false
forceNewDeployment: false,
enableECSManagedTags: false
});
expect(waitUntilServicesStable).toHaveBeenNthCalledWith(
1,
Expand Down Expand Up @@ -1063,7 +1069,8 @@ describe('Deploy to ECS', () => {
desiredCount: 4,
service: 'service-456',
taskDefinition: 'task:def:arn',
forceNewDeployment: true
forceNewDeployment: true,
enableECSManagedTags: false
});
});

Expand All @@ -1087,7 +1094,8 @@ describe('Deploy to ECS', () => {
cluster: 'default',
service: 'service-456',
taskDefinition: 'task:def:arn',
forceNewDeployment: false
forceNewDeployment: false,
enableECSManagedTags: false
});
});

Expand All @@ -1113,6 +1121,7 @@ describe('Deploy to ECS', () => {
.mockReturnValueOnce('') // cluster
.mockReturnValueOnce('') // wait-for-service-stability
.mockReturnValueOnce('') // wait-for-minutes
.mockReturnValueOnce('') // enable-ecs-managed-tags
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('') // desired-count
.mockReturnValueOnce('true'); // run-task
Expand All @@ -1129,7 +1138,8 @@ describe('Deploy to ECS', () => {
launchType: 'FARGATE',
taskDefinition: 'task:def:arn',
overrides: {"containerOverrides": []},
networkConfiguration: null
networkConfiguration: null,
enableECSManagedTags: false
});

expect(core.setOutput).toHaveBeenNthCalledWith(2, 'run-task-arn', ["arn:aws:ecs:fake-region:account_id:task/arn"]);
Expand All @@ -1145,6 +1155,7 @@ describe('Deploy to ECS', () => {
.mockReturnValueOnce('') // wait-for-minutes
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('') // desired-count
.mockReturnValueOnce('true') // enable-ecs-managed-tags
.mockReturnValueOnce('true') // run-task
.mockReturnValueOnce('false') // wait-for-task-stopped
.mockReturnValueOnce('someJoe') // run-task-started-by
Expand All @@ -1164,7 +1175,8 @@ describe('Deploy to ECS', () => {
launchType: 'EC2',
taskDefinition: 'task:def:arn',
overrides: { containerOverrides: [{ name: 'someapp', command: 'somecmd' }] },
networkConfiguration: { awsvpcConfiguration: { subnets: ['a', 'b'], securityGroups: ['c', 'd'], assignPublicIp: "DISABLED" } }
networkConfiguration: { awsvpcConfiguration: { subnets: ['a', 'b'], securityGroups: ['c', 'd'], assignPublicIp: "DISABLED" } },
enableECSManagedTags: true
});
expect(core.setOutput).toHaveBeenNthCalledWith(2, 'run-task-arn', ["arn:aws:ecs:fake-region:account_id:task/arn"]);
});
Expand All @@ -1177,8 +1189,9 @@ describe('Deploy to ECS', () => {
.mockReturnValueOnce('somecluster') // cluster
.mockReturnValueOnce('true') // wait-for-service-stability
.mockReturnValueOnce('') // wait-for-minutes
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('') // desired-count
.mockReturnValueOnce('') // enable-ecs-managed-tags
.mockReturnValueOnce('true') // run-task
.mockReturnValueOnce('false') // wait-for-task-stopped
.mockReturnValueOnce('someJoe') // run-task-started-by
Expand All @@ -1200,15 +1213,17 @@ describe('Deploy to ECS', () => {
cluster: 'somecluster',
service: 'service-456',
taskDefinition: 'task:def:arn',
forceNewDeployment: false
forceNewDeployment: false,
enableECSManagedTags: false
});
expect(mockRunTask).toHaveBeenCalledWith({
startedBy: 'someJoe',
cluster: 'somecluster',
taskDefinition: 'task:def:arn',
launchType: 'EC2',
overrides: { containerOverrides: [{ name: 'someapp', command: 'somecmd' }] },
networkConfiguration: { awsvpcConfiguration: { subnets: ['a', 'b'], securityGroups: ['c', 'd'], assignPublicIp: "DISABLED" } }
networkConfiguration: { awsvpcConfiguration: { subnets: ['a', 'b'], securityGroups: ['c', 'd'], assignPublicIp: "DISABLED" } },
enableECSManagedTags: false
});
expect(core.setOutput).toHaveBeenNthCalledWith(2, 'run-task-arn', ["arn:aws:ecs:fake-region:account_id:task/arn"]);
});
Expand All @@ -1223,6 +1238,7 @@ describe('Deploy to ECS', () => {
.mockReturnValueOnce('') // wait-for-minutes
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('') // desired-count
.mockReturnValueOnce('') // enable-ecs-managed-tags
.mockReturnValueOnce('true') // run-task
.mockReturnValueOnce('true'); // wait-for-task-stopped

Expand All @@ -1244,6 +1260,7 @@ describe('Deploy to ECS', () => {
.mockReturnValueOnce('somecluster') // cluster
.mockReturnValueOnce('true') // wait-for-service-stability
.mockReturnValueOnce('') // wait-for-minutes
.mockReturnValueOnce('') // enable-ecs-managed-tags
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('') // desired-count
.mockReturnValueOnce('true') // run-task
Expand All @@ -1262,7 +1279,8 @@ describe('Deploy to ECS', () => {
taskDefinition: 'task:def:arn',
launchType: 'EC2',
overrides: { containerOverrides: [] },
networkConfiguration: null
networkConfiguration: null,
enableECSManagedTags: false
});
});

Expand Down Expand Up @@ -1317,8 +1335,9 @@ describe('Deploy to ECS', () => {
.mockReturnValueOnce('') // wait-for-minutes
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('') // desired-count
.mockReturnValueOnce('') // enable-ecs-managed-tags
.mockReturnValueOnce('true') // run-task
.mockReturnValueOnce('false'); // wait-for-task-stopped
.mockReturnValueOnce('false'); // wait-for-task-stopped

mockRunTask.mockImplementation(
() => Promise.resolve({
Expand Down Expand Up @@ -1427,4 +1446,4 @@ describe('Deploy to ECS', () => {
expect(core.setFailed).toHaveBeenNthCalledWith(1, 'Failed to register task definition in ECS: Could not parse');
expect(core.setFailed).toHaveBeenNthCalledWith(2, 'Could not parse');
});
});
});

0 comments on commit 5ae7be6

Please sign in to comment.