mirror of
https://github.com/morten-olsen/with-ssm.git
synced 2026-02-08 00:46:23 +01:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14c4d5c386 | ||
|
|
00786d5508 |
@@ -117,7 +117,7 @@ override the SSM-resolved values. To avoid this:
|
|||||||
|
|
||||||
- Use `.env.with-ssm` instead of `.env` for SSM references
|
- Use `.env.with-ssm` instead of `.env` for SSM references
|
||||||
- Or use environment variable substitution if your app supports it:
|
- Or use environment variable substitution if your app supports it:
|
||||||
`${API_KEY:-SSM:/myapp/api-key}`
|
`API_KEY=${API_KEY:-SSM:/myapp/api-key}`
|
||||||
|
|
||||||
### 🚀 Deployment Considerations
|
### 🚀 Deployment Considerations
|
||||||
|
|
||||||
|
|||||||
75
src/start.ts
75
src/start.ts
@@ -5,48 +5,41 @@ import { exec } from './utils/exec.js';
|
|||||||
import { getEnv } from './utils/env.js';
|
import { getEnv } from './utils/env.js';
|
||||||
import { replaceParams } from './utils/ssm.js';
|
import { replaceParams } from './utils/ssm.js';
|
||||||
|
|
||||||
const main = async () => {
|
const argv = await yargs(hideBin(process.argv))
|
||||||
const argv = await yargs(hideBin(process.argv))
|
.usage('Usage: $0 [options] -- <command>')
|
||||||
.usage('Usage: $0 [options] -- <command>')
|
.option('region', {
|
||||||
.option('region', {
|
type: 'string',
|
||||||
type: 'string',
|
description: 'The AWS region to use for SSM.',
|
||||||
description: 'The AWS region to use for SSM.',
|
})
|
||||||
})
|
.option('profile', {
|
||||||
.option('profile', {
|
type: 'string',
|
||||||
type: 'string',
|
description: 'The AWS profile to use from your credentials file.',
|
||||||
description: 'The AWS profile to use from your credentials file.',
|
})
|
||||||
})
|
.option('file', {
|
||||||
.option('file', {
|
alias: 'f',
|
||||||
alias: 'f',
|
type: 'string',
|
||||||
type: 'string',
|
description: 'The file to use for environment variables. (multiple files can be specified)',
|
||||||
description: 'The file to use for environment variables. (multiple files can be specified)',
|
default: ['.env', '.env.with-ssm'],
|
||||||
default: ['.env', '.env.with-ssm'],
|
})
|
||||||
})
|
.demandCommand(1, 'Error: You must provide a command to execute after --')
|
||||||
.demandCommand(1, 'Error: You must provide a command to execute after --')
|
.alias('h', 'help')
|
||||||
.alias('h', 'help')
|
.epilogue('For more information, check the documentation.')
|
||||||
.epilogue('For more information, check the documentation.')
|
.parse();
|
||||||
.parse();
|
|
||||||
|
|
||||||
const command = argv._[0] as string;
|
const command = argv._[0] as string;
|
||||||
const commandArgs = argv._.slice(1).map(String);
|
const commandArgs = argv._.slice(1).map(String);
|
||||||
|
|
||||||
if (!command) {
|
if (!command) {
|
||||||
console.error('No command provided');
|
console.error('No command provided');
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const files = argv.file && Array.isArray(argv.file) ? argv.file : [argv.file];
|
|
||||||
const hostEnv = await getEnv(files);
|
|
||||||
const env = await replaceParams(hostEnv);
|
|
||||||
|
|
||||||
exec({
|
|
||||||
command,
|
|
||||||
env,
|
|
||||||
args: commandArgs,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
main().catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = argv.file && Array.isArray(argv.file) ? argv.file : [argv.file];
|
||||||
|
const hostEnv = await getEnv(files);
|
||||||
|
const env = await replaceParams(hostEnv);
|
||||||
|
|
||||||
|
exec({
|
||||||
|
command,
|
||||||
|
env,
|
||||||
|
args: commandArgs,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
const splitArgs = (args: string[]) => {
|
|
||||||
const separatorIndex = args.indexOf('--');
|
|
||||||
const actionArgs = args.slice(0, separatorIndex);
|
|
||||||
const command = args[separatorIndex + 1];
|
|
||||||
const commandArgs = args.slice(separatorIndex + 2);
|
|
||||||
|
|
||||||
return {
|
|
||||||
actionArgs,
|
|
||||||
command,
|
|
||||||
commandArgs,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export { splitArgs };
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { GetParametersCommand, SSMClient } from '@aws-sdk/client-ssm';
|
import { GetParametersCommand, SSMClient, type Parameter } from '@aws-sdk/client-ssm';
|
||||||
|
|
||||||
import { debug } from './debug.js';
|
import { debug } from './debug.js';
|
||||||
|
|
||||||
@@ -30,18 +30,42 @@ const replaceParams = async (
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
const command = new GetParametersCommand({
|
// Chunk names into groups of 10 (AWS SSM GetParametersCommand limit)
|
||||||
Names: names,
|
const chunks: string[][] = [];
|
||||||
WithDecryption: true,
|
debug(`Chunking ${names.length} names into groups of 10`);
|
||||||
});
|
for (let i = 0; i < names.length; i += 10) {
|
||||||
|
chunks.push(names.slice(i, i + 10));
|
||||||
|
}
|
||||||
|
|
||||||
const response = await ssm.send(command);
|
debug(`Processing ${chunks.length} chunks`);
|
||||||
if (response.InvalidParameters?.length || 0 > 0) {
|
|
||||||
console.error('Invalid SSM parameters', response.InvalidParameters);
|
// Fetch parameters in chunks and combine results
|
||||||
|
const allParams: Parameter[] = [];
|
||||||
|
const allInvalidParams: string[] = [];
|
||||||
|
|
||||||
|
for (const chunk of chunks) {
|
||||||
|
const command = new GetParametersCommand({
|
||||||
|
Names: chunk,
|
||||||
|
WithDecryption: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await ssm.send(command);
|
||||||
|
|
||||||
|
if (response.Parameters) {
|
||||||
|
allParams.push(...response.Parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.InvalidParameters) {
|
||||||
|
allInvalidParams.push(...response.InvalidParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allInvalidParams.length > 0) {
|
||||||
|
console.error('Invalid SSM parameters', allInvalidParams);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = response.Parameters ?? [];
|
const params = allParams;
|
||||||
|
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(env).map(([key, value]) => {
|
Object.entries(env).map(([key, value]) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user