Skip to content

Commit

Permalink
Development (#1)
Browse files Browse the repository at this point in the history
* adding KMS
* Developing cloudformation and get stack profile.
* migrated batchGetHashKey and BatchGet over from leo-sdk for dynamodb
* upgrading aws sdk
* new cloudformation building
* support global secondary indexes, add batch write to table
* Pass the profile through from the config file. This is so it will make it to the aws sync command.
* Changed the cloudformation util to be able to extend cloudformation with different kinds of elements instead of just resources.
* If profile and no credentials, get the credentials so stuff will work properly.
* Adding SQS
  • Loading branch information
Handyman authored Jun 19, 2018
1 parent d5b563c commit 308b46e
Show file tree
Hide file tree
Showing 13 changed files with 949 additions and 13 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
.idea
18 changes: 16 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
let cache = {};

const secrets = require("./lib/secretsmanager");
const cloudformation = require('./lib/cloudformation');
const dynamodb = require("./lib/dynamodb");
const kms = require("./lib/kms");
const secrets = require("./lib/secretsmanager");
const sqs = require("./lib/sqs");
const AWS = require('aws-sdk');

function build(configuration) {
if (configuration.profile && !configuration.credentials) {
configuration.credentials = new AWS.SharedIniFileCredentials({profile: configuration.profile});
}

return {
region: configuration.region,
cloudformation: cloudformation(configuration),
dynamodb: dynamodb(configuration),
kms: kms(configuration),
secrets: secrets(configuration),
dynamodb: dynamodb(configuration)
profile: configuration.profile,
config: configuration,
sqs: sqs(configuration)
};
}

Expand Down
174 changes: 174 additions & 0 deletions lib/cloudformation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
"use strict";
const aws = require('aws-sdk');
const readline = require('readline');

module.exports = function(configuration) {
let service = new aws.CloudFormation(configuration);
return {
_service: service,
getStackResources: function(stack) {
return service.listStackResources({
StackName: stack
}).promise().then((data) => {
if (data.NextToken) {
console.log("We need to deal with next token");
}
var resources = {};
data.StackResourceSummaries.map((resource) => {
resources[resource.LogicalResourceId] = {
type: resource.ResourceType,
id: resource.PhysicalResourceId,
name: resource.LogicalResourceId
};
});

return resources;
});
},
get: function(stack, opts) {
return service.getTemplate(Object.assign({
StackName: stack,
}, opts)).promise().then(data => JSON.parse(data.TemplateBody));
},
runChangeSet: function(stack, file, opts) {
let updateOpts = Object.assign({}, opts);
if (updateOpts.Parameters) {
updateOpts.Parameters = updateOpts.Parameters.map(param => ({
ParameterKey: param.ParameterKey,
UsePreviousValue: param.UsePreviousValue,
ParameterValue: param.ParameterValue
}));
}
let changeSetId = null;
let changeSetName = "leo-cli-" + Date.now();
let params = Object.assign({
ChangeSetName: changeSetName,
ChangeSetType: "UPDATE",
StackName: stack,
TemplateURL: file,
Capabilities: [
"CAPABILITY_IAM",
]
}, updateOpts);
return service.createChangeSet(params).promise().then(data => {
changeSetId = data.Id;
service.api.waiters["changeSetCreateComplete"].delay = 5;
return this.waitFor("changeSetCreateComplete", {
ChangeSetName: changeSetId
});
}).then(data => {
changeSetId = data.ChangeSetId;
console.log(changeSetId);

function rightPad(val, count) {
return (val + " ".repeat(count)).slice(0, count) + " ";
}
console.log(`${rightPad("Action",30)}${rightPad("Logical ID",30)}${rightPad("Physical ID",30)}${rightPad("Resource Type",30)}${rightPad("Replacement",30)}`);
data.Changes.map(change => {
change = change.ResourceChange;
console.log(`${rightPad(change.Action,30)}${rightPad(change.LogicalResourceId,30)}${rightPad(change.PhysicalResourceId,30)}${rightPad(change.ResourceType,30)}${rightPad(change.Replacement,30)}`);
});
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve) => {
rl.question('Press [Enter] to execute change set', (data) => {
rl.close();
console.log("Executing Change Set");
resolve(service.executeChangeSet({
ChangeSetName: changeSetId
}).promise().then(data => {
service.api.waiters["stackUpdateComplete"].delay = 10;
return this.waitFor("stackUpdateComplete", {
StackName: stack
});
}));
});
})
}).catch(err => {
console.log(err);
if (err.message.match(/^Stack.*does not exist/)) {
return this.createStack(stack, file, updateOpts.Parameters, opts, true, true);
} else {
throw err;
}
});
},
run: function(stack, file, opts) {
let updateOpts = Object.assign({}, opts);
if (updateOpts.Parameters) {
updateOpts.Parameters = updateOpts.Parameters.map(param => ({
ParameterKey: param.ParameterKey,
UsePreviousValue: param.UsePreviousValue,
ParameterValue: param.ParameterValue
}));
}
console.log(updateOpts);
return service.updateStack(Object.assign({
StackName: stack,
TemplateURL: file,
Capabilities: [
"CAPABILITY_IAM",
]
}, updateOpts)).promise().then(data => {
service.api.waiters["stackUpdateComplete"].delay = 10;
return this.waitFor("stackUpdateComplete", {
StackName: stack
});
}).catch(err => {
if (err.message.match(/^Stack.*does not exist/)) {
return this.createStack(stack, file, updateOpts.Parameters, opts, true, true);
} else {
throw err;
}
});
},
describeStackResources: function(stack) {
return service.describeStackResources({
StackName: stack
}).promise().then(data => data.StackResources);
},
waitFor: function(action, params) {
return service.waitFor(action, params).promise();
},
createStack: async function createStack(name, template, paramaters = [], waitFor = true, describeStack = true) {
let templateBody;
if (typeof template === "string") {
templateBody = "TemplateURL";
} else {
templateBody = "TemplateBody";
template = JSON.stringify(template);
}

let promise = service.createStack({
StackName: name,
Capabilities: [
"CAPABILITY_IAM"
],
OnFailure: "DELETE",
[templateBody]: template,
Parameters: paramaters
}).promise();
if (waitFor || describeStack) {
service.api.waiters["stackCreateComplete"].delay = 10;
promise = promise.then(() => this.waitFor("stackCreateComplete", {
StackName: name
})).then(waitdata => ({
stack: name,
region: configuration.region,
details: waitdata.Stacks[0]
}));
} else if (describeStack) {
promise = promise.then(() => this.describeStackResources(name)).then(data => ({
stack: name,
region: configuration.region,
details: {
StackResources: data
}
}));
}
return promise;
}
};
};
Loading

0 comments on commit 308b46e

Please sign in to comment.