mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-21 02:01:35 +00:00
Merge pull request #818 from balena-io/fix-unmanaged-selects
Fixes for unmanaged balenaOS
This commit is contained in:
commit
80b4872d7e
@ -296,7 +296,7 @@ module.exports = class ApplicationManager extends EventEmitter
|
||||
).get(appId)
|
||||
|
||||
getTargetApp: (appId) =>
|
||||
@config.get('apiEndpoint').then (endpoint = '') ->
|
||||
@config.get('apiEndpoint').then (endpoint) ->
|
||||
@db.models('app').where({ appId, source: endpoint }).select()
|
||||
.then ([ app ]) =>
|
||||
if !app?
|
||||
|
@ -9,6 +9,7 @@ import supervisorVersion = require('../lib/supervisor-version');
|
||||
import * as constants from '../lib/constants';
|
||||
import * as osRelease from '../lib/os-release';
|
||||
import { ConfigValue } from '../lib/types';
|
||||
import { checkTruthy } from '../lib/validation';
|
||||
|
||||
// A provider for schema entries with source 'func'
|
||||
type ConfigProviderFunctionGetter = () => Bluebird<any>;
|
||||
@ -51,7 +52,9 @@ export function createProviderFunctions(
|
||||
return config
|
||||
.getMany(['apiEndpoint', 'supervisorOfflineMode'])
|
||||
.then(({ apiEndpoint, supervisorOfflineMode }) => {
|
||||
return Boolean(supervisorOfflineMode) || !Boolean(apiEndpoint);
|
||||
return (
|
||||
checkTruthy(supervisorOfflineMode as boolean) || !apiEndpoint
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
@ -108,6 +111,9 @@ export function createProviderFunctions(
|
||||
mixpanelHost: {
|
||||
get: () => {
|
||||
return config.get('apiEndpoint').then(apiEndpoint => {
|
||||
if (!apiEndpoint) {
|
||||
return null;
|
||||
}
|
||||
const url = new URL(apiEndpoint as string);
|
||||
return { host: url.host, path: '/mixpanel' };
|
||||
});
|
||||
|
@ -4,16 +4,13 @@ import { Transaction } from 'knex';
|
||||
import * as _ from 'lodash';
|
||||
import { generateUniqueKey } from 'resin-register-device';
|
||||
|
||||
import ConfigJsonConfigBackend from './config/configJson';
|
||||
import ConfigJsonConfigBackend from './configJson';
|
||||
|
||||
import {
|
||||
ConfigProviderFunctions,
|
||||
createProviderFunctions,
|
||||
} from './config/functions';
|
||||
import * as constants from './lib/constants';
|
||||
import { ConfigMap, ConfigSchema, ConfigValue } from './lib/types';
|
||||
import { ConfigProviderFunctions, createProviderFunctions } from './functions';
|
||||
import * as constants from '../lib/constants';
|
||||
import { ConfigMap, ConfigSchema, ConfigValue } from '../lib/types';
|
||||
|
||||
import DB = require('./db');
|
||||
import DB = require('../db');
|
||||
|
||||
interface ConfigOpts {
|
||||
db: DB;
|
||||
@ -26,14 +23,14 @@ class Config extends EventEmitter {
|
||||
private providerFunctions: ConfigProviderFunctions;
|
||||
|
||||
public schema: ConfigSchema = {
|
||||
apiEndpoint: { source: 'config.json' },
|
||||
apiEndpoint: { source: 'config.json', default: '' },
|
||||
apiTimeout: { source: 'config.json', default: 15 * 60 * 1000 },
|
||||
listenPort: { source: 'config.json', default: 48484 },
|
||||
deltaEndpoint: { source: 'config.json', default: 'https://delta.resin.io' },
|
||||
uuid: { source: 'config.json', mutable: true },
|
||||
apiKey: { source: 'config.json', mutable: true, removeIfNull: true },
|
||||
deviceApiKey: { source: 'config.json', mutable: true },
|
||||
deviceType: { source: 'config.json', default: 'raspberry-pi' },
|
||||
deviceApiKey: { source: 'config.json', mutable: true, default: '' },
|
||||
deviceType: { source: 'config.json', default: 'unknown' },
|
||||
username: { source: 'config.json' },
|
||||
userId: { source: 'config.json' },
|
||||
deviceId: { source: 'config.json', mutable: true },
|
||||
@ -52,6 +49,7 @@ class Config extends EventEmitter {
|
||||
supervisorOfflineMode: { source: 'config.json', default: false },
|
||||
hostname: { source: 'config.json', mutable: true },
|
||||
persistentLogging: { source: 'config.json', default: false, mutable: true },
|
||||
localMode: { source: 'config.json', mutable: true, default: 'false' },
|
||||
|
||||
version: { source: 'func' },
|
||||
currentApiKey: { source: 'func' },
|
||||
@ -70,7 +68,6 @@ class Config extends EventEmitter {
|
||||
initialConfigReported: { source: 'db', mutable: true, default: 'false' },
|
||||
initialConfigSaved: { source: 'db', mutable: true, default: 'false' },
|
||||
containersNormalised: { source: 'db', mutable: true, default: 'false' },
|
||||
localMode: { source: 'db', mutable: true, default: 'false' },
|
||||
loggingEnabled: { source: 'db', mutable: true, default: 'true' },
|
||||
connectivityCheckEnabled: { source: 'db', mutable: true, default: 'true' },
|
||||
delta: { source: 'db', mutable: true, default: 'false' },
|
||||
@ -295,7 +292,7 @@ class Config extends EventEmitter {
|
||||
if (offlineMode) {
|
||||
return;
|
||||
}
|
||||
if (deviceApiKey == null) {
|
||||
if (!deviceApiKey) {
|
||||
return this.set({ deviceApiKey: this.newUniqueKey() });
|
||||
}
|
||||
});
|
@ -13,6 +13,7 @@ validation = require './lib/validation'
|
||||
systemd = require './lib/systemd'
|
||||
updateLock = require './lib/update-lock'
|
||||
{ singleToMulticontainerApp } = require './lib/migration'
|
||||
{ ENOENT, EISDIR } = require './lib/errors'
|
||||
|
||||
DeviceConfig = require './device-config'
|
||||
ApplicationManager = require './application-manager'
|
||||
@ -167,7 +168,7 @@ module.exports = class DeviceState extends EventEmitter
|
||||
@config.getMany([
|
||||
'initialConfigSaved', 'listenPort', 'apiSecret', 'osVersion', 'osVariant',
|
||||
'version', 'provisioned', 'apiEndpoint', 'connectivityCheckEnabled', 'legacyAppsPresent',
|
||||
'targetStateSet'
|
||||
'targetStateSet', 'offlineMode'
|
||||
])
|
||||
.then (conf) =>
|
||||
Promise.try =>
|
||||
@ -213,7 +214,8 @@ module.exports = class DeviceState extends EventEmitter
|
||||
.then =>
|
||||
@triggerApplyTarget({ initial: true })
|
||||
|
||||
initNetworkChecks: ({ apiEndpoint, connectivityCheckEnabled }) =>
|
||||
initNetworkChecks: ({ apiEndpoint, connectivityCheckEnabled, offlineMode }) =>
|
||||
return if validation.checkTruthy(offlineMode)
|
||||
network.startConnectivityCheck apiEndpoint, connectivityCheckEnabled, (connected) =>
|
||||
@connected = connected
|
||||
@config.on 'change', (changedConfig) ->
|
||||
@ -383,6 +385,12 @@ module.exports = class DeviceState extends EventEmitter
|
||||
commit: commitToPin,
|
||||
app: appToPin,
|
||||
}
|
||||
# Ensure that this is actually a file, and not an empty path
|
||||
# It can be an empty path because if the file does not exist
|
||||
# on host, the docker daemon creates an empty directory when
|
||||
# the bind mount is added
|
||||
.catch ENOENT, EISDIR, ->
|
||||
console.log('No apps.json file present, skipping preload')
|
||||
.catch (err) =>
|
||||
@eventTracker.track('Loading preloaded apps failed', { error: err })
|
||||
|
||||
|
@ -12,7 +12,7 @@ export type EventTrackProperties = Dictionary<any>;
|
||||
interface InitArgs {
|
||||
uuid: string;
|
||||
offlineMode: boolean;
|
||||
mixpanelHost: { host: string; path: string };
|
||||
mixpanelHost: { host: string; path: string } | null;
|
||||
mixpanelToken: string;
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ export class EventTracker {
|
||||
uuid,
|
||||
supervisorVersion,
|
||||
};
|
||||
if (offlineMode) {
|
||||
if (offlineMode || mixpanelHost == null) {
|
||||
return;
|
||||
}
|
||||
this.client = Mixpanel.init(mixpanelToken, {
|
||||
|
@ -25,6 +25,10 @@ export function EEXIST(err: CodedSysError): boolean {
|
||||
return err.code === 'EEXIST';
|
||||
}
|
||||
|
||||
export function EISDIR(err: CodedSysError): boolean {
|
||||
return err.code === 'EISDIR';
|
||||
}
|
||||
|
||||
export function UnitNotLoadedError(err: string[]): boolean {
|
||||
return endsWith(err[0], 'not loaded.');
|
||||
}
|
||||
|
57
src/migrations/M00001.js
Normal file
57
src/migrations/M00001.js
Normal file
@ -0,0 +1,57 @@
|
||||
const fs = require('fs');
|
||||
const configJsonPath = process.env.CONFIG_MOUNT_POINT;
|
||||
|
||||
const { checkTruthy } = require('../lib/validation');
|
||||
|
||||
exports.up = function (knex, Promise) {
|
||||
return knex('config').where({ key: 'localMode' }).select('value')
|
||||
.then((results) => {
|
||||
if (results.length === 0) {
|
||||
// We don't need to do anything
|
||||
return;
|
||||
}
|
||||
|
||||
let value = checkTruthy(results[0].value);
|
||||
value = value != null ? value : false;
|
||||
|
||||
return new Promise((resolve) => {
|
||||
if (!configJsonPath) {
|
||||
console.log('Unable to locate config.json! Things may fail unexpectedly!');
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
fs.readFile(configJsonPath, (err, data) => {
|
||||
if (err) {
|
||||
console.log('Failed to read config.json! Things may fail unexpectedly!');
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const parsed = JSON.parse(data.toString());
|
||||
// Assign the local mode value
|
||||
parsed.localMode = value;
|
||||
|
||||
fs.writeFile(configJsonPath, JSON.stringify(parsed), (err) => {
|
||||
if (err) {
|
||||
console.log('Failed to write config.json! Things may fail unexpectedly!');
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
console.log('Failed to parse config.json! Things may fail unexpectedly!');
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
return knex('config').where('key', 'localMode').del();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.down = function (knex, Promise) {
|
||||
return Promise.reject(new Error('Not Implemented'));
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ describe 'APIBinder', ->
|
||||
expect(mode).to.equal(true)
|
||||
# Check that there is no deviceApiKey
|
||||
@config.getMany([ 'deviceApiKey', 'uuid' ]).then (conf) ->
|
||||
expect(conf['deviceApiKey']).to.be.undefined
|
||||
expect(conf['deviceApiKey']).to.be.empty
|
||||
expect(conf['uuid']).to.not.be.undefined
|
||||
|
||||
describe 'Minimal config offline mode', ->
|
||||
@ -156,5 +156,5 @@ describe 'APIBinder', ->
|
||||
@config.get('offlineMode').then (mode) =>
|
||||
expect(mode).to.equal(true)
|
||||
@config.getMany([ 'deviceApiKey', 'uuid' ]).then (conf) ->
|
||||
expect(conf['deviceApiKey']).to.be.undefined
|
||||
expect(conf['deviceApiKey']).to.be.empty
|
||||
expect(conf['uuid']).to.not.be.undefined
|
||||
|
Loading…
x
Reference in New Issue
Block a user