Skip to content

Commit 53f37af

Browse files
committed
Allow people to use KUBECONFIG env var and multiple config files #4816
Signed-off-by: Victor Rubezhny <[email protected]>
1 parent e978837 commit 53f37af

File tree

14 files changed

+850
-276
lines changed

14 files changed

+850
-276
lines changed
11.3 KB
Loading

package.json

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@
146146
"got": "^11.8.6",
147147
"hasha": "^5.2.2",
148148
"istanbul": "^0.4.5",
149+
"js-yaml": "^4.1.0",
149150
"json-schema": "^0.4.0",
150151
"json-to-ast": "^2.1.0",
151-
"js-yaml": "^4.1.0",
152152
"leasot": "^14.4.0",
153153
"lodash": "^4.17.21",
154154
"mkdirp": "^3.0.1",
@@ -188,8 +188,8 @@
188188
"xterm": "^5.3.0",
189189
"xterm-addon-fit": "^0.8.0",
190190
"xterm-addon-serialize": "^0.11.0",
191-
"xterm-addon-webgl": "^0.16.0",
192191
"xterm-addon-web-links": "^0.9.0",
192+
"xterm-addon-webgl": "^0.16.0",
193193
"xterm-headless": "^5.3.0"
194194
},
195195
"overrides": {
@@ -222,6 +222,7 @@
222222
"onCommand:openshift.explorer.login.clipboard",
223223
"onCommand:openshift.explorer.logout",
224224
"onCommand:openshift.explorer.refresh",
225+
"onCommand:openshift.explorer.describe.kubeconfig",
225226
"onCommand:openshift.componentTypesView.refresh",
226227
"onCommand:openshift.project.create",
227228
"onCommand:openshift.project.set",
@@ -281,7 +282,7 @@
281282
"icons": {
282283
"current-context": {
283284
"description": "context",
284-
"default": "selection"
285+
"default": "layers-active"
285286
},
286287
"project-node": {
287288
"description": "project node",
@@ -391,6 +392,11 @@
391392
"light": "images/title/light/icon-issue.svg"
392393
}
393394
},
395+
{
396+
"command": "openshift.explorer.describe.kubeconfig",
397+
"title": "Print effective Kube config",
398+
"category": "OpenShift"
399+
},
394400
{
395401
"command": "openshift.show.feedback",
396402
"title": "Share your feedback",
@@ -2294,4 +2300,4 @@
22942300
"publisherId": "eed56242-9699-4317-8bc7-e9f4b9bdd3ff",
22952301
"isPreReleaseVersion": false
22962302
}
2297-
}
2303+
}

