Skip to content

Commit 238f98a

Browse files
JessicaJHeegorkemdgolovin
authored
Contribute to Kubernetes cloud explorer (#2962)
* initial implementation for cloud explorer Updates kubernetes tools cloud explorer with options to signup for Developer Sandbox and Local OpenShift * Rename tree item with + icon to 'Create Red Hat Account' Signed-off-by: Denis Golovin dgolovin@redhat.com * Add "onView:kubernetes.cloudExplorer" activation event Signed-off-by: Denis Golovin dgolovin@redhat.com * Allow Cluster editor open on crc or sandbox page Signed-off-by: Denis Golovin dgolovin@redhat.com * Rebase and clean up Signed-off-by: Jessica He <jhe@redhat.com> --------- Signed-off-by: Denis Golovin dgolovin@redhat.com Signed-off-by: Jessica He <jhe@redhat.com> Co-authored-by: Gorkem Ercan <gorkem.ercan@gmail.com> Co-authored-by: Denis Golovin <dgolovin@redhat.com>
1 parent 75290e9 commit 238f98a

File tree

5 files changed

+207
-9
lines changed

5 files changed

+207
-9
lines changed

package.json

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
"K8s",
4343
"Cloud",
4444
"podman",
45-
"Helm"
45+
"Helm",
46+
"kubernetes-extension-cloud-provider"
4647
],
4748
"icon": "images/openshift_extension.png",
4849
"main": "./out/src/extension",
@@ -214,6 +215,7 @@
214215
"onView:openshiftProjectExplorer",
215216
"onView:extension.vsKubernetesExplorer",
216217
"onView:openshiftComponentTypesView",
218+
"onView:kubernetes.cloudExplorer",
217219
"onCommand:openshift.welcome",
218220
"onCommand:openshift.getStarted",
219221
"onCommand:openshift.about",
@@ -795,6 +797,16 @@
795797
"command": "openshift.component.deleteSourceFolder",
796798
"title": "Delete Source Code Folder",
797799
"category": "OpenShift"
800+
},
801+
{
802+
"command": "openshift.sandbox.open.dashboard",
803+
"title": "Open Developer Console",
804+
"category": "OpenShift"
805+
},
806+
{
807+
"command": "openshift.sandbox.signup",
808+
"title": "Provision OpenShift Developer Sandbox",
809+
"category": "OpenShift"
798810
}
799811
],
800812
"keybindings": [
@@ -1146,6 +1158,16 @@
11461158
}
11471159
],
11481160
"view/item/context": [
1161+
{
1162+
"command": "openshift.sandbox.signup",
1163+
"category": "1@1",
1164+
"when": "viewItem == openshift.sandbox.status.none"
1165+
},
1166+
{
1167+
"command": "openshift.sandbox.open.dashboard",
1168+
"category": "1@1",
1169+
"when": "viewItem == openshift.sandbox.status.ready"
1170+
},
11491171
{
11501172
"command": "clusters.openshift.csv.create",
11511173
"group": "1@1",
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/*-----------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat, Inc. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE file in the project root for license information.
4+
*-----------------------------------------------------------------------------------------------*/
5+
import * as k8s from 'vscode-kubernetes-tools-api';
6+
import * as vscode from 'vscode';
7+
import { vsCommand } from '../vscommand';
8+
import { createSandboxAPI, SBSignupResponse } from '../openshift/sandbox';
9+
import ClusterViewLoader from '../webview/cluster/clusterViewLoader';
10+
import path = require('path');
11+
12+
const sandboxAPI = createSandboxAPI();
13+
14+
class RedHatCloudItem extends vscode.TreeItem {
15+
16+
}
17+
18+
class RedHatTreeDataProvier implements vscode.TreeDataProvider<RedHatCloudItem> {
19+
private eventEmitter: vscode.EventEmitter<RedHatCloudItem> = new vscode.EventEmitter<RedHatCloudItem>()
20+
readonly onDidChangeTreeData: vscode.Event<RedHatCloudItem> = this.eventEmitter.event
21+
22+
getTreeItem(element: RedHatCloudItem): vscode.TreeItem | Thenable<vscode.TreeItem> {
23+
return element
24+
}
25+
26+
getChildren(element?: RedHatCloudItem): vscode.ProviderResult<RedHatCloudItem[]> {
27+
if (!element) {
28+
return this.getTopLevelItems();
29+
}
30+
return [];
31+
}
32+
33+
getParent?(element: RedHatCloudItem): unknown {
34+
throw new Error('Method not implemented.');
35+
}
36+
37+
resolveTreeItem?(item: vscode.TreeItem, element: unknown, token: vscode.CancellationToken): vscode.ProviderResult<vscode.TreeItem> {
38+
throw new Error('Method not implemented.');
39+
}
40+
41+
private async getTopLevelItems(): Promise<RedHatCloudItem[]> {
42+
const sessionCheck = await vscode.authentication.getSession('redhat-account-auth', ['openid'], { createIfNone: false });
43+
if (sessionCheck) {
44+
const sandboxItem = await this.buildDevSandboxItem();
45+
const openshiftLocalItem = this.buildOpenshiftLocalItem();
46+
return [sandboxItem, openshiftLocalItem];
47+
}
48+
const loginItem = new RedHatCloudItem('Sign in to Red Hat');
49+
loginItem.iconPath = new vscode.ThemeIcon('account');
50+
loginItem.tooltip = 'Sign in to Red Hat';
51+
loginItem.command = {
52+
command: 'cloud.redhat.login',
53+
title: 'Sign in to Red Hat',
54+
}
55+
56+
const signUpItem = new RedHatCloudItem('Create Red Hat Account');
57+
signUpItem.tooltip = 'Create Red Hat Account';
58+
signUpItem.iconPath = new vscode.ThemeIcon('add');
59+
signUpItem.command = {
60+
command: '_openshift.open.signup',
61+
title: 'Create Red Hat Account',
62+
tooltip: 'Create Red Hat Account'
63+
}
64+
return [loginItem, signUpItem];
65+
}
66+
67+
private async buildDevSandboxItem() {
68+
const signupStatus = await RedHatTreeDataProvier.getSandboxSignupStatus();
69+
const sandboxItem = new RedHatCloudItem('Developer Sandbox');
70+
sandboxItem.tooltip = 'Get 30-days free access to a shared OpenShift and Kubernetes cluster.';
71+
sandboxItem.iconPath = vscode.Uri.file(path.join(__dirname, '..', '..', '..', 'images', 'title', 'logo.svg'));
72+
if (!signupStatus) {
73+
sandboxItem.contextValue = 'openshift.sandbox.status.none';
74+
}
75+
else if (signupStatus.status.ready) {
76+
sandboxItem.contextValue = 'openshift.sandbox.status.ready';
77+
}
78+
sandboxItem.command = {
79+
command: 'openshift.sandbox.open.setup',
80+
title: 'Set up Developer Sandbox',
81+
}
82+
return sandboxItem;
83+
}
84+
85+
private buildOpenshiftLocalItem() {
86+
const openshiftLocalItem = new RedHatCloudItem('Openshift Local');
87+
openshiftLocalItem.tooltip = 'Provision OpenShift 4 cluster to your local computer.';
88+
openshiftLocalItem.iconPath = new vscode.ThemeIcon('vm');
89+
openshiftLocalItem.command = {
90+
command: 'openshift.local.open.setup',
91+
title: 'Install OpenShift Local',
92+
}
93+
return openshiftLocalItem;
94+
}
95+
96+
@vsCommand('openshift.sandbox.signup')
97+
static async signupForSandbox(): Promise<string> {
98+
const authSession = await vscode.authentication.getSession('redhat-account-auth', ['openid'], { createIfNone: false });
99+
if (authSession) {
100+
// eslint-disable-next-line dot-notation
101+
const signupResponse = await sandboxAPI.signUp(authSession['idToken'] as string);
102+
if (!signupResponse) {
103+
return 'Sign up request for OpenShift Sandbox failed, please try again.';
104+
}
105+
await RedHatTreeDataProvier.refreshView();
106+
107+
}
108+
}
109+
110+
@vsCommand('openshift.local.open.setup')
111+
static async openCrCWizard(): Promise<void> {
112+
const webViewPanel: vscode.WebviewPanel = await ClusterViewLoader.loadView('Add OpenShift Cluster');
113+
await webViewPanel.webview.postMessage({ action: 'openCluster', param: 'crc' });
114+
}
115+
116+
@vsCommand('openshift.sandbox.open.setup')
117+
static async openSandboxWizard(): Promise<void> {
118+
const webViewPanel: vscode.WebviewPanel = await ClusterViewLoader.loadView('Add OpenShift Cluster');
119+
await webViewPanel.webview.postMessage({ action: 'openCluster', param: 'sandbox' });
120+
}
121+
122+
@vsCommand('cloud.redhat.login', false)
123+
static async loginToRedHatCloud(): Promise<void> {
124+
const session = await vscode.authentication.getSession('redhat-account-auth', ['openid'], { createIfNone: true });
125+
if (session) {
126+
await RedHatTreeDataProvier.refreshView();
127+
}
128+
}
129+
130+
@vsCommand('_openshift.open.signup', false)
131+
static async signupForRedHatAccount(): Promise<void> {
132+
return vscode.commands.executeCommand('vscode.open', 'https://red.ht/3MkQ54W');
133+
}
134+
135+
@vsCommand('openshift.sandbox.open.dashboard', false)
136+
static async openDashboard(): Promise<void> {
137+
const sandboxStatus = await RedHatTreeDataProvier.getSandboxSignupStatus();
138+
if (sandboxStatus) {
139+
return vscode.commands.executeCommand('vscode.open', sandboxStatus.consoleURL);
140+
}
141+
}
142+
143+
private static async getSandboxSignupStatus(): Promise<SBSignupResponse | undefined> {
144+
const authSession = await vscode.authentication.getSession('redhat-account-auth', ['openid'], { createIfNone: false });
145+
if (authSession) {
146+
// eslint-disable-next-line dot-notation
147+
return await sandboxAPI.getSignUpStatus(authSession['idToken'] as string);
148+
}
149+
return undefined;
150+
}
151+
private static async refreshView() {
152+
const cloudExplorer = await k8s.extension.cloudExplorer.v1;
153+
if (cloudExplorer.available) {
154+
cloudExplorer.api.refresh();
155+
}
156+
}
157+
}
158+
159+
class RedHatCloudProvider implements k8s.CloudExplorerV1.CloudProvider {
160+
getKubeconfigYaml(cluster: any): Promise<string> {
161+
throw new Error('Method not implemented.');
162+
}
163+
readonly cloudName = 'Red Hat OpenShift';
164+
readonly treeDataProvider = new RedHatTreeDataProvier();
165+
}
166+
167+
export const REDHAT_CLOUD_PROVIDER = new RedHatCloudProvider();

src/extension.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import {
1515
window,
1616
workspace
1717
} from 'vscode';
18+
import * as k8s from 'vscode-kubernetes-tools-api';
19+
import { REDHAT_CLOUD_PROVIDER } from './cloudProvider/redhatCloudProvider';
1820
import { ComponentsTreeDataProvider } from './componentsView';
1921
import { DebugSessionsView } from './debug';
2022
import { OpenShiftExplorer } from './explorer';
@@ -56,7 +58,14 @@ async function verifyBundledBinaries(): Promise<{ odoPath: string, ocPath: strin
5658
};
5759
}
5860

59-
export async function activate(extensionContext: ExtensionContext): Promise<any> {
61+
async function registerKubernetesCloudProvider(): Promise<void> {
62+
const cloudProvider = await k8s.extension.cloudExplorer.v1;
63+
if (cloudProvider.available) {
64+
cloudProvider.api.registerCloudProvider(REDHAT_CLOUD_PROVIDER);
65+
}
66+
}
67+
68+
export async function activate(extensionContext: ExtensionContext): Promise<unknown> {
6069
WelcomePage.createOrShow();
6170
await commands.executeCommand('setContext', 'isVSCode', env.uiKind);
6271
// UIKind.Desktop ==1 & UIKind.Web ==2. These conditions are checked for browser based & electron based IDE.
@@ -102,7 +111,7 @@ export async function activate(extensionContext: ExtensionContext): Promise<any>
102111
kind: QuickPickItemKind.Separator
103112
},
104113
{
105-
label:'Add OpenShift Cluster'
114+
label: 'Add OpenShift Cluster'
106115
},
107116
{
108117
label: 'Login to Cluster'
@@ -133,7 +142,7 @@ export async function activate(extensionContext: ExtensionContext): Promise<any>
133142
{
134143
label: 'Getting Started Walkthrough'
135144
}
136-
]);
145+
]);
137146
switch (selection?.label) {
138147
case 'Add OpenShift Cluster':
139148
await commands.executeCommand('openshift.explorer.addCluster');
@@ -166,8 +175,7 @@ export async function activate(extensionContext: ExtensionContext): Promise<any>
166175
});
167176
}
168177

169-
function createStatusBarItem(context: ExtensionContext)
170-
{
178+
function createStatusBarItem(context: ExtensionContext) {
171179
const item = window.createStatusBarItem(StatusBarAlignment.Left, 1);
172180
item.command = 'openshift.openStatusBar';
173181
context.subscriptions.push(item);
@@ -176,7 +184,7 @@ export async function activate(extensionContext: ExtensionContext): Promise<any>
176184
item.show();
177185
}
178186

179-
createStatusBarItem(extensionContext) ;
187+
createStatusBarItem(extensionContext);
180188

181189
function updateStatusBarItem(statusBarItem: StatusBarItem, text: string): void {
182190
if (!workspace.getConfiguration('openshiftToolkit').get('crcBinaryLocation')) {
@@ -192,6 +200,8 @@ export async function activate(extensionContext: ExtensionContext): Promise<any>
192200

193201
await ComponentTypesView.instance.getAllComponents();
194202

203+
await registerKubernetesCloudProvider();
204+
195205
startTelemetry(extensionContext);
196206
await verifyBinariesInRemoteContainer();
197207

src/webview/@types/windows/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ interface Window {
1515
cmdText?: string;
1616
vscodeApi: VscodeAPI;
1717
acquireVsCodeApi: () => VscodeAPI;
18-
}
18+
}

src/webview/cluster/clusterViewLoader.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,5 +372,4 @@ export default class ClusterViewLoader {
372372
}
373373
}
374374
}
375-
376375
}

0 commit comments

Comments
 (0)