mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-21 02:01:35 +00:00
Merge pull request #762 from resin-io/balena-config
deviceConfig: allow BALENA_ config variables
This commit is contained in:
commit
a762ba9dc0
@ -324,13 +324,15 @@ module.exports = class APIBinder
|
||||
targetConfig = targetState.local.config
|
||||
Promise.mapSeries _.toPairs(currentConfig), ([ key, value ]) =>
|
||||
# We never want to disable VPN if, for instance, it failed to start so far
|
||||
if key == 'RESIN_SUPERVISOR_VPN_CONTROL'
|
||||
if key == 'SUPERVISOR_VPN_CONTROL'
|
||||
value = 'true'
|
||||
if !targetConfig[key]? and value != defaultConfig[key]
|
||||
# At some point the namespace in the API should change to BALENA_
|
||||
# but for now we only have RESIN_
|
||||
envVar = {
|
||||
value
|
||||
device: deviceId
|
||||
name: key
|
||||
name: 'RESIN_' + key
|
||||
}
|
||||
@resinApi.post
|
||||
resource: 'device_config_variable'
|
||||
|
@ -54,15 +54,31 @@ export function bootConfigToEnv(
|
||||
.value();
|
||||
}
|
||||
|
||||
export function filterConfigKeys(
|
||||
function filterNamespaceFromConfig(
|
||||
namespace: RegExp,
|
||||
conf: { [key: string]: any },
|
||||
): { [key: string]: any } {
|
||||
return _.mapKeys(_.pickBy(conf, (_v, k) => {
|
||||
return namespace.test(k);
|
||||
}), (_v,k) => {
|
||||
return k.replace(namespace, '$1');
|
||||
});
|
||||
}
|
||||
|
||||
export function filterAndFormatConfigKeys(
|
||||
configBackend: DeviceConfigBackend | null,
|
||||
allowedKeys: string[],
|
||||
conf: { [key: string]: any },
|
||||
): { [key: string]: any } {
|
||||
|
||||
const isConfigType = configBackend != null;
|
||||
const namespaceRegex = /^BALENA_(.*)/;
|
||||
const legacyNamespaceRegex = /^RESIN_(.*)/;
|
||||
const confFromNamespace = filterNamespaceFromConfig(namespaceRegex, conf);
|
||||
const confFromLegacyNamespace = filterNamespaceFromConfig(legacyNamespaceRegex, conf);
|
||||
const confWithoutNamespace = _.defaults(confFromNamespace, confFromLegacyNamespace);
|
||||
|
||||
return _.pickBy(conf, (_v, k) => {
|
||||
return _.pickBy(confWithoutNamespace, (_v, k) => {
|
||||
return _.includes(allowedKeys, k) || (isConfigType && configBackend!.isBootConfigVar(k));
|
||||
});
|
||||
}
|
||||
|
@ -12,22 +12,22 @@ module.exports = class DeviceConfig
|
||||
constructor: ({ @db, @config, @logger }) ->
|
||||
@rebootRequired = false
|
||||
@configKeys = {
|
||||
appUpdatePollInterval: { envVarName: 'RESIN_SUPERVISOR_POLL_INTERVAL', varType: 'int', defaultValue: '60000' }
|
||||
localMode: { envVarName: 'RESIN_SUPERVISOR_LOCAL_MODE', varType: 'bool', defaultValue: 'false' }
|
||||
connectivityCheckEnabled: { envVarName: 'RESIN_SUPERVISOR_CONNECTIVITY_CHECK', varType: 'bool', defaultValue: 'true' }
|
||||
loggingEnabled: { envVarName: 'RESIN_SUPERVISOR_LOG_CONTROL', varType: 'bool', defaultValue: 'true' }
|
||||
delta: { envVarName: 'RESIN_SUPERVISOR_DELTA', varType: 'bool', defaultValue: 'false' }
|
||||
deltaRequestTimeout: { envVarName: 'RESIN_SUPERVISOR_DELTA_REQUEST_TIMEOUT', varType: 'int', defaultValue: '30000' }
|
||||
deltaApplyTimeout: { envVarName: 'RESIN_SUPERVISOR_DELTA_APPLY_TIMEOUT', varType: 'int', defaultValue: '' }
|
||||
deltaRetryCount: { envVarName: 'RESIN_SUPERVISOR_DELTA_RETRY_COUNT', varType: 'int', defaultValue: '30' }
|
||||
deltaRetryInterval: { envVarName: 'RESIN_SUPERVISOR_DELTA_RETRY_INTERVAL', varType: 'int', defaultValue: '10000' }
|
||||
deltaVersion: { envVarName: 'RESIN_SUPERVISOR_DELTA_VERSION', varType: 'int', defaultValue: '2' }
|
||||
lockOverride: { envVarName: 'RESIN_SUPERVISOR_OVERRIDE_LOCK', varType: 'bool', defaultValue: 'false' }
|
||||
persistentLogging: { envVarName: 'RESIN_SUPERVISOR_PERSISTENT_LOGGING', varType: 'bool', defaultValue: 'false', rebootRequired: true }
|
||||
appUpdatePollInterval: { envVarName: 'SUPERVISOR_POLL_INTERVAL', varType: 'int', defaultValue: '60000' }
|
||||
localMode: { envVarName: 'SUPERVISOR_LOCAL_MODE', varType: 'bool', defaultValue: 'false' }
|
||||
connectivityCheckEnabled: { envVarName: 'SUPERVISOR_CONNECTIVITY_CHECK', varType: 'bool', defaultValue: 'true' }
|
||||
loggingEnabled: { envVarName: 'SUPERVISOR_LOG_CONTROL', varType: 'bool', defaultValue: 'true' }
|
||||
delta: { envVarName: 'SUPERVISOR_DELTA', varType: 'bool', defaultValue: 'false' }
|
||||
deltaRequestTimeout: { envVarName: 'SUPERVISOR_DELTA_REQUEST_TIMEOUT', varType: 'int', defaultValue: '30000' }
|
||||
deltaApplyTimeout: { envVarName: 'SUPERVISOR_DELTA_APPLY_TIMEOUT', varType: 'int', defaultValue: '' }
|
||||
deltaRetryCount: { envVarName: 'SUPERVISOR_DELTA_RETRY_COUNT', varType: 'int', defaultValue: '30' }
|
||||
deltaRetryInterval: { envVarName: 'SUPERVISOR_DELTA_RETRY_INTERVAL', varType: 'int', defaultValue: '10000' }
|
||||
deltaVersion: { envVarName: 'SUPERVISOR_DELTA_VERSION', varType: 'int', defaultValue: '2' }
|
||||
lockOverride: { envVarName: 'SUPERVISOR_OVERRIDE_LOCK', varType: 'bool', defaultValue: 'false' }
|
||||
persistentLogging: { envVarName: 'SUPERVISOR_PERSISTENT_LOGGING', varType: 'bool', defaultValue: 'false', rebootRequired: true }
|
||||
}
|
||||
@validKeys = [
|
||||
'RESIN_SUPERVISOR_VPN_CONTROL',
|
||||
'RESIN_OVERRIDE_LOCK',
|
||||
'SUPERVISOR_VPN_CONTROL',
|
||||
'OVERRIDE_LOCK',
|
||||
].concat(_.map(@configKeys, 'envVarName'))
|
||||
@actionExecutors = {
|
||||
changeConfig: (step) =>
|
||||
@ -40,7 +40,7 @@ module.exports = class DeviceConfig
|
||||
.tapCatch (err) =>
|
||||
@logger.logConfigChange(step.humanReadableTarget, { err })
|
||||
setVPNEnabled: (step, { initial = false } = {}) =>
|
||||
logValue = { RESIN_SUPERVISOR_VPN_CONTROL: step.target }
|
||||
logValue = { SUPERVISOR_VPN_CONTROL: step.target }
|
||||
if !initial
|
||||
@logger.logConfigChange(logValue)
|
||||
@setVPNEnabled(step.target)
|
||||
@ -80,9 +80,9 @@ module.exports = class DeviceConfig
|
||||
@getConfigBackend()
|
||||
]
|
||||
.then ([ conf, configBackend ]) =>
|
||||
conf = configUtils.filterConfigKeys(configBackend, @validKeys, conf)
|
||||
if initial or !conf.RESIN_SUPERVISOR_VPN_CONTROL?
|
||||
conf.RESIN_SUPERVISOR_VPN_CONTROL = 'true'
|
||||
conf = configUtils.filterAndFormatConfigKeys(configBackend, @validKeys, conf)
|
||||
if initial or !conf.SUPERVISOR_VPN_CONTROL?
|
||||
conf.SUPERVISOR_VPN_CONTROL = 'true'
|
||||
for own k, { envVarName, defaultValue } of @configKeys
|
||||
conf[envVarName] ?= defaultValue
|
||||
return conf
|
||||
@ -98,17 +98,22 @@ module.exports = class DeviceConfig
|
||||
@getBootConfig(configBackend)
|
||||
(vpnStatus, bootConfig) =>
|
||||
currentConf = {
|
||||
RESIN_SUPERVISOR_VPN_CONTROL: (vpnStatus ? 'true').toString()
|
||||
SUPERVISOR_VPN_CONTROL: (vpnStatus ? 'true').toString()
|
||||
}
|
||||
for own key, { envVarName } of @configKeys
|
||||
currentConf[envVarName] = (conf[key] ? '').toString()
|
||||
return _.assign(currentConf, bootConfig)
|
||||
)
|
||||
|
||||
filterAndFormatConfigKeys: (conf) =>
|
||||
@getConfigBackend()
|
||||
.then (configBackend) =>
|
||||
configUtils.filterAndFormatConfigKeys(configBackend, @validKeys, conf)
|
||||
|
||||
getDefaults: =>
|
||||
Promise.try =>
|
||||
return _.extend({
|
||||
RESIN_SUPERVISOR_VPN_CONTROL: 'true'
|
||||
SUPERVISOR_VPN_CONTROL: 'true'
|
||||
}, _.mapValues(_.mapKeys(@configKeys, 'envVarName'), 'defaultValue'))
|
||||
|
||||
bootConfigChangeRequired: (configBackend, current, target) =>
|
||||
@ -143,8 +148,8 @@ module.exports = class DeviceConfig
|
||||
checkInt(a) == checkInt(b)
|
||||
}
|
||||
# If the legacy lock override is used, place it as the new variable
|
||||
if checkTruthy(target['RESIN_OVERRIDE_LOCK'])
|
||||
target['RESIN_SUPERVISOR_OVERRIDE_LOCK'] = target['RESIN_OVERRIDE_LOCK']
|
||||
if checkTruthy(target['OVERRIDE_LOCK'])
|
||||
target['SUPERVISOR_OVERRIDE_LOCK'] = target['OVERRIDE_LOCK']
|
||||
reboot = false
|
||||
for own key, { envVarName, varType, rebootRequired } of @configKeys
|
||||
if !match[varType](current[envVarName], target[envVarName])
|
||||
@ -162,11 +167,11 @@ module.exports = class DeviceConfig
|
||||
|
||||
# Check if we need to perform special case actions for the VPN
|
||||
if !checkTruthy(offlineMode) &&
|
||||
!_.isEmpty(target['RESIN_SUPERVISOR_VPN_CONTROL']) &&
|
||||
@checkBoolChanged(current, target, 'RESIN_SUPERVISOR_VPN_CONTROL')
|
||||
!_.isEmpty(target['SUPERVISOR_VPN_CONTROL']) &&
|
||||
@checkBoolChanged(current, target, 'SUPERVISOR_VPN_CONTROL')
|
||||
steps.push({
|
||||
action: 'setVPNEnabled'
|
||||
target: target['RESIN_SUPERVISOR_VPN_CONTROL']
|
||||
target: target['SUPERVISOR_VPN_CONTROL']
|
||||
})
|
||||
|
||||
# Do we need to change the boot config?
|
||||
|
@ -306,23 +306,28 @@ module.exports = class DeviceState extends EventEmitter
|
||||
@emitAsync('change')
|
||||
|
||||
_convertLegacyAppsJson: (appsArray) =>
|
||||
config = _.reduce(appsArray, (conf, app) =>
|
||||
return _.merge({}, conf, @deviceConfig.filterConfigKeys(app.config))
|
||||
deviceConf = _.reduce(appsArray, (conf, app) =>
|
||||
return _.merge({}, conf, app.config)
|
||||
, {})
|
||||
apps = _.keyBy(_.map(appsArray, singleToMulticontainerApp), 'appId')
|
||||
return { apps, config }
|
||||
@deviceConfig.filterAndFormatConfigKeys(deviceConf)
|
||||
.then (filteredDeviceConf)->
|
||||
return { apps, config: filteredDeviceConf }
|
||||
|
||||
loadTargetFromFile: (appsPath) ->
|
||||
appsPath ?= constants.appsJsonPath
|
||||
fs.readFileAsync(appsPath, 'utf8')
|
||||
.then(JSON.parse)
|
||||
.then (stateFromFile) =>
|
||||
if _.isArray(stateFromFile)
|
||||
# This is a legacy apps.json
|
||||
return @_convertLegacyAppsJson(stateFromFile)
|
||||
else
|
||||
return stateFromFile
|
||||
.then (stateFromFile) =>
|
||||
commitToPin = null
|
||||
appToPin = null
|
||||
if !_.isEmpty(stateFromFile)
|
||||
if _.isArray(stateFromFile)
|
||||
# This is a legacy apps.json
|
||||
stateFromFile = @_convertLegacyAppsJson(stateFromFile)
|
||||
images = _.flatMap stateFromFile.apps, (app, appId) =>
|
||||
# multi-app warning!
|
||||
# The following will need to be changed once running multiple applications is possible
|
||||
|
@ -37,7 +37,7 @@ const constants = {
|
||||
'io.balena.supervised': 'true',
|
||||
},
|
||||
bootBlockDevice: '/dev/mmcblk0p1',
|
||||
hostConfigVarPrefix: 'RESIN_HOST_',
|
||||
hostConfigVarPrefix: 'HOST_',
|
||||
};
|
||||
|
||||
if (process.env.DOCKER_HOST == null) {
|
||||
|
@ -32,20 +32,20 @@ testTarget1 = {
|
||||
local: {
|
||||
name: 'aDevice'
|
||||
config: {
|
||||
'RESIN_HOST_CONFIG_gpu_mem': '256'
|
||||
'RESIN_SUPERVISOR_CONNECTIVITY_CHECK': 'true'
|
||||
'RESIN_SUPERVISOR_DELTA': 'false'
|
||||
'RESIN_SUPERVISOR_DELTA_APPLY_TIMEOUT': ''
|
||||
'RESIN_SUPERVISOR_DELTA_REQUEST_TIMEOUT': '30000'
|
||||
'RESIN_SUPERVISOR_DELTA_RETRY_COUNT': '30'
|
||||
'RESIN_SUPERVISOR_DELTA_RETRY_INTERVAL': '10000'
|
||||
'RESIN_SUPERVISOR_DELTA_VERSION': '2'
|
||||
'RESIN_SUPERVISOR_LOCAL_MODE': 'false'
|
||||
'RESIN_SUPERVISOR_LOG_CONTROL': 'true'
|
||||
'RESIN_SUPERVISOR_OVERRIDE_LOCK': 'false'
|
||||
'RESIN_SUPERVISOR_POLL_INTERVAL': '60000'
|
||||
'RESIN_SUPERVISOR_VPN_CONTROL': 'true'
|
||||
'RESIN_SUPERVISOR_PERSISTENT_LOGGING': 'false'
|
||||
'HOST_CONFIG_gpu_mem': '256'
|
||||
'SUPERVISOR_CONNECTIVITY_CHECK': 'true'
|
||||
'SUPERVISOR_DELTA': 'false'
|
||||
'SUPERVISOR_DELTA_APPLY_TIMEOUT': ''
|
||||
'SUPERVISOR_DELTA_REQUEST_TIMEOUT': '30000'
|
||||
'SUPERVISOR_DELTA_RETRY_COUNT': '30'
|
||||
'SUPERVISOR_DELTA_RETRY_INTERVAL': '10000'
|
||||
'SUPERVISOR_DELTA_VERSION': '2'
|
||||
'SUPERVISOR_LOCAL_MODE': 'false'
|
||||
'SUPERVISOR_LOG_CONTROL': 'true'
|
||||
'SUPERVISOR_OVERRIDE_LOCK': 'false'
|
||||
'SUPERVISOR_POLL_INTERVAL': '60000'
|
||||
'SUPERVISOR_VPN_CONTROL': 'true'
|
||||
'SUPERVISOR_PERSISTENT_LOGGING': 'false'
|
||||
}
|
||||
apps: {
|
||||
'1234': {
|
||||
@ -114,20 +114,20 @@ testTargetWithDefaults2 = {
|
||||
local: {
|
||||
name: 'aDeviceWithDifferentName'
|
||||
config: {
|
||||
'RESIN_HOST_CONFIG_gpu_mem': '512'
|
||||
'RESIN_SUPERVISOR_CONNECTIVITY_CHECK': 'true'
|
||||
'RESIN_SUPERVISOR_DELTA': 'false'
|
||||
'RESIN_SUPERVISOR_DELTA_APPLY_TIMEOUT': ''
|
||||
'RESIN_SUPERVISOR_DELTA_REQUEST_TIMEOUT': '30000'
|
||||
'RESIN_SUPERVISOR_DELTA_RETRY_COUNT': '30'
|
||||
'RESIN_SUPERVISOR_DELTA_RETRY_INTERVAL': '10000'
|
||||
'RESIN_SUPERVISOR_DELTA_VERSION': '2'
|
||||
'RESIN_SUPERVISOR_LOCAL_MODE': 'false'
|
||||
'RESIN_SUPERVISOR_LOG_CONTROL': 'true'
|
||||
'RESIN_SUPERVISOR_OVERRIDE_LOCK': 'false'
|
||||
'RESIN_SUPERVISOR_POLL_INTERVAL': '60000'
|
||||
'RESIN_SUPERVISOR_VPN_CONTROL': 'true'
|
||||
'RESIN_SUPERVISOR_PERSISTENT_LOGGING': 'false'
|
||||
'HOST_CONFIG_gpu_mem': '512'
|
||||
'SUPERVISOR_CONNECTIVITY_CHECK': 'true'
|
||||
'SUPERVISOR_DELTA': 'false'
|
||||
'SUPERVISOR_DELTA_APPLY_TIMEOUT': ''
|
||||
'SUPERVISOR_DELTA_REQUEST_TIMEOUT': '30000'
|
||||
'SUPERVISOR_DELTA_RETRY_COUNT': '30'
|
||||
'SUPERVISOR_DELTA_RETRY_INTERVAL': '10000'
|
||||
'SUPERVISOR_DELTA_VERSION': '2'
|
||||
'SUPERVISOR_LOCAL_MODE': 'false'
|
||||
'SUPERVISOR_LOG_CONTROL': 'true'
|
||||
'SUPERVISOR_OVERRIDE_LOCK': 'false'
|
||||
'SUPERVISOR_POLL_INTERVAL': '60000'
|
||||
'SUPERVISOR_VPN_CONTROL': 'true'
|
||||
'SUPERVISOR_PERSISTENT_LOGGING': 'false'
|
||||
}
|
||||
apps: {
|
||||
'1234': {
|
||||
@ -232,6 +232,7 @@ describe 'deviceState', ->
|
||||
return Service.fromComposeObject(s, { appName: 'superapp' })
|
||||
# We serialize and parse JSON to avoid checking fields that are functions or undefined
|
||||
expect(JSON.parse(JSON.stringify(targetState))).to.deep.equal(JSON.parse(JSON.stringify(testTarget)))
|
||||
.finally =>
|
||||
@deviceState.applications.images.save.restore()
|
||||
@deviceState.deviceConfig.getCurrent.restore()
|
||||
|
||||
|
@ -21,7 +21,14 @@ describe 'DeviceConfig', ->
|
||||
@timeout(5000)
|
||||
prepare()
|
||||
@fakeDB = {}
|
||||
@fakeConfig = {}
|
||||
@fakeConfig = {
|
||||
get: (key) ->
|
||||
Promise.try ->
|
||||
if key == 'deviceType'
|
||||
return 'raspberrypi3'
|
||||
else
|
||||
throw new Error('Unknown fake config key')
|
||||
}
|
||||
@fakeLogger = {
|
||||
logSystemMessage: spy()
|
||||
}
|
||||
@ -43,36 +50,36 @@ describe 'DeviceConfig', ->
|
||||
.then (conf) ->
|
||||
fs.readFile.restore()
|
||||
expect(conf).to.deep.equal({
|
||||
RESIN_HOST_CONFIG_initramfs: 'initramf.gz 0x00800000'
|
||||
RESIN_HOST_CONFIG_dtparam: '"i2c=on","audio=on"'
|
||||
RESIN_HOST_CONFIG_dtoverlay: '"ads7846","lirc-rpi,gpio_out_pin=17,gpio_in_pin=13"'
|
||||
RESIN_HOST_CONFIG_foobar: 'baz'
|
||||
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'
|
||||
})
|
||||
|
||||
it 'properly reads a real config.txt file', ->
|
||||
@deviceConfig.getBootConfig(rpiConfigBackend)
|
||||
.then (conf) ->
|
||||
expect(conf).to.deep.equal({
|
||||
RESIN_HOST_CONFIG_dtparam: '"i2c_arm=on","spi=on","audio=on"'
|
||||
RESIN_HOST_CONFIG_enable_uart: '1'
|
||||
RESIN_HOST_CONFIG_disable_splash: '1'
|
||||
RESIN_HOST_CONFIG_avoid_warnings: '1'
|
||||
RESIN_HOST_CONFIG_gpu_mem: '16'
|
||||
HOST_CONFIG_dtparam: '"i2c_arm=on","spi=on","audio=on"'
|
||||
HOST_CONFIG_enable_uart: '1'
|
||||
HOST_CONFIG_disable_splash: '1'
|
||||
HOST_CONFIG_avoid_warnings: '1'
|
||||
HOST_CONFIG_gpu_mem: '16'
|
||||
})
|
||||
|
||||
# Test that the format for special values like initramfs and array variables is preserved
|
||||
it 'does not allow setting forbidden keys', ->
|
||||
current = {
|
||||
RESIN_HOST_CONFIG_initramfs: 'initramf.gz 0x00800000'
|
||||
RESIN_HOST_CONFIG_dtparam: '"i2c=on","audio=on"'
|
||||
RESIN_HOST_CONFIG_dtoverlay: '"ads7846","lirc-rpi,gpio_out_pin=17,gpio_in_pin=13"'
|
||||
RESIN_HOST_CONFIG_foobar: 'baz'
|
||||
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'
|
||||
}
|
||||
target = {
|
||||
RESIN_HOST_CONFIG_initramfs: 'initramf.gz 0x00810000'
|
||||
RESIN_HOST_CONFIG_dtparam: '"i2c=on","audio=on"'
|
||||
RESIN_HOST_CONFIG_dtoverlay: '"ads7846","lirc-rpi,gpio_out_pin=17,gpio_in_pin=13"'
|
||||
RESIN_HOST_CONFIG_foobar: 'baz'
|
||||
HOST_CONFIG_initramfs: 'initramf.gz 0x00810000'
|
||||
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'
|
||||
}
|
||||
promise = Promise.try =>
|
||||
@deviceConfig.bootConfigChangeRequired(rpiConfigBackend, current, target)
|
||||
@ -86,16 +93,16 @@ describe 'DeviceConfig', ->
|
||||
|
||||
it 'does not try to change config.txt if it should not change', ->
|
||||
current = {
|
||||
RESIN_HOST_CONFIG_initramfs: 'initramf.gz 0x00800000'
|
||||
RESIN_HOST_CONFIG_dtparam: '"i2c=on","audio=on"'
|
||||
RESIN_HOST_CONFIG_dtoverlay: '"ads7846","lirc-rpi,gpio_out_pin=17,gpio_in_pin=13"'
|
||||
RESIN_HOST_CONFIG_foobar: 'baz'
|
||||
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'
|
||||
}
|
||||
target = {
|
||||
RESIN_HOST_CONFIG_initramfs: 'initramf.gz 0x00800000'
|
||||
RESIN_HOST_CONFIG_dtparam: '"i2c=on","audio=on"'
|
||||
RESIN_HOST_CONFIG_dtoverlay: '"ads7846","lirc-rpi,gpio_out_pin=17,gpio_in_pin=13"'
|
||||
RESIN_HOST_CONFIG_foobar: 'baz'
|
||||
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'
|
||||
}
|
||||
promise = Promise.try =>
|
||||
@deviceConfig.bootConfigChangeRequired(rpiConfigBackend, current, target)
|
||||
@ -108,17 +115,17 @@ describe 'DeviceConfig', ->
|
||||
stub(fsUtils, 'writeFileAtomic').resolves()
|
||||
stub(childProcess, 'execAsync').resolves()
|
||||
current = {
|
||||
RESIN_HOST_CONFIG_initramfs: 'initramf.gz 0x00800000'
|
||||
RESIN_HOST_CONFIG_dtparam: '"i2c=on","audio=on"'
|
||||
RESIN_HOST_CONFIG_dtoverlay: '"ads7846","lirc-rpi,gpio_out_pin=17,gpio_in_pin=13"'
|
||||
RESIN_HOST_CONFIG_foobar: 'baz'
|
||||
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'
|
||||
}
|
||||
target = {
|
||||
RESIN_HOST_CONFIG_initramfs: 'initramf.gz 0x00800000'
|
||||
RESIN_HOST_CONFIG_dtparam: '"i2c=on","audio=off"'
|
||||
RESIN_HOST_CONFIG_dtoverlay: '"lirc-rpi,gpio_out_pin=17,gpio_in_pin=13"'
|
||||
RESIN_HOST_CONFIG_foobar: 'bat'
|
||||
RESIN_HOST_CONFIG_foobaz: 'bar'
|
||||
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'
|
||||
}
|
||||
promise = Promise.try =>
|
||||
@deviceConfig.bootConfigChangeRequired(rpiConfigBackend, current, target)
|
||||
@ -141,6 +148,23 @@ describe 'DeviceConfig', ->
|
||||
childProcess.execAsync.restore()
|
||||
@fakeLogger.logSystemMessage.reset()
|
||||
|
||||
it 'accepts RESIN_ and BALENA_ variables', ->
|
||||
@deviceConfig.filterAndFormatConfigKeys({
|
||||
FOO: 'bar',
|
||||
BAR: 'baz',
|
||||
RESIN_HOST_CONFIG_foo: 'foobaz',
|
||||
BALENA_HOST_CONFIG_foo: 'foobar',
|
||||
RESIN_HOST_CONFIG_other: 'val',
|
||||
BALENA_HOST_CONFIG_baz: 'bad',
|
||||
BALENA_SUPERVISOR_POLL_INTERVAL: '100',
|
||||
}).then (filteredConf) ->
|
||||
expect(filteredConf).to.deep.equal({
|
||||
HOST_CONFIG_foo: 'foobar',
|
||||
HOST_CONFIG_other: 'val',
|
||||
HOST_CONFIG_baz: 'bad',
|
||||
SUPERVISOR_POLL_INTERVAL: '100',
|
||||
});
|
||||
|
||||
describe 'Extlinux files', ->
|
||||
|
||||
it 'should correctly write to extlinux.conf files', ->
|
||||
@ -150,7 +174,7 @@ describe 'DeviceConfig', ->
|
||||
current = {
|
||||
}
|
||||
target = {
|
||||
RESIN_HOST_EXTLINUX_isolcpus: '2'
|
||||
HOST_EXTLINUX_isolcpus: '2'
|
||||
}
|
||||
|
||||
promise = Promise.try =>
|
||||
|
@ -18,10 +18,10 @@ describe 'Config Utilities', ->
|
||||
|
||||
it 'correctly transforms environments to boot config objects', ->
|
||||
bootConfig = configUtils.envToBootConfig(rpiBackend, {
|
||||
RESIN_HOST_CONFIG_initramfs: 'initramf.gz 0x00800000'
|
||||
RESIN_HOST_CONFIG_dtparam: '"i2c=on","audio=on"'
|
||||
RESIN_HOST_CONFIG_dtoverlay: '"ads7846","lirc-rpi,gpio_out_pin=17,gpio_in_pin=13"'
|
||||
RESIN_HOST_CONFIG_foobar: 'baz'
|
||||
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'
|
||||
})
|
||||
expect(bootConfig).to.deep.equal({
|
||||
initramfs: 'initramf.gz 0x00800000'
|
||||
|
Loading…
x
Reference in New Issue
Block a user