I wasn't able to get the output in a live stream, however I made the site work by using web-pages instead.
The Ansible function starts when I redirect to another page after clicking the setup button.
Few lessons -
Shifted from spawn to spawnSync.
Removed promisify.
Added a conditional to throw an exception for the try-catch block
Changed ansible.js code -
//Run Ansible and report errors
async function ansibleRunAndReturn(site_name) {
//Copy relevant global file to mujoerp_automation/glabal_vars/all
const src = await __dirname+'/ansible/'+site_name
const dest = await path.join(__dirname, '../mujoerp_automation/group_vars/all')
await fse.copy(src, dest, function (err) {
if (err) throw err
console.log(src+ ' Global vars file copied to ' +dest)
})
//Change playbook location as required
const playbook = await path.join(__dirname, '../mujoerp_automation/master.yml')
const ansibleProcess = await spawnSync('sh', ['-c', `echo redhat237 | sudo -S ansible-playbook ${playbook}`], {encoding: 'utf8'})//stdio: 'inherit', })
const stdout = await console.log(ansibleProcess.stdout)
await console.log(ansibleProcess.stderr)
const output = await console.log(ansibleProcess.output)
await console.log(ansibleProcess.status)
if (ansibleProcess.status != 0) {
throw 'Server setup failed'
}
return {playbook, ansibleProcess, stdout, output }
}
Changed Route for the "Control-Centre"
//Render Control Setup
app.get('/control-setup/:userid', (req,res) => {
let userid = req.params.userid
let email = Users.findById(userid).exec(function (err, data) {
if (err) throw error
res.render('controlSetup', {
helpers: {
userid: function () { return req.params.userid },
email: data.email,
site: data.docker.site,
admin: data.docker.adminpwd,
cpus: data.docker.cpus,
memory: data.docker.memory,
storage: data.docker.storage
}
})
})
})
//Render Control Edit
app.get('/control-edit/:userid', (req,res) => {
let userid = req.params.userid
let email = Users.findById(userid).exec(function (err, data) {
if (err) throw error
res.render('controlEdit', {
helpers: {
userid: function () { return req.params.userid },
email: data.email,
cpus: data.docker.cpus,
memory: data.docker.memory,
storage: data.docker.storage
}
})
})
})
//Render Ansible output
app.get('/control-setup/:userid/output', async (req,res) => {
let userid = await req.params.userid
await Users.findById(userid).exec(async function (err, result) {
if (err) throw err
let site = result.docker.site
let site_name = site.slice(8)
try {
await res.render('output')
await ansible.ansibleRunAndReturn(site_name)
await res.redirect('/docker/control/'+userid)
} catch (e) {
res.redirect('/docker/control-setup/'+userid+'/error')
}
})
})
app.get('/control-setup/:userid/error', async (req,res) => {
res.render('error')
})
//Setup/Edit Docker details for docker
app.post('/control-setup/:userid',
//validation
[
body('site').isURL({allow_underscores: true}),
body('admin').isLength({ min: 6 })
], async (req,res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const userid = req.params.userid
//Setup or Edit
var site = req.body.site
var adminpwd = req.body.admin
var cpus = req.body.cpus
var memory = req.body.memory
var storage = req.body.storage
//Needs a function to get the next available port
var dockerPort = await freePort()
console.log(dockerPort)
//Cutting https:// from input
var site_name = site.slice(8)
//Save or Edit in DB
Users.updateOne({_id: userid}, {docker: {site: site, adminpwd: adminpwd, hostPort: dockerPort, cpus: cpus, memory: memory, storage: storage}}, {upsert: true, new: true},
function (err, result) {
if (err) throw err
console.log('Docker Parameters Setup in User' + result)
})
await ansible.createGlobal(site_name, adminpwd, dockerPort, cpus, memory, storage)
await res.redirect(userid+'/output')
})
As always since I'm still quite new to development, if anyone has any better options or ways to actually implement a live stream of the spawnSync command, I would really appreciate learning those techniques or logic.