mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-23 02:32:43 +00:00
Merge pull request #1847 from balena-os/apps-json-rename
Rename apps.json after initial preload
This commit is contained in:
commit
70ec8c9af4
@ -8,21 +8,19 @@ import * as deviceConfig from '../device-config';
|
|||||||
import * as eventTracker from '../event-tracker';
|
import * as eventTracker from '../event-tracker';
|
||||||
import * as images from '../compose/images';
|
import * as images from '../compose/images';
|
||||||
|
|
||||||
import constants = require('../lib/constants');
|
|
||||||
import { AppsJsonParseError, EISDIR, ENOENT } from '../lib/errors';
|
import { AppsJsonParseError, EISDIR, ENOENT } from '../lib/errors';
|
||||||
import log from '../lib/supervisor-console';
|
import log from '../lib/supervisor-console';
|
||||||
|
|
||||||
import { convertLegacyAppsJson } from '../lib/migration';
|
import { convertLegacyAppsJson } from '../lib/migration';
|
||||||
import { AppsJsonFormat } from '../types/state';
|
import { AppsJsonFormat } from '../types/state';
|
||||||
|
import * as fsUtils from '../lib/fs-utils';
|
||||||
|
|
||||||
export async function loadTargetFromFile(
|
export function appsJsonBackup(appsPath: string) {
|
||||||
appsPath: Nullable<string>,
|
return `${appsPath}.preloaded`;
|
||||||
): Promise<void> {
|
}
|
||||||
|
|
||||||
|
export async function loadTargetFromFile(appsPath: string): Promise<void> {
|
||||||
log.info('Attempting to load any preloaded applications');
|
log.info('Attempting to load any preloaded applications');
|
||||||
if (!appsPath) {
|
|
||||||
appsPath = constants.appsJsonPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const content = await fs.readFile(appsPath, 'utf8');
|
const content = await fs.readFile(appsPath, 'utf8');
|
||||||
|
|
||||||
@ -73,7 +71,7 @@ export async function loadTargetFromFile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const image of imgs) {
|
for (const image of imgs) {
|
||||||
const name = await images.normalise(image.name);
|
const name = images.normalise(image.name);
|
||||||
image.name = name;
|
image.name = name;
|
||||||
await images.save(image);
|
await images.save(image);
|
||||||
}
|
}
|
||||||
@ -114,5 +112,23 @@ export async function loadTargetFromFile(
|
|||||||
error: e,
|
error: e,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
const targetPath = appsJsonBackup(appsPath);
|
||||||
|
if (!(await fsUtils.exists(targetPath))) {
|
||||||
|
// Try to rename the path so the preload target state won't
|
||||||
|
// be used again if the database gets deleted for any reason.
|
||||||
|
// If the target file already exists or something fails, just debug
|
||||||
|
// the failure.
|
||||||
|
await fsUtils
|
||||||
|
.safeRename(appsPath, targetPath)
|
||||||
|
.then(() => fsUtils.writeFileAtomic(appsPath, '{}'))
|
||||||
|
.then(() => log.debug(`Migrated existing apps.json`))
|
||||||
|
.catch((e) =>
|
||||||
|
log.debug(
|
||||||
|
`Continuing without migrating apps.json because of`,
|
||||||
|
e.message,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import * as path from 'path';
|
||||||
import { checkString } from './validation';
|
import { checkString } from './validation';
|
||||||
|
|
||||||
const bootMountPointFromEnv = checkString(process.env.BOOT_MOUNTPOINT);
|
const bootMountPointFromEnv = checkString(process.env.BOOT_MOUNTPOINT);
|
||||||
@ -49,7 +50,9 @@ const constants = {
|
|||||||
'lo',
|
'lo',
|
||||||
supervisorNetworkInterface,
|
supervisorNetworkInterface,
|
||||||
],
|
],
|
||||||
appsJsonPath: process.env.APPS_JSON_PATH || '/boot/apps.json',
|
appsJsonPath:
|
||||||
|
process.env.APPS_JSON_PATH ||
|
||||||
|
path.join(rootMountPoint, '/mnt/data', 'apps.json'),
|
||||||
ipAddressUpdateInterval: 30 * 1000,
|
ipAddressUpdateInterval: 30 * 1000,
|
||||||
imageCleanupErrorIgnoreTimeout: 3600 * 1000,
|
imageCleanupErrorIgnoreTimeout: 3600 * 1000,
|
||||||
maxDeltaDownloads: 3,
|
maxDeltaDownloads: 3,
|
||||||
|
@ -10,10 +10,14 @@ import * as images from '../src/compose/images';
|
|||||||
import { ConfigTxt } from '../src/config/backends/config-txt';
|
import { ConfigTxt } from '../src/config/backends/config-txt';
|
||||||
import * as deviceState from '../src/device-state';
|
import * as deviceState from '../src/device-state';
|
||||||
import * as deviceConfig from '../src/device-config';
|
import * as deviceConfig from '../src/device-config';
|
||||||
import { loadTargetFromFile } from '../src/device-state/preload';
|
import {
|
||||||
|
loadTargetFromFile,
|
||||||
|
appsJsonBackup,
|
||||||
|
} from '../src/device-state/preload';
|
||||||
import Service from '../src/compose/service';
|
import Service from '../src/compose/service';
|
||||||
import { intialiseContractRequirements } from '../src/lib/contracts';
|
import { intialiseContractRequirements } from '../src/lib/contracts';
|
||||||
import * as updateLock from '../src/lib/update-lock';
|
import * as updateLock from '../src/lib/update-lock';
|
||||||
|
import * as fsUtils from '../src/lib/fs-utils';
|
||||||
|
|
||||||
const mockedInitialConfig = {
|
const mockedInitialConfig = {
|
||||||
RESIN_SUPERVISOR_CONNECTIVITY_CHECK: 'true',
|
RESIN_SUPERVISOR_CONNECTIVITY_CHECK: 'true',
|
||||||
@ -224,8 +228,10 @@ describe('deviceState', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('loads a target state from an apps.json file and saves it as target state, then returns it', async () => {
|
it('loads a target state from an apps.json file and saves it as target state, then returns it', async () => {
|
||||||
await loadTargetFromFile(process.env.ROOT_MOUNTPOINT + '/apps.json');
|
const appsJson = process.env.ROOT_MOUNTPOINT + '/apps.json';
|
||||||
|
await loadTargetFromFile(appsJson);
|
||||||
const targetState = await deviceState.getTarget();
|
const targetState = await deviceState.getTarget();
|
||||||
|
expect(await fsUtils.exists(appsJsonBackup(appsJson))).to.be.true;
|
||||||
|
|
||||||
expect(targetState)
|
expect(targetState)
|
||||||
.to.have.property('local')
|
.to.have.property('local')
|
||||||
@ -283,14 +289,22 @@ describe('deviceState', () => {
|
|||||||
.to.have.property('labels')
|
.to.have.property('labels')
|
||||||
.that.has.property('io.balena.something')
|
.that.has.property('io.balena.something')
|
||||||
.that.equals('bar');
|
.that.equals('bar');
|
||||||
|
|
||||||
|
// Restore renamed apps.json
|
||||||
|
await fsUtils.safeRename(appsJsonBackup(appsJson), appsJson);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('stores info for pinning a device after loading an apps.json with a pinDevice field', async () => {
|
it('stores info for pinning a device after loading an apps.json with a pinDevice field', async () => {
|
||||||
await loadTargetFromFile(process.env.ROOT_MOUNTPOINT + '/apps-pin.json');
|
const appsJson = process.env.ROOT_MOUNTPOINT + '/apps-pin.json';
|
||||||
|
await loadTargetFromFile(appsJson);
|
||||||
|
|
||||||
const pinned = await config.get('pinDevice');
|
const pinned = await config.get('pinDevice');
|
||||||
expect(pinned).to.have.property('app').that.equals(1234);
|
expect(pinned).to.have.property('app').that.equals(1234);
|
||||||
expect(pinned).to.have.property('commit').that.equals('abcdef');
|
expect(pinned).to.have.property('commit').that.equals('abcdef');
|
||||||
|
expect(await fsUtils.exists(appsJsonBackup(appsJson))).to.be.true;
|
||||||
|
|
||||||
|
// Restore renamed apps.json
|
||||||
|
await fsUtils.safeRename(appsJsonBackup(appsJson), appsJson);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('emits a change event when a new state is reported', (done) => {
|
it('emits a change event when a new state is reported', (done) => {
|
||||||
@ -303,7 +317,7 @@ describe('deviceState', () => {
|
|||||||
|
|
||||||
const services: Service[] = [];
|
const services: Service[] = [];
|
||||||
for (const service of testTarget.local.apps['1234'].services) {
|
for (const service of testTarget.local.apps['1234'].services) {
|
||||||
const imageName = await images.normalise(service.image);
|
const imageName = images.normalise(service.image);
|
||||||
service.image = imageName;
|
service.image = imageName;
|
||||||
(service as any).imageName = imageName;
|
(service as any).imageName = imageName;
|
||||||
services.push(
|
services.push(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user