Skip to content

Commit

Permalink
ADDED: Import and export command, no tests provided (#9)
Browse files Browse the repository at this point in the history
* ADDED: Import and export command, no tests provided

* ADDED: Tests

* FIXED: Dependency

* ADDED: Change message

* RELEASE: 2.3.1

* FIXED: Dependency
  • Loading branch information
Compulsed authored Feb 3, 2019
1 parent 1b71265 commit 7a5e014
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 3 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [v2.3.1](2019-02-04)

### Added
- `import` & `export` command to import/export key values from specified provider

## [v2.3.0](2019-02-01)

### Changed
Expand Down
31 changes: 30 additions & 1 deletion bin/oprah
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
const chalk = require('chalk');
const pjson = require('../package.json');
const program = require('commander');
const Bluebird = require('bluebird');
const { makeOprah } = require('../lib/make-oprah');
const { logError, log } = require('../lib/utils/logger');

Expand Down Expand Up @@ -54,13 +55,41 @@ program
oprahPromise = makeOprah(params).init();
});

program
.command('export')
.description('Export of all of the configuration from the provider to a text json file')
.option('-p, --path [path]', 'The location for the output secrets & configuration file (default: "/tmp/oprah-exports.json")')
.action(({ path }) => {
const params = {
stage: program.stage,
config: program.config,
};

oprahPromise = makeOprah(params)
.export(path || '/tmp/oprah-exports.json');
});

program
.command('import')
.description('Import all of the configuration from the json from to a provider')
.option('-p, --path [path]', 'The location of the secrets and configuration file (default: "/tmp/oprah-exports.json")')
.action(({ path }) => {
const params = {
stage: program.stage,
config: program.config,
};

oprahPromise = makeOprah(params)
.import(path || '/tmp/oprah-exports.json');
});

