Skip to content

Commit 78dd780

Browse files
datho7561vrubezhny
authored andcommitted
Fix login to sandbox workflow
- Install portfinder as a runtime dependency (needed to start the extension when running as a vsix) - Remove the hack to create a service account to avoid being logged out. - Find and switch to the user's project when logging into a sandbox cluster - Fix the missing logo in the add cluster page Signed-off-by: David Thompson <davthomp@redhat.com>
1 parent dc57763 commit 78dd780

File tree

5 files changed

+32
-65
lines changed

5 files changed

+32
-65
lines changed

package-lock.json

Lines changed: 2 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
"lodash": "^4.17.21",
8585
"make-fetch-happen": "^13.0.1",
8686
"mkdirp": "^3.0.1",
87+
"portfinder": "^1.0.32",
8788
"rxjs": "^7.8.1",
8889
"semver": "^7.6.1",
8990
"shelljs": "^0.8.5",
@@ -157,7 +158,6 @@
157158
"mocha": "^10.4.0",
158159
"mocha-jenkins-reporter": "^0.4.7",
159160
"npm-run-all": "^4.1.5",
160-
"portfinder": "^1.0.32",
161161
"prettier": "^3.2.5",
162162
"pretty-bytes": "^6.1.1",
163163
"proxyquire": "^2.1.3",

src/explorer.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ import { HelmRepo } from './helm/helmChartType';
2828
import { Oc } from './oc/ocWrapper';
2929
import { Component } from './openshift/component';
3030
import { getServiceKindStubs } from './openshift/serviceHelpers';
31+
import { PortForward } from './port-forward';
3132
import { KubeConfigUtils, getKubeConfigFiles, getNamespaceKind } from './util/kubeUtils';
33+
import { LoginUtil } from './util/loginUtil';
3234
import { Platform } from './util/platform';
3335
import { Progress } from './util/progress';
3436
import { FileContentChangeNotifier, WatchUtil } from './util/watch';
3537
import { vsCommand } from './vscommand';
3638
import { CustomResourceDefinitionStub } from './webview/common/createServiceTypes';
3739
import { OpenShiftTerminalManager } from './webview/openshift-terminal/openShiftTerminal';
38-
import { LoginUtil } from './util/loginUtil';
39-
import { PortForward } from './port-forward';
4040

4141
type ExplorerItem = KubernetesObject | Helm.HelmRelease | Context | TreeItem | OpenShiftObject | HelmRepo;
4242

@@ -164,7 +164,7 @@ export class OpenShiftExplorer implements TreeDataProvider<ExplorerItem>, Dispos
164164
void commands.executeCommand('setContext', 'isLoggedIn', true);
165165
return {
166166
contextValue: 'openshift.k8sContext',
167-
label: this.kubeConfig.getCluster(element.cluster).server,
167+
label: this.kubeConfig.getCluster(element.cluster)?.server,
168168
collapsibleState: TreeItemCollapsibleState.Collapsed,
169169
iconPath: path.resolve(__dirname, '../../images/context/cluster-node.png')
170170
};

src/openshift/cluster.ts

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55

66
import { KubernetesObject } from '@kubernetes/client-node';
77
import { Cluster as KcuCluster, Context as KcuContext } from '@kubernetes/client-node/dist/config_types';
8-
import * as fs from 'fs/promises';
9-
import * as YAML from 'js-yaml';
8+
import * as https from 'https';
109
import { ExtensionContext, QuickInputButtons, QuickPickItem, QuickPickItemButtonEvent, ThemeIcon, Uri, commands, env, window, workspace } from 'vscode';
1110
import { CommandText } from '../base/command';
1211
import { CliChannel } from '../cli';
@@ -17,14 +16,13 @@ import * as NameValidator from '../openshift/nameValidator';
1716
import { TokenStore } from '../util/credentialManager';
1817
import { Filters } from '../util/filters';
1918
import { inputValue, quickBtn } from '../util/inputValue';
20-
import { KubeConfigUtils, getKubeConfigFiles } from '../util/kubeUtils';
19+
import { KubeConfigUtils } from '../util/kubeUtils';
2120
import { LoginUtil } from '../util/loginUtil';
2221
import { Platform } from '../util/platform';
2322
import { Progress } from '../util/progress';
2423
import { VsCommandError, vsCommand } from '../vscommand';
2524
import { OpenShiftTerminalManager } from '../webview/openshift-terminal/openShiftTerminal';
2625
import OpenShiftItem, { clusterRequired } from './openshiftItem';
27-
import * as https from 'https';
2826

