diff --git a/package-lock.json b/package-lock.json index c9c869087..5582fc5a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -562,8 +562,7 @@ "arr-union": { "version": "3.1.0", "resolved": "http://localhost:8080/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, "array-from": { "version": "2.1.1", @@ -822,8 +821,7 @@ "camelcase": { "version": "5.3.1", "resolved": "http://localhost:8080/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "caseless": { "version": "0.12.0", @@ -935,6 +933,18 @@ } } }, + "clone-deep": { + "version": "0.2.4", + "resolved": "http://localhost:8080/clone-deep/-/clone-deep-0.2.4.tgz", + "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", + "requires": { + "for-own": "^0.1.3", + "is-plain-object": "^2.0.1", + "kind-of": "^3.0.2", + "lazy-cache": "^1.0.3", + "shallow-clone": "^0.1.2" + } + }, "clone-response": { "version": "1.0.2", "resolved": "http://localhost:8080/clone-response/-/clone-response-1.0.2.tgz", @@ -1082,6 +1092,11 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "deepmerge": { + "version": "4.2.2", + "resolved": "http://localhost:8080/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + }, "defer-to-connect": { "version": "1.1.1", "resolved": "http://localhost:8080/defer-to-connect/-/defer-to-connect-1.1.1.tgz", @@ -1101,6 +1116,11 @@ "resolved": "http://localhost:8080/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "depd": { + "version": "2.0.0", + "resolved": "http://localhost:8080/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, "diff": { "version": "3.5.0", "resolved": "http://localhost:8080/diff/-/diff-3.5.0.tgz", @@ -1750,6 +1770,19 @@ "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, + "for-in": { + "version": "1.0.2", + "resolved": "http://localhost:8080/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "http://localhost:8080/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "^1.0.1" + } + }, "forever-agent": { "version": "0.6.1", "resolved": "http://localhost:8080/forever-agent/-/forever-agent-0.6.1.tgz", @@ -2386,7 +2419,6 @@ "version": "2.0.4", "resolved": "http://localhost:8080/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "requires": { "isobject": "^3.0.1" } @@ -2449,8 +2481,7 @@ "isobject": { "version": "3.0.1", "resolved": "http://localhost:8080/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "isomorphic-ws": { "version": "4.0.1", @@ -2582,6 +2613,11 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json-stream": { + "version": "1.0.0", + "resolved": "http://localhost:8080/json-stream/-/json-stream-1.0.0.tgz", + "integrity": "sha1-GjhU4o0rvuqzHMfd9oPS3cVlJwg=" + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "http://localhost:8080/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -2654,6 +2690,94 @@ "json-buffer": "3.0.0" } }, + "kind-of": { + "version": "3.2.2", + "resolved": "http://localhost:8080/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "http://localhost:8080/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + } + } + }, + "kubernetes-client": { + "version": "8.3.6", + "resolved": "http://localhost:8080/kubernetes-client/-/kubernetes-client-8.3.6.tgz", + "integrity": "sha512-XR33WdXUKY3JIS/4inruneS7h4nVQZbMQGU0iJzChVU1i/4eDYA3czqAEXUUOo5xjytpY+SS9UpsqC+47MXcJA==", + "requires": { + "@kubernetes/client-node": "0.10.2", + "camelcase": "^5.3.1", + "deepmerge": "^4.2.2", + "depd": "^2.0.0", + "js-yaml": "^3.13.1", + "json-stream": "^1.0.0", + "openid-client": "2.5.0", + "pump": "^3.0.0", + "qs": "^6.9.0", + "request": "^2.88.0", + "swagger-fluent": "^4.0.0", + "url-join": "^4.0.1", + "ws": "^7.2.0" + }, + "dependencies": { + "@kubernetes/client-node": { + "version": "0.10.2", + "resolved": "http://localhost:8080/@kubernetes/client-node/-/client-node-0.10.2.tgz", + "integrity": "sha512-JvsmxbTwiMqsh9LyuXMzT5HjoENFbB3a/JroJsobuAzkxN162UqAOvg++/AA+ccIMWRR2Qln4FyaOJ0a4eKyXg==", + "requires": { + "@types/js-yaml": "^3.12.1", + "@types/node": "^10.12.0", + "@types/request": "^2.47.1", + "@types/underscore": "^1.8.9", + "@types/ws": "^6.0.1", + "isomorphic-ws": "^4.0.1", + "js-yaml": "^3.13.1", + "json-stream": "^1.0.0", + "jsonpath-plus": "^0.19.0", + "request": "^2.88.0", + "shelljs": "^0.8.2", + "tslib": "^1.9.3", + "underscore": "^1.9.1", + "ws": "^6.1.0" + }, + "dependencies": { + "ws": { + "version": "6.2.1", + "resolved": "http://localhost:8080/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "@types/node": { + "version": "10.17.17", + "resolved": "http://localhost:8080/@types/node/-/node-10.17.17.tgz", + "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==" + }, + "qs": { + "version": "6.9.1", + "resolved": "http://localhost:8080/qs/-/qs-6.9.1.tgz", + "integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==" + }, + "ws": { + "version": "7.2.1", + "resolved": "http://localhost:8080/ws/-/ws-7.2.1.tgz", + "integrity": "sha512-sucePNSafamSKoOqoNfBd8V0StlkzJKL2ZAhGQinCfNQ+oacw+Pk7lcdAElecBF2VkLNZRiIb5Oi1Q5lVUVt2A==" + } + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "http://localhost:8080/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, "leasot": { "version": "10.0.0", "resolved": "http://localhost:8080/leasot/-/leasot-10.0.0.tgz", @@ -2922,6 +3046,16 @@ "tmpl": "1.0.x" } }, + "merge-deep": { + "version": "3.0.2", + "resolved": "http://localhost:8080/merge-deep/-/merge-deep-3.0.2.tgz", + "integrity": "sha512-T7qC8kg4Zoti1cFd8Cr0M+qaZfOwjlPDEdZIIPPB2JZctjaPM4fX+i7HOId69tAti2fvO6X5ldfYUONDODsrkA==", + "requires": { + "arr-union": "^3.1.0", + "clone-deep": "^0.2.4", + "kind-of": "^3.0.2" + } + }, "merge-descriptors": { "version": "1.0.1", "resolved": "http://localhost:8080/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -2979,6 +3113,27 @@ "resolved": "http://localhost:8080/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, + "mixin-object": { + "version": "2.0.1", + "resolved": "http://localhost:8080/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "http://localhost:8080/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=" + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "http://localhost:8080/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + } + } + }, "mkdirp": { "version": "0.5.1", "resolved": "http://localhost:8080/mkdirp/-/mkdirp-0.5.1.tgz", @@ -3497,6 +3652,15 @@ } } }, + "openshift-rest-client": { + "version": "4.0.0", + "resolved": "http://localhost:8080/openshift-rest-client/-/openshift-rest-client-4.0.0.tgz", + "integrity": "sha512-4hH5YiMOv2A+YEAJIAk4wbgbkvpJIdsq5Uc9L4/xfTfPWTsrjkOndxVAq74ggljjjaDMpYmTRFIhrz4Extcp9Q==", + "requires": { + "kubernetes-client": "~8.3.0", + "request": "~2.88.0" + } + }, "optimist": { "version": "0.6.1", "resolved": "http://localhost:8080/optimist/-/optimist-0.6.1.tgz", @@ -4018,6 +4182,42 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "shallow-clone": { + "version": "0.1.2", + "resolved": "http://localhost:8080/shallow-clone/-/shallow-clone-0.1.2.tgz", + "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^2.0.1", + "lazy-cache": "^0.2.3", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "http://localhost:8080/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "http://localhost:8080/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "kind-of": { + "version": "2.0.1", + "resolved": "http://localhost:8080/kind-of/-/kind-of-2.0.1.tgz", + "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", + "requires": { + "is-buffer": "^1.0.2" + } + }, + "lazy-cache": { + "version": "0.2.7", + "resolved": "http://localhost:8080/lazy-cache/-/lazy-cache-0.2.7.tgz", + "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=" + } + } + }, "shebang-command": { "version": "1.2.0", "resolved": "http://localhost:8080/shebang-command/-/shebang-command-1.2.0.tgz", @@ -4289,6 +4489,15 @@ "has-flag": "^3.0.0" } }, + "swagger-fluent": { + "version": "4.0.0", + "resolved": "http://localhost:8080/swagger-fluent/-/swagger-fluent-4.0.0.tgz", + "integrity": "sha512-48DKLp7sBPwhIzJ1FzDDdMa2Wmp/D8caU0SD9UKclDCoN5tCCz7SyX0pW+WdVlADI/txXk0hzzCLbB7OuxzoGw==", + "requires": { + "merge-deep": "^3.0.2", + "request": "^2.88.0" + } + }, "table": { "version": "5.4.6", "resolved": "http://localhost:8080/table/-/table-5.4.6.tgz", @@ -4681,6 +4890,11 @@ "punycode": "^2.1.0" } }, + "url-join": { + "version": "4.0.1", + "resolved": "http://localhost:8080/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, "url-parse-lax": { "version": "3.0.0", "resolved": "http://localhost:8080/url-parse-lax/-/url-parse-lax-3.0.0.tgz", diff --git a/package.json b/package.json index 1d6a5de2f..d201a02b5 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "hasha": "5.0.0", "js-yaml": "^3.13.1", "mkdirp": "^0.5.1", + "openshift-rest-client": "^4.0.0", "pify": "^4.0.1", "rxjs": "^6.5.3", "semver": "^6.3.0", @@ -548,7 +549,8 @@ }, { "command": "clusters.openshift.project.openConsole", - "title": "Open Project in Console" + "title": "Open Project in Console", + "Category": "OpenShift" }, { "command": "clusters.openshift.build.showLog", @@ -592,7 +594,8 @@ }, { "command": "clusters.openshift.build.openConsole", - "title": "Open in Console" + "title": "Open in Console", + "Category": "OpenShift" }, { "command": "clusters.openshift.deploy.rcShowLog.palette", @@ -616,11 +619,18 @@ }, { "command": "clusters.openshift.deployment.openConsole", - "title": "Open in Console" + "title": "Open in Console", + "Category": "OpenShift" }, { "command": "clusters.openshift.imagestream.openConsole", - "title": "Open in Console" + "title": "Open in Console", + "Category": "OpenShift" + }, + { + "command": "clusters.openshift.route.open", + "title": "Open in Browser", + "Category": "OpenShift" } ], "keybindings": [ @@ -762,6 +772,10 @@ { "command": "clusters.openshift.deploy.dc.showLog", "when": "view == openshiftProjectExplorer" + }, + { + "command": "clusters.openshift.route.open", + "when": "false" } ], "view/title": [ @@ -1049,6 +1063,11 @@ { "command": "clusters.openshift.project.openConsole", "when": "view == extension.vsKubernetesExplorer && viewItem =~ /vsKubernetes\\.resource\\.project*/i" + }, + { + "command": "clusters.openshift.route.open", + "group": "2@0", + "when": "view == extension.vsKubernetesExplorer && viewItem =~ /vsKubernetes\\.resource\\.route/i" } ] }, diff --git a/src/extension.ts b/src/extension.ts index a56263253..6998ce8ac 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -19,14 +19,15 @@ import { Build } from './k8s/build'; import { DeploymentConfig } from './k8s/deployment'; import { Console } from './k8s/console'; import { OdoImpl } from './odo'; - import { TokenStore } from './util/credentialManager'; import { Oc } from './oc'; +import { Route } from './k8s/route'; import path = require('path'); import fsx = require('fs-extra'); import treeKill = require('tree-kill'); + let clusterExplorer: k8s.ClusterExplorerV1 | undefined; let lastNamespace = ''; @@ -204,6 +205,7 @@ export async function activate(extensionContext: vscode.ExtensionContext): Promi vscode.commands.registerCommand('openshift.component.linkService', (context) => execute(Component.linkService, context)), vscode.commands.registerCommand('openshift.explorer.reportIssue', () => OpenShiftExplorer.reportIssue()), vscode.commands.registerCommand('clusters.openshift.useProject', (context) => vscode.commands.executeCommand('extension.vsKubernetesUseNamespace', context)), + vscode.commands.registerCommand('clusters.openshift.route.open', (context) => execute(Route.openUrl, context)), OpenShiftExplorer.getInstance() ]; disposable.forEach((value) => extensionContext.subscriptions.push(value)); diff --git a/src/k8s/route.ts b/src/k8s/route.ts new file mode 100644 index 000000000..38cfa833e --- /dev/null +++ b/src/k8s/route.ts @@ -0,0 +1,39 @@ +/*----------------------------------------------------------------------------------------------- + * Copyright (c) Red Hat, Inc. All rights reserved. + * Licensed under the MIT License. See LICENSE file in the project root for license information. + *-----------------------------------------------------------------------------------------------*/ + +import { KubeConfig } from '@kubernetes/client-node'; +import { Uri, commands } from 'vscode'; + +const openshiftRestClient = require('openshift-rest-client').OpenshiftClient; + + export class Route { + + public static getUrl(namespace: string, name: string): Promise { + return openshiftRestClient().then((client: any) => { + return client.apis["route.openshift.io"].v1 + .namespaces(namespace) + .routes(name) + .get() + .then((response: any) => { + const hostName = response?.body?.spec.host; + if (hostName === undefined) { + throw Error(`Cannot identify host name for Route '${name}'`); + } + return response.body.spec.tls ? `https://${hostName}` : `http://${hostName}`; + }); + }); + } + + public static async openUrl(context): Promise { + const kc = new KubeConfig(); + kc.loadFromDefault(); + const currentContextObj = kc.getContextObject(kc.getCurrentContext()); + if (currentContextObj === undefined) { + throw Error('Cannot find current context in Kubernetes configuration.') + } + const url = await Route.getUrl(currentContextObj.namespace, context.name) + commands.executeCommand('vscode.open', Uri.parse(url)); + } + }