balena-supervisor/src/supervisor.ts
Cameron Diver 37945b4aa5 Don't attempt to setup a log stream to the cloud before provision
Change-type: patch
Signed-off-by: Cameron Diver <cameron@balena.io>
2019-07-09 13:21:05 +01:00

119 lines
3.2 KiB
TypeScript

import APIBinder from './api-binder';
import Config, { ConfigKey } from './config';
import Database from './db';
import EventTracker from './event-tracker';
import Logger from './logger';
import SupervisorAPI from './supervisor-api';
import DeviceState = require('./device-state');
import constants = require('./lib/constants');
import log from './lib/supervisor-console';
import version = require('./lib/supervisor-version');
const startupConfigFields: ConfigKey[] = [
'uuid',
'listenPort',
'apiEndpoint',
'apiSecret',
'apiTimeout',
'unmanaged',
'deviceApiKey',
'mixpanelToken',
'mixpanelHost',
'loggingEnabled',
'localMode',
'legacyAppsPresent',
];
export class Supervisor {
private db: Database;
private config: Config;
private eventTracker: EventTracker;
private logger: Logger;
private deviceState: DeviceState;
private apiBinder: APIBinder;
private api: SupervisorAPI;
public constructor() {
this.db = new Database();
this.config = new Config({ db: this.db });
this.eventTracker = new EventTracker();
this.logger = new Logger({ db: this.db, eventTracker: this.eventTracker });
this.deviceState = new DeviceState({
config: this.config,
db: this.db,
eventTracker: this.eventTracker,
logger: this.logger,
});
this.apiBinder = new APIBinder({
config: this.config,
db: this.db,
deviceState: this.deviceState,
eventTracker: this.eventTracker,
});
// FIXME: rearchitect proxyvisor to avoid this circular dependency
// by storing current state and having the APIBinder query and report it / provision devices
this.deviceState.applications.proxyvisor.bindToAPI(this.apiBinder);
// We could also do without the below dependency, but it's part of a much larger refactor
this.deviceState.applications.apiBinder = this.apiBinder;
this.api = new SupervisorAPI({
config: this.config,
eventTracker: this.eventTracker,
routers: [this.apiBinder.router, this.deviceState.router],
healthchecks: [
this.apiBinder.healthcheck.bind(this.apiBinder),
this.deviceState.healthcheck.bind(this.deviceState),
],
});
}
public async init() {
log.info(`Supervisor v${version} starting up...`);
await this.db.init();
await this.config.init();
const conf = await this.config.getMany(startupConfigFields);
// We can't print to the dashboard until the logger
// has started up, so we leave a trail of breadcrumbs
// in the logs in case runtime fails to get to the
// first dashboard logs
log.debug('Starting event tracker');
await this.eventTracker.init(conf);
log.debug('Starting api binder');
await this.apiBinder.initClient();
log.debug('Starting logging infrastructure');
this.logger.init({
enableLogs: conf.loggingEnabled,
config: this.config,
...conf,
});
this.logger.logSystemMessage('Supervisor starting', {}, 'Supervisor start');
if (conf.legacyAppsPresent) {
log.info('Legacy app detected, running migration');
this.deviceState.normaliseLegacy(this.apiBinder.balenaApi);
}
await this.deviceState.init();
log.info('Starting API server');
this.api.listen(
constants.allowedInterfaces,
conf.listenPort,
conf.apiTimeout,
);
this.deviceState.on('shutdown', () => this.api.stop());
await this.apiBinder.start();
}
}
export default Supervisor;