2927
export interface QuickPickItemExt extends QuickPickItem {
3028
name: string,
@@ -1006,9 +1004,6 @@ export class Cluster extends OpenShiftItem {
10061004

10071005
try {
10081006
await Oc.Instance.loginWithToken(clusterURL, ocToken, abortController);
1009-
if (Cluster.isOpenShiftSandbox(clusterURL)) {
1010-
await Cluster.installPipelineUserContext();
1011-
}
10121007
return Cluster.loginMessage(clusterURL);
10131008
} catch (error) {
10141009
if (abortController?.signal.aborted) return null;
@@ -1041,7 +1036,8 @@ export class Cluster extends OpenShiftItem {
10411036
apiEndpointUrl: string,
10421037
oauthRequestTokenUrl: string,
10431038
): Promise<string | null> {
1044-
const clipboard = await Cluster.readFromClipboard();
1039+
// for whatever reason the token is padded with spaces at the beginning and end when copied from the website
1040+
const clipboard = (await Cluster.readFromClipboard()).trim();
10451041
if (!clipboard) {
10461042
const choice = await window.showErrorMessage(
10471043
'Cannot parse token in clipboard. Please click `Get token` button below, copy token into clipboard and press `Login to Sandbox` button again.',
@@ -1055,44 +1051,6 @@ export class Cluster extends OpenShiftItem {
10551051
return Cluster.tokenLogin(apiEndpointUrl, true, clipboard);
10561052
}
10571053

1058-
static async installPipelineUserContext(): Promise<void> {
1059-
const kcu = new KubeConfigUtils();
1060-
const kcFiles = getKubeConfigFiles();
1061-
if (kcFiles.length === 0) {
1062-
throw new Error('Could not locate Kube Config when trying to replace OpenShift Sandbox token with a longer-lived token');
1063-
}
1064-
const kcPath = kcFiles[0];
1065-
const kcActual = YAML.load((await fs.readFile(kcPath)).toString('utf-8')) as {
1066-
users: { name: string; user: { token: string } }[];
1067-
contexts: {
1068-
context: { cluster: string; user: string; namespace: string };
1069-
name: string;
1070-
}[];
1071-
'current-context': string;
1072-
clusters: object[];
1073-
};
1074-
1075-
const currentCtx = kcu.getCurrentContext();
1076-
const currentCtxObj = kcActual.contexts.find(ctx => ctx.name === currentCtx);
1077-
const sandboxUser = currentCtxObj.context.user;
1078-
const sandboxUserObj = kcActual.users.find(user => user.name === sandboxUser);
1079-
1080-
const serviceAccounts = await Oc.Instance.getKubernetesObjects('ServiceAccount');
1081-
const pipelineServiceAccount = serviceAccounts.find(serviceAccount => serviceAccount.metadata.name === 'pipeline');
1082-
if (!pipelineServiceAccount) {
1083-
return;
1084-
}
1085-
const secrets = await Oc.Instance.getKubernetesObjects('Secret');
1086-
const pipelineTokenSecret = secrets.find((secret) => secret.metadata.name.startsWith('pipeline-token')) as any;
1087-
const pipelineToken = Buffer.from(pipelineTokenSecret.data.token, 'base64').toString();
1088-
1089-
sandboxUserObj.user = {
1090-
token: pipelineToken
1091-
}
1092-
1093-
await fs.writeFile(kcPath, YAML.dump(kcActual, { lineWidth: Number.POSITIVE_INFINITY }));
1094-
}
1095-
10961054
static async loginUsingClipboardInfo(dashboardUrl: string): Promise<string | null> {
10971055
const clipboard = await Cluster.readFromClipboard();
10981056
if (!NameValidator.ocLoginCommandMatches(clipboard)) {

src/webview/cluster/clusterViewLoader.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
import { ChildProcess, spawn } from 'child_process';
66
import * as fs from 'fs';
77
import * as path from 'path';
8+
import { clearInterval } from 'timers';
89
import * as vscode from 'vscode';
910
import { CommandText } from '../../base/command';
11+
import { Oc } from '../../oc/ocWrapper';
1012
import { Cluster } from '../../openshift/cluster';
1113
import { createSandboxAPI } from '../../openshift/sandbox';
1214
import { ExtCommandTelemetryEvent } from '../../telemetry';
1315
import { ChildProcessUtil } from '../../util/childProcessUtil';
1416
import { ExtensionID } from '../../util/constants';
17+
import { KubeConfigUtils } from '../../util/kubeUtils';
1518
import { vsCommand } from '../../vscommand';
1619
import { loadWebviewHtml } from '../common-ext/utils';
1720
import { OpenShiftTerminalManager } from '../openshift-terminal/openShiftTerminal';
@@ -186,6 +189,22 @@ async function clusterEditorMessageListener (event: any ): Promise<any> {
186189
const result = await Cluster.loginUsingClipboardToken(event.payload.apiEndpointUrl, event.payload.oauthRequestTokenUrl);
187190
if (result) void vscode.window.showInformationMessage(`${result}`);
188191
telemetryEventLoginToSandbox.send();
192+
const timeout = setInterval(() => {
193+
const currentUser = new KubeConfigUtils().getCurrentUser();
194+
if (currentUser) {
195+
clearInterval(timeout);
196+
const projectPrefix = currentUser.name.substring(
197+
0,
198+
currentUser.name.indexOf('/'),
199+
);
200+
void Oc.Instance.getProjects().then((projects) => {
201+
const userProject = projects.find((project) =>
202+
project.name.includes(projectPrefix),
203+
);
204+
void Oc.Instance.setProject(userProject.name);
205+
});
206+
}
207+
}, 1000);
189208
} catch (err) {
190209
void vscode.window.showErrorMessage(err.message);
191210
telemetryEventLoginToSandbox.sendError('Login into Sandbox Cluster failed.');
@@ -201,9 +220,9 @@ async function clusterEditorMessageListener (event: any ): Promise<any> {
201220
async function pollClipboard(signupStatus) {
202221
const oauthInfo = await sandboxAPI.getOauthServerInfo(signupStatus.apiEndpoint);
203222
while (panel) {
204-
const previousContent = await vscode.env.clipboard.readText();
223+
const previousContent = (await vscode.env.clipboard.readText()).trim();
205224
await new Promise(r => setTimeout(r, 500));
206-
const currentContent = await vscode.env.clipboard.readText();
225+
const currentContent = (await vscode.env.clipboard.readText()).trim();
207226
if (previousContent && previousContent !== currentContent) {
208227
let errCode = '';
209228
if (!Cluster.validateLoginToken(currentContent)){
@@ -359,7 +378,7 @@ export default class ClusterViewLoader {
359378
}
360379

361380
static async loadView(title: string): Promise<vscode.WebviewPanel> {
362-
const localResourceRoot = vscode.Uri.file(path.join(ClusterViewLoader.extensionPath, 'out', 'cluster', 'app'));
381+
const localResourceRoot = vscode.Uri.file(path.join(ClusterViewLoader.extensionPath, 'out'));
363382
if (panel) {
364383
// If we already have a panel, show it in the target column
365384
panel.reveal(vscode.ViewColumn.One);

0 commit comments

Comments
 (0)