Skip to content

Commit

Permalink
feat: support dockerLabels (#274)
Browse files Browse the repository at this point in the history
* support dockerLabels

Signed-off-by: John Seekins <john.seekins@pathccm.com>

* fix broken tests and slightly increase test coverage

Signed-off-by: John Seekins <john.seekins@pathccm.com>

---------

Signed-off-by: John Seekins <john.seekins@pathccm.com>
  • Loading branch information
johnseekins-pathccm authored Oct 23, 2023
1 parent b8492cb commit b9718e5
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ input of the second:
environment-variables: |
LOG_LEVEL=info
ENVIRONMENT=prod
docker-labels: |
SERVICE=service
VERSION=version
- name: Modify Amazon ECS task definition with second container
id: render-app-container
Expand Down
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ inputs:
log-configuration-options:
description: "Create/Override options inside logConfiguration. Each variable is of the form key=value, you can specify multiple variables with multi-line YAML strings."
required: false
docker-labels:
description: "Create/Override options inside dockerLabels. Each variable is key=value, you can specify multiple variables with multi-line YAML."
required: false
outputs:
task-definition:
description: 'The path to the rendered task definition file'
Expand Down
19 changes: 19 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ async function run() {

const logConfigurationLogDriver = core.getInput("log-configuration-log-driver", { required: false });
const logConfigurationOptions = core.getInput("log-configuration-options", { required: false });
const dockerLabels = core.getInput('docker-labels', { required: false });

// Parse the task definition
const taskDefPath = path.isAbsolute(taskDefinitionFile) ?
Expand Down Expand Up @@ -103,6 +104,24 @@ async function run() {
})
}

if (dockerLabels) {
// If dockerLabels object is missing, create it
if (!containerDef.dockerLabels) { containerDef.dockerLabels = {} }

// Get pairs by splitting on newlines
dockerLabels.split('\n').forEach(function (label) {
// Trim whitespace
label = label.trim();
if (label && label.length) {
if (label.indexOf("=") == -1 ) {
throw new Error(`Can't parse logConfiguration option ${label}. Must be in key=value format, one per line`);
}
const [key, value] = label.split("=");
containerDef.dockerLabels[key] = value;
}
})
}

// Write out a new task definition file
var updatedTaskDefFile = tmp.fileSync({
tmpdir: process.env.RUNNER_TEMP,
Expand Down
19 changes: 19 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ async function run() {

const logConfigurationLogDriver = core.getInput("log-configuration-log-driver", { required: false });
const logConfigurationOptions = core.getInput("log-configuration-options", { required: false });
const dockerLabels = core.getInput('docker-labels', { required: false });

// Parse the task definition
const taskDefPath = path.isAbsolute(taskDefinitionFile) ?
Expand Down Expand Up @@ -97,6 +98,24 @@ async function run() {
})
}

if (dockerLabels) {
// If dockerLabels object is missing, create it
if (!containerDef.dockerLabels) { containerDef.dockerLabels = {} }

// Get pairs by splitting on newlines
dockerLabels.split('\n').forEach(function (label) {
// Trim whitespace
label = label.trim();
if (label && label.length) {
if (label.indexOf("=") == -1 ) {
throw new Error(`Can't parse logConfiguration option ${label}. Must be in key=value format, one per line`);
}
const [key, value] = label.split("=");
containerDef.dockerLabels[key] = value;
}
})
}

// Write out a new task definition file
var updatedTaskDefFile = tmp.fileSync({
tmpdir: process.env.RUNNER_TEMP,
Expand Down
99 changes: 99 additions & 0 deletions index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,105 @@ describe('Render task definition', () => {
expect(core.setFailed).toBeCalledWith('Task definition file does not exist: does-not-exist-task-definition.json');
});

test('renders a task definition with docker labels', async () => {
core.getInput = jest
.fn()
.mockReturnValueOnce('task-definition.json')
.mockReturnValueOnce('web')
.mockReturnValueOnce('nginx:latest')
.mockReturnValueOnce('EXAMPLE=here')
.mockReturnValueOnce('awslogs')
.mockReturnValueOnce('awslogs-create-group=true\nawslogs-group=/ecs/web\nawslogs-region=us-east-1\nawslogs-stream-prefix=ecs')
.mockReturnValueOnce('key1=value1\nkey2=value2');

await run();

expect(tmp.fileSync).toHaveBeenNthCalledWith(1, {
tmpdir: '/home/runner/work/_temp',
prefix: 'task-definition-',
postfix: '.json',
keep: true,
discardDescriptor: true
});

expect(fs.writeFileSync).toHaveBeenNthCalledWith(1, 'new-task-def-file-name',
JSON.stringify({
family: 'task-def-family',
containerDefinitions: [
{
name: "web",
image: "nginx:latest",
environment: [
{
name: "FOO",
value: "bar"
},
{
name: "DONT-TOUCH",
value: "me"
},
{
name: "HELLO",
value: "world"
},
{
name: "EXAMPLE",
value: "here"
}
],
logConfiguration: {
logDriver: "awslogs",
options: {
"awslogs-create-group": "true",
"awslogs-group": "/ecs/web",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
},
dockerLabels : {
"key1":"value1",
"key2":"value2"
}
},
{
name: "sidecar",
image: "hello"
}
]
}, null, 2)
);
});

test('renders a task definition at an absolute path with bad docker labels', async () => {
core.getInput = jest
.fn()
.mockReturnValueOnce('/hello/task-definition.json')
.mockReturnValueOnce('web')
.mockReturnValueOnce('nginx:latest')
.mockReturnValueOnce('EXAMPLE=here')
.mockReturnValueOnce('awslogs')
.mockReturnValueOnce('awslogs-create-group=true\nawslogs-group=/ecs/web\nawslogs-region=us-east-1\nawslogs-stream-prefix=ecs')
.mockReturnValueOnce('key1=update_value1\nkey2\nkey3=value3');

jest.mock('/hello/task-definition.json', () => ({
family: 'task-def-family',
containerDefinitions: [
{
name: "web",
image: "some-other-image",
dockerLabels : {
"key1":"value1",
"key2":"value2"
}
}
]
}), { virtual: true });

await run();

expect(core.setFailed).toBeCalledWith('Can\'t parse logConfiguration option key2. Must be in key=value format, one per line');
});

test('error returned for non-JSON task definition contents', async () => {
jest.mock('./non-json-task-definition.json', () => ("hello"), { virtual: true });

Expand Down

0 comments on commit b9718e5

Please sign in to comment.