This repository has been archived on 2025-12-25. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
qmi-cloud/server/workers/docker/tf.js
Manuel Romero a8288938f5 if isExtenal
2020-05-21 15:16:55 +02:00

261 lines
8.3 KiB
JavaScript

const Docker = require('dockerode');
const docker = new Docker({
'socketPath': '/home/docker.sock'
});
const fs = require('fs');
const GIT_SCENARIOS = process.env.GIT_SCENARIOS;
const GIT_TAG = process.env.GIT_TAG || "master";
const DOCKERIMAGE = "qlikgear/terraform:1.0.1";
const SSHPATH = process.env.SSHPATH;
function hook_stdout(callback) {
var old_write = process.stdout.write
process.stdout.write = (function(write) {
return function(string, encoding, fd) {
write.apply(process.stdout, arguments)
callback(string, encoding, fd)
}
})(process.stdout.write)
return function() {
process.stdout.write = old_write
}
}
function _buildVarsExec( exec, provision, scenario ) {
let prefix = scenario.name.toUpperCase();
prefix = prefix.replace(/AZQMI/g, 'QMI');
exec.push('-var');
exec.push(`prefix=${prefix}`);
if ( scenario.subscription && scenario.subscription.subsId ) {
exec.push('-var');
exec.push(`subscription_id=${scenario.subscription.subsId}`);
}
if ( scenario.subscription && scenario.subscription.vnetExists ) {
exec.push('-var');
exec.push(`subnet_id=${scenario.subscription.subnetId}`);
if ( scenario.isExternal ) {
exec.push('-var');
exec.push(`app_gw_subnet=${scenario.subscription.appGwSubnetId}`);
}
}
exec.push('-var');
exec.push(`provision_id=${provision._id}`);
exec.push('-var');
exec.push(`user_id=${provision.user.displayName}`);
if (!provision.vmImage) {
//Old way
if ( provision.vmType ) {
exec.push('-var');
exec.push(`vm_type=${provision.vmType}`);
}
if ( provision.nodeCount) {
exec.push('-var');
exec.push(`agent_count=${provision.nodeCount}`);
}
} else if ( provision.vmImage ) {
//New way
for ( let key in provision.vmImage ) {
if ( provision.vmImage[key].nodeCount ) {
exec.push('-var');
exec.push(`agent_count_${key}=${provision[key].nodeCount}`);
}
if ( provision.vmImage[key].vmType ) {
exec.push('-var');
exec.push(`vm_type_${key}=${provision.vmImage[key].vmType}`);
}
if ( provision.vmImage[key].diskSizeGb ) {
exec.push('-var');
exec.push(`disk_size_gb_${key}=${provision.vmImage[key].diskSizeGb}`);
}
if ( provision.vmImage[key].version ) {
exec.push('-var');
exec.push(`image_reference_${key}=${provision.vmImage[key].version.image}`);
}
}
}
if ( provision.isExternalAccess ) {
exec.push('-var');
exec.push(`is_external_access=${provision.isExternalAccess}`);
}
return exec;
}
const init = function( provision ) {
const name = `qmi-tf-init-${provision._id}`;
console.log(`Init: will spin up container: ${name}`);
var processStream = fs.createWriteStream(provision.logFile, {flags:'a'});
let exec = ['terraform', 'init', '-no-color', `-from-module=${GIT_SCENARIOS}//${provision.scenario}?ref=${GIT_TAG}`];
console.log('Init: exec: '+exec.join(" "));
return docker.run(DOCKERIMAGE, exec, processStream, {
//"Env": ["VAR_ENV=whatever"],
"name": name,
"WorkingDir": "/app",
"HostConfig": {
"Binds": [
`${provision.path}:/app`
]
}
}).then(function(data) {
var output = data[0];
var container = data[1];
console.log(`Init: ${name} (${container.id}) has finished with code: ${output.StatusCode}`);
return container.remove();
}).then(function() {
console.log(`Init: ${name} removed!`);
return provision;
});
};
const plan = function( provision, scenario ) {
const name = `qmi-tf-plan-${provision._id}`;
console.log(`Plan: will spin up container: ${name}`);
var processStream = fs.createWriteStream(provision.logFile, {flags:'a'});
//var processStream = process.stdout;
var exec = ['terraform', 'plan', '-no-color', '-input=false', '-out=tfplan' ];
exec = _buildVarsExec(exec, provision, scenario);
console.log('Plan: exec: '+exec.join(" "));
return docker.run(DOCKERIMAGE, exec, processStream, {
//"Env": ["VAR_ENV=whatever"],
"name": name,
"WorkingDir": "/app",
"HostConfig": {
"Binds": [
`${provision.path}:/app`,
`${SSHPATH}:/root/.ssh`
],
"NetworkMode": "host"
}
}).then(function(data){
var container = data[1];
console.log(`Plan: ${name} (${container.id}) has finished with code: ${data[0].StatusCode}`);
return container.remove();
}).then(function() {
console.log(`Plan: ${name} removed!`);
return fs.readFileSync(provision.logFile);
})
};
const apply = function( provision ) {
const name = `qmi-tf-apply-${provision._id}`;
console.log(`Apply: will spin up container: ${name}`);
var processStream = fs.createWriteStream(provision.logFile, {flags:'a'});
//var processStream = process.stdout;
var exec = ['terraform', 'apply', 'tfplan', '-no-color'];
console.log('Apply: exec: '+exec.join(" "));
return docker.run(DOCKERIMAGE, exec, processStream, {
//"Env": ["VAR_ENV=whatever"],
"name": name,
"WorkingDir": "/app",
"HostConfig": {
"Binds": [
`${provision.path}:/app`,
`${SSHPATH}:/root/.ssh`
],
"NetworkMode": "host"
}
}).then(function(data){
let container = data[1];
console.log(`Apply: ${name} (${container.id}) has finished with code: ${data[0].StatusCode}`);
return container.remove();
}).then(function() {
console.log(`Apply: ${name} removed!`);
return fs.readFileSync(provision.logFile);
})
}
const destroy = function(destroyMongo, provision, scenario) {
const name = `qmi-tf-destroy-${destroyMongo._id}`;
console.log(`Destroy: will spin up container: ${name}`);
var processStream = fs.createWriteStream(destroyMongo.logFile, {flags:'a'});
var exec = ['terraform', 'destroy', '-auto-approve', '-no-color'];
exec = _buildVarsExec(exec, provision, scenario);
console.log('Destroy: exec: '+exec.join(" "));
return docker.run(DOCKERIMAGE, exec, processStream, {
//"Env": ["VAR_ENV=whatever"],
"name": name,
"WorkingDir": "/app",
"HostConfig": {
"Binds": [
`${provision.path}:/app`,
`${SSHPATH}:/root/.ssh`
]
}
}).then(function(data) {
var container = data[1];
console.log(`Destroy: '${name}' (${container.id}) has finished with code: ${data[0].StatusCode}`);
return container.remove();
}).then(async function(data) {
console.log(`Destroy: '${name}' removed!`);
return fs.readFileSync(destroyMongo.logFile);
});
};
const outputs = function(provision) {
const name = `qmi-tf-output-${provision._id}`;
console.log(`Output: will spin up container: ${name}`);
var exec = ['terraform', 'output', '-no-color', '-json'];
console.log('Output: exec: '+exec.join(" "));
var tfout = "";
var unhook = hook_stdout(function(string, encoding, fd) {
tfout += string.trim();
});
return docker.run(DOCKERIMAGE, exec, process.stdout, {
//"Env": ["VAR_ENV=whatever"],
"name": name,
"WorkingDir": "/app",
"HostConfig": {
"Binds": [
`${provision.path}:/app`
]
}
}).then(function(data) {
unhook();
var container = data[1];
console.log(`Output: '${name}' (${container.id}) has finished with code: ${data[0].StatusCode}`);
return container.remove();
}).then(async function(data) {
console.log(`Output: '${name}' removed!`);
console.log("Output: tfout: " + tfout);
var out = JSON.parse(tfout);
var o = {};
for (var key in out) {
o[key] = out[key].value;
}
return o;
});
};
module.exports.init = init;
module.exports.plan = plan;
module.exports.apply = apply;
module.exports.destroy = destroy;
module.exports.outputs = outputs;