Ensure the balena-fin always has it's overlay assigned

Change-type: patch
Closes: #884
Signed-off-by: Cameron Diver <cameron@balena.io>
This commit is contained in:
Cameron Diver 2019-02-05 15:40:29 +00:00
parent d0c9b697da
commit 2e09ed071c
No known key found for this signature in database
GPG Key ID: 49690ED87032539F
2 changed files with 68 additions and 5 deletions

View File

@ -5,7 +5,7 @@ import { SchemaTypeKey } from './config/schema-type';
import Database, { Transaction } from './db';
import Logger from './logger';
import { DeviceConfigBackend } from './config/backend';
import { DeviceConfigBackend, ConfigOptions } from './config/backend';
import * as configUtils from './config/utils';
import { UnitNotLoadedError } from './lib/errors';
import * as systemd from './lib/systemd';
@ -311,13 +311,21 @@ export class DeviceConfig {
configBackend: DeviceConfigBackend | null,
current: Dictionary<string>,
target: Dictionary<string>,
deviceType: string,
): boolean {
const targetBootConfig = configUtils.envToBootConfig(configBackend, target);
let targetBootConfig = configUtils.envToBootConfig(configBackend, target);
const currentBootConfig = configUtils.envToBootConfig(
configBackend,
current,
);
if (deviceType === 'fincm3') {
// current will always have the balena-fin dtoverlay, but the target does
// not have to as this is one that we enforce. If there is no balena-fin in the
// target state, add it
targetBootConfig = DeviceConfig.ensureFinOverlay(targetBootConfig);
}
if (!_.isEqual(currentBootConfig, targetBootConfig)) {
_.each(targetBootConfig, (value, key) => {
// Ignore null check because we can't get here if configBackend is null
@ -355,7 +363,10 @@ export class DeviceConfig {
const steps: ConfigStep[] = [];
const unmanaged = await this.config.get('unmanaged');
const { deviceType, unmanaged } = await this.config.getMany([
'deviceType',
'unmanaged',
]);
const backend = await this.getConfigBackend();
const configChanges: Dictionary<string> = {};
@ -403,7 +414,7 @@ export class DeviceConfig {
}
// Do we need to change the boot config?
if (this.bootConfigChangeRequired(backend, current, target)) {
if (this.bootConfigChangeRequired(backend, current, target, deviceType)) {
steps.push({
action: 'setBootConfig',
target,
@ -447,13 +458,18 @@ export class DeviceConfig {
return false;
}
const conf = configUtils.envToBootConfig(backend, target);
let conf = configUtils.envToBootConfig(backend, target);
this.logger.logSystemMessage(
`Applying boot config: ${JSON.stringify(conf)}`,
{},
'Apply boot config in progress',
);
// Ensure that the fin always has it's dtoverlay
if ((await this.config.get('deviceType')) === 'fincm3') {
conf = DeviceConfig.ensureFinOverlay(conf);
}
try {
await backend.setBootConfig(conf);
this.logger.logSystemMessage(
@ -514,6 +530,23 @@ export class DeviceConfig {
): boolean {
return checkTruthy(current[key]) !== checkTruthy(target[key]);
}
// Modifies conf
private static ensureFinOverlay(conf: ConfigOptions) {
if (conf.dtoverlay != null) {
if (_.isArray(conf.dtoverlay)) {
if (!_.includes(conf.dtoverlay, 'balena-fin')) {
conf.dtoverlay.push('balena-fin');
}
} else if (conf.dtoverlay !== 'balena-fin') {
conf.dtoverlay = [conf.dtoverlay, 'balena-fin'];
}
} else {
conf.dtoverlay = ['balena-fin'];
}
conf.dtoverlay = (conf.dtoverlay as string[]).filter(s => !_.isEmpty(s));
return conf;
}
}
export default DeviceConfig;

View File

@ -198,5 +198,35 @@ describe 'DeviceConfig', ->
childProcess.execAsync.restore()
@fakeLogger.logSystemMessage.reset()
describe 'Balena fin', ->
it 'should always add the balena-fin dtoverlay', ->
expect(DeviceConfig.ensureFinOverlay({})).to.deep.equal({ dtoverlay: ['balena-fin'] })
expect(DeviceConfig.ensureFinOverlay({ test: '123', test2: ['123'], test3: ['123', '234'] })).to
.deep.equal({ test: '123', test2: ['123'], test3: ['123', '234'], dtoverlay: ['balena-fin'] })
expect(DeviceConfig.ensureFinOverlay({ dtoverlay: 'test' })).to.deep.equal({ dtoverlay: ['test', 'balena-fin'] })
expect(DeviceConfig.ensureFinOverlay({ dtoverlay: ['test'] })).to.deep.equal({ dtoverlay: ['test', 'balena-fin'] })
it 'should not cause a config change when the cloud does not specify the balena-fin overlay', ->
expect(@deviceConfig.bootConfigChangeRequired(
rpiConfigBackend,
{ HOST_CONFIG_dtoverlay: '"test","balena-fin"' },
{ HOST_CONFIG_dtoverlay: '"test"' },
'fincm3'
)).to.equal(false)
expect(@deviceConfig.bootConfigChangeRequired(
rpiConfigBackend,
{ HOST_CONFIG_dtoverlay: '"test","balena-fin"' },
{ HOST_CONFIG_dtoverlay: 'test' },
'fincm3'
)).to.equal(false)
expect(@deviceConfig.bootConfigChangeRequired(
rpiConfigBackend,
{ HOST_CONFIG_dtoverlay: '"test","test2","balena-fin"' },
{ HOST_CONFIG_dtoverlay: '"test","test2"' },
'fincm3'
)).to.equal(false)
# This will require stubbing device.reboot, gosuper.post, config.get/set
it 'applies the target state'