mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-21 18:06:47 +00:00
Merge pull request #1490 from balena-io/1472-device-type
Change source of deviceType to device-type.json
This commit is contained in:
commit
22402dbb93
@ -1,5 +1,6 @@
|
||||
import * as Bluebird from 'bluebird';
|
||||
import * as _ from 'lodash';
|
||||
import * as memoizee from 'memoizee';
|
||||
import { fs } from 'mz';
|
||||
import { URL } from 'url';
|
||||
|
||||
@ -38,22 +39,44 @@ export const fnSchema = {
|
||||
macAddress: () => {
|
||||
return macAddress.getAll(constants.macAddressPath);
|
||||
},
|
||||
deviceArch: async () => {
|
||||
try {
|
||||
// FIXME: We should be mounting the following file into the supervisor from the
|
||||
// start-resin-supervisor script, changed in meta-resin - but until then, hardcode it
|
||||
const data = await fs.readFile(
|
||||
`${constants.rootMountPoint}/resin-boot/device-type.json`,
|
||||
'utf8',
|
||||
);
|
||||
const deviceInfo = JSON.parse(data);
|
||||
deviceArch: memoizee(
|
||||
async () => {
|
||||
try {
|
||||
// FIXME: We should be mounting the following file into the supervisor from the
|
||||
// start-resin-supervisor script, changed in meta-resin - but until then, hardcode it
|
||||
const data = await fs.readFile(
|
||||
`${constants.bootMountPoint}/device-type.json`,
|
||||
'utf8',
|
||||
);
|
||||
const deviceInfo = JSON.parse(data);
|
||||
|
||||
return deviceInfo.arch;
|
||||
} catch (e) {
|
||||
log.error(`Unable to get architecture: ${e}`);
|
||||
return 'unknown';
|
||||
}
|
||||
},
|
||||
return deviceInfo.arch;
|
||||
} catch (e) {
|
||||
log.error(`Unable to get architecture: ${e}`);
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
{ promise: true },
|
||||
),
|
||||
deviceType: memoizee(
|
||||
async () => {
|
||||
try {
|
||||
// FIXME: We should be mounting the following file into the supervisor from the
|
||||
// start-resin-supervisor script, changed in meta-resin - but until then, hardcode it
|
||||
const data = await fs.readFile(
|
||||
`${constants.bootMountPoint}/device-type.json`,
|
||||
'utf8',
|
||||
);
|
||||
const deviceInfo = JSON.parse(data);
|
||||
|
||||
return deviceInfo.slug;
|
||||
} catch (e) {
|
||||
log.error(`Unable to get device type: ${e}`);
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
{ promise: true },
|
||||
),
|
||||
provisioningOptions: () => {
|
||||
return config
|
||||
.getMany([
|
||||
|
@ -87,11 +87,29 @@ export async function get<T extends SchemaTypeKey>(
|
||||
// Cast the promise as something that produces an unknown, and this means that
|
||||
// we can validate the output of the function as well, ensuring that the type matches
|
||||
const promiseValue = FnSchema.fnSchema[fnKey]();
|
||||
return promiseValue.then((value: unknown) => {
|
||||
const decoded = schemaTypes[key].type.decode(value);
|
||||
return promiseValue
|
||||
.then((value: unknown) => {
|
||||
const decoded = schemaTypes[key].type.decode(value);
|
||||
|
||||
return checkValueDecode(decoded, key, value) && decoded.right;
|
||||
});
|
||||
return checkValueDecode(decoded, key, value) && decoded.right;
|
||||
})
|
||||
.catch(() => {
|
||||
const defaultValue = schemaTypes[key].default;
|
||||
if (defaultValue instanceof t.Type) {
|
||||
// For functions, this can happen if t.never is used as default
|
||||
// value. In that case decoding and the value check below will throw
|
||||
// (which is what is expected)
|
||||
// if future functions use NullOrUndefined as with values above
|
||||
// this branch will return undefined. In any case this should never
|
||||
// happen
|
||||
const maybeDecoded = (defaultValue as t.Type<any>).decode(undefined);
|
||||
|
||||
return (
|
||||
checkValueDecode(maybeDecoded, key, undefined) && maybeDecoded.right
|
||||
);
|
||||
}
|
||||
return defaultValue as SchemaReturn<T>;
|
||||
});
|
||||
} else {
|
||||
throw new Error(`Unknown config value ${key}`);
|
||||
}
|
||||
|
@ -34,11 +34,6 @@ export const schema = {
|
||||
mutable: true,
|
||||
removeIfNull: false,
|
||||
},
|
||||
deviceType: {
|
||||
source: 'config.json',
|
||||
mutable: false,
|
||||
removeIfNull: false,
|
||||
},
|
||||
deviceId: {
|
||||
source: 'config.json',
|
||||
mutable: true,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as _ from 'lodash';
|
||||
import { fs } from 'mz';
|
||||
import { SinonStub, stub } from 'sinon';
|
||||
|
||||
import chai = require('./lib/chai-config');
|
||||
import prepare = require('./lib/prepare');
|
||||
@ -7,6 +8,7 @@ import * as conf from '../src/config';
|
||||
|
||||
import constants = require('../src/lib/constants');
|
||||
import { SchemaTypeKey } from '../src/config/schema-type';
|
||||
import { fnSchema } from '../src/config/functions';
|
||||
|
||||
// tslint:disable-next-line
|
||||
chai.use(require('chai-events'));
|
||||
@ -130,4 +132,136 @@ describe('Config', () => {
|
||||
expect(conf.remove('version' as any)).to.be.rejected;
|
||||
});
|
||||
});
|
||||
|
||||
describe('Config data sources', () => {
|
||||
after(() => {
|
||||
// Clean up memoized values
|
||||
});
|
||||
|
||||
it('should obtain deviceArch from device-type.json', async () => {
|
||||
const [slug, arch] = ['raspberrypi3', 'armv7hf'];
|
||||
stub(fs, 'readFile').resolves(
|
||||
JSON.stringify({
|
||||
slug,
|
||||
arch,
|
||||
}),
|
||||
);
|
||||
|
||||
const deviceArch = await conf.get('deviceArch');
|
||||
expect(deviceArch).to.equal(arch);
|
||||
expect(fs.readFile).to.be.calledOnce;
|
||||
expect(fs.readFile).to.be.calledWith(
|
||||
`${constants.bootMountPoint}/device-type.json`,
|
||||
'utf8',
|
||||
);
|
||||
|
||||
(fs.readFile as SinonStub).restore();
|
||||
});
|
||||
|
||||
it('should obtain deviceType from device-type.json', async () => {
|
||||
const [slug, arch] = ['raspberrypi3', 'armv7hf'];
|
||||
stub(fs, 'readFile').resolves(
|
||||
JSON.stringify({
|
||||
slug,
|
||||
arch,
|
||||
}),
|
||||
);
|
||||
|
||||
const deviceType = await conf.get('deviceType');
|
||||
expect(deviceType).to.equal(slug);
|
||||
expect(fs.readFile).to.be.calledOnce;
|
||||
expect(fs.readFile).to.be.calledWith(
|
||||
`${constants.bootMountPoint}/device-type.json`,
|
||||
'utf8',
|
||||
);
|
||||
|
||||
(fs.readFile as SinonStub).restore();
|
||||
});
|
||||
|
||||
it('should memoize values from device-type.json', async () => {
|
||||
const [slug, arch] = ['raspberrypi3', 'armv7hf'];
|
||||
stub(fs, 'readFile').resolves(
|
||||
JSON.stringify({
|
||||
slug,
|
||||
arch,
|
||||
}),
|
||||
);
|
||||
|
||||
const deviceArch = await conf.get('deviceArch');
|
||||
expect(deviceArch).to.equal(arch);
|
||||
|
||||
// The result should still be memoized from the
|
||||
// call on the previous test
|
||||
expect(fs.readFile).to.not.be.called;
|
||||
|
||||
const deviceType = await conf.get('deviceType');
|
||||
expect(deviceType).to.equal(slug);
|
||||
|
||||
// The result should still be memoized from the
|
||||
// call on the previous test
|
||||
expect(fs.readFile).to.not.be.called;
|
||||
|
||||
(fs.readFile as SinonStub).restore();
|
||||
});
|
||||
|
||||
it('should not memoize errors when reading deviceArch', (done) => {
|
||||
// Clean up memoized value
|
||||
fnSchema.deviceArch.clear();
|
||||
|
||||
// File not found
|
||||
stub(fs, 'readFile').throws('File not found');
|
||||
|
||||
expect(conf.get('deviceArch')).to.eventually.equal('unknown');
|
||||
expect(fs.readFile).to.be.calledOnce;
|
||||
(fs.readFile as SinonStub).restore();
|
||||
|
||||
// Next call should not throw
|
||||
const [slug, arch] = ['raspberrypi3', 'armv7hf'];
|
||||
stub(fs, 'readFile').resolves(
|
||||
JSON.stringify({
|
||||
slug,
|
||||
arch,
|
||||
}),
|
||||
);
|
||||
|
||||
// We need to let rejection be discovered
|
||||
// https://github.com/medikoo/memoizee/issues/93
|
||||
setTimeout(() => {
|
||||
expect(conf.get('deviceArch')).to.eventually.equal(arch);
|
||||
expect(fs.readFile).to.be.calledOnce;
|
||||
(fs.readFile as SinonStub).restore();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not memoize errors when reading deviceType', (done) => {
|
||||
// Clean up memoized value
|
||||
fnSchema.deviceType.clear();
|
||||
|
||||
// File not found
|
||||
stub(fs, 'readFile').throws('File not found');
|
||||
|
||||
expect(conf.get('deviceType')).to.eventually.equal('unknown');
|
||||
expect(fs.readFile).to.be.calledOnce;
|
||||
(fs.readFile as SinonStub).restore();
|
||||
|
||||
// Next call should not throw
|
||||
const [slug, arch] = ['raspberrypi3', 'armv7hf'];
|
||||
stub(fs, 'readFile').resolves(
|
||||
JSON.stringify({
|
||||
slug,
|
||||
arch,
|
||||
}),
|
||||
);
|
||||
|
||||
// We need to let rejection be discovered
|
||||
// https://github.com/medikoo/memoizee/issues/93
|
||||
setTimeout(() => {
|
||||
expect(conf.get('deviceType')).to.eventually.equal(slug);
|
||||
expect(fs.readFile).to.be.calledOnce;
|
||||
(fs.readFile as SinonStub).restore();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user