Skip to content

Commit 0e4c6aa

Browse files
committed
ports
1 parent 7d27150 commit 0e4c6aa

File tree

3 files changed

+207
-118
lines changed

3 files changed

+207
-118
lines changed

components/server/src/workspace/gitpod-server-impl.ts

Lines changed: 6 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import {
2828
GitpodToken,
2929
GitpodTokenType,
3030
PermissionName,
31-
PortVisibility,
3231
PrebuiltWorkspace,
3332
PrebuiltWorkspaceContext,
3433
SetWorkspaceTimeoutResult,
@@ -70,7 +69,6 @@ import {
7069
PrebuildEvent,
7170
RoleOrPermission,
7271
WORKSPACE_TIMEOUT_DEFAULT_SHORT,
73-
PortProtocol,
7472
WorkspaceInstanceRepoStatus,
7573
} from "@gitpod/gitpod-protocol";
7674
import { BlockedRepository } from "@gitpod/gitpod-protocol/lib/blocked-repositories-protocol";
@@ -102,13 +100,9 @@ import { WorkspaceManagerClientProvider } from "@gitpod/ws-manager/lib/client-pr
102100
import {
103101
AdmissionLevel,
104102
ControlAdmissionRequest,
105-
ControlPortRequest,
106103
DescribeWorkspaceRequest,
107104
MarkActiveRequest,
108-
PortSpec,
109-
PortVisibility as ProtoPortVisibility,
110105
SetTimeoutRequest,
111-
PortProtocol as ProtoPortProtocol,
112106
StopWorkspacePolicy,
113107
TakeSnapshotRequest,
114108
} from "@gitpod/ws-manager/lib/core_pb";
@@ -158,7 +152,6 @@ import { EntitlementService } from "../billing/entitlement-service";
158152
import { formatPhoneNumber } from "../user/phone-numbers";
159153
import { IDEService } from "../ide-service";
160154
import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution";
161-
import * as grpc from "@grpc/grpc-js";
162155
import { CostCenterJSON } from "@gitpod/gitpod-protocol/lib/usage";
163156
import { createCookielessId, maskIp } from "../analytics";
164157
import {
@@ -189,7 +182,7 @@ import { RedisSubscriber } from "../messaging/redis-subscriber";
189182
import { UsageService } from "../orgs/usage-service";
190183
import { UserService } from "../user/user-service";
191184
import { SSHKeyService } from "../user/sshkey-service";
192-
import { StartWorkspaceOptions, WorkspaceService } from "./workspace-service";
185+
import { StartWorkspaceOptions, WorkspaceService, mapGrpcError } from "./workspace-service";
193186
import { GitpodTokenService } from "../user/gitpod-token-service";
194187

195188
// shortcut
@@ -1143,7 +1136,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
11431136
// This is an old tab with open workspace: drop silently
11441137
return;
11451138
} else {
1146-
e = this.mapGrpcError(e);
1139+
e = mapGrpcError(e);
11471140
throw e;
11481141
}
11491142
}
@@ -1837,7 +1830,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
18371830
traceAPIParams(ctx, { workspaceId });
18381831
traceWI(ctx, { workspaceId });
18391832

1840-
await this.checkAndBlockUser("getOpenPorts");
1833+
const user = await this.checkAndBlockUser("getOpenPorts");
18411834

18421835
const instance = await this.workspaceDb.trace(ctx).findRunningInstance(workspaceId);
18431836
const workspace = await this.workspaceDb.trace(ctx).findById(workspaceId);
@@ -1847,30 +1840,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
18471840

18481841
await this.guardAccess({ kind: "workspaceInstance", subject: instance, workspace }, "get");
18491842

