mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-22 15:02:23 +00:00
Merge pull request #2167 from balena-os/hw-arch-contract
Add `arch.sw` to supported container requirements
This commit is contained in:
commit
3b6878fd80
@ -25,7 +25,8 @@ export interface ServiceContracts {
|
|||||||
type PotentialContractRequirements =
|
type PotentialContractRequirements =
|
||||||
| 'sw.supervisor'
|
| 'sw.supervisor'
|
||||||
| 'sw.l4t'
|
| 'sw.l4t'
|
||||||
| 'hw.device-type';
|
| 'hw.device-type'
|
||||||
|
| 'arch.sw';
|
||||||
type ContractRequirements = {
|
type ContractRequirements = {
|
||||||
[key in PotentialContractRequirements]?: string;
|
[key in PotentialContractRequirements]?: string;
|
||||||
};
|
};
|
||||||
@ -35,11 +36,13 @@ const contractRequirementVersions: ContractRequirements = {};
|
|||||||
export function initializeContractRequirements(opts: {
|
export function initializeContractRequirements(opts: {
|
||||||
supervisorVersion: string;
|
supervisorVersion: string;
|
||||||
deviceType: string;
|
deviceType: string;
|
||||||
|
deviceArch: string;
|
||||||
l4tVersion?: string;
|
l4tVersion?: string;
|
||||||
}) {
|
}) {
|
||||||
contractRequirementVersions['sw.supervisor'] = opts.supervisorVersion;
|
contractRequirementVersions['sw.supervisor'] = opts.supervisorVersion;
|
||||||
contractRequirementVersions['sw.l4t'] = opts.l4tVersion;
|
contractRequirementVersions['sw.l4t'] = opts.l4tVersion;
|
||||||
contractRequirementVersions['hw.device-type'] = opts.deviceType;
|
contractRequirementVersions['hw.device-type'] = opts.deviceType;
|
||||||
|
contractRequirementVersions['arch.sw'] = opts.deviceArch;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidRequirementType(
|
function isValidRequirementType(
|
||||||
@ -162,10 +165,10 @@ const contractObjectValidator = t.type({
|
|||||||
|
|
||||||
function getContractsFromVersions(components: ContractRequirements) {
|
function getContractsFromVersions(components: ContractRequirements) {
|
||||||
return _.map(components, (value, component) => {
|
return _.map(components, (value, component) => {
|
||||||
if (component === 'hw.device-type') {
|
if (component === 'hw.device-type' || component === 'arch.sw') {
|
||||||
return {
|
return {
|
||||||
type: component,
|
type: component,
|
||||||
slug: component,
|
slug: value,
|
||||||
name: value,
|
name: value,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
@ -45,6 +45,7 @@ export class Supervisor {
|
|||||||
initializeContractRequirements({
|
initializeContractRequirements({
|
||||||
supervisorVersion: version,
|
supervisorVersion: version,
|
||||||
deviceType: await config.get('deviceType'),
|
deviceType: await config.get('deviceType'),
|
||||||
|
deviceArch: await config.get('deviceArch'),
|
||||||
l4tVersion: await osRelease.getL4tVersion(),
|
l4tVersion: await osRelease.getL4tVersion(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ describe('device-state', () => {
|
|||||||
initializeContractRequirements({
|
initializeContractRequirements({
|
||||||
supervisorVersion: '11.0.0',
|
supervisorVersion: '11.0.0',
|
||||||
deviceType: 'intel-nuc',
|
deviceType: 'intel-nuc',
|
||||||
|
deviceArch: 'amd64',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -406,8 +407,8 @@ describe('device-state', () => {
|
|||||||
name: 'Enforce supervisor version',
|
name: 'Enforce supervisor version',
|
||||||
requires: [
|
requires: [
|
||||||
{
|
{
|
||||||
type: 'sw.supervisor',
|
type: 'arch.sw',
|
||||||
version: '>=12.0.0',
|
version: 'armv7hf',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -1,22 +1,19 @@
|
|||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import { SinonStub, stub } from 'sinon';
|
|
||||||
import * as semver from 'semver';
|
import * as semver from 'semver';
|
||||||
|
import { SinonStub, stub } from 'sinon';
|
||||||
|
|
||||||
import * as constants from '~/lib/constants';
|
|
||||||
import {
|
|
||||||
containerContractsFulfilled,
|
|
||||||
initializeContractRequirements,
|
|
||||||
validateContract,
|
|
||||||
} from '~/lib/contracts';
|
|
||||||
import * as osRelease from '~/lib/os-release';
|
import * as osRelease from '~/lib/os-release';
|
||||||
import supervisorVersion = require('~/lib/supervisor-version');
|
import supervisorVersion = require('~/lib/supervisor-version');
|
||||||
import * as fsUtils from '~/lib/fs-utils';
|
import * as fsUtils from '~/lib/fs-utils';
|
||||||
|
|
||||||
describe('lib/contracts', () => {
|
describe('lib/contracts', () => {
|
||||||
|
type Contracts = typeof import('~/src/lib/contracts');
|
||||||
|
const contracts = require('~/src/lib/contracts') as Contracts;
|
||||||
before(() => {
|
before(() => {
|
||||||
initializeContractRequirements({
|
contracts.initializeContractRequirements({
|
||||||
supervisorVersion,
|
supervisorVersion,
|
||||||
deviceType: 'intel-nuc',
|
deviceType: 'intel-nuc',
|
||||||
|
deviceArch: 'amd64',
|
||||||
l4tVersion: '32.2',
|
l4tVersion: '32.2',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -24,14 +21,14 @@ describe('lib/contracts', () => {
|
|||||||
describe('Contract validation', () => {
|
describe('Contract validation', () => {
|
||||||
it('should correctly validate a contract with no requirements', () =>
|
it('should correctly validate a contract with no requirements', () =>
|
||||||
expect(() =>
|
expect(() =>
|
||||||
validateContract({
|
contracts.validateContract({
|
||||||
slug: 'user-container',
|
slug: 'user-container',
|
||||||
}),
|
}),
|
||||||
).to.be.not.throw());
|
).to.be.not.throw());
|
||||||
|
|
||||||
it('should correctly validate a contract with extra fields', () =>
|
it('should correctly validate a contract with extra fields', () =>
|
||||||
expect(() =>
|
expect(() =>
|
||||||
validateContract({
|
contracts.validateContract({
|
||||||
slug: 'user-container',
|
slug: 'user-container',
|
||||||
name: 'user-container',
|
name: 'user-container',
|
||||||
version: '3.0.0',
|
version: '3.0.0',
|
||||||
@ -40,15 +37,15 @@ describe('lib/contracts', () => {
|
|||||||
|
|
||||||
it('should not validate a contract without the minimum required fields', () => {
|
it('should not validate a contract without the minimum required fields', () => {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
expect(() => validateContract({})).to.throw(),
|
expect(() => contracts.validateContract({})).to.throw(),
|
||||||
expect(() => validateContract({ name: 'test' })).to.throw(),
|
expect(() => contracts.validateContract({ name: 'test' })).to.throw(),
|
||||||
expect(() => validateContract({ requires: [] })).to.throw(),
|
expect(() => contracts.validateContract({ requires: [] })).to.throw(),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly validate a contract with requirements', () =>
|
it('should correctly validate a contract with requirements', () =>
|
||||||
expect(() =>
|
expect(() =>
|
||||||
validateContract({
|
contracts.validateContract({
|
||||||
slug: 'user-container',
|
slug: 'user-container',
|
||||||
requires: [
|
requires: [
|
||||||
{
|
{
|
||||||
@ -58,13 +55,15 @@ describe('lib/contracts', () => {
|
|||||||
{
|
{
|
||||||
type: 'sw.supervisor',
|
type: 'sw.supervisor',
|
||||||
},
|
},
|
||||||
|
{ type: 'hw.device-type', slug: 'raspberrypi3' },
|
||||||
|
{ type: 'arch.sw', slug: 'aarch64' },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
).to.not.throw());
|
).to.not.throw());
|
||||||
|
|
||||||
it('should not validate a contract with requirements without the minimum required fields', () => {
|
it('should not validate a contract with requirements without the minimum required fields', () => {
|
||||||
return expect(() =>
|
return expect(() =>
|
||||||
validateContract({
|
contracts.validateContract({
|
||||||
slug: 'user-container',
|
slug: 'user-container',
|
||||||
requires: [
|
requires: [
|
||||||
{
|
{
|
||||||
@ -92,16 +91,16 @@ describe('lib/contracts', () => {
|
|||||||
// We ensure that the versions we're using for testing
|
// We ensure that the versions we're using for testing
|
||||||
// are the same as the time of implementation, otherwise
|
// are the same as the time of implementation, otherwise
|
||||||
// these tests could fail or succeed when they shouldn't
|
// these tests could fail or succeed when they shouldn't
|
||||||
expect(await osRelease.getOSSemver(constants.hostOSVersionPath)).to.equal(
|
// expect(await osRelease.getOSSemver(constants.hostOSVersionPath)).to.equal(
|
||||||
'2.0.6',
|
// '2.0.6',
|
||||||
);
|
// );
|
||||||
expect(semver.gt(supervisorVersionGreater, supervisorVersion)).to.be.true;
|
expect(semver.gt(supervisorVersionGreater, supervisorVersion)).to.be.true;
|
||||||
expect(semver.lt(supervisorVersionLesser, supervisorVersion)).to.be.true;
|
expect(semver.lt(supervisorVersionLesser, supervisorVersion)).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should correctly run containers with no requirements', async () => {
|
it('Should correctly run containers with no requirements', async () => {
|
||||||
expect(
|
expect(
|
||||||
containerContractsFulfilled({
|
contracts.containerContractsFulfilled({
|
||||||
service: {
|
service: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -114,7 +113,7 @@ describe('lib/contracts', () => {
|
|||||||
.to.have.property('valid')
|
.to.have.property('valid')
|
||||||
.that.equals(true);
|
.that.equals(true);
|
||||||
expect(
|
expect(
|
||||||
containerContractsFulfilled({
|
contracts.containerContractsFulfilled({
|
||||||
service: {
|
service: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -137,7 +136,7 @@ describe('lib/contracts', () => {
|
|||||||
|
|
||||||
it('should correctly run containers whose requirements are satisfied', async () => {
|
it('should correctly run containers whose requirements are satisfied', async () => {
|
||||||
expect(
|
expect(
|
||||||
containerContractsFulfilled({
|
contracts.containerContractsFulfilled({
|
||||||
service: {
|
service: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -148,6 +147,7 @@ describe('lib/contracts', () => {
|
|||||||
type: 'sw.supervisor',
|
type: 'sw.supervisor',
|
||||||
version: `>${supervisorVersionLesser}`,
|
version: `>${supervisorVersionLesser}`,
|
||||||
},
|
},
|
||||||
|
{ type: 'hw.device-type', slug: 'intel-nuc' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
optional: false,
|
optional: false,
|
||||||
@ -158,7 +158,7 @@ describe('lib/contracts', () => {
|
|||||||
.that.equals(true);
|
.that.equals(true);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
containerContractsFulfilled({
|
contracts.containerContractsFulfilled({
|
||||||
service: {
|
service: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -169,6 +169,8 @@ describe('lib/contracts', () => {
|
|||||||
type: 'sw.supervisor',
|
type: 'sw.supervisor',
|
||||||
version: `<${supervisorVersionGreater}`,
|
version: `<${supervisorVersionGreater}`,
|
||||||
},
|
},
|
||||||
|
{ type: 'sw.arch', name: 'amd64' },
|
||||||
|
{ type: 'hw.device-type', slug: 'intel-nuc' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
optional: false,
|
optional: false,
|
||||||
@ -179,7 +181,7 @@ describe('lib/contracts', () => {
|
|||||||
.that.equals(true);
|
.that.equals(true);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
containerContractsFulfilled({
|
contracts.containerContractsFulfilled({
|
||||||
service: {
|
service: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -190,6 +192,7 @@ describe('lib/contracts', () => {
|
|||||||
type: 'sw.supervisor',
|
type: 'sw.supervisor',
|
||||||
version: `>${supervisorVersionLesser}`,
|
version: `>${supervisorVersionLesser}`,
|
||||||
},
|
},
|
||||||
|
{ type: 'sw.arch', slug: 'amd64' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
optional: false,
|
optional: false,
|
||||||
@ -200,7 +203,7 @@ describe('lib/contracts', () => {
|
|||||||
.that.equals(true);
|
.that.equals(true);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
containerContractsFulfilled({
|
contracts.containerContractsFulfilled({
|
||||||
service: {
|
service: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -215,6 +218,7 @@ describe('lib/contracts', () => {
|
|||||||
type: 'sw.l4t',
|
type: 'sw.l4t',
|
||||||
version: '32.2',
|
version: '32.2',
|
||||||
},
|
},
|
||||||
|
{ type: 'hw.device-type', slug: 'intel-nuc' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
optional: false,
|
optional: false,
|
||||||
@ -225,7 +229,7 @@ describe('lib/contracts', () => {
|
|||||||
.that.equals(true);
|
.that.equals(true);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
containerContractsFulfilled({
|
contracts.containerContractsFulfilled({
|
||||||
service: {
|
service: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -246,6 +250,8 @@ describe('lib/contracts', () => {
|
|||||||
name: 'user-container1',
|
name: 'user-container1',
|
||||||
slug: 'user-container1',
|
slug: 'user-container1',
|
||||||
requires: [
|
requires: [
|
||||||
|
// sw.os is not a supported contract type, so validation
|
||||||
|
// ignores this requirement
|
||||||
{
|
{
|
||||||
type: 'sw.os',
|
type: 'sw.os',
|
||||||
version: '<3.0.0',
|
version: '<3.0.0',
|
||||||
@ -261,7 +267,7 @@ describe('lib/contracts', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should refuse to run containers whose requirements are not satisfied', async () => {
|
it('Should refuse to run containers whose requirements are not satisfied', async () => {
|
||||||
let fulfilled = containerContractsFulfilled({
|
let fulfilled = contracts.containerContractsFulfilled({
|
||||||
service: {
|
service: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -282,7 +288,70 @@ describe('lib/contracts', () => {
|
|||||||
.to.have.property('unmetServices')
|
.to.have.property('unmetServices')
|
||||||
.that.deep.equals(['service']);
|
.that.deep.equals(['service']);
|
||||||
|
|
||||||
fulfilled = containerContractsFulfilled({
|
fulfilled = contracts.containerContractsFulfilled({
|
||||||
|
service: {
|
||||||
|
contract: {
|
||||||
|
type: 'sw.container',
|
||||||
|
name: 'user-container',
|
||||||
|
slug: 'user-container',
|
||||||
|
requires: [
|
||||||
|
{
|
||||||
|
type: 'hw.device-type',
|
||||||
|
slug: 'raspberrypi3',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(fulfilled).to.have.property('valid').that.equals(false);
|
||||||
|
expect(fulfilled)
|
||||||
|
.to.have.property('unmetServices')
|
||||||
|
.that.deep.equals(['service']);
|
||||||
|
|
||||||
|
fulfilled = contracts.containerContractsFulfilled({
|
||||||
|
service: {
|
||||||
|
contract: {
|
||||||
|
type: 'sw.container',
|
||||||
|
name: 'user-container',
|
||||||
|
slug: 'user-container',
|
||||||
|
requires: [
|
||||||
|
{
|
||||||
|
type: 'arch.sw',
|
||||||
|
slug: 'armv7hf',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(fulfilled).to.have.property('valid').that.equals(false);
|
||||||
|
expect(fulfilled)
|
||||||
|
.to.have.property('unmetServices')
|
||||||
|
.that.deep.equals(['service']);
|
||||||
|
|
||||||
|
fulfilled = contracts.containerContractsFulfilled({
|
||||||
|
service: {
|
||||||
|
contract: {
|
||||||
|
type: 'sw.container',
|
||||||
|
name: 'user-container',
|
||||||
|
slug: 'user-container',
|
||||||
|
requires: [
|
||||||
|
{
|
||||||
|
type: 'hw.device-type',
|
||||||
|
name: 'raspberrypi3',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(fulfilled).to.have.property('valid').that.equals(false);
|
||||||
|
expect(fulfilled)
|
||||||
|
.to.have.property('unmetServices')
|
||||||
|
.that.deep.equals(['service']);
|
||||||
|
|
||||||
|
fulfilled = contracts.containerContractsFulfilled({
|
||||||
service2: {
|
service2: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -303,7 +372,7 @@ describe('lib/contracts', () => {
|
|||||||
.to.have.property('unmetServices')
|
.to.have.property('unmetServices')
|
||||||
.that.deep.equals(['service2']);
|
.that.deep.equals(['service2']);
|
||||||
|
|
||||||
fulfilled = containerContractsFulfilled({
|
fulfilled = contracts.containerContractsFulfilled({
|
||||||
service: {
|
service: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -342,7 +411,7 @@ describe('lib/contracts', () => {
|
|||||||
describe('Optional containers', () => {
|
describe('Optional containers', () => {
|
||||||
it('should correctly run passing optional containers', async () => {
|
it('should correctly run passing optional containers', async () => {
|
||||||
const { valid, unmetServices, fulfilledServices } =
|
const { valid, unmetServices, fulfilledServices } =
|
||||||
containerContractsFulfilled({
|
contracts.containerContractsFulfilled({
|
||||||
service1: {
|
service1: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -364,7 +433,7 @@ describe('lib/contracts', () => {
|
|||||||
|
|
||||||
it('should corrrectly omit failing optional containers', async () => {
|
it('should corrrectly omit failing optional containers', async () => {
|
||||||
const { valid, unmetServices, fulfilledServices } =
|
const { valid, unmetServices, fulfilledServices } =
|
||||||
containerContractsFulfilled({
|
contracts.containerContractsFulfilled({
|
||||||
service1: {
|
service1: {
|
||||||
contract: {
|
contract: {
|
||||||
type: 'sw.container',
|
type: 'sw.container',
|
||||||
@ -385,150 +454,182 @@ describe('lib/contracts', () => {
|
|||||||
},
|
},
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
|
service3: {
|
||||||
|
contract: {
|
||||||
|
type: 'sw.container',
|
||||||
|
slug: 'service3',
|
||||||
|
requires: [
|
||||||
|
{
|
||||||
|
type: 'hw.device-type',
|
||||||
|
slug: 'raspberrypi3',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
service4: {
|
||||||
|
contract: {
|
||||||
|
type: 'sw.container',
|
||||||
|
slug: 'service3',
|
||||||
|
requires: [
|
||||||
|
{
|
||||||
|
type: 'arch.sw',
|
||||||
|
slug: 'armv7hf',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
expect(valid).to.equal(true);
|
expect(valid).to.equal(true);
|
||||||
expect(unmetServices).to.deep.equal(['service1']);
|
expect(unmetServices).to.deep.equal([
|
||||||
|
'service1',
|
||||||
|
'service3',
|
||||||
|
'service4',
|
||||||
|
]);
|
||||||
expect(fulfilledServices).to.deep.equal(['service2']);
|
expect(fulfilledServices).to.deep.equal(['service2']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe('L4T version detection', () => {
|
describe('L4T version detection', () => {
|
||||||
let execStub: SinonStub;
|
let execStub: SinonStub;
|
||||||
|
|
||||||
const seedExec = (version: string) => {
|
const seedExec = (version: string) => {
|
||||||
execStub = stub(fsUtils, 'exec').resolves({
|
execStub = stub(fsUtils, 'exec').resolves({
|
||||||
stdout: Buffer.from(version),
|
stdout: Buffer.from(version),
|
||||||
stderr: Buffer.from(''),
|
stderr: Buffer.from(''),
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
execStub.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should correctly parse L4T version strings', async () => {
|
|
||||||
seedExec('4.9.140-l4t-r32.2+g3dcbed5');
|
|
||||||
expect(await osRelease.getL4tVersion()).to.equal('32.2.0');
|
|
||||||
expect(execStub.callCount).to.equal(1);
|
|
||||||
execStub.restore();
|
|
||||||
|
|
||||||
seedExec('4.4.38-l4t-r28.2+g174510d');
|
|
||||||
expect(await osRelease.getL4tVersion()).to.equal('28.2.0');
|
|
||||||
expect(execStub.callCount).to.equal(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should correctly handle l4t versions which contain three numbers', async () => {
|
|
||||||
seedExec('4.4.38-l4t-r32.3.1+g174510d');
|
|
||||||
expect(await osRelease.getL4tVersion()).to.equal('32.3.1');
|
|
||||||
expect(execStub.callCount).to.equal(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return undefined when there is no l4t string in uname', async () => {
|
|
||||||
seedExec('4.18.14-yocto-standard');
|
|
||||||
expect(await osRelease.getL4tVersion()).to.be.undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('L4T comparison', () => {
|
|
||||||
const seedEngine = async (version: string) => {
|
|
||||||
if (execStub != null) {
|
|
||||||
execStub.restore();
|
|
||||||
}
|
|
||||||
seedExec(version);
|
|
||||||
initializeContractRequirements({
|
|
||||||
supervisorVersion,
|
|
||||||
deviceType: 'intel-nuc',
|
|
||||||
l4tVersion: await osRelease.getL4tVersion(),
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should allow semver matching even when l4t does not fulfill semver', async () => {
|
afterEach(() => {
|
||||||
await seedEngine('4.4.38-l4t-r31.0');
|
execStub.restore();
|
||||||
|
|
||||||
expect(
|
|
||||||
containerContractsFulfilled({
|
|
||||||
service: {
|
|
||||||
contract: {
|
|
||||||
type: 'sw.container',
|
|
||||||
slug: 'user-container',
|
|
||||||
requires: [
|
|
||||||
{
|
|
||||||
type: 'sw.l4t',
|
|
||||||
version: '>=31.0.0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.to.have.property('valid')
|
|
||||||
.that.equals(true);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
containerContractsFulfilled({
|
|
||||||
service: {
|
|
||||||
contract: {
|
|
||||||
type: 'sw.container',
|
|
||||||
slug: 'user-container',
|
|
||||||
requires: [
|
|
||||||
{
|
|
||||||
type: 'sw.l4t',
|
|
||||||
version: '<31.0.0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.to.have.property('valid')
|
|
||||||
.that.equals(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow semver matching when l4t does fulfill semver', async () => {
|
it('should correctly parse L4T version strings', async () => {
|
||||||
await seedEngine('4.4.38-l4t-r31.0.1');
|
seedExec('4.9.140-l4t-r32.2+g3dcbed5');
|
||||||
|
expect(await osRelease.getL4tVersion()).to.equal('32.2.0');
|
||||||
|
expect(execStub.callCount).to.equal(1);
|
||||||
|
execStub.restore();
|
||||||
|
|
||||||
expect(
|
seedExec('4.4.38-l4t-r28.2+g174510d');
|
||||||
containerContractsFulfilled({
|
expect(await osRelease.getL4tVersion()).to.equal('28.2.0');
|
||||||
service: {
|
expect(execStub.callCount).to.equal(1);
|
||||||
contract: {
|
});
|
||||||
type: 'sw.container',
|
|
||||||
slug: 'user-container',
|
|
||||||
requires: [
|
|
||||||
{
|
|
||||||
type: 'sw.l4t',
|
|
||||||
version: '>=31.0.0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.to.have.property('valid')
|
|
||||||
.that.equals(true);
|
|
||||||
|
|
||||||
expect(
|
it('should correctly handle l4t versions which contain three numbers', async () => {
|
||||||
containerContractsFulfilled({
|
seedExec('4.4.38-l4t-r32.3.1+g174510d');
|
||||||
service: {
|
expect(await osRelease.getL4tVersion()).to.equal('32.3.1');
|
||||||
contract: {
|
expect(execStub.callCount).to.equal(1);
|
||||||
type: 'sw.container',
|
});
|
||||||
slug: 'user-container',
|
|
||||||
requires: [
|
it('should return undefined when there is no l4t string in uname', async () => {
|
||||||
{
|
seedExec('4.18.14-yocto-standard');
|
||||||
type: 'sw.l4t',
|
expect(await osRelease.getL4tVersion()).to.be.undefined;
|
||||||
version: '<31.0.0',
|
});
|
||||||
},
|
|
||||||
],
|
describe('L4T comparison', () => {
|
||||||
|
const seedEngine = async (version: string) => {
|
||||||
|
const engine = require('~/src/lib/contracts') as Contracts;
|
||||||
|
|
||||||
|
seedExec(version);
|
||||||
|
engine.initializeContractRequirements({
|
||||||
|
supervisorVersion,
|
||||||
|
deviceType: 'intel-nuc',
|
||||||
|
deviceArch: 'amd64',
|
||||||
|
l4tVersion: await osRelease.getL4tVersion(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return engine;
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should allow semver matching even when l4t does not fulfill semver', async () => {
|
||||||
|
const engine = await seedEngine('4.4.38-l4t-r31.0');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
engine.containerContractsFulfilled({
|
||||||
|
service: {
|
||||||
|
contract: {
|
||||||
|
type: 'sw.container',
|
||||||
|
slug: 'user-container',
|
||||||
|
requires: [
|
||||||
|
{
|
||||||
|
type: 'sw.l4t',
|
||||||
|
version: '>=31.0.0',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optional: false,
|
||||||
},
|
},
|
||||||
optional: false,
|
}),
|
||||||
},
|
)
|
||||||
}),
|
.to.have.property('valid')
|
||||||
)
|
.that.equals(true);
|
||||||
.to.have.property('valid')
|
|
||||||
.that.equals(false);
|
expect(
|
||||||
|
engine.containerContractsFulfilled({
|
||||||
|
service: {
|
||||||
|
contract: {
|
||||||
|
type: 'sw.container',
|
||||||
|
slug: 'user-container',
|
||||||
|
requires: [
|
||||||
|
{
|
||||||
|
type: 'sw.l4t',
|
||||||
|
version: '<31.0.0',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.to.have.property('valid')
|
||||||
|
.that.equals(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow semver matching when l4t does fulfill semver', async () => {
|
||||||
|
const engine = await seedEngine('4.4.38-l4t-r31.0.1');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
engine.containerContractsFulfilled({
|
||||||
|
service: {
|
||||||
|
contract: {
|
||||||
|
type: 'sw.container',
|
||||||
|
slug: 'user-container',
|
||||||
|
requires: [
|
||||||
|
{
|
||||||
|
type: 'sw.l4t',
|
||||||
|
version: '>=31.0.0',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.to.have.property('valid')
|
||||||
|
.that.equals(true);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
engine.containerContractsFulfilled({
|
||||||
|
service: {
|
||||||
|
contract: {
|
||||||
|
type: 'sw.container',
|
||||||
|
slug: 'user-container',
|
||||||
|
requires: [
|
||||||
|
{
|
||||||
|
type: 'sw.l4t',
|
||||||
|
version: '<31.0.0',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.to.have.property('valid')
|
||||||
|
.that.equals(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
Loading…
Reference in New Issue
Block a user