Skip to content

Instantly share code, notes, and snippets.

@wesleyduff
Created January 7, 2019 20:45
Show Gist options
  • Save wesleyduff/80b18346cce700977b40c779e1d07dec to your computer and use it in GitHub Desktop.
Save wesleyduff/80b18346cce700977b40c779e1d07dec to your computer and use it in GitHub Desktop.
Feature Flags : Example - Should have vault-<env>.json setup in the correct location and tests updated
/*
This file is setup for feature flags.
Develop features and turn them on and off as needed for testing or small rollbacks.
*/
module.exports = {
feature_useVault : false
}
const featureFlagUtils = () => {
return {
getVaultJsonFile : function(env) {
env = env.toLowerCase();
const vault = require(`../config/vault-${env}.json`);
return vault;
},
validateUpdatedVaultFile: function(env){
env = env.toLowerCase();
const vault = this.getVaultJsonFile(env);
if(vault.placeholder){
RavenLogger.error('Raven-Alert: File was not updated by the deployment ansible script')
throw new Error('The file has not been updated by ansible script during deployment');
} else {
RavenLogger.info(`Vault : Vault has been setup`, {env: env, vault: typeof vault})
return {
status: 'success',
code: 200,
message: 'The file was updated by the deployment'
}
}
}
}
}
module.exports = featureFlagUtils();
/* Need this so tests will pass */
global.RavenIngestLogger = {
error: function(val){
console.log(`mock RavenIngestLogger -> Error : ${JSON.stringify(val)}`);
},
debug: function(val){
console.log(`mock RavenIngestLogger -> debug : ${typeof val === 'string' ? val : JSON.stringify(val)}`);
},
info: function(val){
console.log(`mock RavenIngestLogger -> info : ${JSON.stringify(val)}`);
}
}
/* Need this so tests will pass */
global.RavenLogger = {
error: function(val){
console.log(`mock RavenIngestLogger -> Error : ${JSON.stringify(val)}`);
},
debug: function(val){
console.log(`mock RavenIngestLogger -> debug : ${typeof val === 'string' ? val : JSON.stringify(val)}`);
},
info: function(val){
console.log(`mock RavenIngestLogger -> info : ${JSON.stringify(val)}`);
}
}
/*
Base setup for a test
*/
const
chai = require('chai'),
chaiHttp = require('chai-http'),
assert = chai.assert,
should = chai.should(),
spies = require('chai-spies'),
expect = chai.expect,
MockRavenIngestLogger = require('./MOCK_RavenIngestLogger'),
MockRavenLogger = require('./MOCK_RavenLogger'),
nock = require('nock'),
sinon = require('sinon'),
featureFlagUtils = require('./flag_utils.js');
describe(' Testing VAULT integration ... -> ', () => {
/*
Additional items used for this testsuite.
*/
describe(' Verify everything is wired up for Vault -->', () => {
it('Should have a feature flag called "feature_useVault" under feature_flags/index.js', () => {
const featureFlags = require('../../feature_flags');
expect(featureFlags.feature_useVault).to.exist;
});
it('Should have a vault-env.json file for each environment', () => {
try{
const local = require('../../config/vault-local.json'),
dev = require('../../config/vault-dev.json'),
engprod = require('../../config/vault-engprod.json'),
stage = require('../../config/vault-stage.json'),
prod = require('../../config/vault-prod.json');
expect(true).to.equal(true); //passes the test because the try catch will fail if one of the files are not there.
} catch(exception){
assert.fail(0,1, exception.message);
}
})
})
describe('Verifying vault json contents before deployment -->', () => {
const local = require('../../config/vault-local.json'),
dev = require('../../config/vault-dev.json'),
engprod = require('../../config/vault-engprod.json'),
stage = require('../../config/vault-stage.json'),
prod = require('../../config/vault-prod.json');
it('Should have a property of placeholder for all vault json files except local', () => {
expect(dev.placeholder, 'a property of placeholder should be present in the vault-dev.json file and should not be undefined').to.exist;
expect(engprod.placeholder, 'a property of placeholder should be present in the vault-engprod.json file and should not be undefined').to.exist;
expect(stage.placeholder, 'a property of placeholder should be present in the vault-stage.json file and should not be undefined').to.exist;
expect(prod.placeholder, 'a property of placeholder should be present in the vault-prod.json file and should not be undefined').to.exist;
expect(local.placeholder, 'a property of placeholder should NOT be present in the vault-local.json file').to.not.exist;
})
})
describe('Verify the mocked vault configs after deployment --> ', () => {
describe(' FAILURES --> ', () => {
const sandbox = sinon.createSandbox();
let RavenLoggerSpy;
before(() => {
RavenLoggerSpy = sandbox.spy(RavenLogger, 'error');
})
after(() => {
sandbox.restore();
})
it('Should have a method to validate the vault json file has been updated from the ansible script', () => {
expect(featureFlagUtils.validateUpdatedVaultFile).to.be.a('function');
});
it('Should throw an error when placeholder is NOT undefined', () => {
const env = "DEV";
try {
featureFlagUtils.validateUpdatedVaultFile(env);
assert.fail(0,1,"Should return an error");
} catch(exception){
expect(exception.message, 'The file was not updated by the deployment as expected').to.exist;
}
})
it('Should log to RavenLogger with proper Alert : message, object type', () => {
const env = "DEV";
try {
featureFlagUtils.validateUpdatedVaultFile(env);
assert.fail(0,1,"Should return an error");
} catch(exception){
expect(exception.message, 'The file was not updated by the deployment as expected').to.exist;
assert(RavenLoggerSpy.calledWithExactly('Raven-Alert: File was not updated by the deployment ansible script'), 'Raven logger was not called wtih Alert for Alert type exception')
}
})
})
describe(' SUCCESS --> ', () => {
const sandbox = sinon.createSandbox();
let getVaultFile_stub;
before(() => {
getVaultFile_stub = sandbox.stub(featureFlagUtils, 'getVaultJsonFile');
})
after(() => {
sandbox.restore();
})
it('Should return a truthy response when the property "placeholder" IS undefined', () => {
const env = "DEV";
getVaultFile_stub.returns({
"mocked":"value"
})
const actual = featureFlagUtils.validateUpdatedVaultFile(env);
const expected = {
status: 'success',
code: 200,
message: 'The file was updated by the deployment'
};
expect(JSON.stringify(actual)).to.equal(JSON.stringify(expected));
})
})
})
})
@wesleyduff
Copy link
Author

Were using something called RavenLogger. This logger is on the global instance within our codebase.
Change the logger and file locations as needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment