From 78f0edc1392ae7a93e7f93377b8e640533fec7fb Mon Sep 17 00:00:00 2001 From: Kobeep Date: Mon, 24 Feb 2025 22:13:42 +0100 Subject: [PATCH 1/8] Elentron init --- .github/workflows/CICD.yml | 1 - electron_app/index.html | 38 ++++++++++++++++++++++++ electron_app/main.js | 59 ++++++++++++++++++++++++++++++++++++++ electron_app/package.json | 11 +++++++ electron_app/preload.js | 8 ++++++ 5 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 electron_app/index.html create mode 100644 electron_app/main.js create mode 100644 electron_app/package.json create mode 100644 electron_app/preload.js diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 95e3857..b80ae2e 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -90,7 +90,6 @@ jobs: name: Create GitHub Release needs: build runs-on: ubuntu-latest - # Release tylko przy pushu do main if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} steps: diff --git a/electron_app/index.html b/electron_app/index.html new file mode 100644 index 0000000..0a871ea --- /dev/null +++ b/electron_app/index.html @@ -0,0 +1,38 @@ + + + + + Docker Monitor + + +

Docker Monitor

+ + +

+
+  
+
+
diff --git a/electron_app/main.js b/electron_app/main.js
new file mode 100644
index 0000000..07a131e
--- /dev/null
+++ b/electron_app/main.js
@@ -0,0 +1,59 @@
+// Electron main process
+const { app, BrowserWindow, ipcMain } = require('electron');
+const { spawn } = require('child_process');
+const path = require('path');
+
+function createWindow() {
+  // Create main window
+  const mainWindow = new BrowserWindow({
+    width: 800,
+    height: 600,
+    webPreferences: {
+      contextIsolation: true,
+      preload: path.join(__dirname, 'preload.js')
+    }
+  });
+  mainWindow.loadFile('index.html');
+}
+
+app.whenReady().then(() => {
+  createWindow();
+  app.on('activate', () => {
+    if (BrowserWindow.getAllWindows().length === 0) {
+      createWindow();
+    }
+  });
+});
+
+// Quit on close if not macOS
+app.on('window-all-closed', () => {
+  if (process.platform !== 'darwin') {
+    app.quit();
+  }
+});
+
+// Handle CLI calls
+ipcMain.handle('run-monitor', async (event, args) => {
+  return new Promise((resolve, reject) => {
+    // Use 'monitor' from PATH or full path
+    const cmd = spawn('monitor', args);
+    let output = '';
+    let errorOut = '';
+
+    cmd.stdout.on('data', (data) => {
+      output += data.toString();
+    });
+
+    cmd.stderr.on('data', (data) => {
+      errorOut += data.toString();
+    });
+
+    cmd.on('close', (code) => {
+      if (code === 0) {
+        resolve(output.trim());
+      } else {
+        reject(errorOut.trim());
+      }
+    });
+  });
+});
diff --git a/electron_app/package.json b/electron_app/package.json
new file mode 100644
index 0000000..97e3f13
--- /dev/null
+++ b/electron_app/package.json
@@ -0,0 +1,11 @@
+{
+  "name": "monitor-electron",
+  "version": "1.0.0",
+  "main": "main.js",
+  "scripts": {
+    "start": "electron ."
+  },
+  "dependencies": {
+    "electron": "^25.2.1"
+  }
+}
diff --git a/electron_app/preload.js b/electron_app/preload.js
new file mode 100644
index 0000000..39a12b3
--- /dev/null
+++ b/electron_app/preload.js
@@ -0,0 +1,8 @@
+// Expose safe API to renderer
+const { contextBridge, ipcRenderer } = require('electron');
+
+contextBridge.exposeInMainWorld('electronAPI', {
+  runMonitor: async (args) => {
+    return await ipcRenderer.invoke('run-monitor', args);
+  },
+});

From e4fa36d4a364903eba8bbed070fcfca7d3f1d4e3 Mon Sep 17 00:00:00 2001
From: Kobeep 
Date: Tue, 25 Feb 2025 21:56:10 +0100
Subject: [PATCH 2/8] Elentron test

---
 .github/workflows/CI.yml  | 47 ++++++++++++++++++-------
 electron_app/index.html   | 72 ++++++++++++++++++++++++++-------------
 electron_app/main.js      | 67 ++++++++++++++++++------------------
 electron_app/package.json |  7 ++--
 electron_app/preload.js   | 12 +++++--
 electron_app/sshUtils.js  | 19 +++++++++++
 6 files changed, 150 insertions(+), 74 deletions(-)
 create mode 100644 electron_app/sshUtils.js

diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index f13dc6a..91c802d 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -6,8 +6,8 @@ on:
   workflow_dispatch:
 
 jobs:
-  build:
-    name: Build/Test
+  CLI:
+    name: Build/Test CLI
     runs-on: ubuntu-latest
 
     steps:
@@ -31,20 +31,19 @@ jobs:
       - name: Install Docker and Docker Compose
         run: |
           sudo apt-get update
-          for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
+          for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove -y $pkg; done
           sudo apt-get update
-          sudo apt-get install ca-certificates curl
+          sudo apt-get install -y ca-certificates curl
           sudo install -m 0755 -d /etc/apt/keyrings
           sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
           sudo chmod a+r /etc/apt/keyrings/docker.asc
 
-          # Add the repository to Apt sources:
           echo \
             "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
-            $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
+            $(. /etc/os-release && echo \"$VERSION_CODENAME\") stable" | \
             sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
           sudo apt-get update
-          sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
+          sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
 
       - name: Set Up SSH Config for CI
         run: |
@@ -63,19 +62,43 @@ jobs:
         run: docker compose -f docker-compose.yml up -d
 
       - name: Wait for Local Containers to Initialize
-        run: sleep 10  # Ensure services are fully started
+        run: sleep 10
 
       - name: Run Installation Script
-        run: |
-          python3 install.py
+        run: python3 install.py
 
       - name: Verify Monitor Commands
         run: |
-          echo "🔄 Testing monitor --service"
+          echo "🔄 Testing monitor service"
           monitor service || { echo "❌ monitor service failed"; exit 1; }
 
-          echo "🔄 Testing monitor --state"
+          echo "🔄 Testing monitor state"
           monitor state || { echo "❌ monitor state failed"; exit 1; }
 
       - name: Stop and Clean Up Docker Containers
         run: docker compose down
+
+  ElectronApp:
+    name: Build/Test Electron App
+    needs: [CLI]
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: Checkout Repository
+        uses: actions/checkout@v3
+
+      - name: Set up Node
+        uses: actions/setup-node@v3
+        with:
+          node-version: '16'
+
+      - name: Install Electron Dependencies
+        run: |
+          cd electron_app
+          npm install
+
+      - name: Test Electron App
+        run: |
+          cd electron_app
+          # Przykład: npm run test (dodaj w package.json skrypt "test")
+          npm run test
diff --git a/electron_app/index.html b/electron_app/index.html
index 0a871ea..ab2dbcd 100644
--- a/electron_app/index.html
+++ b/electron_app/index.html
@@ -2,36 +2,62 @@
 
 
   
-  Docker Monitor
+  Electron Docker Monitor
+  
 
 
-  

Docker Monitor

- - -

+  

Electron Docker Monitor

+ + +
No data yet
+ +
+ +

Remote Hosts

+ + +
diff --git a/electron_app/main.js b/electron_app/main.js index 07a131e..91127b3 100644 --- a/electron_app/main.js +++ b/electron_app/main.js @@ -1,19 +1,21 @@ -// Electron main process +// Main process const { app, BrowserWindow, ipcMain } = require('electron'); -const { spawn } = require('child_process'); const path = require('path'); +const Docker = require('dockerode'); +const { getSSHHosts } = require('./sshUtils'); + +let docker = new Docker(); function createWindow() { - // Create main window - const mainWindow = new BrowserWindow({ - width: 800, + const win = new BrowserWindow({ + width: 900, height: 600, webPreferences: { contextIsolation: true, preload: path.join(__dirname, 'preload.js') } }); - mainWindow.loadFile('index.html'); + win.loadFile('index.html'); } app.whenReady().then(() => { @@ -25,35 +27,32 @@ app.whenReady().then(() => { }); }); -// Quit on close if not macOS app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } + if (process.platform !== 'darwin') app.quit(); }); -// Handle CLI calls -ipcMain.handle('run-monitor', async (event, args) => { - return new Promise((resolve, reject) => { - // Use 'monitor' from PATH or full path - const cmd = spawn('monitor', args); - let output = ''; - let errorOut = ''; - - cmd.stdout.on('data', (data) => { - output += data.toString(); - }); - - cmd.stderr.on('data', (data) => { - errorOut += data.toString(); - }); - - cmd.on('close', (code) => { - if (code === 0) { - resolve(output.trim()); - } else { - reject(errorOut.trim()); - } - }); - }); +ipcMain.handle('start-poll', async () => { + return fetchContainers(); +}); + +// SSH host list +ipcMain.handle('get-ssh-hosts', async () => { + return getSSHHosts(); }); + +ipcMain.handle('connect-remote', async (event, hostAlias) => { + return `Connected to remote host: ${hostAlias}`; +}); + +async function fetchContainers() { + try { + const containers = await docker.listContainers({ all: true }); + return containers.map((c) => ({ + name: c.Names[0], + status: c.Status, + ports: c.Ports + })); + } catch (err) { + return []; + } +} diff --git a/electron_app/package.json b/electron_app/package.json index 97e3f13..d9faf23 100644 --- a/electron_app/package.json +++ b/electron_app/package.json @@ -3,9 +3,12 @@ "version": "1.0.0", "main": "main.js", "scripts": { - "start": "electron ." + "start": "electron .", + "test": "echo 'Running basic Electron test...' && npx electron --version" }, "dependencies": { - "electron": "^25.2.1" + "electron": "^25.2.1", + "dockerode": "^3.3.3", + "ssh-config": "^2.2.3" } } diff --git a/electron_app/preload.js b/electron_app/preload.js index 39a12b3..88c313a 100644 --- a/electron_app/preload.js +++ b/electron_app/preload.js @@ -1,8 +1,14 @@ -// Expose safe API to renderer +// Expose API to renderer const { contextBridge, ipcRenderer } = require('electron'); contextBridge.exposeInMainWorld('electronAPI', { - runMonitor: async (args) => { - return await ipcRenderer.invoke('run-monitor', args); + startPoll: async () => { + return await ipcRenderer.invoke('start-poll'); }, + getSSHHosts: async () => { + return await ipcRenderer.invoke('get-ssh-hosts'); + }, + connectRemote: async (hostAlias) => { + return await ipcRenderer.invoke('connect-remote', hostAlias); + } }); diff --git a/electron_app/sshUtils.js b/electron_app/sshUtils.js new file mode 100644 index 0000000..b354372 --- /dev/null +++ b/electron_app/sshUtils.js @@ -0,0 +1,19 @@ +const fs = require('fs'); +const path = require('path'); +const SSHConfig = require('ssh-config'); + +function getSSHHosts() { + try { + const configPath = path.join(process.env.HOME || process.env.USERPROFILE, '.ssh', 'config'); + const data = fs.readFileSync(configPath, 'utf8'); + const parsed = SSHConfig.parse(data); + return parsed + .filter((item) => item.type === SSHConfig.DIRECTIVE && item.param === 'Host') + .map((item) => item.value) + .filter((host) => host !== '*'); + } catch (err) { + return []; + } +} + +module.exports = { getSSHHosts }; From fcbaa52300155f2f5c7749eaaf7672601149041f Mon Sep 17 00:00:00 2001 From: Kobeep Date: Tue, 25 Feb 2025 22:00:52 +0100 Subject: [PATCH 3/8] Elentron test#2 --- electron_app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electron_app/package.json b/electron_app/package.json index d9faf23..c82090a 100644 --- a/electron_app/package.json +++ b/electron_app/package.json @@ -9,6 +9,6 @@ "dependencies": { "electron": "^25.2.1", "dockerode": "^3.3.3", - "ssh-config": "^2.2.3" + "ssh-config": "^2.2.4" } } From f9a6cacc05d8e21a89eea8bf5842295a27381e51 Mon Sep 17 00:00:00 2001 From: Kobeep Date: Tue, 25 Feb 2025 22:14:05 +0100 Subject: [PATCH 4/8] Elentron test#3 --- electron_app/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/electron_app/package.json b/electron_app/package.json index c82090a..8a3c01d 100644 --- a/electron_app/package.json +++ b/electron_app/package.json @@ -7,8 +7,8 @@ "test": "echo 'Running basic Electron test...' && npx electron --version" }, "dependencies": { - "electron": "^25.2.1", - "dockerode": "^3.3.3", - "ssh-config": "^2.2.4" + "electron": "^34.2.0", + "dockerode": "^4.0.4", + "ssh-config": "^5.0.3" } } From 34ec9d040aff69161d9a310f3f0056cf9d746c08 Mon Sep 17 00:00:00 2001 From: Kobeep Date: Tue, 25 Feb 2025 22:20:24 +0100 Subject: [PATCH 5/8] Elentron test#4 --- .github/workflows/CI.yml | 51 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 91c802d..2795941 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -78,27 +78,30 @@ jobs: - name: Stop and Clean Up Docker Containers run: docker compose down - ElectronApp: - name: Build/Test Electron App - needs: [CLI] - runs-on: ubuntu-latest - - steps: - - name: Checkout Repository - uses: actions/checkout@v3 - - - name: Set up Node - uses: actions/setup-node@v3 - with: - node-version: '16' - - - name: Install Electron Dependencies - run: | - cd electron_app - npm install - - - name: Test Electron App - run: | - cd electron_app - # Przykład: npm run test (dodaj w package.json skrypt "test") - npm run test + ElectronApp: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Set up Node + uses: actions/setup-node@v3 + with: + node-version: '16' + + - name: Install Dependencies + run: | + cd electron_app + npm install + + - name: Fix Electron sandbox + run: | + cd electron_app + sudo chown root:root node_modules/electron/dist/chrome-sandbox + sudo chmod 4755 node_modules/electron/dist/chrome-sandbox + + - name: Test Electron App + run: | + cd electron_app + npm test From 24ad5bd259f03de36e68e9756ac333e03ef5889a Mon Sep 17 00:00:00 2001 From: Kobeep Date: Tue, 25 Feb 2025 22:22:11 +0100 Subject: [PATCH 6/8] Elentron test#5 --- .github/workflows/CI.yml | 54 ++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 2795941..7154877 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -78,30 +78,30 @@ jobs: - name: Stop and Clean Up Docker Containers run: docker compose down - ElectronApp: - runs-on: ubuntu-latest - - steps: - - name: Checkout Repository - uses: actions/checkout@v3 - - - name: Set up Node - uses: actions/setup-node@v3 - with: - node-version: '16' - - - name: Install Dependencies - run: | - cd electron_app - npm install - - - name: Fix Electron sandbox - run: | - cd electron_app - sudo chown root:root node_modules/electron/dist/chrome-sandbox - sudo chmod 4755 node_modules/electron/dist/chrome-sandbox - - - name: Test Electron App - run: | - cd electron_app - npm test + ElectronApp: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Set up Node + uses: actions/setup-node@v3 + with: + node-version: '16' + + - name: Install Dependencies + run: | + cd electron_app + npm install + + - name: Fix Electron sandbox + run: | + cd electron_app + sudo chown root:root node_modules/electron/dist/chrome-sandbox + sudo chmod 4755 node_modules/electron/dist/chrome-sandbox + + - name: Test Electron App + run: | + cd electron_app + npm test From ffc1fe83647734a0e18630d6c18454593cca4bd2 Mon Sep 17 00:00:00 2001 From: Kobeep Date: Tue, 25 Feb 2025 22:28:20 +0100 Subject: [PATCH 7/8] Elentron test#6 --- electron_app/package.json | 7 +++++- electron_app/test/e2e.spec.js | 46 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 electron_app/test/e2e.spec.js diff --git a/electron_app/package.json b/electron_app/package.json index 8a3c01d..b411f94 100644 --- a/electron_app/package.json +++ b/electron_app/package.json @@ -4,11 +4,16 @@ "main": "main.js", "scripts": { "start": "electron .", - "test": "echo 'Running basic Electron test...' && npx electron --version" + "test": "mocha test/e2e.spec.js" }, "dependencies": { "electron": "^34.2.0", "dockerode": "^4.0.4", "ssh-config": "^5.0.3" + }, + "devDependencies": { + "spectron": "^15.0.0", + "mocha": "^10.2.0", + "chai": "^4.3.7" } } diff --git a/electron_app/test/e2e.spec.js b/electron_app/test/e2e.spec.js new file mode 100644 index 0000000..c8720a2 --- /dev/null +++ b/electron_app/test/e2e.spec.js @@ -0,0 +1,46 @@ +// Spectron E2E test +const { Application } = require('spectron'); +const assert = require('chai').assert; +const path = require('path'); + +describe('Electron App Tests', function() { + this.timeout(10000); // Increase if needed + let app; + + before(async () => { + // Path to local electron bin + const electronPath = path.join(__dirname, '..', 'node_modules', '.bin', 'electron'); + // App root + const appPath = path.join(__dirname, '..'); + + app = new Application({ + path: electronPath, + args: [appPath] + }); + + await app.start(); + }); + + after(async () => { + if (app && app.isRunning()) { + await app.stop(); + } + }); + + it('shows the main window', async () => { + const count = await app.client.getWindowCount(); + assert.equal(count, 1, 'Main window not found'); + }); + + it('has correct title', async () => { + const title = await app.client.getTitle(); + assert.equal(title, 'Electron Docker Monitor', 'Title mismatch'); + }); + + it('renders UI elements', async () => { + // Example: check if a button or text is present + const button = await app.client.$('#btnStart'); + const exists = await button.isExisting(); + assert.isTrue(exists, 'btnStart not found'); + }); +}); From e27e63323867e50cdee57b3ef12b10833e2613c5 Mon Sep 17 00:00:00 2001 From: Kobeep Date: Thu, 27 Feb 2025 21:34:42 +0100 Subject: [PATCH 8/8] Elentron test#7 --- .github/workflows/CI.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7154877..7da67a8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -101,7 +101,10 @@ jobs: sudo chown root:root node_modules/electron/dist/chrome-sandbox sudo chmod 4755 node_modules/electron/dist/chrome-sandbox - - name: Test Electron App + - name: Install xvfb + run: sudo apt-get update && sudo apt-get install -y xvfb + + - name: Run Electron Tests run: | cd electron_app - npm test + xvfb-run -a npm test