1850-
const req = new DescribeWorkspaceRequest();
1851-
req.setId(instance.id);
1852-
const client = await this.workspaceManagerClientProvider.get(instance.region);
1853-
const desc = await client.describeWorkspace(ctx, req);
1854-
1855-
if (!desc.hasStatus()) {
1856-
throw new Error("describeWorkspace returned no status");
1857-
}
1858-
1859-
const status = desc.getStatus()!;
1860-
const ports = status
1861-
.getSpec()!
1862-
.getExposedPortsList()
1863-
.map(
1864-
(p) =>
1865-
<WorkspaceInstancePort>{
1866-
port: p.getPort(),
1867-
url: p.getUrl(),
1868-
visibility: this.portVisibilityFromProto(p.getVisibility()),
1869-
protocol: this.portProtocolFromProto(p.getProtocol()),
1870-
},
1871-
);
1872-
1873-
return ports;
1843+
return await this.workspaceService.getOpenPorts(user.id, workspaceId);
18741844
}
18751845

18761846
public async updateGitStatus(
@@ -1924,61 +1894,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
19241894
traceWI(ctx, { instanceId: runningInstance.id });
19251895
await this.guardAccess({ kind: "workspaceInstance", subject: runningInstance, workspace }, "update");
19261896

1927-
const req = new ControlPortRequest();
1928-
req.setId(runningInstance.id);
1929-
const spec = new PortSpec();
1930-
spec.setPort(port.port);
1931-
spec.setVisibility(this.portVisibilityToProto(port.visibility));
1932-
spec.setProtocol(this.portProtocolToProto(port.protocol));
1933-
req.setSpec(spec);
1934-
req.setExpose(true);
1935-
1936-
try {
1937-
const client = await this.workspaceManagerClientProvider.get(runningInstance.region);
1938-
await client.controlPort(ctx, req);
1939-
} catch (e) {
1940-
throw this.mapGrpcError(e);
1941-
}
1942-
}
1943-
1944-
private portVisibilityFromProto(visibility: ProtoPortVisibility): PortVisibility {
1945-
switch (visibility) {
1946-
default: // the default in the protobuf def is: private
1947-
case ProtoPortVisibility.PORT_VISIBILITY_PRIVATE:
1948-
return "private";
1949-
case ProtoPortVisibility.PORT_VISIBILITY_PUBLIC:
1950-
return "public";
1951-
}
1952-
}
1953-
1954-
private portVisibilityToProto(visibility: PortVisibility | undefined): ProtoPortVisibility {
1955-
switch (visibility) {
1956-
default: // the default for requests is: private
1957-
case "private":
1958-
return ProtoPortVisibility.PORT_VISIBILITY_PRIVATE;
1959-
case "public":
1960-
return ProtoPortVisibility.PORT_VISIBILITY_PUBLIC;
1961-
}
1962-
}
1963-
1964-
private portProtocolFromProto(protocol: ProtoPortProtocol): PortProtocol {
1965-
switch (protocol) {
1966-
default: // the default in the protobuf def is: http
1967-
case ProtoPortProtocol.PORT_PROTOCOL_HTTP:
1968-
return "http";
1969-
case ProtoPortProtocol.PORT_PROTOCOL_HTTPS:
1970-
return "https";
1971-
}
1972-
}
1973-
1974-
private portProtocolToProto(protocol: PortProtocol | undefined): ProtoPortProtocol {
1975-
switch (protocol) {
1976-
default: // the default for requests is: http
1977-
case "http":
1978-
return ProtoPortProtocol.PORT_PROTOCOL_HTTP;
1979-
case "https":
1980-
return ProtoPortProtocol.PORT_PROTOCOL_HTTPS;
1981-
}
1897+
return await this.workspaceService.openPort(user.id, workspaceId, port);
19821898
}
19831899

