local mode: Add local mode manager module to handle cleanup

Change-type: minor
Signed-off-by: Cameron Diver <cameron@resin.io>
This commit is contained in:
Cameron Diver 2018-10-11 14:27:46 +01:00
parent 3e665c0f4a
commit 5906e1427c
No known key found for this signature in database
GPG Key ID: 69264F9C923F55C1
3 changed files with 90 additions and 5 deletions

View File

@ -9,6 +9,7 @@ path = require 'path'
constants = require './lib/constants'
Docker = require './lib/docker-utils'
{ LocalModeManager } = require './local-mode'
updateLock = require './lib/update-lock'
{ checkTruthy, checkInt, checkString } = require './lib/validation'
{ NotFoundError } = require './lib/errors'
@ -72,6 +73,7 @@ module.exports = class ApplicationManager extends EventEmitter
@networks = new NetworkManager({ @docker, @logger })
@volumes = new Volumes({ @docker, @logger })
@proxyvisor = new Proxyvisor({ @config, @logger, @db, @docker, @images, applications: this })
@localModeManager = new LocalModeManager(@config, @docker, @logger, @db)
@timeSpentFetching = 0
@fetchesInProgress = 0
@_targetVolatilePerImageId = {}
@ -181,6 +183,8 @@ module.exports = class ApplicationManager extends EventEmitter
init: =>
@images.cleanupDatabase()
.then =>
@localModeManager.init()
.then =>
@services.attachToRunning()
.then =>

86
src/local-mode.ts Normal file
View File

@ -0,0 +1,86 @@
import * as Bluebird from 'bluebird';
import * as Docker from 'dockerode';
import * as _ from 'lodash';
import Config = require('./config');
import Database = require('./db');
import { checkTruthy } from './lib/validation';
import { Logger } from './logger';
/**
* This class handles any special cases necessary for switching
* modes in localMode.
*
* Currently this is needed because of inconsistencies in the way
* that the state machine handles local mode and normal operation.
* We should aim to remove these inconsistencies in the future.
*/
export class LocalModeManager {
public constructor(
public config: Config,
public docker: Docker,
public logger: Logger,
public db: Database,
) { }
public async init() {
// Setup a listener to catch state changes relating to local mode
this.config.on('change', (changed) => {
if (changed.localMode != null) {
const localMode = checkTruthy(changed.localMode) || false;
// First switch the logger to it's correct state
this.logger.switchBackend(localMode);
// If we're leaving local mode, make sure to remove all of the
// leftover artifacts
if (!localMode) {
this.removeLocalModeArtifacts();
}
}
});
const localMode = checkTruthy(await this.config.get('localMode') || false);
if (!localMode) {
// Remove any leftovers if necessary
await this.removeLocalModeArtifacts();
}
}
public async removeLocalModeArtifacts(): Promise<void> {
try {
const images = await this.getLocalModeImages();
const containers = await this.getLocalModeContainers(images);
await Bluebird.map(containers, (containerId) => {
console.log('Removing local mode container: ', containerId);
return this.docker.getContainer(containerId).remove({ force: true });
});
await Bluebird.map(images, (imageId) => {
console.log('Removing local mode image: ', imageId);
return this.docker.getImage(imageId).remove({ force: true });
});
// Remove any local mode state added to the database
await this.db.models('app').del().where({ source: 'local' });
} catch (e) {
console.log('There was an error clearing local mode artifacts: ', e);
}
}
private async getLocalModeImages(): Promise<string[]> {
// Return all local mode images present on the local docker daemon
return _.map(await this.docker.listImages({ filters: { label: [ 'io.resin.local.image=1' ] } }), 'Id');
}
private async getLocalModeContainers(localModeImageIds: string[]): Promise<string[]> {
return _(await this.docker.listContainers())
.filter(({ Image }) => _.includes(localModeImageIds, Image))
.map('Id')
.value();
}
}
export default LocalModeManager;

View File

@ -60,11 +60,6 @@ module.exports = class Supervisor extends EventEmitter
enableLogs: checkTruthy(conf.loggingEnabled),
localMode: checkTruthy(conf.localMode)
})
# Setup log backend switching for local mode changes
@config.on 'change', (changed) =>
if changed.localMode?
@logger.switchBackend(checkTruthy(changed.localMode))
.then =>
@deviceState.init()
.then =>