1.0.0
This commit is contained in:
168
src/websocket/container.js
Normal file
168
src/websocket/container.js
Normal file
@ -0,0 +1,168 @@
|
||||
import { Transform } from 'stream'
|
||||
import chalk from 'chalk'
|
||||
|
||||
const WIN_IMAGE_NAME = 'electronuserland/builder:wine-mono'
|
||||
const LINUX_IMAGE_NAME = 'electronuserland/builder:10'
|
||||
|
||||
export default (io, socket, docker) => {
|
||||
socket.on('exec', function (id, w, h) {
|
||||
var container = docker.getContainer(id)
|
||||
var cmd = {
|
||||
'AttachStdout': true,
|
||||
'AttachStderr': true,
|
||||
'AttachStdin': true,
|
||||
'Tty': true,
|
||||
Cmd: ['/bin/bash']
|
||||
}
|
||||
container.exec(cmd, (err, exec) => {
|
||||
var options = {
|
||||
'Tty': true,
|
||||
stream: true,
|
||||
stdin: true,
|
||||
stdout: true,
|
||||
stderr: true,
|
||||
// fix vim
|
||||
hijack: true
|
||||
}
|
||||
|
||||
container.wait((err, data) => {
|
||||
console.log(err)
|
||||
socket.emit('end', 'ended')
|
||||
})
|
||||
|
||||
if (err) {
|
||||
return
|
||||
}
|
||||
|
||||
exec.start(options, (err, stream) => {
|
||||
console.log(err)
|
||||
var dimensions = {
|
||||
h,
|
||||
w
|
||||
}
|
||||
if (dimensions.h !== 0 && dimensions.w !== 0) {
|
||||
exec.resize(dimensions, () => {})
|
||||
}
|
||||
|
||||
stream.on('data', (chunk) => {
|
||||
socket.emit('show', chunk.toString())
|
||||
})
|
||||
|
||||
socket.on('cmd', (data) => {
|
||||
stream.write(data)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
socket.on('logs', function (id) {
|
||||
const container = docker.getContainer(id)
|
||||
|
||||
const logsOpts = {
|
||||
follow: true,
|
||||
stdout: true,
|
||||
stderr: true,
|
||||
timestamps: false
|
||||
}
|
||||
|
||||
container.logs(logsOpts, (err, stream) => {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
socket.emit('err', chalk.red('Error:\n') + err + '.\n')
|
||||
return
|
||||
}
|
||||
|
||||
stream.on('data', (data) => { socket.emit('show', data.toString('utf-8')) })
|
||||
stream.on('end', function () {
|
||||
socket.emit('show', '\n===Stream finished===\n')
|
||||
stream.destroy()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
socket.on('pull', function (type) {
|
||||
let imageName = null
|
||||
switch (type) {
|
||||
case 'win':
|
||||
imageName = WIN_IMAGE_NAME
|
||||
break
|
||||
case 'linux':
|
||||
imageName = LINUX_IMAGE_NAME
|
||||
break
|
||||
}
|
||||
|
||||
docker.pull(imageName, function (err, stream) {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
socket.emit('err', chalk.red('Error:\n') + err + '.\n')
|
||||
return
|
||||
}
|
||||
|
||||
const bytesToSize = (bytes) => {
|
||||
if (bytes === 0) return '0 B'
|
||||
const k = 1000 // or 1024
|
||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i]
|
||||
}
|
||||
|
||||
let downTmp = []
|
||||
let downTmpId = []
|
||||
const commaSplitter = new Transform({
|
||||
readableObjectMode: true,
|
||||
transform (chunk, encoding, callback) {
|
||||
let tmp = ''
|
||||
try {
|
||||
var result = chunk.toString().match(/{(.*)}/)
|
||||
result = result ? result[0] : null
|
||||
if (!result) callback()
|
||||
tmp = JSON.parse(result)
|
||||
if (tmp.id) {
|
||||
if (downTmpId.includes(tmp.id)) {
|
||||
for (const n in downTmp) {
|
||||
if (downTmp[n].id === tmp.id) {
|
||||
if (tmp.progressDetail && tmp.progressDetail.current && tmp.progressDetail.total) {
|
||||
const percentage = Math.floor(100 * tmp.progressDetail.current / tmp.progressDetail.total)
|
||||
downTmp[n].val = ': [' + percentage + '%] Total ' + bytesToSize(tmp.progressDetail.total)
|
||||
} else if (tmp.status) {
|
||||
downTmp[n].val = ': ' + tmp.status
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
downTmpId.push(tmp.id)
|
||||
const temp = {}
|
||||
temp.id = tmp.id
|
||||
if (tmp.progressDetail && tmp.progressDetail.current && tmp.progressDetail.total) {
|
||||
const percentage = Math.floor(100 * tmp.progressDetail.current / tmp.progressDetail.total)
|
||||
temp.val = ': [' + percentage + '%] Total ' + bytesToSize(tmp.progressDetail.total)
|
||||
} else if (tmp.status) {
|
||||
temp.val = ': ' + tmp.status
|
||||
}
|
||||
downTmp.push(temp)
|
||||
}
|
||||
|
||||
let str = ''
|
||||
for (const n in downTmp) {
|
||||
str += downTmp[n].id + downTmp[n].val + '\n'
|
||||
}
|
||||
socket.emit('progress', str)
|
||||
}
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
}
|
||||
|
||||
callback()
|
||||
}
|
||||
})
|
||||
|
||||
stream.pipe(commaSplitter)
|
||||
stream.once('end', () => {
|
||||
socket.emit('progress', chalk.green('All: [100%] Finish。\n'))
|
||||
// socket.emit('end', imageName + ' install ' + chalk.green('success') + '.\n')
|
||||
downTmp = []
|
||||
downTmpId = []
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
93
src/websocket/git.js
Normal file
93
src/websocket/git.js
Normal file
@ -0,0 +1,93 @@
|
||||
import git from 'simple-git'
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { SYSTEM } from '../config'
|
||||
|
||||
const GIT_SSH_COMMAND = 'ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
|
||||
|
||||
const mkdirsSync = (dirname) => {
|
||||
if (fs.existsSync(dirname)) {
|
||||
return true
|
||||
} else {
|
||||
if (mkdirsSync(path.dirname(dirname))) {
|
||||
fs.mkdirSync(dirname)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default (io, socket, docker) => {
|
||||
socket.on('gitPull', (data) => {
|
||||
const repoPath = SYSTEM.REPOPATH
|
||||
const workPath = SYSTEM.WORKPATH
|
||||
const sourcePath = path.join(workPath, '/source')
|
||||
const linuxPath = path.join(workPath, '/linux')
|
||||
const winPath = path.join(workPath, '/win')
|
||||
|
||||
const gitClone = (repoPath, workPath, type) => {
|
||||
git().env({
|
||||
...process.env,
|
||||
GIT_SSH_COMMAND
|
||||
})
|
||||
.clone(repoPath, workPath, (err) => {
|
||||
if (err) {
|
||||
socket.emit('err', chalk.red(type + ' clone error:\n') + err + '\n')
|
||||
return
|
||||
}
|
||||
socket.emit('show', chalk.green(type + ' clone is finished!\n'))
|
||||
})
|
||||
}
|
||||
|
||||
const gitPull = (workPath, type) => {
|
||||
git(workPath).env({
|
||||
...process.env,
|
||||
GIT_SSH_COMMAND
|
||||
})
|
||||
.pull((err, update) => {
|
||||
if (err) {
|
||||
socket.emit('err', chalk.red(type + ' pull error:\n') + err + '\n')
|
||||
return
|
||||
}
|
||||
if (update && update.summary.changes) {
|
||||
socket.emit('show', chalk.green(type + ' update success.\n'))
|
||||
} else {
|
||||
socket.emit('show', chalk.green(type + ' update success, no change.\n'))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (!fs.existsSync(sourcePath)) {
|
||||
mkdirsSync(sourcePath)
|
||||
gitClone(repoPath, sourcePath, 'Source')
|
||||
} else {
|
||||
if (fs.readdirSync(sourcePath).includes('.git')) {
|
||||
gitPull(sourcePath, 'Source')
|
||||
} else {
|
||||
gitClone(repoPath, sourcePath, 'Source')
|
||||
}
|
||||
}
|
||||
|
||||
if (!fs.existsSync(linuxPath)) {
|
||||
mkdirsSync(linuxPath)
|
||||
gitClone(repoPath, linuxPath, 'Linux')
|
||||
} else {
|
||||
if (fs.readdirSync(linuxPath).includes('.git')) {
|
||||
gitPull(linuxPath, 'Linux')
|
||||
} else {
|
||||
gitClone(repoPath, linuxPath, 'Linux')
|
||||
}
|
||||
}
|
||||
|
||||
if (!fs.existsSync(winPath)) {
|
||||
mkdirsSync(winPath)
|
||||
gitClone(repoPath, winPath, 'Win')
|
||||
} else {
|
||||
if (fs.readdirSync(winPath).includes('.git')) {
|
||||
gitPull(winPath, 'Win')
|
||||
} else {
|
||||
gitClone(repoPath, winPath, 'Win')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
30
src/websocket/index.js
Normal file
30
src/websocket/index.js
Normal file
@ -0,0 +1,30 @@
|
||||
import container from './container'
|
||||
import git from './git'
|
||||
import log from './log'
|
||||
import JsSHA from 'jssha'
|
||||
import {
|
||||
SYSTEM
|
||||
} from '../config'
|
||||
|
||||
export default (io, docker) => {
|
||||
console.log('Websocket Runing...')
|
||||
io.on('connection', function (socket) {
|
||||
console.log('One user connected - ' + socket.id)
|
||||
socket.emit('requireAuth', 'distribution')
|
||||
socket.emit('opend', new Date())
|
||||
|
||||
socket.on('auth', function (token) {
|
||||
const shaObj = new JsSHA('SHA-512', 'TEXT')
|
||||
shaObj.update(SYSTEM.TOKEN)
|
||||
const hash = shaObj.getHash('HEX')
|
||||
if (token === hash) {
|
||||
container(io, socket, docker)
|
||||
git(io, socket, docker)
|
||||
log(io, socket, docker)
|
||||
socket.emit('auth', 'success')
|
||||
} else {
|
||||
socket.emit('auth', 'fail')
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
25
src/websocket/log.js
Normal file
25
src/websocket/log.js
Normal file
@ -0,0 +1,25 @@
|
||||
import fs from 'fs'
|
||||
import db from '../lib/db'
|
||||
|
||||
export default (io, socket, docker) => {
|
||||
socket.on('log', function (path) {
|
||||
path = decodeURI(path)
|
||||
|
||||
const logLast = db.get('buildLog')
|
||||
.filter({logPath: path})
|
||||
.sortBy((item) => -item.startDate)
|
||||
.take()
|
||||
.first()
|
||||
.value()
|
||||
|
||||
if (logLast && logLast.logPath) {
|
||||
try {
|
||||
socket.emit('show', fs.readFileSync(logLast.logPath) + '\n')
|
||||
} catch (err) {
|
||||
socket.emit('show', err.toString() + '\n')
|
||||
}
|
||||
} else {
|
||||
socket.emit('show', 'No file.')
|
||||
}
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user