program
.command('list')
.description('List all remote configurations and secrets.')
.action(() => {
const params = {
stage: program.stage,
config: program.config
config: program.config,
};

oprahPromise = makeOprah(params).list();
Expand Down
36 changes: 36 additions & 0 deletions lib/commands/import-export/make-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';

const chalk = require('chalk');
const get = require('lodash.get');
const fs = require('fs');

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

const makeExport = ({ settingsService, parameterStore }) => {
return (filePath) => settingsService.getSettings()
.tap(() => log(chalk.white(`Getting parameters..`)))
.then(settings => {
const secretsPromise = parameterStore.getParameters({
parameterNames: get(settings, 'secretParameters')
});

const configsPromise = parameterStore.getParameters({
parameterNames: get(settings, 'configParameters')
});

return Promise.all([ secretsPromise, configsPromise ]);
})
.tap(() => log(chalk.white(`Saving parameters to: ${filePath}`)))
.then(([ secrets, configs ]) => {
const writeOutput = {
configs,
secrets,
};

fs.writeFileSync(filePath, JSON.stringify(writeOutput, null, 2));
});
};

module.exports = {
makeExport,
};
62 changes: 62 additions & 0 deletions lib/commands/import-export/make-export.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const { makeExport } = require('./make-export');

const Bluebird = require('bluebird');

const fs = require('fs');

jest.mock('fs', () => ({
writeFileSync: jest.fn(),
}));

describe('export', () => {
let exportFunction;
const getSettingsMock = jest.fn();
const getParametersMock = jest.fn();

beforeEach(() => {
exportFunction = makeExport({
settingsService: {
getSettings: getSettingsMock,
},
parameterStore: {
getParameters: getParametersMock,
},
});
});

it('should write to the specified file path', () => {
getSettingsMock.mockImplementation(() => Bluebird.resolve({
secretParameters: [
'path/to/secret1',
],
configParameters: [
'path/to/config1',
]
}));

getParametersMock
.mockImplementationOnce(() => Bluebird.resolve({
'path/to/secret1': 'secret1Value',
}))
.mockImplementationOnce(() => Bluebird.resolve({
'path/to/config1': 'config1Value',
}));

const filePath = './test.json';

return exportFunction(filePath)
.then(() => {
const writeOutput = {
configs: {
'path/to/config1': 'config1Value',
},
secrets: {
'path/to/secret1': 'secret1Value',
},
};

expect(fs.writeFileSync)
.toHaveBeenCalledWith(filePath, JSON.stringify(writeOutput, null, 2))
});
});
});
56 changes: 56 additions & 0 deletions lib/commands/import-export/make-import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
'use strict';

const chalk = require('chalk');
const get = require('lodash.get');
const fs = require('fs');
const mapKeys = require('lodash.mapkeys');

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

const configurationImport = (parameterStore, settings, importedConfig) => {
const path = get(settings, 'config.path')

const configurationParameters = mapKeys(importedConfig, (_, key) => {
return `${path}/${key}`;
});

return parameterStore.updateConfigs({
parameters: configurationParameters
});
};

const secretImport = (parameterStore, settings, importedSecrets) => {
const path = get(settings, 'secret.path');

const secretParameters = mapKeys(importedSecrets, (_, key) => {
return `${path}/${key}`;
});

return parameterStore.updateSecrets({
parameters: secretParameters
});
};

const makeImport = ({ settingsService, parameterStore }) => {
return (filePath) => settingsService.getSettings()
.tap(() => log(chalk.white(`Getting parameters from: ${filePath}`)))
.then(settings => {
const importedExport = JSON.parse(fs.readFileSync(filePath));

return { settings, importedExport };
})
.then(({ settings, importedExport }) => {
const importedConfig = get(importedExport, 'configs', {});
const importedSecrets = get(importedExport, 'secrets', {});

return Promise.all([
configurationImport(parameterStore, settings, importedConfig),
secretImport(parameterStore, settings, importedSecrets),
]);
})
.tap(() => log(chalk.white(`Saved parameters to provider`)))
};

module.exports = {
makeImport,
};
86 changes: 86 additions & 0 deletions lib/commands/import-export/make-import.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
const { makeImport } = require('./make-import');

const Bluebird = require('bluebird');

const fs = require('fs');

jest.mock('fs', () => ({
readFileSync: jest.fn(),
}));

describe('import', () => {
let importFunction;
const getSettingsMock = jest.fn();
const updateConfigsMock = jest.fn();
const updateSecretsMock = jest.fn();

beforeEach(() => {
importFunction = makeImport({
settingsService: {
getSettings: getSettingsMock,
},
parameterStore: {
updateConfigs: updateConfigsMock,
updateSecrets: updateSecretsMock,
},
});
});

it('should write to the specified file path', () => {
const readResult = {
configs: {
'path/to/config1': 'config1Value',
},
secrets: {
'path/to/secret1': 'secret1Value',
},
};

getSettingsMock.mockImplementation(() => Bluebird.resolve({
config: {
path: 'service/path',
},
secret: {
path: 'service/path',
},
secretParameters: [
'path/to/secret1',
],
configParameters: [
'path/to/config1',
]
}));

updateConfigsMock
.mockImplementation(() => Bluebird.resolve());

updateSecretsMock
.mockImplementation(() => Bluebird.resolve());

fs
.readFileSync
.mockImplementation(() => JSON.stringify(readResult, null, 2));

const filePath = './test.json';

return importFunction(filePath)
.then(() => {
expect(fs.readFileSync)
.toHaveBeenCalledWith(filePath);

expect(updateConfigsMock)
.toHaveBeenCalledWith({
parameters: {
'service/path/path/to/config1': 'config1Value'
}
})

expect(updateSecretsMock)
.toHaveBeenCalledWith({
parameters: {
'service/path/path/to/secret1': 'secret1Value',
}
});
});
});
});
6 changes: 5 additions & 1 deletion lib/make-oprah.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ const path = require('path');
const { log } = require('../lib/utils/logger');
const { makeParameterStore } = require('./services/parameter-store/make-parameter-store');
const { makeSettingsService } = require('./services/settings/make-settings-service');
const { makeCfService } = require('./services//cf/make-cf-service');
const { makeCfService } = require('./services/cf/make-cf-service');
const { makeList } = require('./commands/list/make-list');
const { makeRun } = require('./commands/run/make-run');
const { makeExport } = require('./commands/import-export/make-export');
const { makeImport } = require('./commands/import-export/make-import');
const { makeInit } = require('./commands/init/make-init');
const { makeConfigure } = require('./commands/configure/make-configure');

Expand Down Expand Up @@ -47,6 +49,8 @@ const makeOprah = ({ stage, config, variables = {}, interactive = false }) => {
init,
run: makeRun({ init, configure }),
list: makeList({ settingsService, parameterStore }),
export: makeExport({ settingsService, parameterStore }),
import: makeImport({ settingsService, parameterStore }),
};
};

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "oprah",
"version": "2.3.0",
"version": "2.3.1",
"description": "Package to deploy parameters to AWS",
"repository": "https://github.com/ACloudGuru/oprah.git",
"author": "subash adhikari <[email protected]>",
Expand Down

0 comments on commit 7a5e014

Please sign in to comment.