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