src/explorer.ts

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,20 @@
66
import { Context, KubernetesObject } from '@kubernetes/client-node';
77
import * as fs from 'fs';
88
import * as path from 'path';
9+
import * as tmp from 'tmp';
910
import {
11+
commands,
1012
Disposable,
1113
Event,
1214
EventEmitter,
15+
extensions,
16+
TextDocumentShowOptions,
1317
ThemeIcon,
1418
TreeDataProvider,
1519
TreeItem,
1620
TreeItemCollapsibleState,
1721
TreeView,
1822
Uri,
19-
commands,
20-
extensions,
2123
version,
2224
window,
2325
workspace
@@ -31,7 +33,7 @@ import { Oc } from './oc/ocWrapper';
3133
import { Component } from './openshift/component';
3234
import { getServiceKindStubs, getServices } from './openshift/serviceHelpers';
3335
import { PortForward } from './port-forward';
34-
import { KubeConfigUtils, getKubeConfigFiles, getNamespaceKind, isOpenShiftCluster } from './util/kubeUtils';
36+
import { getKubeConfigFiles, getNamespaceKind, isOpenShiftCluster, KubeConfigInfo } from './util/kubeUtils';
3537
import { LoginUtil } from './util/loginUtil';
3638
import { Platform } from './util/platform';
3739
import { Progress } from './util/progress';
@@ -106,7 +108,7 @@ export class OpenShiftExplorer implements TreeDataProvider<ExplorerItem>, Dispos
106108

107109
private kubeConfigWatchers: FileContentChangeNotifier[];
108110
private kubeContext: Context;
109-
private kubeConfig: KubeConfigUtils;
111+
private kubeConfigInfo: KubeConfigInfo;
110112

111113
private executionContext: ExecutionContext = new ExecutionContext();
112114

@@ -120,8 +122,8 @@ export class OpenShiftExplorer implements TreeDataProvider<ExplorerItem>, Dispos
120122

121123
private constructor() {
122124
try {
123-
this.kubeConfig = new KubeConfigUtils();
124-
this.kubeContext = this.kubeConfig.getContextObject(this.kubeConfig.currentContext);
125+
this.kubeConfigInfo = new KubeConfigInfo();
126+
this.kubeContext = this.kubeConfigInfo.getEffectiveKubeConfig().getContextObject(this.kubeConfigInfo.getEffectiveKubeConfig().currentContext);
125127
} catch {
126128
// ignore config loading error and let odo report it on first call
127129
}
@@ -137,17 +139,18 @@ export class OpenShiftExplorer implements TreeDataProvider<ExplorerItem>, Dispos
137139
}
138140
for (const fsw of this.kubeConfigWatchers) {
139141
fsw.emitter?.on('file-changed', () => {
140-
const ku2 = new KubeConfigUtils();
141-
const newCtx = ku2.getContextObject(ku2.currentContext);
142+
const kci2 = new KubeConfigInfo();
143+
const kc2 = kci2.getEffectiveKubeConfig();
144+
const newCtx = kc2.getContextObject(kc2.currentContext);
142145
if (Boolean(this.kubeContext) !== Boolean(newCtx)
143-
|| (this.kubeContext.cluster !== newCtx.cluster
144-
|| this.kubeContext.user !== newCtx.user
145-
|| this.kubeContext.namespace !== newCtx.namespace)) {
146+
|| (this.kubeContext?.cluster !== newCtx?.cluster
147+
|| this.kubeContext?.user !== newCtx?.user
148+
|| this.kubeContext?.namespace !== newCtx?.namespace)) {
146149
this.refresh();
147150
this.onDidChangeContextEmitter.fire(newCtx?.name); // newCtx can be 'null'
148151
}
149152
this.kubeContext = newCtx;
150-
this.kubeConfig = ku2;
153+
this.kubeConfigInfo = kci2;
151154
});
152155
}
153156
this.treeView = window.createTreeView<ExplorerItem>('openshiftProjectExplorer', {
@@ -202,7 +205,7 @@ export class OpenShiftExplorer implements TreeDataProvider<ExplorerItem>, Dispos
202205
void commands.executeCommand('setContext', 'isLoggedIn', true);
203206
return {
204207
contextValue: 'openshift.k8sContext',
205-
label: this.kubeConfig.getCluster(element.cluster)?.server,
208+
label: this.kubeConfigInfo.getEffectiveKubeConfig().getCluster(element.cluster)?.server,
206209
collapsibleState: TreeItemCollapsibleState.Collapsed,
207210
iconPath: imagePath('context/cluster-node.png')
208211
};
@@ -466,7 +469,7 @@ export class OpenShiftExplorer implements TreeDataProvider<ExplorerItem>, Dispos
466469
} catch {
467470
// ignore because ether server is not accessible or user is logged out
468471
}
469-
OpenShiftExplorer.getInstance().onDidChangeContextEmitter.fire(new KubeConfigUtils().currentContext);
472+
OpenShiftExplorer.getInstance().onDidChangeContextEmitter.fire(this.kubeConfigInfo.getEffectiveKubeConfig().currentContext);
470473
} else if ('name' in element) { // we are dealing with context here
471474
// user is logged into cluster from current context
472475
// and project should be shown as child node of current context
@@ -494,7 +497,7 @@ export class OpenShiftExplorer implements TreeDataProvider<ExplorerItem>, Dispos
494497
},
495498
} as KubernetesObject]
496499
} else {
497-
const projectName = this.kubeConfig.extractProjectNameFromCurrentContext() || 'default';
500+
const projectName = this.kubeConfigInfo.extractProjectNameFromCurrentContext() || 'default';
498501
result = [await createOrSetProjectItem(projectName, this.executionContext)];
499502
}
500503

@@ -544,7 +547,7 @@ export class OpenShiftExplorer implements TreeDataProvider<ExplorerItem>, Dispos
544547
try {
545548
return this.getPods(element);
546549
} catch {
547-
return [ couldNotGetItem(element.kind, this.kubeConfig.getCluster(this.kubeContext.cluster)?.server) ];
550+
return [ couldNotGetItem(element.kind, this.kubeConfigInfo.getEffectiveKubeConfig().getCluster(this.kubeContext.cluster)?.server) ];
548551
}
549552
} else if ('kind' in element && element.kind === 'project') {
550553
const deployments = {
@@ -651,7 +654,7 @@ export class OpenShiftExplorer implements TreeDataProvider<ExplorerItem>, Dispos
651654
try {
652655
collections = await Oc.Instance.getKubernetesObjects(element.kind, undefined, undefined, this.executionContext);
653656
} catch {
654-
collections = [ couldNotGetItem(element.kind, this.kubeConfig.getCluster(this.kubeContext.cluster)?.server) ];
657+
collections = [ couldNotGetItem(element.kind, this.kubeConfigInfo.getEffectiveKubeConfig().getCluster(this.kubeContext.cluster)?.server) ];
655658
}
656659
break;
657660
}
@@ -872,4 +875,28 @@ export class OpenShiftExplorer implements TreeDataProvider<ExplorerItem>, Dispos
872875
].join('\n');
873876
return `${packageJSON.bugs}/new?labels=kind/bug&title=&body=**Environment**\n${body}\n**Description**`;
874877
}
878+
879+
@vsCommand('openshift.explorer.describe.kubeconfig', true)
880+
static async describeEffectiveConfig(): Promise<void> {
881+
const k8sConfig: string = new KubeConfigInfo().dumpEffectiveKubeConfig();
882+
const tempK8sConfigFile = await new Promise<string>((resolve, reject) => {
883+
tmp.file({ prefix: 'effective.config' ,postfix: '.yaml' }, (err, name) => {
884+
if (err) {
885+
reject(err);
886+
}
887+
resolve(name);
888+
});
889+
});
890+
fs.writeFileSync(tempK8sConfigFile, k8sConfig, 'utf-8')
891+
fs.chmodSync(tempK8sConfigFile, 0o400);
892+
const fileUri = Uri.parse(tempK8sConfigFile);
893+
window.showTextDocument(fileUri, { preview: true, readOnly: true } as TextDocumentShowOptions);
894+
const onCloseSubscription = workspace.onDidCloseTextDocument((closedDoc) => {
895+
if (closedDoc.uri.toString() === fileUri.toString()) {
896+
fs.chmodSync(tempK8sConfigFile, 0o600);
897+
fs.unlinkSync(tempK8sConfigFile);
898+
onCloseSubscription.dispose();
899+
}
900+
});
901+
}
875902
}

