parent
e401809ad5
commit
8319859828
@ -0,0 +1,62 @@
|
|||||||
|
const { Injectable } = require('flitter-di')
|
||||||
|
const RoutineExecutionResult = require('./RoutineExecutionResult')
|
||||||
|
const StepResult = require('./StepResult')
|
||||||
|
const InvalidRoutineTypeError = require('./error/InvalidRoutineTypeError')
|
||||||
|
|
||||||
|
class Routine extends Injectable {
|
||||||
|
static get services() {
|
||||||
|
return [...super.services, 'states', 'app']
|
||||||
|
}
|
||||||
|
|
||||||
|
_config
|
||||||
|
_hosts
|
||||||
|
_type
|
||||||
|
|
||||||
|
constructor(hosts, config, type = 'checks') {
|
||||||
|
super()
|
||||||
|
this.app.make(StepResult)
|
||||||
|
this.app.make(RoutineExecutionResult)
|
||||||
|
|
||||||
|
this._config = config
|
||||||
|
this._hosts = hosts
|
||||||
|
this._type = type
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute() {
|
||||||
|
const result = await this._build_result()
|
||||||
|
|
||||||
|
for ( const step of result.steps ) {
|
||||||
|
if ( this._type === 'checks' ) {
|
||||||
|
step.status = (await step.step.check()) ? 'success' : 'fail'
|
||||||
|
step.message = step.status === 'success' ? 'Check passed.' : step.step.check_message()
|
||||||
|
} else if ( this._type === 'apply' ) {
|
||||||
|
if ( !(await step.step.check()) ) {
|
||||||
|
await step.step.apply()
|
||||||
|
step.status = (await step.step.check()) ? 'success' : 'fail'
|
||||||
|
step.message = step.status === 'success' ? 'State applied successfully.' : step.step.failure_message()
|
||||||
|
} else {
|
||||||
|
step.status = 'success'
|
||||||
|
step.message = 'Check passed.'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new InvalidRoutineTypeError(this._type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.overall_state = result.steps.every(x => x.status === 'success') ? 'success' : 'fail'
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
async _build_result() {
|
||||||
|
const steps = []
|
||||||
|
for ( const step_config of this._config.steps ) {
|
||||||
|
const step = this.states.from_config(this._hosts[step_config.host], step_config)
|
||||||
|
const result = new StepResult(this, step)
|
||||||
|
steps.push(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RoutineExecutionResult(steps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = Routine
|
@ -0,0 +1,23 @@
|
|||||||
|
const { Injectable } = require('flitter-di')
|
||||||
|
|
||||||
|
class RoutineExecutionResult extends Injectable {
|
||||||
|
steps = []
|
||||||
|
overall_state = 'pending' // pending | success | fail
|
||||||
|
|
||||||
|
constructor(steps = []) {
|
||||||
|
super()
|
||||||
|
this.steps = steps
|
||||||
|
}
|
||||||
|
|
||||||
|
get status() {
|
||||||
|
if ( this.steps.some(x => x.status === 'pending') ) return 'pending'
|
||||||
|
else if ( this.steps.some(x => x.status === 'fail') ) return 'fail'
|
||||||
|
else return 'success'
|
||||||
|
}
|
||||||
|
|
||||||
|
failures() {
|
||||||
|
return this.steps.filter(x => x.status === 'fail')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = RoutineExecutionResult
|
@ -0,0 +1,16 @@
|
|||||||
|
const { Injectable } = require('flitter-di')
|
||||||
|
|
||||||
|
class StepResult extends Injectable {
|
||||||
|
step
|
||||||
|
routine
|
||||||
|
status = 'pending' // pending | success | fail
|
||||||
|
message = ''
|
||||||
|
|
||||||
|
constructor(routine, step) {
|
||||||
|
super()
|
||||||
|
this.routine = routine
|
||||||
|
this.step = step
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = StepResult
|
@ -0,0 +1,7 @@
|
|||||||
|
class InvalidRoutineTypeError extends Error {
|
||||||
|
constructor(routine_type) {
|
||||||
|
super(`Invalid routine type: ${routine_type}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = InvalidRoutineTypeError
|
@ -0,0 +1,25 @@
|
|||||||
|
const State = require('../State')
|
||||||
|
|
||||||
|
class IsAliveState extends State {
|
||||||
|
async apply() {
|
||||||
|
throw new Error('IsAliveState cannot be applied. It is a check measure only.')
|
||||||
|
}
|
||||||
|
|
||||||
|
async check() {
|
||||||
|
return this._host.is_alive()
|
||||||
|
}
|
||||||
|
|
||||||
|
async reverse() {
|
||||||
|
throw new Error('IsAliveState cannot be reversed. It is a check measure only.')
|
||||||
|
}
|
||||||
|
|
||||||
|
failure_message() {
|
||||||
|
return `Unable to connect to host "${this._host.name}".`
|
||||||
|
}
|
||||||
|
|
||||||
|
check_message() {
|
||||||
|
return this.failure_message()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = IsAliveState
|
@ -0,0 +1,30 @@
|
|||||||
|
const { Service } = require('flitter-di')
|
||||||
|
const Routine = require('../classes/routine/Routine')
|
||||||
|
|
||||||
|
/*
|
||||||
|
* routines Service
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* This is a service file that will be made available through Flitter's
|
||||||
|
* dependency injector to the rest of the application based on its given
|
||||||
|
* canonical name.
|
||||||
|
*
|
||||||
|
* e.g. app.di().service("routines")
|
||||||
|
*/
|
||||||
|
class RoutinesService extends Service {
|
||||||
|
static get services() {
|
||||||
|
return [...super.services, 'app', 'configs', 'hosts']
|
||||||
|
}
|
||||||
|
|
||||||
|
async get(name) {
|
||||||
|
this.app.make(Routine)
|
||||||
|
const config = this.configs.get(`routines:${name}`)
|
||||||
|
const hosts = {}
|
||||||
|
for ( const host_name of config.hosts ) {
|
||||||
|
hosts[host_name] = await this.hosts.get(host_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Routine(hosts, config, config.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = RoutinesService
|
@ -0,0 +1,16 @@
|
|||||||
|
// This is the configuration for the Flitter Gotify wrapper service, 'notify'.
|
||||||
|
const notify = {
|
||||||
|
// URL to the Gotify host (e.g. https://my-gotify.server.url/)
|
||||||
|
host: env('GOTIFY_HOST'),
|
||||||
|
|
||||||
|
// collection of notification channel groups
|
||||||
|
groups: {
|
||||||
|
// default group. You can specify as many groups as you want.
|
||||||
|
// Each group should be an array of Gotify app keys.
|
||||||
|
default: [
|
||||||
|
env('GOTIFY_DEFAULT_APP_KEY'),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = notify
|
@ -0,0 +1,20 @@
|
|||||||
|
const login_config = {
|
||||||
|
type: 'checks',
|
||||||
|
hosts: ['core', 'localhost', 'edge'],
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
type: 'os.alive',
|
||||||
|
host: 'core',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'os.alive',
|
||||||
|
host: 'edge',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'os.alive',
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = login_config
|
@ -0,0 +1,18 @@
|
|||||||
|
const tmpdir_config = {
|
||||||
|
type: 'checks',
|
||||||
|
hosts: ['core', 'localhost'],
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
type: 'fs.directory',
|
||||||
|
host: 'core',
|
||||||
|
path: '/tmp/glmdev',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'fs.directory',
|
||||||
|
host: 'localhost',
|
||||||
|
path: '/tmp/glmdev',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = tmpdir_config
|
@ -0,0 +1,16 @@
|
|||||||
|
const updates_config = {
|
||||||
|
type: 'checks',
|
||||||
|
hosts: ['core', 'localhost'],
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
type: 'package.updates',
|
||||||
|
host: 'core',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'package.updates',
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = updates_config
|
Loading…
Reference in new issue