-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(deploy): support for aws codeDeploy service
- Loading branch information
Showing
1 changed file
with
241 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
}); | ||
} |