mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-01-18 18:56:24 +00:00
Don't attempt to setup a log stream to the cloud before provision
Change-type: patch Signed-off-by: Cameron Diver <cameron@balena.io>
This commit is contained in:
parent
20a83e8e0a
commit
37945b4aa5
@ -528,7 +528,9 @@ export class APIBinder {
|
||||
// the watchdog to kill the supervisor - and killing the supervisor will
|
||||
// not help in this situation
|
||||
log.error(
|
||||
'Non-200 response from the API! Status code: ${e.statusCode} - message:',
|
||||
`Non-200 response from the API! Status code: ${
|
||||
e.statusCode
|
||||
} - message:`,
|
||||
e,
|
||||
);
|
||||
} else {
|
||||
|
@ -26,8 +26,10 @@ interface ConfigOpts {
|
||||
configPath?: string;
|
||||
}
|
||||
|
||||
type ConfigMap<T extends SchemaTypeKey> = { [key in T]: SchemaReturn<key> };
|
||||
type ConfigChangeMap<T extends SchemaTypeKey> = {
|
||||
export type ConfigMap<T extends SchemaTypeKey> = {
|
||||
[key in T]: SchemaReturn<key>
|
||||
};
|
||||
export type ConfigChangeMap<T extends SchemaTypeKey> = {
|
||||
[key in T]?: SchemaReturn<key>
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as Bluebird from 'bluebird';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { ConfigType } from './config';
|
||||
import Config, { ConfigChangeMap, ConfigKey, ConfigType } from './config';
|
||||
import DB from './db';
|
||||
import { EventTracker } from './event-tracker';
|
||||
import Docker from './lib/docker-utils';
|
||||
@ -26,6 +26,7 @@ interface LoggerSetupOptions {
|
||||
localMode: ConfigType<'localMode'>;
|
||||
|
||||
enableLogs: boolean;
|
||||
config: Config;
|
||||
}
|
||||
|
||||
type LogEventObject = Dictionary<any> | null;
|
||||
@ -59,23 +60,53 @@ export class Logger {
|
||||
unmanaged,
|
||||
enableLogs,
|
||||
localMode,
|
||||
config,
|
||||
}: LoggerSetupOptions) {
|
||||
this.balenaBackend = new BalenaLogBackend(
|
||||
apiEndpoint,
|
||||
// This is definitely not correct, but this is indeed
|
||||
// what has been happening before the conversion of
|
||||
// `supervisor.coffee` to typescript. We need to fix
|
||||
// the wider problem of the backend attempting to
|
||||
// communicate with the api without being provisioned
|
||||
uuid || '',
|
||||
deviceApiKey,
|
||||
);
|
||||
this.balenaBackend = new BalenaLogBackend(apiEndpoint, uuid, deviceApiKey);
|
||||
this.localBackend = new LocalLogBackend();
|
||||
|
||||
this.backend = localMode ? this.localBackend : this.balenaBackend;
|
||||
|
||||
this.backend.unmanaged = unmanaged;
|
||||
this.backend.publishEnabled = enableLogs;
|
||||
|
||||
// Only setup a config listener if we have to
|
||||
if (!this.balenaBackend.isIntialised()) {
|
||||
const handler = async (values: ConfigChangeMap<ConfigKey>) => {
|
||||
if (
|
||||
'uuid' in values ||
|
||||
'apiEndpoint' in values ||
|
||||
'deviceApiKey' in values
|
||||
) {
|
||||
// If any of the values we're interested in have
|
||||
// changed, retrieve all of the values, check that
|
||||
// they're all set, and provide them to the
|
||||
// balenaBackend
|
||||
|
||||
const conf = await config.getMany([
|
||||
'uuid',
|
||||
'apiEndpoint',
|
||||
'deviceApiKey',
|
||||
]);
|
||||
|
||||
// We use Boolean here, as deviceApiKey when unset
|
||||
// is '' for legacy reasons. Once we're totally
|
||||
// typescript, we can make it have a default value
|
||||
// of undefined.
|
||||
if (_.every(conf, Boolean)) {
|
||||
// Everything is set, provide the values to the
|
||||
// balenaBackend, and remove our listener
|
||||
this.balenaBackend!.assignFields(
|
||||
conf.apiEndpoint,
|
||||
conf.uuid!,
|
||||
conf.deviceApiKey,
|
||||
);
|
||||
config.removeListener('change', handler);
|
||||
}
|
||||
}
|
||||
};
|
||||
config.on('change', handler);
|
||||
}
|
||||
}
|
||||
|
||||
public switchBackend(localMode: boolean) {
|
||||
|
@ -31,17 +31,18 @@ export class BalenaLogBackend extends LogBackend {
|
||||
private stream: stream.PassThrough;
|
||||
private timeout: NodeJS.Timer;
|
||||
|
||||
public constructor(apiEndpoint: string, uuid: string, deviceApiKey: string) {
|
||||
public initialised = false;
|
||||
|
||||
public constructor(
|
||||
apiEndpoint: string,
|
||||
uuid: Nullable<string>,
|
||||
deviceApiKey: string,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.opts = url.parse(`${apiEndpoint}/device/v2/${uuid}/log-stream`) as any;
|
||||
this.opts.method = 'POST';
|
||||
this.opts.headers = {
|
||||
Authorization: `Bearer ${deviceApiKey}`,
|
||||
'Content-Type': 'application/x-ndjson',
|
||||
'Content-Encoding': 'gzip',
|
||||
};
|
||||
|
||||
if (uuid != null && deviceApiKey !== '') {
|
||||
this.assignFields(apiEndpoint, uuid, deviceApiKey);
|
||||
}
|
||||
// This stream serves serves as a message buffer during reconnections
|
||||
// while we unpipe the old, malfunctioning connection and then repipe a
|
||||
// new one.
|
||||
@ -71,8 +72,15 @@ export class BalenaLogBackend extends LogBackend {
|
||||
});
|
||||
}
|
||||
|
||||
public isIntialised(): boolean {
|
||||
return this.initialised;
|
||||
}
|
||||
|
||||
public log(message: LogMessage) {
|
||||
if (this.unmanaged || !this.publishEnabled) {
|
||||
// TODO: Perhaps don't just drop logs when we haven't
|
||||
// yet initialised (this happens when a device has not yet
|
||||
// been provisioned)
|
||||
if (this.unmanaged || !this.publishEnabled || !this.initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -100,6 +108,18 @@ export class BalenaLogBackend extends LogBackend {
|
||||
this.write(message);
|
||||
}
|
||||
|
||||
public assignFields(apiEndpoint: string, uuid: string, deviceApiKey: string) {
|
||||
this.opts = url.parse(`${apiEndpoint}/device/v2/${uuid}/log-stream`) as any;
|
||||
this.opts.method = 'POST';
|
||||
this.opts.headers = {
|
||||
Authorization: `Bearer ${deviceApiKey}`,
|
||||
'Content-Type': 'application/x-ndjson',
|
||||
'Content-Encoding': 'gzip',
|
||||
};
|
||||
|
||||
this.initialised = true;
|
||||
}
|
||||
|
||||
private setup = _.throttle(() => {
|
||||
this.req = https.request(this.opts);
|
||||
|
||||
|
@ -89,7 +89,11 @@ export class Supervisor {
|
||||
await this.apiBinder.initClient();
|
||||
|
||||
log.debug('Starting logging infrastructure');
|
||||
this.logger.init({ enableLogs: conf.loggingEnabled, ...conf });
|
||||
this.logger.init({
|
||||
enableLogs: conf.loggingEnabled,
|
||||
config: this.config,
|
||||
...conf,
|
||||
});
|
||||
|
||||
this.logger.logSystemMessage('Supervisor starting', {}, 'Supervisor start');
|
||||
if (conf.legacyAppsPresent) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{ expect } = require './lib/chai-config'
|
||||
|
||||
Supervisor = require '../src/supervisor'
|
||||
{ Supervisor } = require '../src/supervisor'
|
||||
|
||||
describe 'Startup', ->
|
||||
it 'should startup correctly', ->
|
||||
|
Loading…
Reference in New Issue
Block a user