19841900
public async closePort(ctx: TraceContext, workspaceId: string, port: number) {
@@ -1999,15 +1915,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
19991915
traceWI(ctx, { instanceId: instance.id });
20001916
await this.guardAccess({ kind: "workspaceInstance", subject: instance, workspace }, "update");
20011917

2002-
const req = new ControlPortRequest();
2003-
req.setId(instance.id);
2004-
const spec = new PortSpec();
2005-
spec.setPort(port);
2006-
req.setSpec(spec);
2007-
req.setExpose(false);
2008-
2009-
const client = await this.workspaceManagerClientProvider.get(instance.region);
2010-
await client.controlPort(ctx, req);
1918+
await this.workspaceService.closePort(user.id, workspaceId, port);
20111919
}
20121920

20131921
async watchWorkspaceImageBuildLogs(ctx: TraceContext, workspaceId: string): Promise<void> {
@@ -3581,23 +3489,6 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
35813489
increaseDashboardErrorBoundaryCounter();
35823490
}
35833491

3584-
private mapGrpcError(err: Error): Error {
3585-
function isGrpcError(err: any): err is grpc.StatusObject {
3586-
return err.code && err.details;
3587-
}
3588-
3589-
if (!isGrpcError(err)) {
3590-
return err;
3591-
}
3592-
3593-
switch (err.code) {
3594-
case grpc.status.RESOURCE_EXHAUSTED:
3595-
return new ApplicationError(ErrorCodes.TOO_MANY_REQUESTS, err.details);
3596-
default:
3597-
return new ApplicationError(ErrorCodes.INTERNAL_SERVER_ERROR, err.details);
3598-
}
3599-
}
3600-
36013492
async getIDToken(): Promise<void> {}
36023493

36033494
public async controlAdmission(ctx: TraceContext, workspaceId: string, level: "owner" | "everyone"): Promise<void> {

components/server/src/workspace/workspace-service.spec.db.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@
66

77
import { TypeORM } from "@gitpod/gitpod-db/lib";
88
import { resetDB } from "@gitpod/gitpod-db/lib/test/reset-db";
9-
import { CommitContext, Organization, Project, User, WorkspaceConfig } from "@gitpod/gitpod-protocol";
9+
import {
10+
CommitContext,
11+
Organization,
12+
Project,
13+
User,
14+
WorkspaceConfig,
15+
WorkspaceInstancePort,
16+
} from "@gitpod/gitpod-protocol";
1017
import { Experiments } from "@gitpod/gitpod-protocol/lib/experiments/configcat-server";
1118
import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
1219
import * as chai from "chai";
@@ -259,6 +266,42 @@ describe("WorkspaceService", async () => {
259266

260267
await expectError(ErrorCodes.NOT_FOUND, svc.setDescription(stranger.id, ws.id, desc));
261268
});
269+
270+
it("should getOpenPorts", async () => {
271+
const svc = container.get(WorkspaceService);
272+
const ws = await createTestWorkspace(svc, org, owner, project);
273+
274+
await expectError(
275+
ErrorCodes.NOT_FOUND,
276+
svc.getOpenPorts(owner.id, ws.id),
277+
"should fail on non-running workspace",
278+
);
279+
});
280+
281+
it("should openPort", async () => {
282+
const svc = container.get(WorkspaceService);
283+
const ws = await createTestWorkspace(svc, org, owner, project);
284+
285+
const port: WorkspaceInstancePort = {
286+
port: 8080,
287+
};
288+
await expectError(
289+
ErrorCodes.NOT_FOUND,
290+
svc.openPort(owner.id, ws.id, port),
291+
"should fail on non-running workspace",
292+
);
293+
});
294+
295+
it("should closePort", async () => {
296+
const svc = container.get(WorkspaceService);
297+
const ws = await createTestWorkspace(svc, org, owner, project);
298+
299+
await expectError(
300+
ErrorCodes.NOT_FOUND,
301+
svc.closePort(owner.id, ws.id, 8080),
302+
"should fail on non-running workspace",
303+
);
304+
});
262305
});
263306

264307
async function createTestWorkspace(svc: WorkspaceService, org: Organization, owner: User, project: Project) {

0 commit comments

Comments
 (0)