src/extension.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import { ServerlessFunctionView } from './serverlessFunction/view';
4040
import { startTelemetry } from './telemetry';
4141
import { ToolsConfig } from './tools';
4242
import { TokenStore } from './util/credentialManager';
43-
import { getNamespaceKind, KubeConfigUtils, setKubeConfig } from './util/kubeUtils';
43+
import { getNamespaceKind, KubeConfigInfo } from './util/kubeUtils';
4444
import { setupWorkspaceDevfileContext } from './util/workspace';
4545
import { registerCommands } from './vscommand';
4646
import ClusterViewLoader from './webview/cluster/clusterViewLoader';
@@ -87,9 +87,6 @@ export async function activate(extensionContext: ExtensionContext): Promise<unkn
8787
// Link from resources to referenced resources
8888
const resourceLinkProvider = new KubernetesResourceLinkProvider();
8989

90-
// pick kube config in case multiple are configured
91-
const setKubeConfigPromise = setKubeConfig();
92-
9390
const crcStatusItem = window.createStatusBarItem(StatusBarAlignment.Left);
9491
crcStatusItem.command = 'openshift.explorer.stopCluster';
9592

@@ -276,8 +273,9 @@ export async function activate(extensionContext: ExtensionContext): Promise<unkn
276273
updateContextStatusBarItem(activeNamespaceStatusBarItem, 'project-node', '', '', false);
277274
}
278275

279-
const kcu: KubeConfigUtils = new KubeConfigUtils();
280-
const currentContext: KcuContext = kcu.findContext(context ? context : kcu.currentContext);
276+
const k8sConfigInfo = new KubeConfigInfo();
277+
const k8sConfig = k8sConfigInfo.getEffectiveKubeConfig();
278+
const currentContext: KcuContext = k8sConfigInfo.findContext(context ? context : k8sConfig.currentContext);
281279
updateContextStatusBarItem(activeContextStatusBarItem, 'current-context', currentContext?.name, `${currentContext?.name}\nCluster: ${currentContext?.cluster}`,
282280
!isContextInfoStatusBarDisabled());
283281
}
@@ -298,9 +296,6 @@ export async function activate(extensionContext: ExtensionContext): Promise<unkn
298296

299297
void OdoPreference.Instance.getRegistries(); // Initializes '~/.odo/preference.json', if not initialized yet
300298

301-
// Wait for finishing Kube Config setup
302-
await setKubeConfigPromise;
303-
304299
return {
305300
verifyBundledBinaries
306301
};

src/k8s/console.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { commands, Disposable, Uri, window } from 'vscode';
77
import { CliChannel } from '../cli';
88
import { Oc } from '../oc/ocWrapper';
99
import { ClusterType } from '../oc/types';
10-
import { KubeConfigUtils } from '../util/kubeUtils';
10+
import { KubeConfigInfo } from '../util/kubeUtils';
1111
import { vsCommand } from '../vscommand';
1212

1313
export class Console implements Disposable {
@@ -24,8 +24,9 @@ export class Console implements Disposable {
2424

2525
static cli = CliChannel.getInstance()
2626
static getCurrentProject(): string {
27-
const k8sConfig = new KubeConfigUtils();
28-
const project = (k8sConfig.contexts).find((ctx) => ctx.name === k8sConfig.currentContext).namespace;
27+
const k8sConfigInfo = new KubeConfigInfo();
28+
const k8sConfig = k8sConfigInfo.getEffectiveKubeConfig();
29+
const project = k8sConfig.contexts?.find((ctx) => ctx.name === k8sConfig.currentContext).namespace;
2930
return project;
3031
}
3132

0 commit comments

Comments
 (0)