Merge pull request #1400 from balena-io/fix-v1-instances

Fix v1 invocations of restart and purge
This commit is contained in:
bulldozer-balena[bot] 2020-07-20 18:13:08 +00:00 committed by GitHub
commit fc3c678cc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,17 +1,20 @@
import * as Bluebird from 'bluebird';
import * as _ from 'lodash';
import { appNotFoundMessage } from '../lib/messages';
import * as logger from '../logger';
import * as volumes from '../compose/volume-manager';
export function doRestart(applications, appId, force) {
const { _lockingIfNecessary, deviceState } = applications;
return _lockingIfNecessary(appId, { force }, () =>
deviceState.getCurrentForComparison().then(function (currentState) {
const app = currentState.local.apps[appId];
const app = safeAppClone(currentState.local.apps[appId]);
const imageIds = _.map(app.services, 'imageId');
applications.clearTargetVolatileForServices(imageIds);
const stoppedApp = safeAppClone(app);
const stoppedApp = _.cloneDeep(app);
stoppedApp.services = [];
currentState.local.apps[appId] = stoppedApp;
return deviceState
@ -31,7 +34,7 @@ export function doRestart(applications, appId, force) {
}
export function doPurge(applications, appId, force) {
const { logger, _lockingIfNecessary, deviceState, volumes } = applications;
const { _lockingIfNecessary, deviceState } = applications;
logger.logSystemMessage(
`Purging data for app ${appId}`,
@ -40,12 +43,12 @@ export function doPurge(applications, appId, force) {
);
return _lockingIfNecessary(appId, { force }, () =>
deviceState.getCurrentForComparison().then(function (currentState) {
const app = currentState.local.apps[appId];
if (app == null) {
if (currentState.local.apps[appId] == null) {
throw new Error(appNotFoundMessage);
}
const app = safeAppClone(currentState.local.apps[appId]);
const purgedApp = safeAppClone(app);
const purgedApp = _.cloneDeep(app);
purgedApp.services = [];
purgedApp.volumes = {};
currentState.local.apps[appId] = purgedApp;
@ -72,16 +75,17 @@ export function doPurge(applications, appId, force) {
.finally(() => deviceState.triggerApplyTarget());
}),
)
.tap(() =>
.then(() =>
logger.logSystemMessage('Purged data', { appId }, 'Purge data success'),
)
.tapCatch((err) =>
.catch((err) => {
logger.logSystemMessage(
`Error purging data: ${err}`,
{ appId, error: err },
'Purge data error',
),
);
);
throw err;
});
}
export function serviceAction(action, serviceId, current, target, options) {
@ -128,13 +132,36 @@ export function safeStateClone(targetState) {
}
export function safeAppClone(app) {
const containerIdForService = _.fromPairs(
_.map(app.services, (svc) => [
svc.serviceName,
svc.containerId.substr(0, 12),
]),
);
return {
appId: app.appId,
name: app.name,
commit: app.commit,
releaseId: app.releaseId,
services: _.map(app.services, (s) => s.toComposeObject()),
volumes: _.mapValues(app.volumes, (v) => v.toComposeObject()),
networks: _.mapValues(app.networks, (n) => n.toComposeObject()),
services: _.map(app.services, (svc) => {
// This is a bit of a hack, but when applying the target state as if it's
// the current state, this will include the previous containerId as a
// network alias. The container ID will be there as Docker adds it
// implicitly when creating a container. Here, we remove any previous
// container IDs before passing it back as target state. We have to do this
// here as when passing it back as target state, the service class cannot
// know that the alias being given is not in fact a user given one.
// TODO: Make the process of moving from a current state to a target state
// well-defined (and implemented in a seperate module)
const svcCopy = _.cloneDeep(svc);
_.each(svcCopy.config.networks, (net) => {
net.aliases = net.aliases.filter(
(alias) => alias !== containerIdForService[svcCopy.serviceName],
);
});
return svcCopy;
}),
volumes: _.cloneDeep(app.volumes),
networks: _.cloneDeep(app.networks),
};
}