Skip to content

Commit ef9058b

Browse files
authored
Merge pull request #67 from oslabs-beta/dev
Updates main branch to v1.2
2 parents dbf115f + a4743dc commit ef9058b

File tree

7 files changed

+18969
-20808
lines changed

7 files changed

+18969
-20808
lines changed

README.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,41 @@ Kaptn is a fully downloadable desktop application that provides a user-friendly
4141
- Troubleshoot any confusion with the Instant Help Desk
4242
- Follow tutorials and master K8s with our Learning Center
4343

44+
## Updates
45+
46+
Version 1.2.0 -
47+
48+
- Adds ability to use kubectl commands without choosing a working directory.
49+
50+
Version 1.1.0 -
51+
52+
- **_Now available for Mac, Windows, and Linux_**
53+
54+
- **Cluster Metrics Visualizer:**
55+
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.
56+
57+
- **Instant Help Desk:**
58+
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.
59+
60+
- **Kaptn Learning Center:**
61+
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.
62+
63+
- **Light/Dark Mode:**
64+
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.
65+
66+
This update also includes various bugs fixes, including:
67+
68+
- Bug where kubectl commands could not be used on some Mac operating systems.
69+
70+
#
71+
4472
## Getting Started
4573

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

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

51-
\*Please note, login functionality is currently disabled. Instead, please continue as guest to access all features of Kaptn.
52-
5379
## Usage Guidelines
5480

5581
### Overview

electron-builder.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"category": "public.app-category.developer-tools"
1818
},
1919
"win": {
20-
"target": "nsis",
20+
"target": "portable",
2121
"icon": "./public/icon.ico",
2222
"requestedExecutionLevel": "asInvoker"
2323
},

main.js

Lines changed: 84 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
1-
const path = require('path');
2-
const {
3-
app,
4-
BrowserWindow,
5-
ipcMain,
6-
Menu,
7-
MenuItem,
8-
globalShortcut,
9-
} = require('electron');
10-
const { exec, spawnSync, spawn } = require('child_process');
11-
const { dialog } = require('electron');
12-
const { clipboard } = require('electron');
13-
const fixPath = require('fix-path');
14-
15-
const isDev = process.env.NODE_ENV === 'development';
1+
const path = require("path");
2+
const { app, BrowserWindow, ipcMain } = require("electron");
3+
const { exec, spawnSync, spawn } = require("child_process");
4+
const fixPath = require("fix-path");
5+
6+
const isDev = process.env.NODE_ENV === "development";
167

