Finished implementing basic manager support for service core

master
Jonatan Nilsson 2020-09-09 15:42:55 +00:00
parent d42f08107b
commit fa13ba565d
21 changed files with 107 additions and 3808 deletions

4
.gitignore vendored
View File

@ -102,3 +102,7 @@ dist
# TernJS port file # TernJS port file
.tern-port .tern-port
db.json
app/*
manage/*

1
.npmrc Normal file
View File

@ -0,0 +1 @@
package-lock=false

View File

@ -51,14 +51,12 @@ export async function unlistenlogs(ctx) {
* Update specific software * Update specific software
*/ */
export async function update(ctx, data, cb) { export async function update(ctx, data, cb) {
if (data.name === 'app') { if (data.name !== 'app' && data.name !== 'manage') {
await ctx.core.updateProgram('app')
} else if (data.name === 'manage') {
await ctx.core.updateProgram('manage')
} else {
ctx.log.warn('Invalid update command for app ' + data.name) ctx.log.warn('Invalid update command for app ' + data.name)
ctx.log.event.warn('Invalid update command for app ' + data.name) ctx.log.event.warn('Invalid update command for app ' + data.name)
return
} }
await ctx.core.updateProgram(data.name)
} }
/* /*
@ -67,14 +65,26 @@ export async function update(ctx, data, cb) {
* Start specific software * Start specific software
*/ */
export async function start(ctx, data, cb) { export async function start(ctx, data, cb) {
if (data.name === 'app') { if (data.name !== 'app' && data.name !== 'manage') {
await ctx.core.startProgram('app')
} else if (data.name === 'manage') {
await ctx.core.startProgram('manage')
} else {
ctx.log.warn('Invalid start command for app ' + data.name) ctx.log.warn('Invalid start command for app ' + data.name)
ctx.log.event.warn('Invalid start command for app ' + data.name) ctx.log.event.warn('Invalid start command for app ' + data.name)
return
} }
await ctx.core.tryStartProgram(data.name)
}
/*
* Event: 'core.updatestart'
*
* Update and start specific software
*/
export async function updatestart(ctx, data, cb) {
if (data.name !== 'app' && data.name !== 'manage') {
ctx.log.warn('Invalid updatestart command for app ' + data.name)
ctx.log.event.warn('Invalid updatestart command for app ' + data.name)
return
}
await ctx.core.start(data.name)
} }
/* /*

View File

@ -28,6 +28,7 @@ function onConnection(server, config, db, log, coreService, data) {
const child = log.child({ const child = log.child({
id: socket.id, id: socket.id,
}) })
child.event = log.event
child.info('Got new socket connection') child.info('Got new socket connection')

View File

@ -1,4 +1,3 @@
import http from 'http'
import path from 'path' import path from 'path'
import { fileURLToPath } from 'url' import { fileURLToPath } from 'url'
import socket from 'socket.io-serveronly' import socket from 'socket.io-serveronly'
@ -7,7 +6,7 @@ import coremonitor from './core/coremonitor.mjs'
import onConnection from './routerio.mjs' import onConnection from './routerio.mjs'
export function run(config, db, log, core) { export function run(config, db, log, core, http, port) {
const __dirname = path.dirname(fileURLToPath(import.meta.url)) const __dirname = path.dirname(fileURLToPath(import.meta.url))
const staticRoot = path.join(__dirname,'../public') const staticRoot = path.join(__dirname,'../public')
@ -70,13 +69,13 @@ export function run(config, db, log, core) {
coremonitor(io, config, db, log, core) coremonitor(io, config, db, log, core)
server.listen(config.managePort, '0.0.0.0', function(err) { server.listen(port, '0.0.0.0', function(err) {
if (err) { if (err) {
log.fatal(err) log.fatal(err)
log.event.error('Error starting server: ' + err.message) log.event.error('Error starting server: ' + err.message)
return process.exit(2) return process.exit(2)
} }
log.event.info(`Server is listening on ${config.managePort} serving files on ${staticRoot}`) log.event.info(`Server is listening on ${port} serving files on ${staticRoot}`)
log.info(`Server is listening on ${config.managePort} serving files on ${staticRoot}`) log.info(`Server is listening on ${port} serving files on ${staticRoot}`)
}) })
} }

View File

@ -6,22 +6,26 @@ const Status = Module({
init: function() { init: function() {
this._name = '...loading...' this._name = '...loading...'
this._management = { this._management = {
name: 'manage',
port: null, port: null,
repository: null, repository: null,
active: null, active: null,
latestInstalled: null, latestInstalled: null,
lastActive: null,
latestVersion: null, latestVersion: null,
running: null, running: null,
updating: null,
starting: null,
} }
this._app = { this._app = {
name: 'app',
port: null, port: null,
repository: null, repository: null,
active: null, active: null,
latestInstalled: null, latestInstalled: null,
lastActive: null,
latestVersion: null, latestVersion: null,
running: null, running: null,
updating: null,
starting: null,
} }
this._socketOn(() => this.loadData()) this._socketOn(() => this.loadData())
@ -40,19 +44,22 @@ const Status = Module({
this.on('core.db', (res) => { this.on('core.db', (res) => {
this._management.active = res.manageActive this._management.active = res.manageActive
this._management.latestInstalled = res.manageLatestInstalled this._management.latestInstalled = res.manageLatestInstalled
this._management.lastActive = res.manageLastActive
this._management.latestVersion = res.manageLatestVersion this._management.latestVersion = res.manageLatestVersion
this._app.active = res.appActive this._app.active = res.appActive
this._app.latestInstalled = res.appLatestInstalled this._app.latestInstalled = res.appLatestInstalled
this._app.lastActive = res.appLastActive
this._app.latestVersion = res.appLatestVersion this._app.latestVersion = res.appLatestVersion
m.redraw() m.redraw()
}) })
this.on('core.status', (res) => { this.on('core.status', (res) => {
console.log(res)
this._management.running = res.manage this._management.running = res.manage
this._management.updating = res.manageUpdating
this._management.starting = res.manageStarting
this._app.running = res.app this._app.running = res.app
this._app.updating = res.appUpdating
this._app.starting = res.appStarting
m.redraw() m.redraw()
}) })
@ -68,6 +75,20 @@ const Status = Module({
socket.emit('core.restart', {}) socket.emit('core.restart', {})
}, },
start: function(name) {
socket.emit('core.updatestart', {
name: name,
})
},
getStatus: function(active) {
if (active.updating) {
return '< Updating >'
} else {
return '< Starting >'
}
},
view: function() { view: function() {
let loopOver = [ let loopOver = [
['Management service', '_management'], ['Management service', '_management'],
@ -91,20 +112,21 @@ const Status = Module({
m('p', this[group[1]].latestInstalled m('p', this[group[1]].latestInstalled
? `Latest installed: ${this[group[1]].latestInstalled}` ? `Latest installed: ${this[group[1]].latestInstalled}`
: '< no version installed >'), : '< no version installed >'),
m('p', this[group[1]].lastActive
? `Last stable version: ${this[group[1]].lastActive}`
: '< no last stable version >'),
m('p', this[group[1]].latestVersion m('p', this[group[1]].latestVersion
? `Latest version: ${this[group[1]].latestVersion}` ? `Latest version: ${this[group[1]].latestVersion}`
: '< no version found >'), : '< no version found >'),
this[group[1]].running !== null this[group[1]].running !== null && this[group[1]].repository
? m('p', ? m('p',
{ class: group[1].running ? 'running' : 'notrunning' }, { class: this[group[1]].running ? 'running' : 'notrunning' },
group[1].running ? 'Running' : 'Not Running' this[group[1]].running ? 'Running' : 'Not Running'
) )
: null, : null,
!this[group[1]].running && (this[group[1]].updating || this[group[1]].starting)
? m('div.status', this.getStatus(this[group[1]]))
: null,
m('button', { m('button', {
hidden: this[group[1]].running || this[group[1]].updating || this[group[1]].starting || !this[group[1]].repository,
onclick: () => this.start(this[group[1]].name),
}, 'Update/Start') }, 'Update/Start')
]) ])
}), }),

View File

@ -68,7 +68,6 @@ const Updater = Module({
this.app = { this.app = {
repository: this[this.activeApp + 'Repository'], repository: this[this.activeApp + 'Repository'],
active: this.db[this.activeApp + 'Active'], active: this.db[this.activeApp + 'Active'],
lastActive: this.db[this.activeApp + 'LastActive'],
latestInstalled: this.db[this.activeApp + 'LatestInstalled'], latestInstalled: this.db[this.activeApp + 'LatestInstalled'],
latestVersion: this.db[this.activeApp + 'LatestVersion'], latestVersion: this.db[this.activeApp + 'LatestVersion'],
logs: '', logs: '',
@ -120,19 +119,16 @@ const Updater = Module({
}, 'Update Manager'), }, 'Update Manager'),
]), ]),
this.activeApp && this.app ? [ this.activeApp && this.app ? [
m('h4', this.app.repository
? `${this.app.repository}`
: '< no repository >'),
m('div.info', [ m('div.info', [
m('p', this.app.active m('p', this.app.repository
? `Running version: ${this.app.active}` ? `Repository: ${this.app.repository}`
: '< no running version >'), : '< no repository >'),
m('p', this.app.latestInstalled m('p', this.app.latestInstalled
? `Latest installed: ${this.app.latestInstalled}` ? `Latest installed: ${this.app.latestInstalled}`
: '< no version installed >'), : '< no version installed >'),
m('p', this.app.lastActive m('p', this.app.active
? `Last stable version: ${this.app.lastActive}` ? `Running version: ${this.app.active}`
: '< no last stable version >'), : '< no running version >'),
m('p', this.app.latestVersion m('p', this.app.latestVersion
? `Latest version: ${this.app.latestVersion}` ? `Latest version: ${this.app.latestVersion}`
: '< no version found >'), : '< no version found >'),

View File

@ -3,7 +3,8 @@
"serviceName": "Service-Core Manager", "serviceName": "Service-Core Manager",
"description": "Manager for service core", "description": "Manager for service core",
"port": 4270, "port": 4270,
"managePort": 4269, "managePort": 4271,
"devPort": 4269,
"appRepository": "thething/sc-helloworld", "appRepository": "thething/sc-helloworld",
"manageRepository": null "manageRepository": null
} }

View File

@ -1,5 +1,5 @@
export function start(config, db, log, core) { export function start(config, db, log, core, http, port) {
return import('./api/server.mjs').then(function(module) { return import('./api/server.mjs').then(function(module) {
return module.run(config, db, log, core) return module.run(config, db, log, core, http, port)
}) })
} }

1092
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,17 +4,22 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"js:build:main": "asbundle app/index.js public/main.js", "js:build:main": "asbundle client/index.js public/main.js",
"dev": "nodemon --watch app --exec \"npm run js:build:main\"", "dev:server": "nodemon --watch runner.mjs --watch api runner.mjs | bunyan",
"dev:client": "nodemon --watch client --exec \"npm run js:build:main\"",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"author": "", "author": "",
"license": "ISC", "license": "WTFPL",
"dependencies": { "dependencies": {
"asbundle": "^2.6.1", "lodash": "^4.17.20",
"mithril": "^2.0.4",
"node-static": "^0.7.11", "node-static": "^0.7.11",
"nodemon": "^2.0.4",
"socket.io-serveronly": "^2.3.0" "socket.io-serveronly": "^2.3.0"
},
"devDependencies": {
"asbundle": "^2.6.1",
"bunyan-lite": "^1.0.1",
"mithril": "^2.0.4",
"nodemon": "^2.0.4"
} }
} }

View File

@ -140,10 +140,10 @@ pre {
#logger span.white { color: rgb(242,242,242); } #logger span.white { color: rgb(242,242,242); }
#logger span.yellow { color: rgb(193,156,0); } #logger span.yellow { color: rgb(193,156,0); }
#logger span.cyan { color: rgb(58,150,221); } #logger span.cyan { color: hsl(206.1, 70.6%, 63.7%); }
#logger span.magenta { color: rgb(136,23,152); } #logger span.magenta { color: hsl(292.6, 73.7%, 58.3%); }
#logger span.red { color: rgb(197,15,31); } #logger span.red { color: hsl(354.7, 85.8%, 67.6%); }
#logger span.green { color: rgb(19,161,14); } #logger span.green { color: hsl(118, 84%, 46.3%); }
#logger span.inverse { #logger span.inverse {
color: #0c0c0c; color: #0c0c0c;
background: white; background: white;
@ -187,16 +187,22 @@ pre {
padding: 0.25rem 1rem; padding: 0.25rem 1rem;
} }
#status .item p.running { #status .item p.running {
color: rgb(19,161,14); color: hsl(118, 84%, 46.3%);
text-align: center; text-align: center;
} }
#status .item p.notrunning { #status .item p.notrunning {
color: rgb(197,15,31); color: hsl(354.7, 85.8%, 67.6%);
text-align: center; text-align: center;
} }
#status button { #status button {
margin-top: 1rem; margin-top: 1rem;
} }
#status .status {
margin-top: 1rem;
align-self: center;
padding: 0.5rem;
color: #ccc;
}
/***************** Updater ********************/ /***************** Updater ********************/
#update { #update {
@ -264,7 +270,7 @@ pre {
@media only screen and (min-height: 650px) { @media only screen and (min-height: 650px) {
#update .console { #update .console {
height: calc(100vh - 340px); height: calc(100vh - 300px);
} }
} }

File diff suppressed because one or more lines are too long

10
runner.mjs Normal file
View File

@ -0,0 +1,10 @@
import ServiceCore from 'service-core'
import * as server from './index.mjs'
const serviceCore = new ServiceCore('sc-manager', import.meta.url)
serviceCore.init(server)
.then(function() {})
.catch(function(err) {
serviceCore.log.error(err, 'Unknown error starting server')
})