This commit is contained in:
peter
2019-08-26 19:59:23 +02:00
parent a18d28accc
commit 38b8d626aa
4 changed files with 134 additions and 43 deletions
+3 -3
View File
@@ -1981,9 +1981,9 @@
}
},
"frontblock-generic": {
"version": "0.29.0",
"resolved": "https://registry.npmjs.org/frontblock-generic/-/frontblock-generic-0.29.0.tgz",
"integrity": "sha512-L+g2hVBgTlqhPXWUMK0T6RtxZUKBI0Ts1SQ4ltspwToPiAWPkqBiAFx8ZK1qwr4kQ/lVeNl6GNX2An5wUkULzw==",
"version": "0.30.1",
"resolved": "https://registry.npmjs.org/frontblock-generic/-/frontblock-generic-0.30.1.tgz",
"integrity": "sha512-r+4/Zq9WGkD6Ma9F2AQp2ZP546jgXLde7aB050HHwF9t0O4ewy+ohfgyvEEH3dpIoQBbUWuD9uaAtahpNUYcqA==",
"requires": {
"@types/lowdb": "^1.0.9",
"@types/node": "^12.7.1",
+1 -1
View File
@@ -26,7 +26,7 @@
"child-process-promise": "^2.2.1",
"express": "^4.16.4",
"frontblock": "^0.14.0",
"frontblock-generic": "^0.29.0",
"frontblock-generic": "^0.30.1",
"git-cherrypicker": "0.0.3",
"git-describe": "^4.0.4",
"http": "0.0.0",
+13 -27
View File
@@ -4,7 +4,7 @@ import * as Logger from 'log4js'
import * as Knex from 'knex'
import { FrontblockApiClient } from 'frontblock';
import { socketioRPC, rpcHooker, ExtendedRpcInfo } from 'frontblock-generic/RPC';
import { ApiClientBase } from 'frontblock-generic/Admin';
import { ApiClientBase, AdminBase } from 'frontblock-generic/Admin';
import express = require('express');
import http = require('http');
import bsock = require('bsock');
@@ -12,6 +12,7 @@ import { promises as fs } from "fs"
import * as path from "path"
import { UpdateManager } from './UpdateManger';
import { FrontblockApiConf, FrontblockApi } from 'frontblock-generic/Api';
import { Plugin } from 'frontblock-generic/Plugin';
var exec = require('child-process-promise').exec;
Logger.configure({
@@ -38,7 +39,7 @@ export type AdminConf = { httpPort: number}
*
* The list of available plugins is published via the frontblock API and downloaded via gitea-releases
*/
export class FrontblockAdmin extends ApiClientBase<AdminConf>{
export class FrontblockAdmin extends AdminBase<AdminConf>{
private express
private httpServer
@@ -46,9 +47,8 @@ export class FrontblockAdmin extends ApiClientBase<AdminConf>{
private wsServer = http.createServer()
private updateManager:UpdateManager = new UpdateManager(this)
constructor(){
super("FrontblockAdmin")
constructor(runningPlugins: Plugin[] = []){
super(runningPlugins)
this.initialize()
}
@@ -72,10 +72,17 @@ export class FrontblockAdmin extends ApiClientBase<AdminConf>{
}
protected makeApiClient(conf: FrontblockApiConf): FrontblockApi {
return new FrontblockApiClient(conf)
// @ts-ignore
if(this.apiClient) this.apiClient.disconnect()
this.apiClient = new FrontblockApiClient(conf)
// @ts-ignore
this.apiClient.connect()
return this.apiClient
}
private async initialize(){
this.addPlugin(this.updateManager)
await this.updateManager.updateAdmin()
await this.updateManager.updatePlatformDependencies()
await this.updateManager.updateDashboard()
@@ -85,27 +92,6 @@ export class FrontblockAdmin extends ApiClientBase<AdminConf>{
this.startWebserver()
}
private initApis(socket){
const adminRPCs:socketioRPC[] = [{
name: 'info',
type: 'call',
visibility: 'private',
func: async () => rpcInfos
}]
const rpcInfos:ExtendedRpcInfo[] = [
...rpcHooker(socket, "Admin", adminRPCs, false),
...rpcHooker(socket, "ApiClient", this.exportRPCs()),
...rpcHooker(socket, "UpdateManager", this.updateManager.exportRPCs()),
...this.updateManager.getLoadedPlugins().flatMap(plugin => rpcHooker(socket, plugin.name, plugin.exportRPCs()))
]
socket.on('close', () => {
logger.info("Client disconnected")
})
}
private startWebserver(){
if(this.httpServer != null || this.express != null){
logger.warn("Webserver is already running")
+117 -12
View File
@@ -3,8 +3,11 @@ import { socketioRPC } from "frontblock-generic/RPC";
import { GitUpdater, RepoFolderStatus } from "./GitUpdater";
import { FrontblockCherryPicker } from "git-cherrypicker";
import * as Logger from 'log4js'
import { mkdirSync } from "fs";
import * as path from "path";
import { FrontblockAdmin } from "./FrontblockAdmin";
import { TableDefiniton } from "frontblock-generic/Admin";
import { promises as fs, mkdirSync } from "fs"
var exec = require('child-process-promise').exec;
Logger.configure({
@@ -20,10 +23,106 @@ Logger.configure({
})
const logger = Logger.getLogger("admin/updatemanager")
abstract class Extension{
constructor(
public name: string,
public version: string,
){}
export class UpdateManager extends Plugin<void>{
name: string = "UpdateManager"
private loadedPlugins:{[name in string]:Plugin<any>} = {}
abstract install():Promise<boolean>
abstract uninstall():Promise<boolean>
abstract update():Promise<boolean>
abstract isOutdated():Promise<boolean>
}
export class NPMExtension extends Extension{
constructor(
name,
version = "latest",
public localPrefix,
){
super(name, version)
}
public async install(): Promise<boolean> {
logger.info("npm install", this.name, 'to', path.resolve(this.localPrefix, this.name))
await fs.mkdir(this.localPrefix, {recursive: true})
const { error, stdout, stderr } = await exec('npm install --prefix '+ this.localPrefix + ' ' + this.name+"@"+this.version)
if (error !== null) {
logger.warn('npm install', this.name, 'from prefix', this.localPrefix, 'stderr:', stderr)
return false
} else {
logger.info('npm install', this.name, 'from prefix', this.localPrefix, 'stdout:', stdout)
return true
}
}
public async uninstall(): Promise<boolean> {
logger.info("npm uninstall", this.name, 'from', path.resolve(this.localPrefix, this.name))
const { error, stdout, stderr } = await exec('npm uninstall --prefix '+ this.localPrefix + ' ' + this.name)
if (error !== null) {
logger.warn('npm uninstall', this.name, 'from prefix', this.localPrefix, 'stderr:', stderr)
return false
} else {
logger.info('npm uninstall', this.name, 'from prefix', this.localPrefix, 'stdout:', stdout)
return true
}
}
public async update(): Promise<boolean> {
logger.info("npm update", path.resolve(this.localPrefix, this.name))
const { error, stdout, stderr } = await exec('npm update --prefix '+ this.localPrefix + ' ' + this.name)
if (error !== null) {
logger.warn('npm update', this.name, 'from prefix', this.localPrefix, 'stderr:', stderr)
return false
} else {
logger.info('npm update', this.name, 'from prefix', this.localPrefix, 'stdout:', stdout)
return true
}
}
public async isOutdated(): Promise<boolean> {
logger.info("npm outdated", path.resolve(this.localPrefix, this.name))
const { error, stdout, stderr } = await exec('npm list --prefix '+ this.localPrefix + ' --depth=0 | grep ' + this.name)
if (error !== null) {
logger.warn('npm outdated', this.name, 'from prefix', this.localPrefix, 'stderr:', stderr)
return false
} else {
logger.info('npm outdated', this.name, 'from prefix', this.localPrefix, 'stdout:', stdout)
return true
}
}
}
export class GitExtension extends Extension{
constructor(
name:string,
version = "latest",
public localPrefix:string,
){
super(name, version)
}
public async install(): Promise<boolean> {
}
public async uninstall(): Promise<boolean> {
}
public async update(): Promise<boolean> {
}
public async isOutdated(): Promise<boolean> {
}
}
export class UpdateManager extends Plugin{
private loadedPlugins:{[name in string]:Plugin} = {}
private dashboardUpdater:GitUpdater
private adminUpdater:GitUpdater
private pluginUpdaters:{[name in string]:GitUpdater} = {}
@@ -32,8 +131,8 @@ export class UpdateManager extends Plugin<void>{
super(admin, "UpdateManager")
}
getDefaultConfig(): void {
return
getDefaultConfig(): {} {
return {}
}
exportRPCs(): socketioRPC[] {
@@ -70,13 +169,23 @@ export class UpdateManager extends Plugin<void>{
}]
}
getTableDefinitions(): TableDefiniton[] {
return []
}
async updatePlatformDependencies(){
logger.info("installing npm stuff")
/*
const res = await exec('npm install --prefix ./plugins knex sqlite3')
logger.warn(res.stderr)
logger.info(res.stdout)
*/
await Promise.all([
new NPMExtension("knex", "./plugins", "0.19.2").install(),
new NPMExtension("sqlite3", "./plugins", "4.1.0").install()
])
}
async updateAdmin(force:boolean = false){
@@ -104,11 +213,6 @@ export class UpdateManager extends Plugin<void>{
return status
}
async installPlugin(name: string, force:boolean = false):Promise<RepoFolderStatus>{
logger.warn("Cloning fb-dist/"+name+".git into ./plugins/"+name+" ..."+(force?" USING FORCE!":""))
this.pluginUpdaters[name] = new GitUpdater("./plugins/"+name)
return await this.pluginUpdaters[name].cloneRepo("https://gitea.frontblock.me/fb-dist/"+name.toLowerCase()+".git", force)
}
async startPlugin(name:string):Promise<boolean>{
if(!this.pluginUpdaters[name]) return false
@@ -133,6 +237,7 @@ export class UpdateManager extends Plugin<void>{
const pluginClass = await eval('require')(str)
const pluginObj = new pluginClass.default()
await pluginObj.start()
this.admin.addPlugin(pluginObj)
this.loadedPlugins[name] = pluginObj
return true
}