Skip to content
Snippets Groups Projects
Commit 50f61667 authored by michael.minelli's avatar michael.minelli
Browse files

Add ExerciceDockerCompose => Class for executing exercice with docker compose

parent 610af7f5
No related branches found
No related tags found
No related merge requests found
import EnonceFile from '../../../shared/types/Dojo/EnonceFile';
import { TypedEmitter } from 'tiny-typed-emitter';
import ExerciceRunningEvents from '../../types/Dojo/ExerciceRunningEvents';
import { spawn } from 'child_process';
import ExerciceCheckerError from '../../../shared/types/Dojo/ExerciceCheckerError';
class ExerciceDockerCompose {
readonly events: TypedEmitter<ExerciceRunningEvents> = new TypedEmitter<ExerciceRunningEvents>();
public displayableLogs: string = '';
public allLogs: string = '';
public isFinished: boolean = false;
public success: boolean = false;
public exitCode: number = -1;
constructor(private projectName: string, private enonceFile: EnonceFile, private executionFolder: string, private composeFileOverride: Array<string> = []) {
this.events.on('logs', (log: string, _error: boolean, displayable: boolean) => {
this.allLogs += log;
this.displayableLogs += displayable ? log : '';
});
this.events.on('finished', (success: boolean, exitCode: number) => {
this.isFinished = true;
this.success = success;
this.exitCode = exitCode;
});
}
run(doDown: boolean = false) {
(async () => {
let containerExitCode: number = -1;
const dockerComposeCommand = `docker compose --project-name ${ this.projectName } --progress plain --file docker-compose.yml ${ this.composeFileOverride.map((file) => `--file ${ file }`).join(' ') }`;
// Run the service
{
try {
this.events.emit('step', 'COMPOSE_RUN', 'Run Docker Compose file');
containerExitCode = await new Promise<number>((resolve, reject) => {
this.events.emit('logs', '####################################################### Docker Compose & Main Container Logs #######################################################\n', false, false);
const dockerCompose = spawn(`${ dockerComposeCommand } run --build --rm ${ this.enonceFile.result.container }`, {
cwd : this.executionFolder,
shell: true,
env : {
'DOCKER_BUILDKIT' : '1',
'BUILDKIT_PROGRESS': 'plain', ...process.env
}
});
dockerCompose.stdout.on('data', (data) => {
this.events.emit('logs', data.toString(), false, true);
});
dockerCompose.stderr.on('data', (data) => {
this.events.emit('logs', data.toString(), true, true);
});
dockerCompose.on('exit', (code) => {
code !== null ? resolve(code) : reject();
});
});
} catch ( error ) {
this.events.emit('endStep', 'COMPOSE_RUN', `Error while running the docker compose file`, true);
this.events.emit('finished', false, ExerciceCheckerError.DOCKER_COMPOSE_RUN_ERROR);
return;
}
this.events.emit('endStep', 'COMPOSE_RUN', `Docker Compose file run successfully`, false);
}
// Get linked services logs
{
try {
this.events.emit('step', 'COMPOSE_LOGS', 'Logs acquisition of linked services');
await new Promise<void>((resolve, reject) => {
this.events.emit('logs', '####################################################### Other Services Logs #######################################################\n', false, false);
const dockerCompose = spawn(`${ dockerComposeCommand } logs --timestamps`, {
cwd : this.executionFolder,
shell: true
});
dockerCompose.stdout.on('data', (data) => {
this.events.emit('logs', data.toString(), false, false);
});
dockerCompose.stderr.on('data', (data) => {
this.events.emit('logs', data.toString(), true, false);
});
dockerCompose.on('exit', (code) => {
code !== null ? resolve() : reject();
});
});
} catch ( error ) {
this.events.emit('endStep', 'COMPOSE_LOGS', `Error while getting the linked services logs`, true);
this.events.emit('finished', false, ExerciceCheckerError.DOCKER_COMPOSE_LOGS_ERROR);
return;
}
this.events.emit('endStep', 'COMPOSE_LOGS', `Linked services logs acquired`, false);
}
// Remove containers if asked
{
if ( doDown ) {
try {
this.events.emit('step', 'COMPOSE_DOWN', 'Stopping and removing containers');
await new Promise<void>((resolve, reject) => {
this.events.emit('logs', '####################################################### Stop and remove containers #######################################################\n', false, false);
const dockerCompose = spawn(`${ dockerComposeCommand } down --volumes`, {
cwd : this.executionFolder,
shell: true
});
dockerCompose.stdout.on('data', (data) => {
this.events.emit('logs', data.toString(), false, false);
});
dockerCompose.stderr.on('data', (data) => {
this.events.emit('logs', data.toString(), true, false);
});
dockerCompose.on('exit', (code) => {
code !== null ? resolve() : reject();
});
});
} catch ( error ) {
this.events.emit('endStep', 'COMPOSE_DOWN', `Error stop and remove containers`, true);
this.events.emit('finished', false, ExerciceCheckerError.DOCKER_COMPOSE_DOWN_ERROR);
return;
}
this.events.emit('endStep', 'COMPOSE_DOWN', `Containers stopped and removed`, false);
}
}
this.events.emit('finished', true, containerExitCode);
})();
}
}
export default ExerciceDockerCompose;
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment