mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-06-20 00:03:51 +00:00
Migrate db-format tests to integration
This commit is contained in:
367
test/integration/device-state/db-format.spec.ts
Normal file
367
test/integration/device-state/db-format.spec.ts
Normal file
@ -0,0 +1,367 @@
|
||||
import { expect } from 'chai';
|
||||
import { isRight } from 'fp-ts/lib/Either';
|
||||
import App from '~/src/compose/app';
|
||||
import Network from '~/src/compose/network';
|
||||
import * as config from '~/src/config';
|
||||
import * as testDb from '~/src/db';
|
||||
import * as dbFormat from '~/src/device-state/db-format';
|
||||
import { TargetApps } from '~/src/types/state';
|
||||
|
||||
function getDefaultNetwork(appId: number) {
|
||||
return {
|
||||
default: Network.fromComposeObject('default', appId, 'deadbeef', {}),
|
||||
};
|
||||
}
|
||||
|
||||
describe('device-state/db-format', () => {
|
||||
let apiEndpoint: string;
|
||||
before(async () => {
|
||||
await config.initialized();
|
||||
|
||||
// TargetStateCache checks the API endpoint to
|
||||
// store and invalidate the cache
|
||||
// TODO: this is an implementation detail that
|
||||
// should not be part of the test suite. We need to change
|
||||
// the target state architecture for this
|
||||
apiEndpoint = await config.get('apiEndpoint');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// Delete all apps between calls to prevent leaking tests
|
||||
await testDb.models('app').del();
|
||||
|
||||
// Disable local mode by default
|
||||
await config.set({ localMode: false });
|
||||
});
|
||||
|
||||
it('converts target apps into the database format', async () => {
|
||||
await dbFormat.setApps(
|
||||
{
|
||||
deadbeef: {
|
||||
id: 1,
|
||||
name: 'test-app',
|
||||
class: 'fleet',
|
||||
releases: {
|
||||
one: {
|
||||
id: 1,
|
||||
services: {
|
||||
ubuntu: {
|
||||
id: 1,
|
||||
image_id: 1,
|
||||
image: 'ubuntu:latest',
|
||||
environment: {},
|
||||
labels: { 'my-label': 'true' },
|
||||
composition: {
|
||||
command: ['sleep', 'infinity'],
|
||||
},
|
||||
},
|
||||
},
|
||||
volumes: {},
|
||||
networks: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'local',
|
||||
);
|
||||
|
||||
const [app] = await testDb.models('app').where({ uuid: 'deadbeef' });
|
||||
expect(app).to.not.be.undefined;
|
||||
expect(app.name).to.equal('test-app');
|
||||
expect(app.releaseId).to.equal(1);
|
||||
expect(app.commit).to.equal('one');
|
||||
expect(app.appId).to.equal(1);
|
||||
expect(app.source).to.equal('local');
|
||||
expect(app.uuid).to.equal('deadbeef');
|
||||
expect(app.isHost).to.equal(0);
|
||||
expect(app.services).to.equal(
|
||||
'[{"image":"ubuntu:latest","environment":{},"labels":{"my-label":"true"},"composition":{"command":["sleep","infinity"]},"appId":1,"appUuid":"deadbeef","releaseId":1,"commit":"one","imageId":1,"serviceId":1,"serviceName":"ubuntu"}]',
|
||||
);
|
||||
expect(app.volumes).to.equal('{}');
|
||||
expect(app.networks).to.equal('{}');
|
||||
});
|
||||
|
||||
it('should retrieve a single app from the database', async () => {
|
||||
await dbFormat.setApps(
|
||||
{
|
||||
deadbeef: {
|
||||
id: 1,
|
||||
name: 'test-app',
|
||||
class: 'fleet',
|
||||
releases: {
|
||||
one: {
|
||||
id: 1,
|
||||
services: {
|
||||
ubuntu: {
|
||||
id: 1,
|
||||
image_id: 1,
|
||||
image: 'ubuntu:latest',
|
||||
environment: {},
|
||||
labels: { 'my-label': 'true' },
|
||||
composition: {
|
||||
command: ['sleep', 'infinity'],
|
||||
},
|
||||
},
|
||||
},
|
||||
volumes: {},
|
||||
networks: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
apiEndpoint,
|
||||
);
|
||||
|
||||
const app = await dbFormat.getApp(1);
|
||||
expect(app).to.be.an.instanceOf(App);
|
||||
expect(app).to.have.property('appId').that.equals(1);
|
||||
expect(app).to.have.property('commit').that.equals('one');
|
||||
expect(app).to.have.property('appName').that.equals('test-app');
|
||||
expect(app).to.have.property('source').that.equals(apiEndpoint);
|
||||
expect(app).to.have.property('services').that.has.lengthOf(1);
|
||||
expect(app).to.have.property('volumes').that.deep.equals({});
|
||||
expect(app)
|
||||
.to.have.property('networks')
|
||||
.that.deep.equals(getDefaultNetwork(1));
|
||||
|
||||
const [service] = app.services;
|
||||
expect(service).to.have.property('appId').that.equals(1);
|
||||
expect(service).to.have.property('serviceId').that.equals(1);
|
||||
expect(service).to.have.property('imageId').that.equals(1);
|
||||
expect(service).to.have.property('releaseId').that.equals(1);
|
||||
expect(service.config)
|
||||
.to.have.property('image')
|
||||
.that.equals('ubuntu:latest');
|
||||
expect(service.config)
|
||||
.to.have.property('labels')
|
||||
.that.deep.includes({ 'my-label': 'true' });
|
||||
expect(service.config)
|
||||
.to.have.property('command')
|
||||
.that.deep.equals(['sleep', 'infinity']);
|
||||
});
|
||||
|
||||
it('should retrieve multiple apps from the database', async () => {
|
||||
await dbFormat.setApps(
|
||||
{
|
||||
deadbeef: {
|
||||
id: 1,
|
||||
name: 'test-app',
|
||||
class: 'fleet',
|
||||
releases: {
|
||||
one: {
|
||||
id: 1,
|
||||
services: {
|
||||
ubuntu: {
|
||||
id: 1,
|
||||
image_id: 1,
|
||||
image: 'ubuntu:latest',
|
||||
environment: {},
|
||||
labels: {},
|
||||
composition: {
|
||||
command: ['sleep', 'infinity'],
|
||||
},
|
||||
},
|
||||
},
|
||||
volumes: {},
|
||||
networks: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
deadc0de: {
|
||||
id: 2,
|
||||
name: 'other-app',
|
||||
class: 'app',
|
||||
releases: {
|
||||
two: {
|
||||
id: 2,
|
||||
services: {},
|
||||
volumes: {},
|
||||
networks: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
apiEndpoint,
|
||||
);
|
||||
|
||||
const apps = Object.values(await dbFormat.getApps());
|
||||
expect(apps).to.have.lengthOf(2);
|
||||
|
||||
const [app, otherapp] = apps;
|
||||
expect(app).to.be.an.instanceOf(App);
|
||||
expect(app).to.have.property('appId').that.equals(1);
|
||||
expect(app).to.have.property('commit').that.equals('one');
|
||||
expect(app).to.have.property('appName').that.equals('test-app');
|
||||
expect(app).to.have.property('source').that.equals(apiEndpoint);
|
||||
expect(app).to.have.property('services').that.has.lengthOf(1);
|
||||
expect(app).to.have.property('volumes').that.deep.equals({});
|
||||
expect(app)
|
||||
.to.have.property('networks')
|
||||
.that.deep.equals(getDefaultNetwork(1));
|
||||
|
||||
expect(otherapp).to.have.property('appId').that.equals(2);
|
||||
expect(otherapp).to.have.property('commit').that.equals('two');
|
||||
expect(otherapp).to.have.property('appName').that.equals('other-app');
|
||||
});
|
||||
|
||||
it('should retrieve non-fleet apps from the database if local mode is set', async () => {
|
||||
await dbFormat.setApps(
|
||||
{
|
||||
deadbeef: {
|
||||
id: 1,
|
||||
name: 'test-app',
|
||||
class: 'fleet',
|
||||
releases: {
|
||||
one: {
|
||||
id: 1,
|
||||
services: {
|
||||
ubuntu: {
|
||||
id: 1,
|
||||
image_id: 1,
|
||||
image: 'ubuntu:latest',
|
||||
environment: {},
|
||||
labels: {},
|
||||
composition: {
|
||||
command: ['sleep', 'infinity'],
|
||||
},
|
||||
},
|
||||
},
|
||||
volumes: {},
|
||||
networks: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
deadc0de: {
|
||||
id: 2,
|
||||
name: 'other-app',
|
||||
class: 'app',
|
||||
releases: {
|
||||
two: {
|
||||
id: 2,
|
||||
services: {},
|
||||
volumes: {},
|
||||
networks: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
apiEndpoint,
|
||||
);
|
||||
|
||||
// Once local mode is set to true, only 'other-app' should be returned
|
||||
// as part of the target
|
||||
await config.set({ localMode: true });
|
||||
|
||||
const apps = Object.values(await dbFormat.getApps());
|
||||
expect(apps).to.have.lengthOf(1);
|
||||
|
||||
const [app] = apps;
|
||||
expect(app).to.be.an.instanceOf(App);
|
||||
expect(app).to.have.property('appId').that.equals(2);
|
||||
expect(app).to.have.property('commit').that.equals('two');
|
||||
expect(app).to.have.property('appName').that.equals('other-app');
|
||||
|
||||
// Set the app as local now
|
||||
await dbFormat.setApps(
|
||||
{
|
||||
deadbeef: {
|
||||
id: 1,
|
||||
name: 'test-app',
|
||||
class: 'fleet',
|
||||
releases: {
|
||||
one: {
|
||||
id: 1,
|
||||
services: {
|
||||
ubuntu: {
|
||||
id: 1,
|
||||
image_id: 1,
|
||||
image: 'ubuntu:latest',
|
||||
environment: {},
|
||||
labels: {},
|
||||
composition: {
|
||||
command: ['sleep', 'infinity'],
|
||||
},
|
||||
},
|
||||
},
|
||||
volumes: {},
|
||||
networks: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'local',
|
||||
);
|
||||
|
||||
// Now both apps should be returned
|
||||
const newapps = Object.values(await dbFormat.getApps());
|
||||
expect(newapps).to.have.lengthOf(2);
|
||||
|
||||
const [newapp, otherapp] = newapps;
|
||||
expect(newapp).to.be.an.instanceOf(App);
|
||||
expect(newapp).to.have.property('appId').that.equals(1);
|
||||
expect(newapp).to.have.property('commit').that.equals('one');
|
||||
expect(newapp).to.have.property('appName').that.equals('test-app');
|
||||
expect(newapp).to.have.property('source').that.equals('local');
|
||||
expect(newapp).to.have.property('services').that.has.lengthOf(1);
|
||||
expect(newapp).to.have.property('volumes').that.deep.equals({});
|
||||
expect(newapp)
|
||||
.to.have.property('networks')
|
||||
.that.deep.equals(getDefaultNetwork(1));
|
||||
|
||||
expect(otherapp).to.have.property('appId').that.equals(2);
|
||||
expect(otherapp).to.have.property('commit').that.equals('two');
|
||||
expect(otherapp).to.have.property('appName').that.equals('other-app');
|
||||
});
|
||||
|
||||
it('should retrieve app target state from database', async () => {
|
||||
const srcApps: TargetApps = {
|
||||
deadbeef: {
|
||||
id: 1,
|
||||
name: 'test-app',
|
||||
class: 'fleet',
|
||||
is_host: false,
|
||||
releases: {
|
||||
one: {
|
||||
id: 1,
|
||||
services: {
|
||||
ubuntu: {
|
||||
id: 1,
|
||||
image_id: 1,
|
||||
image: 'ubuntu:latest',
|
||||
environment: {},
|
||||
labels: { 'my-label': 'true' },
|
||||
composition: {
|
||||
command: ['sleep', 'infinity'],
|
||||
},
|
||||
},
|
||||
},
|
||||
volumes: {},
|
||||
networks: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
deadc0de: {
|
||||
id: 2,
|
||||
name: 'other-app',
|
||||
class: 'app',
|
||||
is_host: false,
|
||||
releases: {
|
||||
two: {
|
||||
id: 2,
|
||||
services: {},
|
||||
volumes: {},
|
||||
networks: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await dbFormat.setApps(srcApps, apiEndpoint);
|
||||
const result = await dbFormat.getTargetJson();
|
||||
expect(
|
||||
isRight(TargetApps.decode(result)),
|
||||
'resulting target apps is a valid TargetApps object',
|
||||
);
|
||||
expect(result).to.deep.equal(srcApps);
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user