mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-04-27 14:29:51 +00:00
Move required configuration check to Backend
The `ensureRequiredOverlay` function is currently ran for any backend, at this moment this causes no issue, since most configuration backends are defined per single device type. However, with the option to modify splash images, which is available for all device types, the function would add unwanted configuration vars to the splash image configuration. Moving it to the config txt backend solves this issue.
This commit is contained in:
parent
0c7cb46d15
commit
e66a775c15
@ -64,4 +64,11 @@ export abstract class ConfigBackend {
|
|||||||
public async initialise(): Promise<ConfigBackend> {
|
public async initialise(): Promise<ConfigBackend> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that all required fields for device type are included in the
|
||||||
|
// provided configuration. It is expected to modify the configuration if
|
||||||
|
// necessary
|
||||||
|
public ensureRequiredConfig(_deviceType: string, conf: ConfigOptions) {
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,4 +148,29 @@ export class ConfigTxt extends ConfigBackend {
|
|||||||
public createConfigVarName(configName: string): string {
|
public createConfigVarName(configName: string): string {
|
||||||
return ConfigTxt.bootConfigVarPrefix + configName;
|
return ConfigTxt.bootConfigVarPrefix + configName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that the balena-fin overlay is defined in the target configuration
|
||||||
|
// overrides the parent
|
||||||
|
public ensureRequiredConfig(deviceType: string, conf: ConfigOptions) {
|
||||||
|
if (deviceType === 'fincm3') {
|
||||||
|
this.ensureDtoverlay(conf, 'balena-fin');
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modifies conf
|
||||||
|
private ensureDtoverlay(conf: ConfigOptions, field: string) {
|
||||||
|
if (conf.dtoverlay == null) {
|
||||||
|
conf.dtoverlay = [];
|
||||||
|
} else if (_.isString(conf.dtoverlay)) {
|
||||||
|
conf.dtoverlay = [conf.dtoverlay];
|
||||||
|
}
|
||||||
|
if (!_.includes(conf.dtoverlay, field)) {
|
||||||
|
conf.dtoverlay.push(field);
|
||||||
|
}
|
||||||
|
conf.dtoverlay = conf.dtoverlay.filter((s) => !_.isEmpty(s));
|
||||||
|
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import { DeviceStatus } from './types/state';
|
|||||||
import * as configUtils from './config/utils';
|
import * as configUtils from './config/utils';
|
||||||
import { SchemaTypeKey } from './config/schema-type';
|
import { SchemaTypeKey } from './config/schema-type';
|
||||||
import { matchesAnyBootConfig } from './config/backends';
|
import { matchesAnyBootConfig } from './config/backends';
|
||||||
import { ConfigOptions, ConfigBackend } from './config/backends/backend';
|
import { ConfigBackend } from './config/backends/backend';
|
||||||
import { Odmdata } from './config/backends/odmdata';
|
import { Odmdata } from './config/backends/odmdata';
|
||||||
|
|
||||||
const vpnServiceName = 'openvpn';
|
const vpnServiceName = 'openvpn';
|
||||||
@ -351,7 +351,7 @@ export function bootConfigChangeRequired(
|
|||||||
const currentBootConfig = configUtils.envToBootConfig(configBackend, current);
|
const currentBootConfig = configUtils.envToBootConfig(configBackend, current);
|
||||||
|
|
||||||
// Some devices require specific overlays, here we apply them
|
// Some devices require specific overlays, here we apply them
|
||||||
ensureRequiredOverlay(deviceType, targetBootConfig);
|
configBackend.ensureRequiredConfig(deviceType, targetBootConfig);
|
||||||
|
|
||||||
// Search for any unsupported values
|
// Search for any unsupported values
|
||||||
_.each(targetBootConfig, (value, key) => {
|
_.each(targetBootConfig, (value, key) => {
|
||||||
@ -597,8 +597,8 @@ export async function setBootConfig(
|
|||||||
'Apply boot config in progress',
|
'Apply boot config in progress',
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ensure devices already have required overlays
|
// Ensure the required target config is available
|
||||||
ensureRequiredOverlay(await config.get('deviceType'), conf);
|
backend.ensureRequiredConfig(await config.get('deviceType'), conf);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await backend.setBootConfig(conf);
|
await backend.setBootConfig(conf);
|
||||||
@ -662,28 +662,3 @@ function checkBoolChanged(
|
|||||||
): boolean {
|
): boolean {
|
||||||
return checkTruthy(current[key]) !== checkTruthy(target[key]);
|
return checkTruthy(current[key]) !== checkTruthy(target[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modifies conf
|
|
||||||
// exported for tests
|
|
||||||
export function ensureRequiredOverlay(deviceType: string, conf: ConfigOptions) {
|
|
||||||
if (deviceType === 'fincm3') {
|
|
||||||
ensureDtoverlay(conf, 'balena-fin');
|
|
||||||
}
|
|
||||||
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modifies conf
|
|
||||||
function ensureDtoverlay(conf: ConfigOptions, field: string) {
|
|
||||||
if (conf.dtoverlay == null) {
|
|
||||||
conf.dtoverlay = [];
|
|
||||||
} else if (_.isString(conf.dtoverlay)) {
|
|
||||||
conf.dtoverlay = [conf.dtoverlay];
|
|
||||||
}
|
|
||||||
if (!_.includes(conf.dtoverlay, field)) {
|
|
||||||
conf.dtoverlay.push(field);
|
|
||||||
}
|
|
||||||
conf.dtoverlay = conf.dtoverlay.filter((s) => !_.isEmpty(s));
|
|
||||||
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
|
@ -11,6 +11,7 @@ import { ConfigTxt } from '../src/config/backends/config-txt';
|
|||||||
import { Odmdata } from '../src/config/backends/odmdata';
|
import { Odmdata } from '../src/config/backends/odmdata';
|
||||||
import { ConfigFs } from '../src/config/backends/config-fs';
|
import { ConfigFs } from '../src/config/backends/config-fs';
|
||||||
import * as constants from '../src/lib/constants';
|
import * as constants from '../src/lib/constants';
|
||||||
|
import * as config from '../src/config';
|
||||||
|
|
||||||
import prepare = require('./lib/prepare');
|
import prepare = require('./lib/prepare');
|
||||||
|
|
||||||
@ -171,6 +172,54 @@ describe('Device Backend Config', () => {
|
|||||||
(child_process.exec as SinonStub).restore();
|
(child_process.exec as SinonStub).restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('ensures required fields are written to config.txt', async () => {
|
||||||
|
stub(fsUtils, 'writeFileAtomic').resolves();
|
||||||
|
stub(child_process, 'exec').resolves();
|
||||||
|
stub(config, 'get').withArgs('deviceType').resolves('fincm3');
|
||||||
|
const current = {
|
||||||
|
HOST_CONFIG_initramfs: 'initramf.gz 0x00800000',
|
||||||
|
HOST_CONFIG_dtparam: '"i2c=on","audio=on"',
|
||||||
|
HOST_CONFIG_dtoverlay:
|
||||||
|
'"ads7846","lirc-rpi,gpio_out_pin=17,gpio_in_pin=13"',
|
||||||
|
HOST_CONFIG_foobar: 'baz',
|
||||||
|
};
|
||||||
|
const target = {
|
||||||
|
HOST_CONFIG_initramfs: 'initramf.gz 0x00800000',
|
||||||
|
HOST_CONFIG_dtparam: '"i2c=on","audio=off"',
|
||||||
|
HOST_CONFIG_dtoverlay: '"lirc-rpi,gpio_out_pin=17,gpio_in_pin=13"',
|
||||||
|
HOST_CONFIG_foobar: 'bat',
|
||||||
|
HOST_CONFIG_foobaz: 'bar',
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
// @ts-ignore accessing private value
|
||||||
|
deviceConfig.bootConfigChangeRequired(configTxtBackend, current, target),
|
||||||
|
).to.equal(true);
|
||||||
|
|
||||||
|
// @ts-ignore accessing private value
|
||||||
|
await deviceConfig.setBootConfig(configTxtBackend, target);
|
||||||
|
expect(child_process.exec).to.be.calledOnce;
|
||||||
|
expect(logSpy).to.be.calledTwice;
|
||||||
|
expect(logSpy.getCall(1).args[2]).to.equal('Apply boot config success');
|
||||||
|
expect(fsUtils.writeFileAtomic).to.be.calledWith(
|
||||||
|
'./test/data/mnt/boot/config.txt',
|
||||||
|
stripIndent`
|
||||||
|
initramfs initramf.gz 0x00800000
|
||||||
|
dtparam=i2c=on
|
||||||
|
dtparam=audio=off
|
||||||
|
dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=13
|
||||||
|
dtoverlay=balena-fin
|
||||||
|
foobar=bat
|
||||||
|
foobaz=bar
|
||||||
|
` + '\n', // add newline because stripIndent trims last newline
|
||||||
|
);
|
||||||
|
|
||||||
|
// Restore stubs
|
||||||
|
(fsUtils.writeFileAtomic as SinonStub).restore();
|
||||||
|
(child_process.exec as SinonStub).restore();
|
||||||
|
(config.get as SinonStub).restore();
|
||||||
|
});
|
||||||
|
|
||||||
it('accepts RESIN_ and BALENA_ variables', async () => {
|
it('accepts RESIN_ and BALENA_ variables', async () => {
|
||||||
return expect(
|
return expect(
|
||||||
deviceConfig.formatConfigKeys({
|
deviceConfig.formatConfigKeys({
|
||||||
@ -258,12 +307,14 @@ describe('Device Backend Config', () => {
|
|||||||
|
|
||||||
describe('Balena fin', () => {
|
describe('Balena fin', () => {
|
||||||
it('should always add the balena-fin dtoverlay', () => {
|
it('should always add the balena-fin dtoverlay', () => {
|
||||||
expect(deviceConfig.ensureRequiredOverlay('fincm3', {})).to.deep.equal({
|
expect(configTxtBackend.ensureRequiredConfig('fincm3', {})).to.deep.equal(
|
||||||
|
{
|
||||||
dtoverlay: ['balena-fin'],
|
dtoverlay: ['balena-fin'],
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
deviceConfig.ensureRequiredOverlay('fincm3', {
|
configTxtBackend.ensureRequiredConfig('fincm3', {
|
||||||
test: '123',
|
test: '123',
|
||||||
test2: ['123'],
|
test2: ['123'],
|
||||||
test3: ['123', '234'],
|
test3: ['123', '234'],
|
||||||
@ -275,12 +326,12 @@ describe('Device Backend Config', () => {
|
|||||||
dtoverlay: ['balena-fin'],
|
dtoverlay: ['balena-fin'],
|
||||||
});
|
});
|
||||||
expect(
|
expect(
|
||||||
deviceConfig.ensureRequiredOverlay('fincm3', {
|
configTxtBackend.ensureRequiredConfig('fincm3', {
|
||||||
dtoverlay: 'test',
|
dtoverlay: 'test',
|
||||||
}),
|
}),
|
||||||
).to.deep.equal({ dtoverlay: ['test', 'balena-fin'] });
|
).to.deep.equal({ dtoverlay: ['test', 'balena-fin'] });
|
||||||
expect(
|
expect(
|
||||||
deviceConfig.ensureRequiredOverlay('fincm3', {
|
configTxtBackend.ensureRequiredConfig('fincm3', {
|
||||||
dtoverlay: ['test'],
|
dtoverlay: ['test'],
|
||||||
}),
|
}),
|
||||||
).to.deep.equal({ dtoverlay: ['test', 'balena-fin'] });
|
).to.deep.equal({ dtoverlay: ['test', 'balena-fin'] });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user