Skip to content

Commit 22c39f2

Browse files
authored
Always use public API (#104)
* Always use public API * 💄
1 parent 4906186 commit 22c39f2

File tree

4 files changed

+42
-89
lines changed

4 files changed

+42
-89
lines changed

src/experiments.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ const EXPERIMENTAL_SETTINGS: string[] = [
1919

2020
export interface IExperimentsService {
2121
getUseLocalSSHProxy(): Promise<boolean>;
22-
getUsePublicAPI(gitpodHost: string): Promise<boolean>;
2322
}
2423

2524
export class ExperimentalSettings extends Disposable implements IExperimentsService {
@@ -147,10 +146,6 @@ export class ExperimentalSettings extends Disposable implements IExperimentsServ
147146
async getUseLocalSSHProxy(): Promise<boolean> {
148147
return (await this.getRaw<boolean>('gitpod_desktop_use_local_ssh_proxy', { 'platform': os.platform() })) ?? false;
149148
}
150-
151-
async getUsePublicAPI(gitpodHost: string): Promise<boolean> {
152-
return (await this.getRaw<boolean>('gitpod_experimental_publicApi', { gitpodHost })) ?? false;
153-
}
154149
}
155150

156151
export function isUserOverrideSetting(key: string): boolean {

src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export async function activate(context: vscode.ExtensionContext) {
126126
// Because auth provider implementation is in the same extension, we need to wait for it to activate first
127127
firstLoadPromise.then(async () => {
128128
if (remoteConnectionInfo) {
129-
remoteSession = new RemoteSession(remoteConnectionInfo.connectionInfo, context, remoteService, hostService, sessionService, experiments, logger!, telemetryService!, notificationService);
129+
remoteSession = new RemoteSession(remoteConnectionInfo.connectionInfo, context, remoteService, hostService, sessionService, logger!, telemetryService!, notificationService);
130130
await remoteSession.initialize();
131131
} else if (sessionService.isSignedIn()) {
132132
remoteService.checkForStoppedWorkspaces(async wsInfo => {

src/remoteConnector.ts

Lines changed: 20 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { Workspace, WorkspaceInstanceStatus_Phase } from '@gitpod/public-api/lib/gitpod/experimental/v1/workspaces_pb';
7-
import { UserSSHPublicKeyValue, WorkspaceInfo } from '@gitpod/gitpod-protocol';
87
import * as crypto from 'crypto';
98
import { utils as sshUtils } from 'ssh2';
109
import { ParsedKey } from 'ssh2-streams';
1110
import * as vscode from 'vscode';
1211
import { Disposable } from './common/dispose';
13-
import { withServerApi } from './internalApi';
1412
import { ITelemetryService, UserFlowTelemetryProperties } from './common/telemetry';
1513
import { addHostToHostFile, checkNewHostInHostkeys } from './ssh/hostfile';
1614
import { ScopeFeature } from './featureSupport';
@@ -33,8 +31,6 @@ export class RemoteConnector extends Disposable {
3331

3432
public static AUTH_COMPLETE_PATH = '/auth-complete';
3533

36-
private usePublicApi: boolean = false;
37-
3834
constructor(
3935
private readonly context: vscode.ExtensionContext,
4036
private readonly sessionService: ISessionService,
@@ -55,27 +51,21 @@ export class RemoteConnector extends Disposable {
5551
private async getWorkspaceSSHDestination({ workspaceId, gitpodHost, debugWorkspace }: SSHConnectionParams): Promise<{ destination: SSHDestination; password?: string }> {
5652
const sshKeysSupported = this.sessionService.getScopes().includes(ScopeFeature.SSHPublicKeys);
5753

58-
const [workspaceInfo, ownerToken, registeredSSHKeys] = await withServerApi(this.sessionService.getGitpodToken(), getServiceURL(gitpodHost), service => Promise.all([
59-
this.usePublicApi ? this.sessionService.getAPI().getWorkspace(workspaceId) : service.server.getWorkspace(workspaceId),
60-
this.usePublicApi ? this.sessionService.getAPI().getOwnerToken(workspaceId) : service.server.getOwnerToken(workspaceId),
61-
sshKeysSupported ? (this.usePublicApi ? this.sessionService.getAPI().getSSHKeys() : service.server.getSSHPublicKeys()) : undefined
62-
]), this.logService);
54+
const [workspaceInfo, ownerToken, registeredSSHKeys] = await Promise.all([
55+
this.sessionService.getAPI().getWorkspace(workspaceId),
56+
this.sessionService.getAPI().getOwnerToken(workspaceId),
57+
sshKeysSupported ? (this.sessionService.getAPI().getSSHKeys()) : undefined
58+
]);
6359

64-
const isNotRunning = this.usePublicApi
65-
? !((workspaceInfo as Workspace)?.status?.instance) || (workspaceInfo as Workspace)?.status?.instance?.status?.phase === WorkspaceInstanceStatus_Phase.STOPPING || (workspaceInfo as Workspace)?.status?.instance?.status?.phase === WorkspaceInstanceStatus_Phase.STOPPED
66-
: !((workspaceInfo as WorkspaceInfo).latestInstance) || (workspaceInfo as WorkspaceInfo).latestInstance?.status?.phase === 'stopping' || (workspaceInfo as WorkspaceInfo).latestInstance?.status?.phase === 'stopped';
60+
const isNotRunning = !((workspaceInfo as Workspace)?.status?.instance) || (workspaceInfo as Workspace)?.status?.instance?.status?.phase === WorkspaceInstanceStatus_Phase.STOPPING || (workspaceInfo as Workspace)?.status?.instance?.status?.phase === WorkspaceInstanceStatus_Phase.STOPPED;
6761
if (isNotRunning) {
6862
throw new NoRunningInstanceError(
6963
workspaceId,
70-
this.usePublicApi
71-
? (workspaceInfo as Workspace)?.status?.instance?.status?.phase ? WorkspaceInstanceStatus_Phase[(workspaceInfo as Workspace)?.status?.instance?.status?.phase!] : undefined
72-
: (workspaceInfo as WorkspaceInfo).latestInstance?.status?.phase
64+
(workspaceInfo as Workspace)?.status?.instance?.status?.phase ? WorkspaceInstanceStatus_Phase[(workspaceInfo as Workspace)?.status?.instance?.status?.phase!] : undefined
7365
);
7466
}
7567

76-
const workspaceUrl = this.usePublicApi
77-
? new URL((workspaceInfo as Workspace).status!.instance!.status!.url)
78-
: new URL((workspaceInfo as WorkspaceInfo).latestInstance!.ideUrl);
68+
const workspaceUrl = new URL((workspaceInfo as Workspace).status!.instance!.status!.url);
7969

8070
const sshHostKeyEndPoint = `https://${workspaceUrl.host}/_ssh/host_keys`;
8171
const sshHostKeyResponse = await fetch(sshHostKeyEndPoint);
@@ -122,18 +112,16 @@ export class RemoteConnector extends Disposable {
122112
let identityKeys = await gatherIdentityFiles(identityFiles, getAgentSock(hostConfiguration), false, this.logService);
123113

124114
if (registeredSSHKeys) {
125-
const registeredKeys = this.usePublicApi
126-
? (registeredSSHKeys as SSHKey[]).map(k => {
127-
const parsedResult = sshUtils.parseKey(k.key);
128-
if (parsedResult instanceof Error || !parsedResult) {
129-
this.logService.error(`Error while parsing SSH public key ${k.name}:`, parsedResult);
130-
return { name: k.name, fingerprint: '' };
131-
}
115+
const registeredKeys = (registeredSSHKeys as SSHKey[]).map(k => {
116+
const parsedResult = sshUtils.parseKey(k.key);
117+
if (parsedResult instanceof Error || !parsedResult) {
118+
this.logService.error(`Error while parsing SSH public key ${k.name}:`, parsedResult);
119+
return { name: k.name, fingerprint: '' };
120+
}
132121

133-
const parsedKey = parsedResult as ParsedKey;
134-
return { name: k.name, fingerprint: crypto.createHash('sha256').update(parsedKey.getPublicSSH()).digest('base64') };
135-
})
136-
: (registeredSSHKeys as UserSSHPublicKeyValue[]).map(k => ({ name: k.name, fingerprint: k.fingerprint }));
122+
const parsedKey = parsedResult as ParsedKey;
123+
return { name: k.name, fingerprint: crypto.createHash('sha256').update(parsedKey.getPublicSSH()).digest('base64') };
124+
});
137125
this.logService.trace(`Registered public keys in Gitpod account:`, registeredKeys.length ? registeredKeys.map(k => `${k.name} SHA256:${k.fingerprint}`).join('\n') : 'None');
138126

139127
identityKeys = identityKeys.filter(k => !!registeredKeys.find(regKey => regKey.fingerprint === k.fingerprint));
@@ -151,18 +139,14 @@ export class RemoteConnector extends Disposable {
151139
}
152140

153141
private async getLocalSSHWorkspaceSSHDestination({ workspaceId, gitpodHost, debugWorkspace }: SSHConnectionParams): Promise<{ destination: SSHDestination; password?: string }> {
154-
const workspaceInfo = await withServerApi(this.sessionService.getGitpodToken(), getServiceURL(gitpodHost), async service => this.usePublicApi ? this.sessionService.getAPI().getWorkspace(workspaceId) : service.server.getWorkspace(workspaceId), this.logService);
142+
const workspaceInfo = await this.sessionService.getAPI().getWorkspace(workspaceId);
155143

156-
const isNotRunning = this.usePublicApi
157-
? !((workspaceInfo as Workspace)?.status?.instance) || (workspaceInfo as Workspace)?.status?.instance?.status?.phase === WorkspaceInstanceStatus_Phase.STOPPING || (workspaceInfo as Workspace)?.status?.instance?.status?.phase === WorkspaceInstanceStatus_Phase.STOPPED
158-
: !((workspaceInfo as WorkspaceInfo).latestInstance) || (workspaceInfo as WorkspaceInfo).latestInstance?.status?.phase === 'stopping' || (workspaceInfo as WorkspaceInfo).latestInstance?.status?.phase === 'stopped';
144+
const isNotRunning = !((workspaceInfo as Workspace)?.status?.instance) || (workspaceInfo as Workspace)?.status?.instance?.status?.phase === WorkspaceInstanceStatus_Phase.STOPPING || (workspaceInfo as Workspace)?.status?.instance?.status?.phase === WorkspaceInstanceStatus_Phase.STOPPED;
159145

160146
if (isNotRunning) {
161147
throw new NoRunningInstanceError(
162148
workspaceId,
163-
this.usePublicApi
164-
? (workspaceInfo as Workspace)?.status?.instance?.status?.phase ? WorkspaceInstanceStatus_Phase[(workspaceInfo as Workspace)?.status?.instance?.status?.phase!] : undefined
165-
: (workspaceInfo as WorkspaceInfo).latestInstance?.status?.phase
149+
(workspaceInfo as Workspace)?.status?.instance?.status?.phase ? WorkspaceInstanceStatus_Phase[(workspaceInfo as Workspace)?.status?.instance?.status?.phase!] : undefined,
166150
);
167151
}
168152

@@ -271,9 +255,6 @@ export class RemoteConnector extends Disposable {
271255
location: vscode.ProgressLocation.Notification
272256
},
273257
async () => {
274-
this.usePublicApi = await this.experiments.getUsePublicAPI(params.gitpodHost);
275-
this.logService.info(`Going to use ${this.usePublicApi ? 'public' : 'server'} API`);
276-
277258
const openSSHVersion = await getOpenSSHVersion();
278259

279260
// Always try to run a local ssh connection collect success metrics

src/remoteSession.ts

Lines changed: 21 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ import { NoRunningInstanceError, SSHConnectionParams, SSH_DEST_KEY, getGitpodRem
88
import { Disposable } from './common/dispose';
99
import { HeartbeatManager } from './heartbeat';
1010
import { WorkspaceState } from './workspaceState';
11-
import { IExperimentsService } from './experiments';
1211
import { ITelemetryService, UserFlowTelemetryProperties } from './common/telemetry';
1312
import { INotificationService } from './services/notificationService';
14-
import { withServerApi } from './internalApi';
1513
import { ISessionService } from './services/sessionService';
1614
import { IHostService } from './services/hostService';
1715
import { ILogService } from './services/logService';
@@ -20,8 +18,6 @@ import { IRemoteService } from './services/remoteService';
2018

2119
export class RemoteSession extends Disposable {
2220

23-
private usePublicApi: boolean = false;
24-
2521
private heartbeatManager: HeartbeatManager | undefined;
2622
private workspaceState: WorkspaceState | undefined;
2723
private extensionServiceServer: ExtensionServiceServer | undefined;
@@ -32,7 +28,6 @@ export class RemoteSession extends Disposable {
3228
private readonly remoteService: IRemoteService,
3329
private readonly hostService: IHostService,
3430
private readonly sessionService: ISessionService,
35-
private readonly experiments: IExperimentsService,
3631
private readonly logService: ILogService,
3732
private readonly telemetryService: ITelemetryService,
3833
private readonly notificationService: INotificationService
@@ -63,45 +58,27 @@ export class RemoteSession extends Disposable {
6358
try {
6459
this.remoteService.startLocalSSHServiceServer().catch(() => {/* ignore */ });
6560

66-
this.usePublicApi = await this.experiments.getUsePublicAPI(this.connectionInfo.gitpodHost);
67-
this.logService.info(`Going to use ${this.usePublicApi ? 'public' : 'server'} API`);
68-
69-
if (this.usePublicApi) {
70-
this.workspaceState = new WorkspaceState(this.connectionInfo.workspaceId, this.sessionService, this.logService);
71-
this.workspaceState.initialize()
72-
.then(() => {
73-
if (!this.workspaceState!.instanceId || !this.workspaceState!.isWorkspaceRunning) {
74-
vscode.commands.executeCommand('workbench.action.remote.close');
75-
return;
76-
}
77-
const instanceId = this.workspaceState!.instanceId;
78-
if (instanceId !== this.connectionInfo.instanceId) {
79-
this.logService.info(`Updating workspace ${this.connectionInfo.workspaceId} latest instance id ${this.connectionInfo.instanceId} => ${instanceId}`);
80-
this.connectionInfo.instanceId = instanceId;
81-
}
82-
83-
const { sshDestStr } = getGitpodRemoteWindowConnectionInfo(this.context)!;
84-
this.context.globalState.update(`${SSH_DEST_KEY}${sshDestStr}`, { ...this.connectionInfo } as SSHConnectionParams);
85-
});
86-
87-
this._register(this.workspaceState.onWorkspaceWillStop(async () => {
88-
await this.remoteService.saveRestartInfo();
89-
vscode.commands.executeCommand('workbench.action.remote.close');
90-
}));
91-
} else {
92-
const workspaceInfo = await withServerApi(this.sessionService.getGitpodToken(), this.connectionInfo.gitpodHost, service => service.server.getWorkspace(this.connectionInfo.workspaceId), this.logService);
93-
if (!workspaceInfo.latestInstance || workspaceInfo.latestInstance?.status?.phase === 'stopping' || workspaceInfo.latestInstance?.status?.phase === 'stopped') {
94-
throw new NoRunningInstanceError(this.connectionInfo.workspaceId, workspaceInfo.latestInstance?.status?.phase);
95-
}
96-
const instanceId = workspaceInfo.latestInstance.id;
97-
if (instanceId !== this.connectionInfo.instanceId) {
98-
this.logService.info(`Updating workspace ${this.connectionInfo.workspaceId} latest instance id ${this.connectionInfo.instanceId} => ${instanceId}`);
99-
this.connectionInfo.instanceId = instanceId;
100-
}
101-
102-
const { sshDestStr } = getGitpodRemoteWindowConnectionInfo(this.context)!;
103-
this.context.globalState.update(`${SSH_DEST_KEY}${sshDestStr}`, { ...this.connectionInfo } as SSHConnectionParams);
104-
}
61+
this.workspaceState = new WorkspaceState(this.connectionInfo.workspaceId, this.sessionService, this.logService);
62+
this.workspaceState.initialize()
63+
.then(() => {
64+
if (!this.workspaceState!.instanceId || !this.workspaceState!.isWorkspaceRunning) {
65+
vscode.commands.executeCommand('workbench.action.remote.close');
66+
return;
67+
}
68+
const instanceId = this.workspaceState!.instanceId;
69+
if (instanceId !== this.connectionInfo.instanceId) {
70+
this.logService.info(`Updating workspace ${this.connectionInfo.workspaceId} latest instance id ${this.connectionInfo.instanceId} => ${instanceId}`);
71+
this.connectionInfo.instanceId = instanceId;
72+
}
73+
74+
const { sshDestStr } = getGitpodRemoteWindowConnectionInfo(this.context)!;
75+
this.context.globalState.update(`${SSH_DEST_KEY}${sshDestStr}`, { ...this.connectionInfo } as SSHConnectionParams);
76+
});
77+
78+
this._register(this.workspaceState.onWorkspaceWillStop(async () => {
79+
await this.remoteService.saveRestartInfo();
80+
vscode.commands.executeCommand('workbench.action.remote.close');
81+
}));
10582

10683
this.heartbeatManager = new HeartbeatManager(this.connectionInfo, this.workspaceState, this.sessionService, this.logService, this.telemetryService);
10784

0 commit comments

Comments
 (0)