Skip to content

Commit

Permalink
feat(deploy): support for aws codeDeploy service
Browse files Browse the repository at this point in the history
  • Loading branch information
Izak88 committed Nov 24, 2017
1 parent f7b35b5 commit 252afd0
Showing 1 changed file with 241 additions and 0 deletions.
241 changes: 241 additions & 0 deletions src/api/deploy/aws-code-deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
import { Observable, Observer } from 'rxjs';
import { attachExec } from '../docker';
import { CommandType } from '../config';
import { findFromEnvVariables } from '../deploy';
import * as style from 'ansi-styles';
import { error } from 'util';
import chalk from 'chalk';

export function codeDeploy(
preferences: any, container: string, variables: string[]): Observable<any> {
return new Observable((observer: Observer<any>) => {

// 1. check preferences
const application = preferences.application;
const applicationRevision = preferences.applicationRevision;
const deployGroup = preferences.deploymentGroup;
const arn = findFromEnvVariables(variables, 'arn') || preferences.arn;
let applicationStore = preferences.applicationStore;
let applicationType = preferences.applicationType;
let applicationFileName = preferences.applicationFile;
let accessKeyId = findFromEnvVariables(variables, 'accessKeyId');
let secretAccessKey = findFromEnvVariables(variables, 'secretAccessKey');
let region = findFromEnvVariables(variables, 'region');
let errors = false;

if (!application) {
const msg = chalk.red('application is not set in yml config file \r\n');
observer.next({ type: 'data', data: msg});
errors = true;
}

if (!applicationStore) {
applicationStore = 's3';
}

if (!applicationType) {
applicationType = 'zip';
}

if (!applicationFileName) {
applicationFileName = `${application}.${applicationType}`;
}

if (!deployGroup) {
const msg = chalk.red('deploymentGroup is not set in yml config file \r\n');
observer.next({ type: 'data', data: msg});
errors = true;
}

if (!accessKeyId) {
if (preferences && preferences.accessKeyId) {
accessKeyId = preferences.accessKeyId;
} else {
const msg = chalk.red('accessKeyId is not set in environment '
+ 'variables or in yml config \r\n');
observer.next({ type: 'data', data: msg});
errors = true;
}
}

if (!secretAccessKey) {
if (preferences && preferences.secretAccessKey) {
secretAccessKey = preferences.secretAccessKey;
} else {
const msg = chalk.red('secretAccessKey is not set in environment variables or'
+ ' in yml config \r\n');
observer.next({ type: 'data', data: msg});
errors = true;
}
}

if (!region) {
if (preferences && preferences.region) {
region = preferences.region;
} else {
const msg = chalk.red('region is not set in environment variables or in yml config \r\n');
observer.next({ type: 'data', data: msg});
errors = true;
}
}

if (!errors) {
let msg = style.yellow.open + style.bold.open + '==> deploy started' +
style.bold.close + style.yellow.close + '\r\n';
observer.next({ type: 'data', data: msg });

// 2. install awscli and set credentials
let command = { type: CommandType.deploy, command: 'sudo apt-get install awscli -y' };
attachExec(container, command)
.toPromise()
.then(result => {
if (!(result && result.data === 0)) {
const msg = `apt-get install awscli failed`;
observer.next({ type: 'containerError', data: msg});
return Promise.reject(-1);
}

command = {
type: CommandType.deploy,
command: `aws configure set aws_access_key_id ${accessKeyId}`
};

return attachExec(container, command).toPromise();
})
.then(result => {
if (!(result && result.data === 0)) {
const msg = 'aws configure aws_access_key_id failed';
observer.next({ type: 'containerError', data: msg});
return Promise.reject(-1);
}

command = {
type: CommandType.deploy,
command: `aws configure set aws_secret_access_key ${secretAccessKey}`
};

return attachExec(container, command).toPromise();
})
.then(result => {
if (!(result && result.data === 0)) {
const msg = 'aws configure aws_secret_access_key failed';
observer.next({ type: 'containerError', data: msg});
return Promise.reject(-1);
}

command = {
type: CommandType.deploy, command: `aws configure set region ${region}`
};

return attachExec(container, command).toPromise();
})
.then(result => {
if (!(result && result.data === 0)) {
const msg = 'aws configure region failed';
observer.next({ type: 'containerError', data: msg});
return Promise.reject(-1);
}

// 3. check if deployment-group exists (otherwise create it)
return depGroupExists(container, application, deployGroup);
})
.then(exists => {
if (!exists) {
if (arn) {
command = {
type: CommandType.deploy,
command: `aws deploy create-deployment-group --application-name ${application}`
+ ` --deployment-group-name ${deployGroup} --service-role-arn ${arn}`
};

return attachExec(container, command)
.toPromise()
.then(result => {
if (!(result && result.data === 0)) {
const msg = 'create-deployment-group failed';
observer.next({ type: 'containerError', data: msg});
return Promise.reject(-1);
}

Promise.resolve();
});
} else {
const msg = `deployment group doesn't exists and arn parameter is empty`;
observer.next({ type: 'containerError', data: msg});
return Promise.reject(-1);
}
} else {
Promise.resolve();
}
})
.then(() => {
// 4. create deployment
let location = `bucket=${application},bundleType=${applicationType},`
+ `key=${applicationFileName}`;
if (applicationRevision) {
location += `,eTag=${applicationRevision}`;
}

command = {
type: CommandType.deploy,
command: `aws deploy create-deployment --application-name ${application}`
+ ` --deployment-group-name ${deployGroup}`
};

if (applicationStore === 's3') {
command.command += ` --s3-location ${location}`;
} else if (applicationStore === 'github') {
command.command += ` --github-location ${location}`;
} else {
const msg = 'ApplicationStore can only be s3 or github,'
+ ' other stores are not supported';
observer.next({ type: 'containerError', data: msg});
return Promise.reject(-1);
}

return attachExec(container, command)
.toPromise()
.then(result => {
if (!(result && result.data === 0)) {
const msg = 'create-deployment failed';
observer.next({ type: 'containerError', data: msg});
return Promise.reject(-1);
}

Promise.resolve();
});
})
.then(() => {
let msg = style.yellow.open + style.bold.open + '==> deployment completed successfully!'
+ style.bold.close + style.yellow.close + '\r\n';
observer.next({ type: 'data', data: msg });
observer.complete();
})
.catch(err => {
observer.error(err);
observer.complete();
});
} else {
observer.error(-1);
observer.complete();
}
});
}

function depGroupExists(container, application, group): Promise<any> {
return new Promise((resolve, reject) => {
const command = `aws deploy get-deployment-group --application-name ${application}`
+ ` --deployment-group ${group}`;
let groupExists = false;
attachExec(container, { type: CommandType.deploy, command: command})
.subscribe(event => {
if (event && event.type && event.type === 'exit') {
if (event.data === 0) {
groupExists = true;
}
}
},
err => reject(err),
() => resolve(groupExists));
});
}

0 comments on commit 252afd0

Please sign in to comment.