From f45c5b92343f884951187d37dfc1df5793fc86b3 Mon Sep 17 00:00:00 2001 From: Lansana DIOMANDE <ldiomande@takima.fr> Date: Wed, 20 Apr 2022 15:11:29 +0200 Subject: [PATCH] feat: creating a base image for desktop exercises --- .gitlab-ci.yml | 2 +- Dockerfile.desktop | 32 ++++++ .../deadlock-extension/package-lock.json | 2 +- .../deadlock-extension/src/core/config.ts | 12 +-- .../deadlock-extension/src/core/gitMission.ts | 3 + .../deadlock-extension/src/core/userConfig.ts | 1 + .../src/recorder/command-recorder.ts | 2 +- .../deadlock-extension/src/recorder/index.ts | 8 +- .../src/recorder/preStop.ts | 6 +- .../deadlock-extension/src/recorder/utils.ts | 16 ++- .../src/view/quickSetupView.ts | 100 +++++++++--------- setup_trace_desktop.py | 12 +++ start.desktop.sh | 43 ++++++++ 13 files changed, 168 insertions(+), 71 deletions(-) create mode 100644 Dockerfile.desktop create mode 100644 setup_trace_desktop.py create mode 100644 start.desktop.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dc83a81d..e62db094 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ build: - docker:18.09.6-dind parallel: matrix: - - VERSION: [code, kube] + - VERSION: [code, kube, desktop] script: - ./build.sh $TAG $VERSION $CI_REGISTRY_IMAGE - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.e-biz.fr diff --git a/Dockerfile.desktop b/Dockerfile.desktop new file mode 100644 index 00000000..23c2ddf4 --- /dev/null +++ b/Dockerfile.desktop @@ -0,0 +1,32 @@ +FROM node:alpine3.15 + +RUN apk update +RUN apk --no-cache add vim && apk --no-cache add nano \ + && apk --no-cache add rsync && apk --no-cache add sudo \ + && apk --no-cache add bash && apk --no-cache add openssh \ + && apk --no-cache add git && apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python + +## User account +RUN addgroup -S sudo && adduser --disabled-password --gecos '' deadlock && \ + adduser deadlock sudo && \ + echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + + +COPY setup_trace_desktop.py setup_trace.py +RUN chmod 700 setup_trace.py +RUN chown deadlock setup_trace.py + +COPY recorder-out deadlock/ +COPY .gitignore_recorder deadlock/.gitignore + + + +COPY start.desktop.sh . +RUN chmod 504 deadlock/ -R +RUN chmod 500 start.desktop.sh + +RUN mkdir /project && mkdir /tmp/.ssh && mkdir /home/deadlock/mission + +RUN chown deadlock:deadlock /home/deadlock + +ENTRYPOINT ["bash", "start.desktop.sh"] \ No newline at end of file diff --git a/deadlock-plugins/deadlock-extension/package-lock.json b/deadlock-plugins/deadlock-extension/package-lock.json index b295b766..e5b42ab7 100644 --- a/deadlock-plugins/deadlock-extension/package-lock.json +++ b/deadlock-plugins/deadlock-extension/package-lock.json @@ -37,7 +37,7 @@ "webpack-cli": "^4.9.1" }, "engines": { - "vscode": "^1.63.0" + "vscode": "^1.66.0" } }, "node_modules/@babel/code-frame": { diff --git a/deadlock-plugins/deadlock-extension/src/core/config.ts b/deadlock-plugins/deadlock-extension/src/core/config.ts index 629d89dd..7222a295 100644 --- a/deadlock-plugins/deadlock-extension/src/core/config.ts +++ b/deadlock-plugins/deadlock-extension/src/core/config.ts @@ -3,17 +3,17 @@ import * as path from 'path'; const homeDir = os.homedir(); // if we are on container, means the directory will depend differently -const onContainer = homeDir.includes('theia') || homeDir.includes('root'); +const onContainer = homeDir.includes('theia') || homeDir.includes('root') || homeDir.includes('deadlock'); const deadlockExtensionPath = path.join(homeDir, 'deadlock-extension'); export const PROJECT_SRC_PATH = onContainer ? '/project' : path.join(homeDir, 'deadlock-extension', '/project'); -export const PROJECT_THEIA_PATH = onContainer - ? path.join('/home/project') +export const PROJECT_DEADLOCK_DESKTOP_PATH = onContainer + ? path.join('/home/deadlock/mission') : path.join(deadlockExtensionPath, 'project-theia'); -export const DOCS_PATH = path.join(path.join(onContainer ? '/home/theia' : deadlockExtensionPath), 'docs'); +export const DOCS_PATH = path.join(path.join(onContainer ? '/home/deadlock' : deadlockExtensionPath), 'docs'); export const CONFIG_PATH = onContainer ? '/home/config/' : path.join(deadlockExtensionPath, 'config'); @@ -21,8 +21,8 @@ export const USER_CHALLENGE_PATH = path.join(CONFIG_PATH, 'user-challenge.json') export const BRIEFING_FILE_NAME = 'briefing.md'; -export const ENV_FILE_PATH = path.join(PROJECT_THEIA_PATH, '/.env'); +export const ENV_FILE_PATH = path.join(PROJECT_DEADLOCK_DESKTOP_PATH, '/.env'); export const BASHRC_PATH = path.join(homeDir, '/.bashrc'); -export const SERVICES_PATHS_PATH = path.join(PROJECT_THEIA_PATH, '/paths.json'); +export const SERVICES_PATHS_PATH = path.join(PROJECT_DEADLOCK_DESKTOP_PATH, '/paths.json'); diff --git a/deadlock-plugins/deadlock-extension/src/core/gitMission.ts b/deadlock-plugins/deadlock-extension/src/core/gitMission.ts index 9e739afc..d56b5086 100644 --- a/deadlock-plugins/deadlock-extension/src/core/gitMission.ts +++ b/deadlock-plugins/deadlock-extension/src/core/gitMission.ts @@ -47,6 +47,9 @@ export default class GitMission { console.log('Init Git mission..'); const remote = await this.readRemote(); + + //TODO: REMOVE + console.log('After finish readremote..'); if (remote === DEFAULT_REMOTE) { return Promise.resolve(this); } diff --git a/deadlock-plugins/deadlock-extension/src/core/userConfig.ts b/deadlock-plugins/deadlock-extension/src/core/userConfig.ts index 46295519..da50d104 100644 --- a/deadlock-plugins/deadlock-extension/src/core/userConfig.ts +++ b/deadlock-plugins/deadlock-extension/src/core/userConfig.ts @@ -1,3 +1,4 @@ +import { log } from './../recorder/utils'; /** * Example: * { diff --git a/deadlock-plugins/deadlock-extension/src/recorder/command-recorder.ts b/deadlock-plugins/deadlock-extension/src/recorder/command-recorder.ts index 17865f4d..99dbc521 100644 --- a/deadlock-plugins/deadlock-extension/src/recorder/command-recorder.ts +++ b/deadlock-plugins/deadlock-extension/src/recorder/command-recorder.ts @@ -47,7 +47,7 @@ export default class CommandRecorder { let lastLineIndexWatched = 0; setInterval(() => { try { - const trace = fs.readFileSync('/home/theia/.bash_history', 'utf8'); + const trace = fs.readFileSync('/home/deadlock/.bash_history', 'utf8'); const lines = trace.split(/\r?\n/); this.commandsInProgress.forEach((command) => (command.still = false)); diff --git a/deadlock-plugins/deadlock-extension/src/recorder/index.ts b/deadlock-plugins/deadlock-extension/src/recorder/index.ts index 51f4a3a4..32d9225b 100644 --- a/deadlock-plugins/deadlock-extension/src/recorder/index.ts +++ b/deadlock-plugins/deadlock-extension/src/recorder/index.ts @@ -1,7 +1,7 @@ import CommandRecorder from './command-recorder'; import GitMission from '../core/gitMission'; import UserConfigNode from './userConfigNode'; -import { PROJECT_SRC_PATH, PROJECT_THEIA_PATH } from '../core/config'; +import { PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH } from '../core/config'; import { copyProjectSources, clearFilesExceptGit, log, error, renameTempToUserGitFiles } from './utils'; import UserConfig from '../core/userConfig'; @@ -10,10 +10,10 @@ export default class Recorder { log('Setup user project..'); if (!userConfig.isProfessor()) { - await copyProjectSources(PROJECT_SRC_PATH, PROJECT_THEIA_PATH, ['.git/']); + await copyProjectSources(PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH, ['.git/']); if (gitMission) { - renameTempToUserGitFiles(PROJECT_THEIA_PATH, gitMission.author); + renameTempToUserGitFiles(PROJECT_DEADLOCK_DESKTOP_PATH, gitMission.author); log('Starting CommandRecorder..'); new CommandRecorder(gitMission).run(); @@ -21,7 +21,7 @@ export default class Recorder { error('Cannot start command recorder, gitMission not found'); } } else { - await copyProjectSources(PROJECT_SRC_PATH, PROJECT_THEIA_PATH); + await copyProjectSources(PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH); } } diff --git a/deadlock-plugins/deadlock-extension/src/recorder/preStop.ts b/deadlock-plugins/deadlock-extension/src/recorder/preStop.ts index e3154055..081c4bde 100644 --- a/deadlock-plugins/deadlock-extension/src/recorder/preStop.ts +++ b/deadlock-plugins/deadlock-extension/src/recorder/preStop.ts @@ -1,6 +1,6 @@ import UserConfigNode from './userConfigNode'; import GitMission from '../core/gitMission'; -import { PROJECT_SRC_PATH, PROJECT_THEIA_PATH } from '../core/config'; +import { PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH } from '../core/config'; import { log, error, commitAndPushCode, CommitFrom } from './utils'; const util = require('util'); @@ -10,13 +10,13 @@ async function containsDiff() { try { // https://man7.org/linux/man-pages/man1/diff.1.html // Exit status is 0 if inputs are the same, 1 if different, 2 if trouble. - await exec(`diff -qr ${PROJECT_SRC_PATH} ${PROJECT_THEIA_PATH}`); + await exec(`diff -qr ${PROJECT_SRC_PATH} ${PROJECT_DEADLOCK_DESKTOP_PATH}`); // When status code is 0 exec does not fail } catch (result) { // when status code is > 0 if (result.code === 1) { const stdout = result.stdout; - if (stdout.indexOf('Files ') !== -1 || stdout.indexOf('Only in /home/project/') !== -1) { + if (stdout.indexOf('Files ') !== -1 || stdout.indexOf('Only in /home/deadlock/') !== -1) { // if user created new file or added a directory return true; } diff --git a/deadlock-plugins/deadlock-extension/src/recorder/utils.ts b/deadlock-plugins/deadlock-extension/src/recorder/utils.ts index cc271f3f..77553de4 100644 --- a/deadlock-plugins/deadlock-extension/src/recorder/utils.ts +++ b/deadlock-plugins/deadlock-extension/src/recorder/utils.ts @@ -1,5 +1,5 @@ import GitMission from '../core/gitMission'; -import { PROJECT_SRC_PATH, PROJECT_THEIA_PATH } from '../core/config'; +import { PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH } from '../core/config'; import { format } from 'date-fns'; import { execSync } from 'child_process'; import { existsSync, renameSync, copyFileSync, PathLike } from 'fs'; @@ -29,9 +29,15 @@ export const error = (message: any, ...args: any[]) => { } }; -export async function copyProjectSources(srcPath: string, theiaPath: string, excludes: Array<string> = []) { +export async function copyProjectSources( + srcPath: string, + userMissionWorkdirPath: string, + excludes: Array<string> = [], +) { const excludeCmd = excludes.map((current) => `--exclude ${current}`).join(' '); - return exec(`rsync -a ${srcPath}/ ${theiaPath} ${excludeCmd} && chown -R theia:theia /home/project`); + return exec( + `rsync -a ${srcPath}/ ${userMissionWorkdirPath} ${excludeCmd} && chown -R deadlock:deadlock /home/deadlock`, + ); } export async function pathContainsFiles(path: string) { @@ -111,9 +117,9 @@ export async function commitAndPushCode(gitMission: GitMission, from: CommitFrom log('Commit & push'); await clearFilesExceptGit(PROJECT_SRC_PATH); - copyGitUserFiles(PROJECT_THEIA_PATH, PROJECT_SRC_PATH, gitMission.author); + copyGitUserFiles(PROJECT_DEADLOCK_DESKTOP_PATH, PROJECT_SRC_PATH, gitMission.author); execSync( - `rsync -r --exclude .git --exclude npm --exclude target ${PROJECT_THEIA_PATH}/* ${PROJECT_SRC_PATH} && cp ${Path.join( + `rsync -r --exclude .git --exclude npm --exclude target ${PROJECT_DEADLOCK_DESKTOP_PATH}/* ${PROJECT_SRC_PATH} && cp ${Path.join( __dirname, '.gitignore', )} ${PROJECT_SRC_PATH} && chown -R root:root /project`, diff --git a/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts b/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts index 0c09a343..26a90fbb 100644 --- a/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts +++ b/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts @@ -28,42 +28,42 @@ export default class QuickSetupView extends WebviewBase { render(): string { return ` - <head> - ${this.renderHeaderHtml()} - </head> - <body> - ${this.renderHtmlBody()} - </body> - `; + <head> + ${this.renderHeaderHtml()} + </head> + <body> + ${this.renderHtmlBody()} + </body> + `; } renderHtmlBody() { const hadMissionWorkdir = this.extensionStore.getMissionWorkdir() !== undefined; return ` - <h1>Quick Setup</h1> - <div class="deadlock-getting-started-card-container"> + <h1>Quick Setup</h1> + <div class="deadlock-getting-started-card-container"> - ${this.renderCardHtml( - 'Connexion à Deadlock', - "Tu as besoin d'être connecté à Deadlock pour continuer.", - { name: 'Se connecter', onClickFunctionName: 'openAuthenticationPageAction' }, - this._isAlreadyConnected, - this._isAlreadyConnected, - )} - ${this.renderCardHtml( - 'Dossier contenant tes exercices', - 'Choisis le dossier qui contiendra tous les exercices Deadlock.', - { - name: 'Choisir un dossier', - onClickFunctionName: 'launchChooseMissionWorkdirAction', - }, - hadMissionWorkdir, - )} - </div> - - - `; + ${this.renderCardHtml( + 'Connexion à Deadlock', + "Tu as besoin d'être connecté à Deadlock pour continuer.", + { name: 'Se connecter', onClickFunctionName: 'openAuthenticationPageAction' }, + this._isAlreadyConnected, + this._isAlreadyConnected, + )} + ${this.renderCardHtml( + 'Dossier contenant tes exercices', + 'Choisis le dossier qui contiendra tous les exercices Deadlock.', + { + name: 'Choisir un dossier', + onClickFunctionName: 'launchChooseMissionWorkdirAction', + }, + hadMissionWorkdir, + )} + </div> + + + `; } renderCardHtml( @@ -75,22 +75,22 @@ export default class QuickSetupView extends WebviewBase { callbackArgs?: string, ) { return ` - <div class="deadlock-getting-started-card"> - <vscode-checkbox ${isChecked ? 'checked' : ''} readonly> </vscode-checkbox> - <div class="card-body"> - <div class="card-title"> - ${title} - </div> - <div class="card-description"> - ${description} - </div> - <vscode-button ${isDisabled ? 'disabled' : ''} onclick="${button.onClickFunctionName}(${callbackArgs})">${ - button.name - }</vscode-button> - </div> - </div> - - `; + <div class="deadlock-getting-started-card"> + <vscode-checkbox ${isChecked ? 'checked' : ''} readonly> </vscode-checkbox> + <div class="card-body"> + <div class="card-title"> + ${title} + </div> + <div class="card-description"> + ${description} + </div> + <vscode-button ${isDisabled ? 'disabled' : ''} onclick="${ + button.onClickFunctionName + }(${callbackArgs})">${button.name}</vscode-button> + </div> + </div> + + `; } renderHeaderHtml() { @@ -111,11 +111,11 @@ export default class QuickSetupView extends WebviewBase { const customScript = this.getExternalRessourcePath(this.extensionUri, ['resources', 'js', 'gettingStartedView.js']); return ` - <meta charset="UTF-8"> - <script type="module" src="${toolkitUri}"></script> - <script type="text/javascript" src="${customScript}"></script> - <link href="${customStyle}" rel="stylesheet" /> - `; + <meta charset="UTF-8"> + <script type="module" src="${toolkitUri}"></script> + <script type="text/javascript" src="${customScript}"></script> + <link href="${customStyle}" rel="stylesheet" /> + `; } onMessageReceive(message: any): void { diff --git a/setup_trace_desktop.py b/setup_trace_desktop.py new file mode 100644 index 00000000..80f70c3c --- /dev/null +++ b/setup_trace_desktop.py @@ -0,0 +1,12 @@ + +open('/home/deadlock/.bash_history', 'a').close() + +bashrc = open('/home/deadlock/.bashrc', 'a') +bashrc.write('\n') +bashrc.write('HISTCONTROL=""') +bashrc.write('\n') +bashrc.write("PROMPT_COMMAND='history -a'") +bashrc.write('\n') + +# Close the file +bashrc.close() \ No newline at end of file diff --git a/start.desktop.sh b/start.desktop.sh new file mode 100644 index 00000000..9b14acbd --- /dev/null +++ b/start.desktop.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +ON_START_UP_FILE="/deadlock/startup.sh" +TAG="[DEADLOCK]" + +# setup ssh key for root user +# must be installed by the API first within /tmp/.ssh +mkdir ~/.ssh +cp /tmp/.ssh/* ~/.ssh/ + +# start init mission script if exists +if [ -f "$ON_START_UP_FILE" ]; then + echo + echo "$TAG Startup your script.." + echo + /bin/bash $ON_START_UP_FILE & +else + echo + echo "$TAG No startup script found." + echo +fi + + +su deadlock -c "python setup_trace.py" +rm setup_trace.py + + +trap "node deadlock/preStop.js" SIGTERM + +# start command recorder +node deadlock/recorder.js & + +echo "WELCOME TO DEADLOCK CHALLENGE" + +child=$! +wait "$child" + + + + + + + -- GitLab