Skip to content

Commit

Permalink
feat: delete parameters in ssm store
Browse files Browse the repository at this point in the history
  • Loading branch information
kyle-ruan authored and patrickshiel committed Aug 27, 2021
1 parent 5d74b1f commit 7e0d65e
Show file tree
Hide file tree
Showing 37 changed files with 264 additions and 74 deletions.
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
nodejs 12.14.0
nodejs 14.15.4
direnv 2.28.0
28 changes: 28 additions & 0 deletions lib/commands/configure/make-cleanup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const get = require('lodash/get');
const property = require('lodash/property');

const makeCleanup = ({ parameterStore }) => async ({ settings }) => {
const configPath = get(settings, 'config.path');
const secretPath = get(settings, 'secret.path');
const parameters = await Promise.all([
parameterStore.getAllParameters({ path: configPath }),
parameterStore.getAllParameters({ path: secretPath })
]).then(([configs, secrets]) => [
...Object.values(configs),
...Object.values(secrets)
]);

const { configParameters = [], secretParameters = [] } = settings;
const unusedParameters = parameters.filter(
({ Name }) => ![...configParameters, ...secretParameters].includes(Name)
);

return (
unusedParameters.length &&
parameterStore.deleteParameters({
parameterNames: unusedParameters.map(property('Name'))
})
);
};

module.exports = { makeCleanup };
2 changes: 1 addition & 1 deletion lib/commands/configure/make-populate-config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const get = require('lodash.get');
const get = require('lodash/get');
const chalk = require('chalk');

const { log } = require('../../utils/logger');
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/configure/make-populate-secret.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const chalk = require('chalk');
const get = require('lodash.get');
const get = require('lodash/get');

const { log } = require('../../utils/logger');

Expand Down
2 changes: 1 addition & 1 deletion lib/commands/configure/make-prompt-required-configs.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// TODO: this file needs a lot of tests
const get = require('lodash.get');
const get = require('lodash/get');
const { promptForValues } = require('./prompt-for-values');
const { validateExistingValues } = require('./validate-existing-values');

Expand Down
2 changes: 1 addition & 1 deletion lib/commands/configure/prompt-for-values.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const get = require('lodash.get');
const get = require('lodash/get');
const chalk = require('chalk');
const prompt = require('prompt');

Expand Down
2 changes: 1 addition & 1 deletion lib/commands/fetch/make-fetch.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const get = require('lodash.get');
const get = require('lodash/get');

const makeFetch = ({ parameterStore, settingsService }) => ({ keys }) =>
settingsService
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/import-export/make-export.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const chalk = require('chalk');
const get = require('lodash.get');
const get = require('lodash/get');
const fs = require('fs');

const { log } = require('../../utils/logger');
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/import-export/make-import.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const chalk = require('chalk');
const get = require('lodash.get');
const get = require('lodash/get');
const fs = require('fs');

const { log } = require('../../utils/logger');
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/init/make-init.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const get = require('lodash.get');
const get = require('lodash/get');
const chalk = require('chalk');
const { log } = require('../../utils/logger');

Expand Down
2 changes: 1 addition & 1 deletion lib/commands/list/make-list.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const chalk = require('chalk');
const get = require('lodash.get');
const get = require('lodash/get');

const { log } = require('../../utils/logger');
const { listParameters } = require('./list-parameters');
Expand Down
2 changes: 1 addition & 1 deletion lib/services/cf/get-outputs.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const get = require('lodash.get');
const get = require('lodash/get');
const AWS = require('aws-sdk');

AWS.config.update({ region: 'us-east-1' });
Expand Down
15 changes: 15 additions & 0 deletions lib/services/parameter-store/make-delete-parameters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const chalk = require('chalk');
const { log } = require('../../utils/logger');

const makeDeleteParameters = ({ getProviderStore }) => async ({
parameterNames
}) => {
log(chalk.gray(`Deleting unused parameters...`));
const providerStore = await getProviderStore();

return providerStore
.deleteParameters({ parameterNames })
.then(() => log(chalk.gray('Parameters deleted')));
};

module.exports = { makeDeleteParameters };
15 changes: 15 additions & 0 deletions lib/services/parameter-store/make-get-all-parameters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const { sortParameters } = require('./sort-parameters');

const makeGetAllParameters = ({ getProviderStore }) => async ({ path }) => {
if (!path) {
throw new Error('Missing path!');
}

const providerStore = await getProviderStore();

const parameters = await providerStore.getAllParametersByPath({ path });

return sortParameters(parameters);
};

module.exports = { makeGetAllParameters };
4 changes: 3 additions & 1 deletion lib/services/parameter-store/make-get-parameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ const makeGetParameters = ({ getProviderStore }) => ({
}

return getProviderStore()
.then(providerStore => providerStore.getAllParameters({ parameterNames }))
.then(providerStore =>
providerStore.getAllParametersByNames({ parameterNames })
)
.then(sortParameters);
};

Expand Down
2 changes: 1 addition & 1 deletion lib/services/parameter-store/make-get-parameters.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { makeGetParameters } = require('./make-get-parameters');
const getParameters = makeGetParameters({
getProviderStore: () =>
Promise.resolve({
getAllParameters: mockGetAllParameters
getAllParametersByNames: mockGetAllParameters
})
});
describe('getParameters', () => {
Expand Down
2 changes: 1 addition & 1 deletion lib/services/parameter-store/make-get-provider-store.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const get = require('lodash.get');
const get = require('lodash/get');
const { makeSsmStore } = require('./stores/ssm/make-ssm-store');

const makeGetProviderStore = ({ settingsService }) => () =>
Expand Down
8 changes: 7 additions & 1 deletion lib/services/parameter-store/make-parameter-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@ const { makeGetProviderStore } = require('./make-get-provider-store');
const { makeUpdateSecrets } = require('./make-update-secrets');
const { makeUpdateConfigs } = require('./make-update-configs');
const { makeGetParameters } = require('./make-get-parameters');
const { makeGetAllParameters } = require('./make-get-all-parameters');
const { makeDeleteParameters } = require('./make-delete-parameters');

const makeParameterStore = ({ settingsService }) => {
const getProviderStore = makeGetProviderStore({ settingsService });
const updateSecrets = makeUpdateSecrets({ getProviderStore });
const updateConfigs = makeUpdateConfigs({ getProviderStore });
const getParameters = makeGetParameters({ getProviderStore });
const getAllParameters = makeGetAllParameters({ getProviderStore });
const deleteParameters = makeDeleteParameters({ getProviderStore });

return {
updateConfigs,
updateSecrets,
getParameters
getParameters,
getAllParameters,
deleteParameters
};
};

Expand Down
18 changes: 18 additions & 0 deletions lib/services/parameter-store/stores/ssm/delete-parameters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const chunk = require('lodash/chunk');
const { getSsmClient } = require('./get-ssm-client');

const deleteParameters = ({ parameterNames }) => {
const ssm = getSsmClient();

const chunks = chunk(parameterNames, 10);
const promises = chunks.map(chunkedParameterNames =>
ssm
.deleteParameters({
Names: chunkedParameterNames
})
.promise()
);
return Promise.all(promises);
};

module.exports = { deleteParameters };
23 changes: 23 additions & 0 deletions lib/services/parameter-store/stores/ssm/delete-parameters.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const mockDeleteParameters = jest.fn().mockImplementation(() => ({
promise: () => Promise.resolve({})
}));

const AWS = require('aws-sdk');

AWS.SSM.mockImplementation(() => ({
deleteParameters: mockDeleteParameters
}));

const { makeSsmStore } = require('./make-ssm-store');

describe('deleteParameters', () => {
it('should delete parameters in batches', async () => {
const parameterNames = [...Array(35).keys()].map(key => `/test/${key}`);

const ssm = makeSsmStore();

await ssm.deleteParameters({ parameterNames });

expect(mockDeleteParameters.mock.calls.length).toEqual(4);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const { getSsmClient } = require('./get-ssm-client');

const ssm = getSsmClient();

const getParametersByPathRecursively = async params => {
const data = await ssm.getParametersByPath(params).promise();

let parameters = data.Parameters || [];

if (data.NextToken) {
const nextParameters = await getParametersByPathRecursively({
...params,
NextToken: data.NextToken
});
parameters = parameters.concat(nextParameters);
}

return parameters;
};

const getAllParametersByPath = async ({ path }) => {
const allParameters = await getParametersByPathRecursively({
Path: path,
Recursive: true
});

return allParameters;
};

module.exports = { getAllParametersByPath };
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const mockGetParametersByPath = jest
.fn()
.mockImplementationOnce(() => ({
promise: () =>
Promise.resolve({
Parameters: [
{
Name: 'TEST/ONE',
Value: '1'
}
],
NextToken: 'first-token'
})
}))
.mockImplementationOnce(() => ({
promise: () =>
Promise.resolve({
Parameters: [
{
Name: 'TEST/TWO',
Value: '2'
}
],
NextToken: 'second-token'
})
}))
.mockImplementationOnce(() => ({
promise: () =>
Promise.resolve({
Parameters: [
{
Name: 'TEST/THREE',
Value: '1'
}
]
})
}));

const AWS = require('aws-sdk');

AWS.SSM.mockImplementation(() => ({
getParametersByPath: mockGetParametersByPath
}));

const { makeSsmStore } = require('./make-ssm-store');

describe('getAllParameterByPath', () => {
it('should get parameters recursively', async () => {
const ssm = makeSsmStore();
const parameters = await ssm.getAllParametersByPath({ path: 'TEST' });
expect(parameters).toEqual([
{
Name: 'TEST/ONE',
Value: '1'
},
{
Name: 'TEST/TWO',
Value: '2'
},
{
Name: 'TEST/THREE',
Value: '1'
}
]);
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const get = require('lodash.get');
const get = require('lodash/get');
const { getSsmClient } = require('./get-ssm-client');

const getParametersFromSSM = ({ parameterNames }) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const get = require('lodash.get');
const get = require('lodash/get');

const makeGetAllParameters = ({ loader }) => ({ parameterNames }) =>
const makeGetAllParametersByNames = ({ loader }) => ({ parameterNames }) =>
loader.loadMany(parameterNames).then(parameters =>
parameters.reduce((acc, parameter, index) => {
const parameterPath = get(parameterNames, index) || '';
Expand All @@ -18,5 +18,5 @@ const makeGetAllParameters = ({ loader }) => ({ parameterNames }) =>
);

module.exports = {
makeGetAllParameters
makeGetAllParametersByNames
};
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ AWS.SSM.mockImplementation(() => ({

const { makeSsmStore } = require('./make-ssm-store');

describe('getAllParameters', () => {
describe('getAllParametersByNames', () => {
let resultPromise;

beforeAll(() => {
const ssmStore = makeSsmStore();
const { getAllParameters } = ssmStore;
resultPromise = getAllParameters({
const { getAllParametersByNames } = ssmStore;
resultPromise = getAllParametersByNames({
parameterNames: [
'TEST/ONE',
'TEST/TWO',
Expand Down
24 changes: 19 additions & 5 deletions lib/services/parameter-store/stores/ssm/make-ssm-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,33 @@ const DataLoader = require('dataloader');
const { makeUpdateConfigs } = require('./make-update-configs');
const { makeUpdateSecrets } = require('./make-update-secrets');
const { getBatchParameters } = require('./get-batch-parameters');
const { makeGetAllParameters } = require('./make-get-all-parameters');
const {
makeGetAllParametersByNames
} = require('./make-get-all-parameters-by-names');
const { getAllParametersByPath } = require('./get-all-parameters-by-path');
const { deleteParameters } = require('./delete-parameters');

const makeSsmStore = () => {
const ssmLoader = new DataLoader(keys =>
getBatchParameters({ parameterNames: keys })
);
const getAllParameters = makeGetAllParameters({ loader: ssmLoader });
const getAllParametersByNames = makeGetAllParametersByNames({
loader: ssmLoader
});
const getLatestVersion = key => ssmLoader.load(key);

return {
getAllParameters,
updateConfigs: makeUpdateConfigs({ getAllParameters, getLatestVersion }),
updateSecrets: makeUpdateSecrets({ getAllParameters, getLatestVersion })
getAllParametersByPath,
getAllParametersByNames,
updateConfigs: makeUpdateConfigs({
getAllParametersByNames,
getLatestVersion
}),
updateSecrets: makeUpdateSecrets({
getAllParametersByNames,
getLatestVersion
}),
deleteParameters
};
};

Expand Down
Loading

0 comments on commit 7e0d65e

Please sign in to comment.