Skip to content

Commit 46a24f1

Browse files
NahutabDevelopjnyoNahutabDevelop
authored
fix: allow secrets to render without environment-variables (#464)
* fix: separate envFiles and secrets condition checks to avoid unintended nesting * test: add test for secrets without environment-variables --------- Co-authored-by: Junya (@jnyo) <jnyo@users.noreply.github.com> Co-authored-by: NahutabDevelop <baykac@amazon.com>
1 parent cdf43c3 commit 46a24f1

3 files changed

Lines changed: 135 additions & 73 deletions

File tree

dist/index.js

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -177,45 +177,45 @@ async function run() {
177177
containerDef.environment.push(variable);
178178
}
179179
})
180+
}
180181

181-
if (secrets) {
182-
// If secrets array is missing, create it
183-
if (!Array.isArray(containerDef.secrets)) {
184-
containerDef.secrets = [];
185-
}
186-
187-
// Get pairs by splitting on newlines
188-
secrets.split('\n').forEach(function (line) {
189-
// Trim whitespace
190-
const trimmedLine = line.trim();
191-
// Skip if empty
192-
if (trimmedLine.length === 0) { return; }
193-
// Split on =
194-
const separatorIdx = trimmedLine.indexOf("=");
195-
// If there's nowhere to split
196-
if (separatorIdx === -1) {
197-
throw new Error(
198-
`Cannot parse the secret '${trimmedLine}'. Secret pairs must be of the form NAME=valueFrom,
199-
where valueFrom is an arn from parameter store or secrets manager. See AWS documentation for more information:
200-
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html.`);
201-
}
202-
// Build object
203-
const secret = {
204-
name: trimmedLine.substring(0, separatorIdx),
205-
valueFrom: trimmedLine.substring(separatorIdx + 1),
206-
};
207-
208-
// Search container definition environment for one matching name
209-
const secretDef = containerDef.secrets.find((s) => s.name == secret.name);
210-
if (secretDef) {
211-
// If found, update
212-
secretDef.valueFrom = secret.valueFrom;
213-
} else {
214-
// Else, create
215-
containerDef.secrets.push(secret);
216-
}
217-
})
182+
if (secrets) {
183+
// If secrets array is missing, create it
184+
if (!Array.isArray(containerDef.secrets)) {
185+
containerDef.secrets = [];
218186
}
187+
188+
// Get pairs by splitting on newlines
189+
secrets.split('\n').forEach(function (line) {
190+
// Trim whitespace
191+
const trimmedLine = line.trim();
192+
// Skip if empty
193+
if (trimmedLine.length === 0) { return; }
194+
// Split on =
195+
const separatorIdx = trimmedLine.indexOf("=");
196+
// If there's nowhere to split
197+
if (separatorIdx === -1) {
198+
throw new Error(
199+
`Cannot parse the secret '${trimmedLine}'. Secret pairs must be of the form NAME=valueFrom,
200+
where valueFrom is an arn from parameter store or secrets manager. See AWS documentation for more information:
201+
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html.`);
202+
}
203+
// Build object
204+
const secret = {
205+
name: trimmedLine.substring(0, separatorIdx),
206+
valueFrom: trimmedLine.substring(separatorIdx + 1),
207+
};
208+
209+
// Search container definition environment for one matching name
210+
const secretDef = containerDef.secrets.find((s) => s.name == secret.name);
211+
if (secretDef) {
212+
// If found, update
213+
secretDef.valueFrom = secret.valueFrom;
214+
} else {
215+
// Else, create
216+
containerDef.secrets.push(secret);
217+
}
218+
})
219219
}
220220

221221
if (logConfigurationLogDriver) {

index.js

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -171,45 +171,45 @@ async function run() {
171171
containerDef.environment.push(variable);
172172
}
173173
})
174+
}
174175

