Skip to content

Commit 42f0290

Browse files
committed
[WIP] force user to select kube config when there are multiple
Signed-off-by: David Thompson <davthomp@redhat.com>
1 parent 47ebefc commit 42f0290

File tree

6 files changed

+60
-38
lines changed

6 files changed

+60
-38
lines changed

src/explorer.ts

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,41 +24,12 @@ import {
2424
import * as Helm from './helm/helm';
2525
import { Oc } from './oc/ocWrapper';
2626
import { Odo } from './odo/odoWrapper';
27-
import { KubeConfigUtils } from './util/kubeUtils';
27+
import { KubeConfigUtils, getKubeConfigFiles } from './util/kubeUtils';
2828
import { Platform } from './util/platform';
2929
import { Progress } from './util/progress';
3030
import { FileContentChangeNotifier, WatchUtil } from './util/watch';
3131
import { vsCommand } from './vscommand';
3232

33-
/**
34-
* Returns the list of kube config files:
35-
* - If KUBECONFIG is not set, just ~/.kube/config
36-
* - If KUBECONFIG is set, follows the semantics for specifying multiple config files described here:
37-
* https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/#append-home-kube-config-to-your-kubeconfig-environment-variable
38-
* BUT: it shows an error if multiple configs are specified, since the Kubernetes client we are using doesn't support this use case.
39-
*/
40-
function getKubeConfigFiles(): string[] {
41-
if (process.env.KUBECONFIG) {
42-
let configuredFiles: string[] = [];
43-
if (process.platform === 'win32') {
44-
configuredFiles = process.env.KUBECONFIG.split(';');
45-
} else {
46-
configuredFiles = process.env.KUBECONFIG.split(':');
47-
}
48-
if (configuredFiles.length > 1) {
49-
void window.showWarningMessage('KUBECONFIG specifies multiple files. Unfortunately, the extension doesn\'t work properly with this setup. Expect things to break.');
50-
}
51-
const filesThatExist: string[] = [];
52-
for (const configFile of configuredFiles) {
53-
if (fs.existsSync(configFile)) {
54-
filesThatExist.push(configFile);
55-
}
56-
}
57-
return filesThatExist;
58-
}
59-
return [path.join(Platform.getUserHomePath(), '.kube', 'config')];
60-
}
61-
6233
type ExplorerItem = KubernetesObject | Helm.HelmRelease | Context | TreeItem;
6334

6435
type PackageJSON = {

src/extension.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { ServerlessFunctionView } from './serverlessFunction/view';
2525
import { startTelemetry } from './telemetry';
2626
import { ToolsConfig } from './tools';
2727
import { TokenStore } from './util/credentialManager';
28+
import { setKubeConfig } from './util/kubeUtils';
2829
import { Platform } from './util/platform';
2930
import { setupWorkspaceDevfileContext } from './util/workspace';
3031
import { registerCommands } from './vscommand';
@@ -71,6 +72,10 @@ export async function activate(extensionContext: ExtensionContext): Promise<unkn
7172
migrateFromOdo018();
7273
Cluster.extensionContext = extensionContext;
7374
TokenStore.extensionContext = extensionContext;
75+
76+
// pick kube config in case multiple are configured
77+
await setKubeConfig();
78+
7479
const crcStatusItem = window.createStatusBarItem(StatusBarAlignment.Left);
7580
crcStatusItem.command = 'openshift.explorer.stopCluster';
7681
const disposable = [

src/openshift/cluster.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { KubernetesObject } from '@kubernetes/client-node';
77
import { ExtensionContext, InputBox, QuickInputButton, QuickInputButtons, QuickPickItem, QuickPickItemButtonEvent, ThemeIcon, Uri, commands, env, window, workspace } from 'vscode';
88
import { CommandText } from '../base/command';
99
import { CliChannel } from '../cli';
10+
import { OpenShiftExplorer } from '../explorer';
1011
import { Oc } from '../oc/ocWrapper';
1112
import { Command } from '../odo/command';
1213
import { Odo } from '../odo/odoWrapper';
@@ -48,7 +49,7 @@ export class Cluster extends OpenShiftItem {
4849
),
4950
)
5051
.then(async () => {
51-
Cluster.explorer.refresh();
52+
OpenShiftExplorer.getInstance().refresh();
5253
Cluster.serverlessView.refresh();
5354
void commands.executeCommand('setContext', 'isLoggedIn', false);
5455
const logoutInfo = await window.showInformationMessage(
@@ -67,7 +68,7 @@ export class Cluster extends OpenShiftItem {
6768

6869
@vsCommand('openshift.explorer.refresh')
6970
static refresh(): void {
70-
Cluster.explorer.refresh();
71+
OpenShiftExplorer.getInstance().refresh();
7172
Cluster.serverlessView.refresh();
7273
}
7374

@@ -806,7 +807,7 @@ export class Cluster extends OpenShiftItem {
806807
}
807808

808809
static async loginMessage(clusterURL: string): Promise<string> {
809-
Cluster.explorer.refresh();
810+
OpenShiftExplorer.getInstance().refresh();
810811
Cluster.serverlessView.refresh();
811812
await commands.executeCommand('setContext', 'isLoggedIn', true);
812813
return `Successfully logged in to '${clusterURL}'`;

src/openshift/openshiftItem.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*-----------------------------------------------------------------------------------------------*/
55

66
import { commands, QuickPickItem, window } from 'vscode';
7-
import { OpenShiftExplorer } from '../explorer';
87
import { Oc } from '../oc/ocWrapper';
98
import { Odo } from '../odo/odoWrapper';
109
import { Project } from '../odo/project';
@@ -26,8 +25,6 @@ export class QuickPickCommand implements QuickPickItem {
2625
export default class OpenShiftItem {
2726
protected static readonly odo = Odo.Instance;
2827

29-
protected static readonly explorer: OpenShiftExplorer = OpenShiftExplorer.getInstance();
30-
3128
protected static readonly serverlessView: ServerlessFunctionView = ServerlessFunctionView.getInstance();
3229

3330
static async getName(message: string, offset?: string, defaultValue = ''): Promise<string> {

src/openshift/project.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class Project extends OpenShiftItem {
3737
} else {
3838
const projectName = selectedItem.label;
3939
await Odo.Instance.setProject(projectName);
40-
Project.explorer.refresh();
40+
OpenShiftExplorer.getInstance().refresh();
4141
Project.serverlessView.refresh();
4242
message = `Project '${projectName}' set as active.`;
4343
}

src/util/kubeUtils.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { KubeConfig, findHomeDir, loadYaml } from '@kubernetes/client-node';
77
import { Cluster, User } from '@kubernetes/client-node/dist/config_types';
88
import * as fs from 'fs';
99
import * as path from 'path';
10-
import { QuickPickItem } from 'vscode';
10+
import { QuickPickItem, window } from 'vscode';
11+
import { Platform } from './platform';
1112

1213
function fileExists(file: string): boolean {
1314
try {
@@ -102,3 +103,50 @@ export class KubeConfigUtils extends KubeConfig {
102103
}
103104

104105
}
106+
107+
/**
108+
* Returns the list of kube config files:
109+
* - If KUBECONFIG is not set, just ~/.kube/config
110+
* - If KUBECONFIG is set, follows the semantics for specifying multiple config files described here:
111+
* https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/#append-home-kube-config-to-your-kubeconfig-environment-variable
112+
* BUT: it shows an error if multiple configs are specified, since the Kubernetes client we are using doesn't support this use case.
113+
*/
114+
export function getKubeConfigFiles(): string[] {
115+
if (process.env.KUBECONFIG) {
116+
let configuredFiles: string[] = [];
117+
if (process.platform === 'win32') {
118+
configuredFiles = process.env.KUBECONFIG.split(';');
119+
} else {
120+
configuredFiles = process.env.KUBECONFIG.split(':');
121+
}
122+
const filesThatExist: string[] = [];
123+
for (const configFile of configuredFiles) {
124+
if (fs.existsSync(configFile)) {
125+
filesThatExist.push(configFile);
126+
}
127+
}
128+
return filesThatExist;
129+
}
130+
return [path.join(Platform.getUserHomePath(), '.kube', 'config')];
131+
}
132+
133+
/**
134+
* If there are multiple kube config files set, force the user to pick one to use.
135+
*/
136+
export async function setKubeConfig() {
137+
const kubeConfigFiles = getKubeConfigFiles();
138+
if (kubeConfigFiles.length > 1) {
139+
let selectedFile;
140+
while(!selectedFile) {
141+
try {
142+
const potentialSelection = await window.showQuickPick(kubeConfigFiles, { canPickMany: false, placeHolder: 'VSCode OpenShift only supports using one kube config. Please select which one to use.' });
143+
if (potentialSelection) {
144+
selectedFile = potentialSelection;
145+
}
146+
} catch (_) {
147+
// do nothing
148+
}
149+
}
150+
process.env.KUBECONFIG = selectedFile;
151+
}
152+
}

0 commit comments

Comments
 (0)