178
function createMainWindow() {
189
const mainWindow = new BrowserWindow({
19-
title: 'Kaptn',
20-
titleBarStyle: 'hidden',
10+
title: "Kaptn",
11+
titleBarStyle: "hidden",
2112
trafficLightPosition: { x: 11.5, y: 8 },
2213
width: 1100,
2314
height: 800,
@@ -30,7 +21,7 @@ function createMainWindow() {
3021
});
3122

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

4536
// Listen to post_command event
46-
ipcMain.on('post_command', (event, arg) => {
37+
ipcMain.on("post_command", (event, arg) => {
4738
const { command, currDir } = arg;
4839

49-
exec(` ${command}`, { cwd: currDir }, (err, stdout, stderr) => {
50-
// Handle failed command execution
51-
if (err) {
52-
let output = err;
53-
// dialog.showErrorBox('', `${err}`);
54-
// return event.sender.send('post_command', output);
55-
}
56-
// Handle successful command execution but returned error (stderr)
57-
if (stderr) {
58-
// dialog.showErrorBox('Success execute, still error:', `${stderr}`);
59-
return event.sender.send('post_command', stderr);
60-
}
61-
// Handle successful command execution with no errors
62-
return event.sender.send('post_command', stdout);
63-
});
40+
// 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
41+
if (currDir === "NONE SELECTED") {
42+
let kubDir = process.env.ZDOTDIR;
43+
exec(` ${command}`, { cwd: kubDir }, (err, stdout, stderr) => {
44+
// Handle failed command execution
45+
if (err) {
46+
let output = err;
47+
}
48+
// Handle successful command execution but returned error (stderr)
49+
if (stderr) {
50+
return event.sender.send("post_command", stderr);
51+
}
52+
// Handle successful command execution with no errors
53+
return event.sender.send("post_command", stdout);
54+
});
55+
} else {
56+
exec(` ${command}`, { cwd: currDir }, (err, stdout, stderr) => {
57+
// Handle failed command execution
58+
if (err) {
59+
let output = err;
60+
}
61+
// Handle successful command execution but returned error (stderr)
62+
if (stderr) {
63+
return event.sender.send("post_command", stderr);
64+
}
65+
// Handle successful command execution with no errors
66+
return event.sender.send("post_command", stdout);
67+
});
68+
}
6469
});
6570

6671
// Listen to prom_setup event
67-
ipcMain.on('prom_setup', (event, arg) => {
72+
ipcMain.on("prom_setup", (event, arg) => {
6873
// This command adds chart repository to helm
6974
spawnSync(
70-
'helm repo add prometheus-community https://prometheus-community.github.io/helm-charts',
71-
{ stdio: 'inherit', shell: true }
75+
"helm repo add prometheus-community https://prometheus-community.github.io/helm-charts",
76+
{ stdio: "inherit", shell: true }
7277
);
7378

7479
// Update helm
75-
spawnSync('helm repo update', { stdio: 'inherit', shell: true });
80+
spawnSync("helm repo update", { stdio: "inherit", shell: true });
7681

7782
// Install helm chart
7883
spawnSync(
79-
'helm install prometheus666 prometheus-community/kube-prometheus-stack',
80-
{ stdio: 'inherit', shell: true }
84+
"helm install prometheus666 prometheus-community/kube-prometheus-stack",
85+
{ stdio: "inherit", shell: true }
8186
);
8287

83-
return event.sender.send('prom_setup', 'Prom setup complete');
88+
return event.sender.send("prom_setup", "Prom setup complete");
8489
});
8590

8691
// Listen to graf_setup event
87-
ipcMain.on('graf_setup', (event, arg) => {
92+
ipcMain.on("graf_setup", (event, arg) => {
8893
let returnValue;
8994
let podName;
90-
const getFunc = exec('kubectl get pods', (err, stdout, stderr) => {
95+
const getFunc = exec("kubectl get pods", (err, stdout, stderr) => {
9196
if (err) {
9297
returnValue = `exec error: ${err}`;
9398
}
9499
if (stderr) {
95100
returnValue = `stderr: ${stderr}`;
96101
}
97102

98-
const output = stdout.split('\n');
103+
const output = stdout.split("\n");
99104
output.forEach((pod) => {
100-
if (pod.includes('prometheus666-grafana')) {
101-
[podName] = pod.split(' ');
105+
if (pod.includes("prometheus666-grafana")) {
106+
[podName] = pod.split(" ");
102107
}
103108
});
104109
});
105110

106-
getFunc.once('close', () => {
107-
spawnSync('kubectl apply -f prometheus666-grafana.yaml', {
108-
studio: 'inherit',
111+
getFunc.once("close", () => {
112+
spawnSync("kubectl apply -f prometheus666-grafana.yaml", {
113+
studio: "inherit",
109114
shell: true,
110115
});
111116
spawnSync(`kubectl delete pod ${podName}`, {
112-
stdio: 'inherit',
117+
stdio: "inherit",
113118
shell: true,
114119
});
115120
});
116121
return event.sender.send(
117-
'graf_setup',
122+
"graf_setup",
118123
`Grafana setup complete: ${returnValue}`
119124
);
120125
});
121126

122127
// Listen to forward_ports event
123-
ipcMain.on('forward_ports', (event, arg) => {
124-
let returnData = '';
128+
ipcMain.on("forward_ports", (event, arg) => {
129+
let returnData = "";
125130
const ports = spawn(
126131
`kubectl port-forward deployment/prometheus666-grafana 3000`,
127132
{
128133
shell: true,
129134
}
130135
);
131136

132-
ports.stderr.on('data', (data) => {
137+
ports.stderr.on("data", (data) => {
133138
returnData = `port forwarding error: ${data}`;
134-
return event.sender.send('forward_ports', returnData);
139+
return event.sender.send("forward_ports", returnData);
135140
});
136141

137-
ports.stdout.on('data', (data) => {
142+
ports.stdout.on("data", (data) => {
138143
returnData = `stdout: ${data}`;
139-
return event.sender.send('forward_ports', returnData);
144+
return event.sender.send("forward_ports", returnData);
140145
});
141146
});
142147

143-
// Listen to forward_ports event
144-
ipcMain.on('kill_port', (event, arg) => {
145-
const ports = spawn(
146-
`kill -9 $(lsof -ti:3000)`,
147-
{
148-
shell: true,
149-
}
150-
);
151-
})
152-
148+
// Listen to forward_ports event
149+
ipcMain.on("kill_port", (event, arg) => {
150+
const ports = spawn(`kill -9 $(lsof -ti:3000)`, {
151+
shell: true,
152+
});
153+
});
153154

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

157159
// Helper function to retrieve the API key and then UID
158160
const getAPIKey = async () => {
159161
try {
160162
// If the API key is not in the cache, fetch it from the API
161-
const response = await fetch('http://localhost:3000/api/auth/keys', {
162-
method: 'POST',
163-
mode: 'no-cors',
163+
const response = await fetch("http://localhost:3000/api/auth/keys", {
164+
method: "POST",
165+
mode: "no-cors",
164166
headers: {
165167
Authorization:
166-
'Basic ' + Buffer.from('admin:prom-operator').toString('base64'),
167-
Accept: '*/*',
168-
'Content-Type': 'application/json',
168+
"Basic " + Buffer.from("admin:prom-operator").toString("base64"),
169+
Accept: "*/*",
170+
"Content-Type": "application/json",
169171
},
170172
body: JSON.stringify({
171173
name: Math.random().toString(36).substring(7),
172-
role: 'Admin',
174+
role: "Admin",
173175
secondsToLive: 86400,
174176
}),
175177
});
@@ -179,7 +181,7 @@ ipcMain.on('retrieve_key', (event, arg) => {
179181
let key = data.key;
180182

181183
const arg = {
182-
dashboard: 'Kubernetes / API server',
184+
dashboard: "Kubernetes / API server",
183185
};
184186
const { dashboard } = arg;
185187

@@ -188,10 +190,10 @@ ipcMain.on('retrieve_key', (event, arg) => {
188190
let response2 = await fetch(
189191
`http://localhost:3000/api/search?query=${encodedDash}`,
190192
{
191-
method: 'GET',
193+
method: "GET",
192194
headers: {
193195
Authorization: `Bearer ${key}`,
194-
'Content-Type': 'application/json',
196+
"Content-Type": "application/json",
195197
},
196198
}
197199
);
@@ -203,27 +205,17 @@ ipcMain.on('retrieve_key', (event, arg) => {
203205
const now = new Date().getTime();
204206
const from = new Date(now - 60 * 60 * 1000).getTime();
205207
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`;
206-
require('electron').shell.openExternal(url);
207-
return event.sender.send('retrieve_key', `true`);
208+
require("electron").shell.openExternal(url);
209+
return event.sender.send("retrieve_key", `true`);
208210
} catch (error) {
209-
return event.sender.send('retrieve_key', `Error: ${error}`);
211+
return event.sender.send("retrieve_key", `Error: ${error}`);
210212
}
211213
};
212214

213215
getAPIKey();
214216
});
215217

216-
217-
ipcMain.on('openbrowser', (event, arg) => {
218-
event.returnValue = 'Message received!';
219-
const now = new Date().getTime();
220-
const from = new Date(now - 60 * 60 * 1000).getTime();
221-
url = `http://localhost:3000/d/${uid}/kubernetes-api-server?orgId=1&refresh=10s&from=${from}&to=${now}&kiosk=true`;
222-
require('electron').shell.openExternal(url);
223-
});
224-
225218
// Load the main window
226219
app.whenReady().then(() => {
227220
createMainWindow();
228-
229221
});

0 commit comments

Comments
 (0)