Updated to latest service-core, fixed some bugs and made it runnable
This commit is contained in:
parent
7e127cd58f
commit
f64acc95eb
10 changed files with 226 additions and 150 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import defaults from '../defaults.mjs'
|
||||||
import { formatLog } from './loghelper.mjs'
|
import { formatLog } from './loghelper.mjs'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -6,7 +7,16 @@ import { formatLog } from './loghelper.mjs'
|
||||||
* Get config
|
* Get config
|
||||||
*/
|
*/
|
||||||
export async function config(ctx, data, cb) {
|
export async function config(ctx, data, cb) {
|
||||||
cb(ctx.config)
|
let merge = {
|
||||||
|
applications: []
|
||||||
|
}
|
||||||
|
for (let app of ctx.core.applications) {
|
||||||
|
merge[app.name] = app.config
|
||||||
|
merge.applications.push(app.name)
|
||||||
|
}
|
||||||
|
let out = defaults(ctx.db.config, merge)
|
||||||
|
console.log(out)
|
||||||
|
cb(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -94,8 +104,8 @@ export async function updatestart(ctx, data, cb) {
|
||||||
*/
|
*/
|
||||||
export async function listencore(ctx) {
|
export async function listencore(ctx) {
|
||||||
ctx.socket.join('core')
|
ctx.socket.join('core')
|
||||||
ctx.socket.emit('core.db', ctx.db.get('core').value())
|
ctx.socket.emit('core.db', ctx.db.data.core)
|
||||||
ctx.socket.emit('core.status', ctx.core.status())
|
ctx.socket.emit('core.status', {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import _ from 'lodash'
|
import defaults from '../defaults.mjs'
|
||||||
import { format } from 'util'
|
import { format } from 'util'
|
||||||
|
|
||||||
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
||||||
|
@ -64,7 +64,7 @@ function indent(s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatLog(data) {
|
export function formatLog(data) {
|
||||||
let rec = _.cloneDeep(data)
|
let rec = defaults(data)
|
||||||
|
|
||||||
delete rec.v;
|
delete rec.v;
|
||||||
|
|
||||||
|
|
34
api/defaults.mjs
Normal file
34
api/defaults.mjs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
// taken from isobject npm library
|
||||||
|
function isObject(val) {
|
||||||
|
return val != null && typeof val === 'object' && Array.isArray(val) === false
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function defaults(options, def) {
|
||||||
|
let out = { }
|
||||||
|
|
||||||
|
if (options) {
|
||||||
|
Object.keys(options || {}).forEach(key => {
|
||||||
|
out[key] = options[key]
|
||||||
|
|
||||||
|
if (Array.isArray(out[key])) {
|
||||||
|
out[key] = out[key].map(item => {
|
||||||
|
if (isObject(item)) return defaults(item)
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
} else if (out[key] && typeof out[key] === 'object') {
|
||||||
|
out[key] = defaults(options[key], def && def[key])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (def) {
|
||||||
|
Object.keys(def).forEach(function(key) {
|
||||||
|
if (typeof out[key] === 'undefined') {
|
||||||
|
out[key] = def[key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
|
@ -21,32 +21,31 @@ function register(ctx, name, method) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function onConnection(server, config, db, log, coreService, data) {
|
function onConnection(server, ctx, data) {
|
||||||
const io = server
|
const io = server
|
||||||
const socket = data
|
const socket = data
|
||||||
|
|
||||||
const child = log.child({
|
const child = ctx.log.child({
|
||||||
id: socket.id,
|
id: socket.id,
|
||||||
})
|
})
|
||||||
child.event = log.event
|
child.event = ctx.log.event
|
||||||
|
|
||||||
child.info('Got new socket connection')
|
child.info('Got new socket connection')
|
||||||
|
|
||||||
let ctx = {
|
let ioCtx = {
|
||||||
config,
|
io: io,
|
||||||
io,
|
socket: socket,
|
||||||
socket,
|
|
||||||
log: child,
|
log: child,
|
||||||
db,
|
db: ctx.db,
|
||||||
core: coreService,
|
core: ctx.core,
|
||||||
logroot: log,
|
logroot: ctx.log,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.socket.on('disconnect', function() {
|
ioCtx.socket.on('disconnect', function() {
|
||||||
child.info('Closed connection')
|
child.info('Closed connection')
|
||||||
})
|
})
|
||||||
|
|
||||||
register(ctx, 'core', core)
|
register(ioCtx, 'core', core)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default onConnection
|
export default onConnection
|
||||||
|
|
123
api/server.mjs
123
api/server.mjs
|
@ -1,84 +1,75 @@
|
||||||
import path from 'path'
|
|
||||||
import { fileURLToPath } from 'url'
|
|
||||||
import socket from 'socket.io-serveronly'
|
import socket from 'socket.io-serveronly'
|
||||||
import nStatic from 'node-static'
|
import nStatic from 'node-static'
|
||||||
import coremonitor from './core/coremonitor.mjs'
|
// import coremonitor from './core/coremonitor.mjs'
|
||||||
|
|
||||||
import onConnection from './routerio.mjs'
|
import onConnection from './routerio.mjs'
|
||||||
|
|
||||||
export function run(config, db, log, core, http, port) {
|
export function run(http, port, ctx) {
|
||||||
return new Promise(function(resolve, reject) {
|
let localUtil = new ctx.sc.Util(import.meta.url)
|
||||||
core.startMonitor()
|
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
const staticRoot = localUtil.getPathFromRoot('../public')
|
||||||
const staticRoot = path.join(__dirname,'../public')
|
|
||||||
|
|
||||||
const fileServer = new nStatic.Server(staticRoot)
|
const fileServer = new nStatic.Server(staticRoot)
|
||||||
const server = http.createServer(function (req, res) {
|
const server = http.createServer(function (req, res) {
|
||||||
const child = log.child({})
|
const child = ctx.log.child({})
|
||||||
|
|
||||||
const d1 = new Date().getTime()
|
const d1 = new Date().getTime()
|
||||||
|
|
||||||
let finishedRequest = false
|
let finishedRequest = false
|
||||||
var done = function () {
|
var done = function () {
|
||||||
if (finishedRequest) return
|
if (finishedRequest) return
|
||||||
finishedRequest = true
|
finishedRequest = true
|
||||||
if (req.url === '/main.css.map') return
|
if (req.url === '/main.css.map') return
|
||||||
var requestTime = new Date().getTime() - d1
|
var requestTime = new Date().getTime() - d1
|
||||||
|
|
||||||
let level = 'debug'
|
let level = 'debug'
|
||||||
if (res.statusCode >= 400) {
|
if (res.statusCode >= 400) {
|
||||||
level = 'warn'
|
level = 'warn'
|
||||||
}
|
}
|
||||||
if (res.statusCode >= 500) {
|
if (res.statusCode >= 500) {
|
||||||
level = 'error'
|
level = 'error'
|
||||||
}
|
|
||||||
|
|
||||||
let status = ''
|
|
||||||
if (res.statusCode >= 400) {
|
|
||||||
status = res.statusCode + ' '
|
|
||||||
}
|
|
||||||
|
|
||||||
child[level]({
|
|
||||||
duration: requestTime,
|
|
||||||
status: res.statusCode,
|
|
||||||
}, `<-- ${status}${req.method} ${req.url}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res.addListener('finish', done);
|
|
||||||
res.addListener('close', done);
|
|
||||||
|
|
||||||
req.addListener('end', function () {
|
let status = ''
|
||||||
if (req.url === '/') {
|
if (res.statusCode >= 400) {
|
||||||
res.writeHead(302, { Location: '/index.html' })
|
status = res.statusCode + ' '
|
||||||
return res.end()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fileServer.serve(req, res, function (err) {
|
child[level]({
|
||||||
if (err) {
|
duration: requestTime,
|
||||||
if (err.status !== 404) {
|
status: res.statusCode,
|
||||||
log.error(err, req.url);
|
}, `<-- ${status}${req.method} ${req.url}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res.addListener('finish', done);
|
||||||
|
res.addListener('close', done);
|
||||||
|
|
||||||
res.writeHead(err.status, err.headers);
|
req.addListener('end', function () {
|
||||||
res.end(err.message);
|
if (req.url === '/') {
|
||||||
|
res.writeHead(302, { Location: '/index.html' })
|
||||||
|
return res.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
fileServer.serve(req, res, function (err) {
|
||||||
|
if (err) {
|
||||||
|
if (err.status !== 404) {
|
||||||
|
ctx.log.error(err, req.url);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}).resume()
|
|
||||||
})
|
|
||||||
|
|
||||||
const io = new socket(server)
|
res.writeHead(err.status, err.headers);
|
||||||
io.on('connection', onConnection.bind(this, io, config, db, log, core))
|
res.end(err.message);
|
||||||
|
}
|
||||||
coremonitor(io, config, db, log, core)
|
});
|
||||||
|
}).resume()
|
||||||
server.listen(port, '0.0.0.0', function(err) {
|
|
||||||
if (err) {
|
|
||||||
return reject(err)
|
|
||||||
}
|
|
||||||
log.event.info(`Server is listening on ${port} serving files on ${staticRoot}`)
|
|
||||||
log.info(`Server is listening on ${port} serving files on ${staticRoot}`)
|
|
||||||
resolve()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const io = new socket(server)
|
||||||
|
io.on('connection', onConnection.bind(this, io, ctx))
|
||||||
|
|
||||||
|
// coremonitor(io, config, db, log, core)
|
||||||
|
|
||||||
|
return server.listenAsync(port)
|
||||||
|
.then(function() {
|
||||||
|
ctx.log.info('Server is listening on port ' + port)
|
||||||
|
})
|
||||||
}
|
}
|
|
@ -5,61 +5,43 @@ const Module = require('../module')
|
||||||
const Status = Module({
|
const Status = Module({
|
||||||
init: function() {
|
init: function() {
|
||||||
this._name = '...loading...'
|
this._name = '...loading...'
|
||||||
this._management = {
|
this._apps = []
|
||||||
name: 'manage',
|
|
||||||
port: null,
|
|
||||||
repository: null,
|
|
||||||
active: null,
|
|
||||||
latestInstalled: null,
|
|
||||||
latestVersion: null,
|
|
||||||
running: null,
|
|
||||||
updating: null,
|
|
||||||
starting: null,
|
|
||||||
}
|
|
||||||
this._app = {
|
|
||||||
name: 'app',
|
|
||||||
port: null,
|
|
||||||
repository: null,
|
|
||||||
active: null,
|
|
||||||
latestInstalled: null,
|
|
||||||
latestVersion: null,
|
|
||||||
running: null,
|
|
||||||
updating: null,
|
|
||||||
starting: null,
|
|
||||||
}
|
|
||||||
|
|
||||||
this._socketOn(() => this.loadData())
|
this._socketOn(() => this.loadData())
|
||||||
},
|
},
|
||||||
|
|
||||||
loadData: function() {
|
loadData: function() {
|
||||||
socket.emit('core.config', {}, (res) => {
|
socket.emit('core.config', {}, (res) => {
|
||||||
this._name = res.name + ' - ' + res.serviceName
|
this._apps = []
|
||||||
this._app.port = res.port
|
console.log('config', res)
|
||||||
this._app.repository = res.appRepository
|
this._name = res.name
|
||||||
this._management.port = res.managePort
|
if (res.title) {
|
||||||
this._management.repository = res.manageRepository
|
this._name += ' - ' + res.title
|
||||||
|
}
|
||||||
|
for (let appName of res.applications) {
|
||||||
|
this._apps.push({
|
||||||
|
name: appName,
|
||||||
|
config: res[appName],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
console.log(this._apps)
|
||||||
m.redraw()
|
m.redraw()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.on('core.db', (res) => {
|
this.on('core.db', (res) => {
|
||||||
this._management.active = res.manageActive
|
console.log('db', res)
|
||||||
this._management.latestInstalled = res.manageLatestInstalled
|
|
||||||
this._management.latestVersion = res.manageLatestVersion
|
|
||||||
this._app.active = res.appActive
|
|
||||||
this._app.latestInstalled = res.appLatestInstalled
|
|
||||||
this._app.latestVersion = res.appLatestVersion
|
|
||||||
|
|
||||||
m.redraw()
|
m.redraw()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.on('core.status', (res) => {
|
this.on('core.status', (res) => {
|
||||||
console.log(res)
|
console.log(res)
|
||||||
this._management.running = res.manage
|
/*this._management.running = res.manage
|
||||||
this._management.updating = res.manageUpdating
|
this._management.updating = res.manageUpdating
|
||||||
this._management.starting = res.manageStarting
|
this._management.starting = res.manageStarting
|
||||||
this._app.running = res.app
|
this._app.running = res.app
|
||||||
this._app.updating = res.appUpdating
|
this._app.updating = res.appUpdating
|
||||||
this._app.starting = res.appStarting
|
this._app.starting = res.appStarting*/
|
||||||
|
|
||||||
m.redraw()
|
m.redraw()
|
||||||
})
|
})
|
||||||
|
@ -97,36 +79,36 @@ const Status = Module({
|
||||||
return m('div#status', [
|
return m('div#status', [
|
||||||
m('h1.header', this._name),
|
m('h1.header', this._name),
|
||||||
m('div.split', [
|
m('div.split', [
|
||||||
loopOver.map((group) => {
|
this._apps.map((app) => {
|
||||||
return m('div.item', [
|
return m('div.item', [
|
||||||
m('h4', group[0]),
|
m('h4', app.name),
|
||||||
m('p', this[group[1]].port
|
m('p', app.config.port
|
||||||
? `Port: ${this[group[1]].port}`
|
? `Port: ${app.config.port}`
|
||||||
: ''),
|
: ''),
|
||||||
m('p', this[group[1]].repository
|
m('p', app.config.repository
|
||||||
? `${this[group[1]].repository}`
|
? `${app.config.repository}`
|
||||||
: '< no repository >'),
|
: '< no repository >'),
|
||||||
m('p', this[group[1]].active
|
m('p', app.config.active
|
||||||
? `Running version: ${this[group[1]].active}`
|
? `Running version: ${app.config.active}`
|
||||||
: '< no running version >'),
|
: '< no running version >'),
|
||||||
m('p', this[group[1]].latestInstalled
|
m('p', app.config.latestInstalled
|
||||||
? `Latest installed: ${this[group[1]].latestInstalled}`
|
? `Latest installed: ${app.config.latestInstalled}`
|
||||||
: '< no version installed >'),
|
: '< no version installed >'),
|
||||||
m('p', this[group[1]].latestVersion
|
m('p', app.config.latestVersion
|
||||||
? `Latest version: ${this[group[1]].latestVersion}`
|
? `Latest version: ${app.config.latestVersion}`
|
||||||
: '< no version found >'),
|
: '< no version found >'),
|
||||||
this[group[1]].running !== null && this[group[1]].repository
|
app.config.running !== null && app.config.repository
|
||||||
? m('p',
|
? m('p',
|
||||||
{ class: this[group[1]].running ? 'running' : 'notrunning' },
|
{ class: app.config.running ? 'running' : 'notrunning' },
|
||||||
this[group[1]].running ? 'Running' : 'Not Running'
|
app.config.running ? 'Running' : 'Not Running'
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
!this[group[1]].running && (this[group[1]].updating || this[group[1]].starting)
|
!app.config.running && (app.config.updating || app.config.starting)
|
||||||
? m('div.status', this.getStatus(this[group[1]]))
|
? m('div.status', this.getStatus(app.config))
|
||||||
: null,
|
: null,
|
||||||
m('button', {
|
m('button', {
|
||||||
hidden: this[group[1]].running || this[group[1]].updating || this[group[1]].starting || !this[group[1]].repository,
|
hidden: app.config.running || app.config.updating || app.config.starting || !app.config.repository,
|
||||||
onclick: () => this.start(this[group[1]].name),
|
onclick: () => this.start(app.config.name),
|
||||||
}, 'Update/Start')
|
}, 'Update/Start')
|
||||||
])
|
])
|
||||||
}),
|
}),
|
||||||
|
|
42
dev.mjs
Normal file
42
dev.mjs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import { ServiceCore, Application, getLog, Util, Core } from 'service-core'
|
||||||
|
import * as index from './index.mjs'
|
||||||
|
|
||||||
|
let util = new Util(import.meta.url)
|
||||||
|
|
||||||
|
const helloWorldConfig = {
|
||||||
|
"provider": "git",
|
||||||
|
"url": "https://git.nfp.is/api/v1/repos/thething/sc-helloworld/releases",
|
||||||
|
"port": 8888,
|
||||||
|
}
|
||||||
|
|
||||||
|
var core = new ServiceCore('sc-manager', import.meta.url)
|
||||||
|
core.config['hello-world'] = helloWorldConfig
|
||||||
|
core.setConfig({
|
||||||
|
port: 4271,
|
||||||
|
})
|
||||||
|
|
||||||
|
core.init(index).then(function() {
|
||||||
|
let provConstructor = Core.providers.get(core.db.config['hello-world'].provider)
|
||||||
|
let provider = new provConstructor(core.db.config['hello-world'])
|
||||||
|
|
||||||
|
let helloWorld = new Application({
|
||||||
|
db: core.db,
|
||||||
|
util: util,
|
||||||
|
log: getLog('hello-world'),
|
||||||
|
core: core.core,
|
||||||
|
}, provider, 'hello-world')
|
||||||
|
|
||||||
|
core.core.applications.push(helloWorld)
|
||||||
|
core.core.applicationMap.set('hello-world', helloWorld)
|
||||||
|
|
||||||
|
helloWorld.startAutoupdater()
|
||||||
|
|
||||||
|
return core.run()
|
||||||
|
}).then(function() {
|
||||||
|
return core.core.applicationMap.get('hello-world').update()
|
||||||
|
}).then(function() {
|
||||||
|
return core.core.runApplication(core.core.applicationMap.get('hello-world'))
|
||||||
|
}).then(function() {
|
||||||
|
let helloApp = core.core.applicationMap.get('hello-world')
|
||||||
|
helloApp.on('updated', core.core.runApplication.bind(core.core, helloApp))
|
||||||
|
})
|
0
hello-world/.gitkeep
Normal file
0
hello-world/.gitkeep
Normal file
10
index.mjs
10
index.mjs
|
@ -1,5 +1,5 @@
|
||||||
export function start(config, db, log, core, http, port) {
|
import { run } from "./api/server.mjs"
|
||||||
return import('./api/server.mjs').then(function(module) {
|
|
||||||
return module.run(config, db, log, core, http, port)
|
export function start(http, port, ctx) {
|
||||||
})
|
return run(http, port, ctx)
|
||||||
}
|
}
|
||||||
|
|
34
package.json
34
package.json
|
@ -4,24 +4,42 @@
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"js:build:main": "asbundle client/index.js public/main.js",
|
"build:main": "asbundle client/index.js public/main.js",
|
||||||
"dev:server": "nodemon --watch runner.mjs --watch api runner.mjs | bunyan",
|
"build:main:watch": "npm-watch build:main",
|
||||||
"dev:client": "nodemon --watch client --exec \"npm run js:build:main\"",
|
"dev:server": "node dev.mjs | bunyan",
|
||||||
"build": "npm run js:build:main",
|
"dev:server:watch": "npm-watch dev:server",
|
||||||
|
"dev": "npm run dev:server && npm run dev:client",
|
||||||
|
"build": "npm run build:main",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
|
"watch": {
|
||||||
|
"dev:server": {
|
||||||
|
"patterns": [
|
||||||
|
"api/*"
|
||||||
|
],
|
||||||
|
"extensions": "js,mjs",
|
||||||
|
"quiet": true,
|
||||||
|
"inherit": true
|
||||||
|
},
|
||||||
|
"build:main": {
|
||||||
|
"patterns": [
|
||||||
|
"client/*"
|
||||||
|
],
|
||||||
|
"extensions": "js,mjs",
|
||||||
|
"quiet": true,
|
||||||
|
"inherit": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "WTFPL",
|
"license": "WTFPL",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lodash": "^4.17.20",
|
"flaska": "^1.2.1",
|
||||||
"node-static": "^0.7.11",
|
"node-static": "^0.7.11",
|
||||||
"socket.io-serveronly": "^2.3.0"
|
"socket.io-serveronly": "^2.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"asbundle": "^2.6.1",
|
"asbundle": "^2.6.1",
|
||||||
"bunyan-lite": "^1.0.1",
|
|
||||||
"mithril": "^2.0.4",
|
"mithril": "^2.0.4",
|
||||||
"nodemon": "^2.0.4",
|
"service-core": "^3.0.0-beta.11"
|
||||||
"service-core": "^2.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue