Skip to content

Commit

Permalink
Merge pull request #67 from oslabs-beta/dev
Browse files Browse the repository at this point in the history
Updates main branch to v1.2
  • Loading branch information
brecht-horn authored Aug 29, 2023
2 parents dbf115f + a4743dc commit ef9058b
Show file tree
Hide file tree
Showing 7 changed files with 18,969 additions and 20,808 deletions.
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,41 @@ Kaptn is a fully downloadable desktop application that provides a user-friendly
- Troubleshoot any confusion with the Instant Help Desk
- Follow tutorials and master K8s with our Learning Center

## Updates

Version 1.2.0 -

- Adds ability to use kubectl commands without choosing a working directory.

Version 1.1.0 -

- **_Now available for Mac, Windows, and Linux_**

- **Cluster Metrics Visualizer:**
Easily sync your Kaptn workspace to Grafana and Prometheus to allow for clear and real-time visualization of your clusters' health. Utilize our quick set-up if you are not already connected, and consider Kaptn your only stop for working with and monitoring your Kubernetes clusters.

- **Instant Help Desk:**
Get help information on demand and at the click of a button with the Instant Help Desk. Now you can get more info about any command or type without leaving the command line, and losing the code you've already written.

- **Kaptn Learning Center:**
Inside the Easy Setup page you can now find the Learning Center with resources you need to learn Kubernetes. You can follow tutorials, read articles and documentation, and master Kubernetes faster than ever.

- **Light/Dark Mode:**
Whether it's eye strain, or just personal preference, we know engineers can be selective about their work environments. So we created a Light/Dark mode that allows you to work with your favorite color combination. Now you can focus on coding with no distractions to your workflow.

This update also includes various bugs fixes, including:

- Bug where kubectl commands could not be used on some Mac operating systems.

#

## Getting Started

1. Download the latest release [here](https://github.com/oslabs-beta/kaptn/releases).
2. Run the installer.

If you get a warning that the app is from an unidentified developer, go to System Preferences > Security & Privacy > General and click "Open Anyway".

\*Please note, login functionality is currently disabled. Instead, please continue as guest to access all features of Kaptn.

## Usage Guidelines

### Overview
Expand Down
2 changes: 1 addition & 1 deletion electron-builder.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"category": "public.app-category.developer-tools"
},
"win": {
"target": "nsis",
"target": "portable",
"icon": "./public/icon.ico",
"requestedExecutionLevel": "asInvoker"
},
Expand Down
176 changes: 84 additions & 92 deletions main.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
const path = require('path');
const {
app,
BrowserWindow,
ipcMain,
Menu,
MenuItem,
globalShortcut,
} = require('electron');
const { exec, spawnSync, spawn } = require('child_process');
const { dialog } = require('electron');
const { clipboard } = require('electron');
const fixPath = require('fix-path');

const isDev = process.env.NODE_ENV === 'development';
const path = require("path");
const { app, BrowserWindow, ipcMain } = require("electron");
const { exec, spawnSync, spawn } = require("child_process");
const fixPath = require("fix-path");

const isDev = process.env.NODE_ENV === "development";

function createMainWindow() {
const mainWindow = new BrowserWindow({
title: 'Kaptn',
titleBarStyle: 'hidden',
title: "Kaptn",
titleBarStyle: "hidden",
trafficLightPosition: { x: 11.5, y: 8 },
width: 1100,
height: 800,
Expand All @@ -30,7 +21,7 @@ function createMainWindow() {
});

if (isDev) {
mainWindow.loadURL('http://localhost:4444/');
mainWindow.loadURL("http://localhost:4444/");
mainWindow.webContents.openDevTools();
} else {
//in production, fix env.PATH for correct CLI use
Expand All @@ -43,133 +34,144 @@ function createMainWindow() {
/******** EVENT LISTENERS ********/

// Listen to post_command event
ipcMain.on('post_command', (event, arg) => {
ipcMain.on("post_command", (event, arg) => {
const { command, currDir } = arg;

exec(` ${command}`, { cwd: currDir }, (err, stdout, stderr) => {
// Handle failed command execution
if (err) {
let output = err;
// dialog.showErrorBox('', `${err}`);
// return event.sender.send('post_command', output);
}
// Handle successful command execution but returned error (stderr)
if (stderr) {
// dialog.showErrorBox('Success execute, still error:', `${stderr}`);
return event.sender.send('post_command', stderr);
}
// Handle successful command execution with no errors
return event.sender.send('post_command', stdout);
});
// if kubectl command is entered with no directory chosen, use ZDOTDIR as directory address when calling exec command --- otherwise ("else" on line 64) submit command normally
if (currDir === "NONE SELECTED") {
let kubDir = process.env.ZDOTDIR;
exec(` ${command}`, { cwd: kubDir }, (err, stdout, stderr) => {
// Handle failed command execution
if (err) {
let output = err;
}
// Handle successful command execution but returned error (stderr)
if (stderr) {
return event.sender.send("post_command", stderr);
}
// Handle successful command execution with no errors
return event.sender.send("post_command", stdout);
});
} else {
exec(` ${command}`, { cwd: currDir }, (err, stdout, stderr) => {
// Handle failed command execution
if (err) {
let output = err;
}
// Handle successful command execution but returned error (stderr)
if (stderr) {
return event.sender.send("post_command", stderr);
}
// Handle successful command execution with no errors
return event.sender.send("post_command", stdout);
});
}
});

// Listen to prom_setup event
ipcMain.on('prom_setup', (event, arg) => {
ipcMain.on("prom_setup", (event, arg) => {
// This command adds chart repository to helm
spawnSync(
'helm repo add prometheus-community https://prometheus-community.github.io/helm-charts',
{ stdio: 'inherit', shell: true }
"helm repo add prometheus-community https://prometheus-community.github.io/helm-charts",
{ stdio: "inherit", shell: true }
);

// Update helm
spawnSync('helm repo update', { stdio: 'inherit', shell: true });
spawnSync("helm repo update", { stdio: "inherit", shell: true });

// Install helm chart
spawnSync(
'helm install prometheus666 prometheus-community/kube-prometheus-stack',
{ stdio: 'inherit', shell: true }
"helm install prometheus666 prometheus-community/kube-prometheus-stack",
{ stdio: "inherit", shell: true }
);

return event.sender.send('prom_setup', 'Prom setup complete');
return event.sender.send("prom_setup", "Prom setup complete");
});

// Listen to graf_setup event
ipcMain.on('graf_setup', (event, arg) => {
ipcMain.on("graf_setup", (event, arg) => {
let returnValue;
let podName;
const getFunc = exec('kubectl get pods', (err, stdout, stderr) => {
const getFunc = exec("kubectl get pods", (err, stdout, stderr) => {
if (err) {
returnValue = `exec error: ${err}`;
}
if (stderr) {
returnValue = `stderr: ${stderr}`;
}

const output = stdout.split('\n');
const output = stdout.split("\n");
output.forEach((pod) => {
if (pod.includes('prometheus666-grafana')) {
[podName] = pod.split(' ');
if (pod.includes("prometheus666-grafana")) {
[podName] = pod.split(" ");
}
});
});

getFunc.once('close', () => {
spawnSync('kubectl apply -f prometheus666-grafana.yaml', {
studio: 'inherit',
getFunc.once("close", () => {
spawnSync("kubectl apply -f prometheus666-grafana.yaml", {
studio: "inherit",
shell: true,
});
spawnSync(`kubectl delete pod ${podName}`, {
stdio: 'inherit',
stdio: "inherit",
shell: true,
});
});
return event.sender.send(
'graf_setup',
"graf_setup",
`Grafana setup complete: ${returnValue}`
);
});

// Listen to forward_ports event
ipcMain.on('forward_ports', (event, arg) => {
let returnData = '';
ipcMain.on("forward_ports", (event, arg) => {
let returnData = "";
const ports = spawn(
`kubectl port-forward deployment/prometheus666-grafana 3000`,
{
shell: true,
}
);

ports.stderr.on('data', (data) => {
ports.stderr.on("data", (data) => {
returnData = `port forwarding error: ${data}`;
return event.sender.send('forward_ports', returnData);
return event.sender.send("forward_ports", returnData);
});

ports.stdout.on('data', (data) => {
ports.stdout.on("data", (data) => {
returnData = `stdout: ${data}`;
return event.sender.send('forward_ports', returnData);
return event.sender.send("forward_ports", returnData);
});
});

// Listen to forward_ports event
ipcMain.on('kill_port', (event, arg) => {
const ports = spawn(
`kill -9 $(lsof -ti:3000)`,
{
shell: true,
}
);
})

// Listen to forward_ports event
ipcMain.on("kill_port", (event, arg) => {
const ports = spawn(`kill -9 $(lsof -ti:3000)`, {
shell: true,
});
});

ipcMain.on('retrieve_key', (event, arg) => {
const cacheKey = 'api_key';
// step 4 - retrieve uid and launch metrics analyzer in new browser window
ipcMain.on("retrieve_key", (event, arg) => {
const cacheKey = "api_key";

// Helper function to retrieve the API key and then UID
const getAPIKey = async () => {
try {
// If the API key is not in the cache, fetch it from the API
const response = await fetch('http://localhost:3000/api/auth/keys', {
method: 'POST',
mode: 'no-cors',
const response = await fetch("http://localhost:3000/api/auth/keys", {
method: "POST",
mode: "no-cors",
headers: {
Authorization:
'Basic ' + Buffer.from('admin:prom-operator').toString('base64'),
Accept: '*/*',
'Content-Type': 'application/json',
"Basic " + Buffer.from("admin:prom-operator").toString("base64"),
Accept: "*/*",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: Math.random().toString(36).substring(7),
role: 'Admin',
role: "Admin",
secondsToLive: 86400,
}),
});
Expand All @@ -179,7 +181,7 @@ ipcMain.on('retrieve_key', (event, arg) => {
let key = data.key;

const arg = {
dashboard: 'Kubernetes / API server',
dashboard: "Kubernetes / API server",
};
const { dashboard } = arg;

Expand All @@ -188,10 +190,10 @@ ipcMain.on('retrieve_key', (event, arg) => {
let response2 = await fetch(
`http://localhost:3000/api/search?query=${encodedDash}`,
{
method: 'GET',
method: "GET",
headers: {
Authorization: `Bearer ${key}`,
'Content-Type': 'application/json',
"Content-Type": "application/json",
},
}
);
Expand All @@ -203,27 +205,17 @@ ipcMain.on('retrieve_key', (event, arg) => {
const now = new Date().getTime();
const from = new Date(now - 60 * 60 * 1000).getTime();
let url = `http://localhost:3000/d/${uid}/kubernetes-api-server?orgId=1&refresh=10s&from=${from}&to=${now}&kiosk=true?username=admin&password=prom-operator`;
require('electron').shell.openExternal(url);
return event.sender.send('retrieve_key', `true`);
require("electron").shell.openExternal(url);
return event.sender.send("retrieve_key", `true`);
} catch (error) {
return event.sender.send('retrieve_key', `Error: ${error}`);
return event.sender.send("retrieve_key", `Error: ${error}`);
}
};

getAPIKey();
});


ipcMain.on('openbrowser', (event, arg) => {
event.returnValue = 'Message received!';
const now = new Date().getTime();
const from = new Date(now - 60 * 60 * 1000).getTime();
url = `http://localhost:3000/d/${uid}/kubernetes-api-server?orgId=1&refresh=10s&from=${from}&to=${now}&kiosk=true`;
require('electron').shell.openExternal(url);
});

// Load the main window
app.whenReady().then(() => {
createMainWindow();

});
Loading

0 comments on commit ef9058b

Please sign in to comment.