Skip to content

Commit f655152

Browse files
Merge pull request #220 from rancher-sandbox/211b-missing-windows-images
Show images on Windows
2 parents 4325ca4 + 39f92e7 commit f655152

File tree

5 files changed

+71
-7
lines changed

5 files changed

+71
-7
lines changed

background.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ Electron.ipcMain.on('do-image-push', async(event, imageName, imageID, tag) => {
256256
event.reply('kim-process-ended', code);
257257
});
258258

259+
Electron.ipcMain.handle('images-fetch', (event) => {
260+
return imageManager.listImages();
261+
});
262+
259263
Electron.ipcMain.on('k8s-state', (event) => {
260264
event.returnValue = k8smanager.state;
261265
});
@@ -332,8 +336,8 @@ Electron.ipcMain.on('k8s-versions', async() => {
332336
}
333337
});
334338

335-
Electron.ipcMain.handle('service-fetch', async(event, namespace) => {
336-
return await k8smanager?.listServices(namespace);
339+
Electron.ipcMain.handle('service-fetch', (event, namespace) => {
340+
return k8smanager?.listServices(namespace);
337341
});
338342

339343
Electron.ipcMain.handle('service-forward', async(event, service, state) => {

src/k8s-engine/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ export class KubeClient extends events.EventEmitter {
217217
* @param {string} endpointName the name of an endpoint that controls ready pods.
218218
* @returns {Promise<k8s.V1Pod?>}
219219
*/
220-
protected async getActivePod(namespace: string, endpointName: string): Promise<k8s.V1Pod | null> {
220+
async getActivePod(namespace: string, endpointName: string): Promise<k8s.V1Pod | null> {
221221
console.log(`Attempting to locate ${ endpointName } pod...`);
222222
// Loop fetching endpoints, until it matches at least one pod.
223223
let target: k8s.V1ObjectReference|undefined;

src/k8s-engine/kim.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ export default class Kim extends EventEmitter {
2727
private showedStderr = false;
2828
private refreshInterval: ReturnType<typeof setInterval> | null = null;
2929
private currentCommand: string | null = null;
30+
// During startup `kim images` repeatedly fires the same error message. Instead,
31+
// keep track of the current error and give a count instead.
32+
private lastErrorMessage = '';
33+
private sameErrorMessageCount = 0;
34+
private images: imageType[] = [];
3035

3136
start() {
3237
this.stop();
@@ -42,7 +47,7 @@ export default class Kim extends EventEmitter {
4247

4348
async runCommand(args: string[], sendNotifications = true): Promise<childResultType> {
4449
const child = spawn(resources.executable('kim'), args);
45-
const result :childResultType = {
50+
const result: childResultType = {
4651
stdout: '', stderr: '', code: 0
4752
};
4853

@@ -58,13 +63,26 @@ export default class Kim extends EventEmitter {
5863
child.stderr.on('data', (data: Buffer) => {
5964
const dataString = data.toString();
6065

61-
console.log(dataString.replace(/([^\r])\n/g, '$1\r\n'));
6266
result.stderr += dataString;
6367
if (sendNotifications) {
6468
this.emit('kim-process-output', dataString, true);
6569
}
6670
});
6771
child.on('exit', (code: number, sig: string) => {
72+
if (result.stderr) {
73+
const timeLessMessage = result.stderr.replace(/\btime=".*?"/g, '');
74+
75+
if (this.lastErrorMessage !== timeLessMessage) {
76+
this.lastErrorMessage = timeLessMessage;
77+
this.sameErrorMessageCount = 1;
78+
console.log(result.stderr.replace(/(?!<\r)\n/g, '\r\n'));
79+
} else {
80+
const m = /(Error: .*)/.exec(this.lastErrorMessage);
81+
82+
this.sameErrorMessageCount += 1;
83+
console.log(`kim ${ args[0] }: ${ m ? m[1] : 'same error message' } #${ this.sameErrorMessageCount }\r`);
84+
}
85+
}
6886
result.code = code;
6987
if (code === 0) {
7088
resolve(result);
@@ -117,6 +135,10 @@ export default class Kim extends EventEmitter {
117135
return results;
118136
}
119137

138+
listImages(): imageType[] {
139+
return this.images;
140+
}
141+
120142
async refreshImages() {
121143
try {
122144
const result: childResultType = await this.getImages();
@@ -129,7 +151,8 @@ export default class Kim extends EventEmitter {
129151
} else {
130152
this.showedStderr = false;
131153
}
132-
this.emit('images-changed', this.parse(result.stdout));
154+
this.images = this.parse(result.stdout);
155+
this.emit('images-changed', this.images);
133156
} catch (err) {
134157
if (!this.showedStderr) {
135158
if (err.stderr && !err.stdout && !err.signal) {

src/k8s-engine/wsl.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import XDGAppPaths from 'xdg-app-paths';
1313

1414
import { Settings } from '../config/settings';
1515
import DownloadProgressListener from '../utils/DownloadProgressListener';
16+
import resources from '../resources';
1617
import * as K8s from './k8s';
1718
import K3sHelper from './k3sHelper';
1819

@@ -307,6 +308,38 @@ export default class WSLBackend extends events.EventEmitter implements K8s.Kuber
307308
this.emit('service-changed', services);
308309
});
309310
this.activeVersion = desiredVersion;
311+
312+
// Temporary workaround: ensure root is mounted as shared -- this will be done later
313+
// Right now the builder pod needs to be restarted after the remount
314+
// TODO: When this code is removed, make `client.getActivePod` protected again.
315+
try {
316+
await childProcess.exec('wsl --user root -d k3s mount --make-shared /');
317+
console.log('Waiting for ensuring root is shared');
318+
await util.promisify(setTimeout)(60_000);
319+
await util.promisify(childProcess.execFile)(resources.executable('kim'), ['builder', 'install', '--force', '--no-wait']);
320+
const startTime = Date.now();
321+
const maxWaitTime = 120_000;
322+
const waitTime = 3_000;
323+
324+
while (true) {
325+
const currentTime = Date.now();
326+
327+
if ((currentTime - startTime) > maxWaitTime) {
328+
console.log(`Waited more than ${ maxWaitTime / 1000 } secs, it might start up later`);
329+
break;
330+
}
331+
// Find a working pod
332+
const pod = await this.client.getActivePod('kube-image', 'builder');
333+
334+
if (pod?.status?.phase === 'Running') {
335+
break;
336+
}
337+
await util.promisify(setTimeout)(waitTime);
338+
}
339+
} catch (e) {
340+
console.log(`Failed to restart the kim builder: ${ e.message }.`);
341+
console.log('The images page will probably be empty');
342+
}
310343
this.setState(K8s.State.STARTED);
311344
} catch (ex) {
312345
this.setState(K8s.State.ERROR);

src/pages/Images.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default {
2020
return {
2121
settings: ipcRenderer.sendSync('settings-read'),
2222
state: ipcRenderer.sendSync('k8s-state'),
23-
images: [],
23+
images: [],
2424
};
2525
},
2626
@@ -35,6 +35,10 @@ export default {
3535
// TODO: put in a status bar
3636
this.$data.settings = settings;
3737
});
38+
ipcRenderer.invoke('images-fetch')
39+
.then((images) => {
40+
this.$data.images = images;
41+
});
3842
},
3943
4044
methods: {

0 commit comments

Comments
 (0)