diff --git a/package-lock.json b/package-lock.json index 0e6e66e00..958986299 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "lodash": "^4.17.21", "make-fetch-happen": "^13.0.1", "mkdirp": "^3.0.1", + "portfinder": "^1.0.32", "rxjs": "^7.8.1", "semver": "^7.6.1", "shelljs": "^0.8.5", @@ -95,7 +96,6 @@ "mocha": "^10.4.0", "mocha-jenkins-reporter": "^0.4.7", "npm-run-all": "^4.1.5", - "portfinder": "^1.0.32", "prettier": "^3.2.5", "pretty-bytes": "^6.1.1", "proxyquire": "^2.1.3", @@ -13806,7 +13806,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/mute-stream": { @@ -14964,7 +14963,6 @@ "version": "1.0.32", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", - "dev": true, "dependencies": { "async": "^2.6.4", "debug": "^3.2.7", @@ -14978,7 +14976,6 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, "dependencies": { "lodash": "^4.17.14" } @@ -14987,7 +14984,6 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -14996,7 +14992,6 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, "dependencies": { "minimist": "^1.2.6" }, @@ -27170,8 +27165,7 @@ "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "mute-stream": { "version": "0.0.8", @@ -27982,7 +27976,6 @@ "version": "1.0.32", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", - "dev": true, "requires": { "async": "^2.6.4", "debug": "^3.2.7", @@ -27993,7 +27986,6 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, "requires": { "lodash": "^4.17.14" } @@ -28002,7 +27994,6 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, "requires": { "ms": "^2.1.1" } @@ -28011,7 +28002,6 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, "requires": { "minimist": "^1.2.6" } diff --git a/package.json b/package.json index a68e4fd40..9c3bc2798 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "lodash": "^4.17.21", "make-fetch-happen": "^13.0.1", "mkdirp": "^3.0.1", + "portfinder": "^1.0.32", "rxjs": "^7.8.1", "semver": "^7.6.1", "shelljs": "^0.8.5", @@ -157,7 +158,6 @@ "mocha": "^10.4.0", "mocha-jenkins-reporter": "^0.4.7", "npm-run-all": "^4.1.5", - "portfinder": "^1.0.32", "prettier": "^3.2.5", "pretty-bytes": "^6.1.1", "proxyquire": "^2.1.3", diff --git a/src/explorer.ts b/src/explorer.ts index 34dc1270a..34977781e 100644 --- a/src/explorer.ts +++ b/src/explorer.ts @@ -28,15 +28,15 @@ import { HelmRepo } from './helm/helmChartType'; import { Oc } from './oc/ocWrapper'; import { Component } from './openshift/component'; import { getServiceKindStubs } from './openshift/serviceHelpers'; +import { PortForward } from './port-forward'; import { KubeConfigUtils, getKubeConfigFiles, getNamespaceKind } from './util/kubeUtils'; +import { LoginUtil } from './util/loginUtil'; import { Platform } from './util/platform'; import { Progress } from './util/progress'; import { FileContentChangeNotifier, WatchUtil } from './util/watch'; import { vsCommand } from './vscommand'; import { CustomResourceDefinitionStub } from './webview/common/createServiceTypes'; import { OpenShiftTerminalManager } from './webview/openshift-terminal/openShiftTerminal'; -import { LoginUtil } from './util/loginUtil'; -import { PortForward } from './port-forward'; type ExplorerItem = KubernetesObject | Helm.HelmRelease | Context | TreeItem | OpenShiftObject | HelmRepo; @@ -164,7 +164,7 @@ export class OpenShiftExplorer implements TreeDataProvider, Dispos void commands.executeCommand('setContext', 'isLoggedIn', true); return { contextValue: 'openshift.k8sContext', - label: this.kubeConfig.getCluster(element.cluster).server, + label: this.kubeConfig.getCluster(element.cluster)?.server, collapsibleState: TreeItemCollapsibleState.Collapsed, iconPath: path.resolve(__dirname, '../../images/context/cluster-node.png') }; diff --git a/src/openshift/cluster.ts b/src/openshift/cluster.ts index 9fac12066..16e5a25d0 100644 --- a/src/openshift/cluster.ts +++ b/src/openshift/cluster.ts @@ -5,8 +5,7 @@ import { KubernetesObject } from '@kubernetes/client-node'; import { Cluster as KcuCluster, Context as KcuContext } from '@kubernetes/client-node/dist/config_types'; -import * as fs from 'fs/promises'; -import * as YAML from 'js-yaml'; +import * as https from 'https'; import { ExtensionContext, QuickInputButtons, QuickPickItem, QuickPickItemButtonEvent, ThemeIcon, Uri, commands, env, window, workspace } from 'vscode'; import { CommandText } from '../base/command'; import { CliChannel } from '../cli'; @@ -17,14 +16,13 @@ import * as NameValidator from '../openshift/nameValidator'; import { TokenStore } from '../util/credentialManager'; import { Filters } from '../util/filters'; import { inputValue, quickBtn } from '../util/inputValue'; -import { KubeConfigUtils, getKubeConfigFiles } from '../util/kubeUtils'; +import { KubeConfigUtils } from '../util/kubeUtils'; import { LoginUtil } from '../util/loginUtil'; import { Platform } from '../util/platform'; import { Progress } from '../util/progress'; import { VsCommandError, vsCommand } from '../vscommand'; import { OpenShiftTerminalManager } from '../webview/openshift-terminal/openShiftTerminal'; import OpenShiftItem, { clusterRequired } from './openshiftItem'; -import * as https from 'https'; export interface QuickPickItemExt extends QuickPickItem { name: string, @@ -1006,9 +1004,6 @@ export class Cluster extends OpenShiftItem { try { await Oc.Instance.loginWithToken(clusterURL, ocToken, abortController); - if (Cluster.isOpenShiftSandbox(clusterURL)) { - await Cluster.installPipelineUserContext(); - } return Cluster.loginMessage(clusterURL); } catch (error) { if (abortController?.signal.aborted) return null; @@ -1041,7 +1036,8 @@ export class Cluster extends OpenShiftItem { apiEndpointUrl: string, oauthRequestTokenUrl: string, ): Promise { - const clipboard = await Cluster.readFromClipboard(); + // for whatever reason the token is padded with spaces at the beginning and end when copied from the website + const clipboard = (await Cluster.readFromClipboard()).trim(); if (!clipboard) { const choice = await window.showErrorMessage( '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 { return Cluster.tokenLogin(apiEndpointUrl, true, clipboard); } - static async installPipelineUserContext(): Promise { - const kcu = new KubeConfigUtils(); - const kcFiles = getKubeConfigFiles(); - if (kcFiles.length === 0) { - throw new Error('Could not locate Kube Config when trying to replace OpenShift Sandbox token with a longer-lived token'); - } - const kcPath = kcFiles[0]; - const kcActual = YAML.load((await fs.readFile(kcPath)).toString('utf-8')) as { - users: { name: string; user: { token: string } }[]; - contexts: { - context: { cluster: string; user: string; namespace: string }; - name: string; - }[]; - 'current-context': string; - clusters: object[]; - }; - - const currentCtx = kcu.getCurrentContext(); - const currentCtxObj = kcActual.contexts.find(ctx => ctx.name === currentCtx); - const sandboxUser = currentCtxObj.context.user; - const sandboxUserObj = kcActual.users.find(user => user.name === sandboxUser); - - const serviceAccounts = await Oc.Instance.getKubernetesObjects('ServiceAccount'); - const pipelineServiceAccount = serviceAccounts.find(serviceAccount => serviceAccount.metadata.name === 'pipeline'); - if (!pipelineServiceAccount) { - return; - } - const secrets = await Oc.Instance.getKubernetesObjects('Secret'); - const pipelineTokenSecret = secrets.find((secret) => secret.metadata.name.startsWith('pipeline-token')) as any; - const pipelineToken = Buffer.from(pipelineTokenSecret.data.token, 'base64').toString(); - - sandboxUserObj.user = { - token: pipelineToken - } - - await fs.writeFile(kcPath, YAML.dump(kcActual, { lineWidth: Number.POSITIVE_INFINITY })); - } - static async loginUsingClipboardInfo(dashboardUrl: string): Promise { const clipboard = await Cluster.readFromClipboard(); if (!NameValidator.ocLoginCommandMatches(clipboard)) { diff --git a/src/webview/cluster/clusterViewLoader.ts b/src/webview/cluster/clusterViewLoader.ts index 660302e98..73593cd53 100644 --- a/src/webview/cluster/clusterViewLoader.ts +++ b/src/webview/cluster/clusterViewLoader.ts @@ -5,13 +5,16 @@ import { ChildProcess, spawn } from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; +import { clearInterval } from 'timers'; import * as vscode from 'vscode'; import { CommandText } from '../../base/command'; +import { Oc } from '../../oc/ocWrapper'; import { Cluster } from '../../openshift/cluster'; import { createSandboxAPI } from '../../openshift/sandbox'; import { ExtCommandTelemetryEvent } from '../../telemetry'; import { ChildProcessUtil } from '../../util/childProcessUtil'; import { ExtensionID } from '../../util/constants'; +import { KubeConfigUtils } from '../../util/kubeUtils'; import { vsCommand } from '../../vscommand'; import { loadWebviewHtml } from '../common-ext/utils'; import { OpenShiftTerminalManager } from '../openshift-terminal/openShiftTerminal'; @@ -186,6 +189,22 @@ async function clusterEditorMessageListener (event: any ): Promise { const result = await Cluster.loginUsingClipboardToken(event.payload.apiEndpointUrl, event.payload.oauthRequestTokenUrl); if (result) void vscode.window.showInformationMessage(`${result}`); telemetryEventLoginToSandbox.send(); + const timeout = setInterval(() => { + const currentUser = new KubeConfigUtils().getCurrentUser(); + if (currentUser) { + clearInterval(timeout); + const projectPrefix = currentUser.name.substring( + 0, + currentUser.name.indexOf('/'), + ); + void Oc.Instance.getProjects().then((projects) => { + const userProject = projects.find((project) => + project.name.includes(projectPrefix), + ); + void Oc.Instance.setProject(userProject.name); + }); + } + }, 1000); } catch (err) { void vscode.window.showErrorMessage(err.message); telemetryEventLoginToSandbox.sendError('Login into Sandbox Cluster failed.'); @@ -201,9 +220,9 @@ async function clusterEditorMessageListener (event: any ): Promise { async function pollClipboard(signupStatus) { const oauthInfo = await sandboxAPI.getOauthServerInfo(signupStatus.apiEndpoint); while (panel) { - const previousContent = await vscode.env.clipboard.readText(); + const previousContent = (await vscode.env.clipboard.readText()).trim(); await new Promise(r => setTimeout(r, 500)); - const currentContent = await vscode.env.clipboard.readText(); + const currentContent = (await vscode.env.clipboard.readText()).trim(); if (previousContent && previousContent !== currentContent) { let errCode = ''; if (!Cluster.validateLoginToken(currentContent)){ @@ -359,7 +378,7 @@ export default class ClusterViewLoader { } static async loadView(title: string): Promise { - const localResourceRoot = vscode.Uri.file(path.join(ClusterViewLoader.extensionPath, 'out', 'cluster', 'app')); + const localResourceRoot = vscode.Uri.file(path.join(ClusterViewLoader.extensionPath, 'out')); if (panel) { // If we already have a panel, show it in the target column panel.reveal(vscode.ViewColumn.One);