deployments/nodejs/lib/deploy.js
2021-01-25 23:42:47 -05:00

253 lines
6.1 KiB
JavaScript

'user strict';
const extend = require('extend');
const axios = require('axios')
const {Repo, Environment, Deployment, Target} = require('../models/repo');
const deployTargets = require('./lxc');
const conf = require('../conf/conf')
async function doDeploy(action, repo, branch, repoSshurl, commit){
var deployment;
try{
console.log(action, repo, branch, repoSshurl, commit)
repo = await Repo.get(repo);
let deployments = await repo.getDeploymentsbyBranch(branch, true)
console.log('deployments', deployments)
if(deployments.length && action === 'delete'){
deployment = deployments[0]
}if(deployments.length){
deployment = deployments[0]
action = 'update';
}else{
var environment = await repo.getEnvironmentsbyBranch(branch)
deployment = await environment.addDeployment()
}
deployment.environment.settings.repoSshurl = repoSshurl
deployment.environment.settings.branch = branch
}catch(error){
console.error('create start', error)
throw new Error('Failed to make new Deployment')
}
try{
deployment = new Depoy(deployment);
setImmediate(async function(deployment, action) {
try{
await deployment[action]()
}catch(error){
console.log('set error', error)
}
}, deployment, action)
return {id: deployment.id};
}catch(error){
console.error('create remote', error)
}
}
function event(deployment, message){
console.info('event:', message)
}
class Depoy{
constructor(deployment){
this.deployment = deployment
this.environment = deployment.environment;
this.settings = pasrseSetings(deployment);
this.secrets = pasrseSecrets(deployment);
this.id = deployment.repo_env_id
this.target = new deployTargets[deployment.target.type](this.settings)
}
async exec(code, info){
await this.event(`exec-start`, {info})
code = `
sudo su
${exportBashVars(this.secrets)}
echo 'nameserver 8.8.8.8' > /etc/resolv.conf
export DEBIAN_FRONTEND=noninteractive
${code}
`
let res = await this.target.exec(code);
await this.event(`exec-finish`, {info, ...res})
return res;
}
async event(name, data){
console.log(`EVENT: ${name}`, data)
}
async log(type, message){
console.log('LOG:', type, message)
}
async setinfo(){
let info = await this.target.info();
if(!info.ip){
return await this.setinfo();
}
let id = info.ip.slice(-2);
let settings = {
sshURL: `${this.settings.host}:22${id}`,
httpURL: `${this.settings.host}:80${id}`,
}
this.settings = {...this.settings, ...settings};
await this.deployment.update('settings', {settings: this.settings, state:'deployed'})
}
async create(){
this.event('deployment-started', {info: `Creating deployment ${this.settings.appName}`})
await this.target.create('bionic-base')
await this.target.start()
await this.setinfo();
console.log(this.settings)
try{
await this.exec(`
while [ ! -f /opt/datacom/firstboot ]; do sleep 1; done
sleep 2
`, 'Wait for target to be ready')
}catch(error){}
await this.init();
await this.updateProxy();
}
async init(){
await this.exec(deployInitScript(this.settings), 'Initializing deployment')
await this.exec(`
cd ${this.settings.workingPath};
./${this.settings.scriptsPath}/${this.environment.environment}/deploy.sh
`, 'Running repo deploy script')
}
async update(){
await this.exec(`
cd ${this.settings.workingPath};
export GIT_SSH_COMMAND="/usr/bin/ssh -o StrictHostKeyChecking=no -i $HOME/.ssh/id_rsa_deploy_key"
git pull origin master;
./${this.settings.scriptsPath}/${this.environment.environment}/update.sh
`, 'Running repo update script')
}
async updateProxy(){
let target = this.settings.httpURL.split(':');
let res = await axios.post(`${conf.httpProxyAPI.host}/api/host/`, {
forcessl: true,
host: this.settings.domain.replace('*', this.settings.branch),
ip: target[0],
targetPort: Number(target[1] || 80),
targetssl: false
}, {
headers: { "auth-token": conf.httpProxyAPI.key }
})
}
async delete(){
await this.target.destroy()
await this.deployment.update({state: 'deleted', isActive: false})
}
}
function deployUpdateScript(argument) {
// body...
}
function deployInitScript(args){
return `
mkdir -p "${args.workingPath}";
mkdir "$HOME/.ssh";
chmod 700 "$HOME/.ssh"
echo "${args.privateKey}" > $HOME/.ssh/id_rsa_deploy_key
chmod 600 $HOME/.ssh/id_rsa_deploy_key
wget https://raw.githubusercontent.com/tests-always-included/mo/master/mo -O /usr/local/bin/mo
chmod +x /usr/local/bin/mo
export GIT_SSH_COMMAND="/usr/bin/ssh -o StrictHostKeyChecking=no -i $HOME/.ssh/id_rsa_deploy_key"
git clone ${args.repoSshurl} ${args.workingPath};
`
}
function exportBashVars(map){
let out = '';
for (const [key, value] of Object.entries(map)){
out += `export ${key}="${value}";`
}
return out
}
function pasrseBase(deployment){
let appName = deployment.repo_env_id.replace('/', '_')
return {
appName: appName,
scriptsPath: deployment.environment.repo.scriptsPath,
privateKey: deployment.environment.repo.privateKey,
environment: deployment.environment.environment,
workingPath: `${deployment.environment.workingPath}/${appName}`,
domain: deployment.environment.domain,
name: appName,
}
}
function pasrseSecrets(deployment){
return {
...deployment.environment.repo.secrets,
...deployment.environment.secrets,
...pasrseBase(deployment),
}
}
function pasrseSetings(deployment){
return {
...deployment.target.settings,
...deployment.environment.repo.settings,
...deployment.environment.settings,
...pasrseBase(deployment),
}
}
module.exports = {doDeploy};
(async function(){try{
// console.log(await doDeploy('create', 'wmantly/static-test', 'master', 'ssh://gitea@git.theta42.com:2222/wmantly/static-test.git'))
// let repo = await Repo.get('wmantly/static-test');
// let deployments = await repo.getDeploymentsbyBranch('master')
// for(let d of deployments){
// try{
// let lxc = new deployTargets.LXC({...{name: d.repo_env_id.replace('/', '_')}, ...d.target.settings})
// await lxc.destroy();
// await d.remove()
// }catch(error){
// console.log('err', error)
// }finally{
// await d.remove()
// }
// }
}catch(error){
console.error('IIFE error:', error)
}})()