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
|
// the watchdog to kill the supervisor - and killing the supervisor will
|
||||||
// not help in this situation
|
// not help in this situation
|
||||||
log.error(
|
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,
|
e,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -26,8 +26,10 @@ interface ConfigOpts {
|
|||||||
configPath?: string;
|
configPath?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigMap<T extends SchemaTypeKey> = { [key in T]: SchemaReturn<key> };
|
export type ConfigMap<T extends SchemaTypeKey> = {
|
||||||
type ConfigChangeMap<T extends SchemaTypeKey> = {
|
[key in T]: SchemaReturn<key>
|
||||||
|
};
|
||||||
|
export type ConfigChangeMap<T extends SchemaTypeKey> = {
|
||||||
[key in T]?: SchemaReturn<key>
|
[key in T]?: SchemaReturn<key>
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as Bluebird from 'bluebird';
|
import * as Bluebird from 'bluebird';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { ConfigType } from './config';
|
import Config, { ConfigChangeMap, ConfigKey, ConfigType } from './config';
|
||||||
import DB from './db';
|
import DB from './db';
|
||||||
import { EventTracker } from './event-tracker';
|
import { EventTracker } from './event-tracker';
|
||||||
import Docker from './lib/docker-utils';
|
import Docker from './lib/docker-utils';
|
||||||
@ -26,6 +26,7 @@ interface LoggerSetupOptions {
|
|||||||
localMode: ConfigType<'localMode'>;
|
localMode: ConfigType<'localMode'>;
|
||||||
|
|
||||||
enableLogs: boolean;
|
enableLogs: boolean;
|
||||||
|
config: Config;
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogEventObject = Dictionary<any> | null;
|
type LogEventObject = Dictionary<any> | null;
|
||||||
@ -59,23 +60,53 @@ export class Logger {
|
|||||||
unmanaged,
|
unmanaged,
|
||||||
enableLogs,
|
enableLogs,
|
||||||
localMode,
|
localMode,
|
||||||
|
config,
|
||||||
}: LoggerSetupOptions) {
|
}: LoggerSetupOptions) {
|
||||||
this.balenaBackend = new BalenaLogBackend(
|
this.balenaBackend = new BalenaLogBackend(apiEndpoint, uuid, deviceApiKey);
|
||||||
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.localBackend = new LocalLogBackend();
|
this.localBackend = new LocalLogBackend();
|
||||||
|
|
||||||
this.backend = localMode ? this.localBackend : this.balenaBackend;
|
this.backend = localMode ? this.localBackend : this.balenaBackend;
|
||||||
|
|
||||||
this.backend.unmanaged = unmanaged;
|
this.backend.unmanaged = unmanaged;
|
||||||
this.backend.publishEnabled = enableLogs;
|
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) {
|
public switchBackend(localMode: boolean) {
|
||||||
|
@ -31,17 +31,18 @@ export class BalenaLogBackend extends LogBackend {
|
|||||||
private stream: stream.PassThrough;
|
private stream: stream.PassThrough;
|
||||||
private timeout: NodeJS.Timer;
|
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();
|
super();
|
||||||
|
|
||||||
this.opts = url.parse(`${apiEndpoint}/device/v2/${uuid}/log-stream`) as any;
|
if (uuid != null && deviceApiKey !== '') {
|
||||||
this.opts.method = 'POST';
|
this.assignFields(apiEndpoint, uuid, deviceApiKey);
|
||||||
this.opts.headers = {
|
}
|
||||||
Authorization: `Bearer ${deviceApiKey}`,
|
|
||||||
'Content-Type': 'application/x-ndjson',
|
|
||||||
'Content-Encoding': 'gzip',
|
|
||||||
};
|
|
||||||
|
|
||||||
// This stream serves serves as a message buffer during reconnections
|
// This stream serves serves as a message buffer during reconnections
|
||||||
// while we unpipe the old, malfunctioning connection and then repipe a
|
// while we unpipe the old, malfunctioning connection and then repipe a
|
||||||
// new one.
|
// new one.
|
||||||
@ -71,8 +72,15 @@ export class BalenaLogBackend extends LogBackend {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isIntialised(): boolean {
|
||||||
|
return this.initialised;
|
||||||
|
}
|
||||||
|
|
||||||
public log(message: LogMessage) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +108,18 @@ export class BalenaLogBackend extends LogBackend {
|
|||||||
this.write(message);
|
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(() => {
|
private setup = _.throttle(() => {
|
||||||
this.req = https.request(this.opts);
|
this.req = https.request(this.opts);
|
||||||
|
|
||||||
|
@ -89,7 +89,11 @@ export class Supervisor {
|
|||||||
await this.apiBinder.initClient();
|
await this.apiBinder.initClient();
|
||||||
|
|
||||||
log.debug('Starting logging infrastructure');
|
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');
|
this.logger.logSystemMessage('Supervisor starting', {}, 'Supervisor start');
|
||||||
if (conf.legacyAppsPresent) {
|
if (conf.legacyAppsPresent) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{ expect } = require './lib/chai-config'
|
{ expect } = require './lib/chai-config'
|
||||||
|
|
||||||
Supervisor = require '../src/supervisor'
|
{ Supervisor } = require '../src/supervisor'
|
||||||
|
|
||||||
describe 'Startup', ->
|
describe 'Startup', ->
|
||||||
it 'should startup correctly', ->
|
it 'should startup correctly', ->
|
||||||
|
Loading…
Reference in New Issue
Block a user