175-
if (secrets) {
176-
// If secrets array is missing, create it
177-
if (!Array.isArray(containerDef.secrets)) {
178-
containerDef.secrets = [];
179-
}
176+
if (secrets) {
177+
// If secrets array is missing, create it
178+
if (!Array.isArray(containerDef.secrets)) {
179+
containerDef.secrets = [];
180+
}
180181

181-
// Get pairs by splitting on newlines
182-
secrets.split('\n').forEach(function (line) {
183-
// Trim whitespace
184-
const trimmedLine = line.trim();
185-
// Skip if empty
186-
if (trimmedLine.length === 0) { return; }
187-
// Split on =
188-
const separatorIdx = trimmedLine.indexOf("=");
189-
// If there's nowhere to split
190-
if (separatorIdx === -1) {
191-
throw new Error(
192-
`Cannot parse the secret '${trimmedLine}'. Secret pairs must be of the form NAME=valueFrom,
193-
where valueFrom is an arn from parameter store or secrets manager. See AWS documentation for more information:
194-
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html.`);
195-
}
196-
// Build object
197-
const secret = {
198-
name: trimmedLine.substring(0, separatorIdx),
199-
valueFrom: trimmedLine.substring(separatorIdx + 1),
200-
};
182+
// Get pairs by splitting on newlines
183+
secrets.split('\n').forEach(function (line) {
184+
// Trim whitespace
185+
const trimmedLine = line.trim();
186+
// Skip if empty
187+
if (trimmedLine.length === 0) { return; }
188+
// Split on =
189+
const separatorIdx = trimmedLine.indexOf("=");
190+
// If there's nowhere to split
191+
if (separatorIdx === -1) {
192+
throw new Error(
193+
`Cannot parse the secret '${trimmedLine}'. Secret pairs must be of the form NAME=valueFrom,
194+
where valueFrom is an arn from parameter store or secrets manager. See AWS documentation for more information:
195+
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html.`);
196+
}
197+
// Build object
198+
const secret = {
199+
name: trimmedLine.substring(0, separatorIdx),
200+
valueFrom: trimmedLine.substring(separatorIdx + 1),
201+
};
201202

202-
// Search container definition environment for one matching name
203-
const secretDef = containerDef.secrets.find((s) => s.name == secret.name);
204-
if (secretDef) {
205-
// If found, update
206-
secretDef.valueFrom = secret.valueFrom;
207-
} else {
208-
// Else, create
209-
containerDef.secrets.push(secret);
210-
}
211-
})
212-
}
203+
// Search container definition environment for one matching name
204+
const secretDef = containerDef.secrets.find((s) => s.name == secret.name);
205+
if (secretDef) {
206+
// If found, update
207+
secretDef.valueFrom = secret.valueFrom;
208+
} else {
209+
// Else, create
210+
containerDef.secrets.push(secret);
211+
}
212+
})
213213
}
214214

215215
if (logConfigurationLogDriver) {

index.test.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,4 +1003,66 @@ describe('Render task definition', () => {
10031003
}, null, 2)
10041004
);
10051005
});
1006+
1007+
test('renders secrets without environment-variables', async () => {
1008+
core.getInput = jest
1009+
.fn()
1010+
.mockReturnValueOnce('/hello/secrets-only-task-definition.json') // task-definition
1011+
.mockReturnValueOnce('web') // container-name
1012+
.mockReturnValueOnce('nginx:latest') // image
1013+
.mockReturnValueOnce('') // environment-variables
1014+
.mockReturnValueOnce('') // env-files
1015+
.mockReturnValueOnce('') // log Configuration Log Driver
1016+
.mockReturnValueOnce('') // log Configuration Options
1017+
.mockReturnValueOnce('') // docker labels
1018+
.mockReturnValueOnce('') // command
1019+
.mockReturnValueOnce('') // task-definition arn
1020+
.mockReturnValueOnce('') // task-definition family
1021+
.mockReturnValueOnce('') // task-definition revision
1022+
.mockReturnValueOnce( // secrets
1023+
'MY_SECRET=arn:aws:secretsmanager:us-east-1:123456789:secret:my-secret\nDB_PASSWORD=arn:aws:ssm:us-east-1:123456789:parameter/db-password'
1024+
);
1025+
1026+
jest.mock('/hello/secrets-only-task-definition.json', () => ({
1027+
family: 'task-def-family',
1028+
containerDefinitions: [
1029+
{
1030+
name: "web",
1031+
image: "some-other-image"
1032+
}
1033+
]
1034+
}), { virtual: true });
1035+
1036+
await run();
1037+
1038+
expect(tmp.fileSync).toHaveBeenNthCalledWith(1, {
1039+
tmpdir: '/home/runner/work/_temp',
1040+
prefix: 'task-definition-',
1041+
postfix: '.json',
1042+
keep: true,
1043+
discardDescriptor: true
1044+
});
1045+
expect(fs.writeFileSync).toHaveBeenNthCalledWith(1, 'new-task-def-file-name',
1046+
JSON.stringify({
1047+
family: 'task-def-family',
1048+
containerDefinitions: [
1049+
{
1050+
name: "web",
1051+
image: "nginx:latest",
1052+
secrets: [
1053+
{
1054+
name: "MY_SECRET",
1055+
valueFrom: "arn:aws:secretsmanager:us-east-1:123456789:secret:my-secret"
1056+
},
1057+
{
1058+
name: "DB_PASSWORD",
1059+
valueFrom: "arn:aws:ssm:us-east-1:123456789:parameter/db-password"
1060+
}
1061+
]
1062+
}
1063+
]
1064+
}, null, 2)
1065+
);
1066+
expect(core.setOutput).toHaveBeenNthCalledWith(1, 'task-definition', 'new-task-def-file-name');
1067+
});
10061068
});

0 commit comments

Comments
 (0)