@gitpod/gitpod-protocol 0.1.5-prs-core-dev-kubeconfig.4 → 0.1.5-prs-test-dazzle-rewrite.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/gitpod-schema.json +21 -2
- package/lib/accounting-protocol.d.ts +0 -1
- package/lib/accounting-protocol.d.ts.map +1 -1
- package/lib/accounting-protocol.js +10 -11
- package/lib/accounting-protocol.js.map +1 -1
- package/lib/admin-protocol.d.ts +8 -2
- package/lib/admin-protocol.d.ts.map +1 -1
- package/lib/admin-protocol.js +2 -13
- package/lib/admin-protocol.js.map +1 -1
- package/lib/analytics.d.ts +13 -1
- package/lib/analytics.d.ts.map +1 -1
- package/lib/context-url.js +4 -4
- package/lib/context-url.js.map +1 -1
- package/lib/context-url.spec.js +45 -48
- package/lib/context-url.spec.js.map +1 -1
- package/lib/email-protocol.js +4 -4
- package/lib/email-protocol.js.map +1 -1
- package/lib/encryption/container-module.js +4 -4
- package/lib/encryption/container-module.js.map +1 -1
- package/lib/encryption/encryption-engine.js +19 -20
- package/lib/encryption/encryption-engine.js.map +1 -1
- package/lib/encryption/encryption-engine.spec.js +29 -36
- package/lib/encryption/encryption-engine.spec.js.map +1 -1
- package/lib/encryption/encryption-service.js +29 -43
- package/lib/encryption/encryption-service.js.map +1 -1
- package/lib/encryption/key-provider.js +25 -30
- package/lib/encryption/key-provider.js.map +1 -1
- package/lib/env.d.ts +1 -1
- package/lib/env.d.ts.map +1 -1
- package/lib/env.js +20 -20
- package/lib/env.js.map +1 -1
- package/lib/gitpod-file-parser.js +25 -41
- package/lib/gitpod-file-parser.js.map +1 -1
- package/lib/gitpod-file-parser.spec.js +116 -116
- package/lib/gitpod-file-parser.spec.js.map +1 -1
- package/lib/gitpod-service.d.ts +40 -13
- package/lib/gitpod-service.d.ts.map +1 -1
- package/lib/gitpod-service.js +150 -273
- package/lib/gitpod-service.js.map +1 -1
- package/lib/ide-protocol.d.ts +81 -0
- package/lib/ide-protocol.d.ts.map +1 -0
- package/lib/ide-protocol.js +8 -0
- package/lib/ide-protocol.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/messaging/browser/connection.d.ts +3 -3
- package/lib/messaging/browser/connection.d.ts.map +1 -1
- package/lib/messaging/browser/connection.js +172 -35
- package/lib/messaging/browser/connection.js.map +1 -1
- package/lib/messaging/browser/window-connection.js +35 -55
- package/lib/messaging/browser/window-connection.js.map +1 -1
- package/lib/messaging/client-call-metrics.d.ts +35 -0
- package/lib/messaging/client-call-metrics.d.ts.map +1 -0
- package/lib/messaging/client-call-metrics.js +83 -0
- package/lib/messaging/client-call-metrics.js.map +1 -0
- package/lib/messaging/connection-error-handler.js +11 -23
- package/lib/messaging/connection-error-handler.js.map +1 -1
- package/lib/messaging/error.d.ts +1 -1
- package/lib/messaging/error.d.ts.map +1 -1
- package/lib/messaging/error.js +2 -2
- package/lib/messaging/error.js.map +1 -1
- package/lib/messaging/handler.d.ts +10 -0
- package/lib/messaging/handler.d.ts.map +1 -1
- package/lib/messaging/node/connection.d.ts +0 -10
- package/lib/messaging/node/connection.d.ts.map +1 -1
- package/lib/messaging/node/connection.js +12 -50
- package/lib/messaging/node/connection.js.map +1 -1
- package/lib/messaging/proxy-factory.d.ts +2 -0
- package/lib/messaging/proxy-factory.d.ts.map +1 -1
- package/lib/messaging/proxy-factory.js +74 -159
- package/lib/messaging/proxy-factory.js.map +1 -1
- package/lib/oss-allowlist.d.ts +14 -0
- package/lib/oss-allowlist.d.ts.map +1 -0
- package/lib/oss-allowlist.js +8 -0
- package/lib/oss-allowlist.js.map +1 -0
- package/lib/permission.d.ts +1 -2
- package/lib/permission.d.ts.map +1 -1
- package/lib/permission.js +12 -13
- package/lib/permission.js.map +1 -1
- package/lib/plans.d.ts +1 -1
- package/lib/plans.d.ts.map +1 -1
- package/lib/plans.js +38 -57
- package/lib/plans.js.map +1 -1
- package/lib/protocol.d.ts +17 -43
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +44 -114
- package/lib/protocol.js.map +1 -1
- package/lib/snapshot-url.d.ts +14 -0
- package/lib/snapshot-url.d.ts.map +1 -0
- package/lib/snapshot-url.js +26 -0
- package/lib/snapshot-url.js.map +1 -0
- package/lib/snapshot-url.spec.d.ts +7 -0
- package/lib/snapshot-url.spec.d.ts.map +1 -0
- package/lib/snapshot-url.spec.js +41 -0
- package/lib/snapshot-url.spec.js.map +1 -0
- package/lib/team-subscription-protocol.js +13 -13
- package/lib/team-subscription-protocol.js.map +1 -1
- package/lib/teams-projects-protocol.d.ts +26 -4
- package/lib/teams-projects-protocol.d.ts.map +1 -1
- package/lib/teams-projects-protocol.js +11 -15
- package/lib/teams-projects-protocol.js.map +1 -1
- package/lib/util/analytics.d.ts.map +1 -1
- package/lib/util/analytics.js +35 -26
- package/lib/util/analytics.js.map +1 -1
- package/lib/util/async-iterator.js +55 -133
- package/lib/util/async-iterator.js.map +1 -1
- package/lib/util/cancelable.js +17 -59
- package/lib/util/cancelable.js.map +1 -1
- package/lib/util/date-time.js +8 -8
- package/lib/util/date-time.js.map +1 -1
- package/lib/util/deferred.js +10 -12
- package/lib/util/deferred.js.map +1 -1
- package/lib/util/disposable.js +26 -39
- package/lib/util/disposable.js.map +1 -1
- package/lib/util/event.js +58 -74
- package/lib/util/event.js.map +1 -1
- package/lib/util/garbage-collected-cache.d.ts +1 -0
- package/lib/util/garbage-collected-cache.d.ts.map +1 -1
- package/lib/util/garbage-collected-cache.js +26 -46
- package/lib/util/garbage-collected-cache.js.map +1 -1
- package/lib/util/generate-workspace-id.d.ts +1 -1
- package/lib/util/generate-workspace-id.d.ts.map +1 -1
- package/lib/util/generate-workspace-id.js +29 -68
- package/lib/util/generate-workspace-id.js.map +1 -1
- package/lib/util/generate-workspace-id.spec.js +57 -78
- package/lib/util/generate-workspace-id.spec.js.map +1 -1
- package/lib/util/gitpod-cookie.d.ts +20 -0
- package/lib/util/gitpod-cookie.d.ts.map +1 -0
- package/lib/util/gitpod-cookie.js +44 -0
- package/lib/util/gitpod-cookie.js.map +1 -0
- package/lib/util/gitpod-host-url.d.ts +1 -1
- package/lib/util/gitpod-host-url.d.ts.map +1 -1
- package/lib/util/gitpod-host-url.js +93 -103
- package/lib/util/gitpod-host-url.js.map +1 -1
- package/lib/util/gitpod-host-url.spec.js +87 -135
- package/lib/util/gitpod-host-url.spec.js.map +1 -1
- package/lib/util/grpc.d.ts +15 -0
- package/lib/util/grpc.d.ts.map +1 -0
- package/lib/util/grpc.js +18 -0
- package/lib/util/grpc.js.map +1 -0
- package/lib/util/jaeger-client-types.d.ts +68 -0
- package/lib/util/jaeger-client-types.d.ts.map +1 -0
- package/lib/util/jaeger-client-types.js +8 -0
- package/lib/util/jaeger-client-types.js.map +1 -0
- package/lib/util/logging.d.ts +49 -33
- package/lib/util/logging.d.ts.map +1 -1
- package/lib/util/logging.js +107 -110
- package/lib/util/logging.js.map +1 -1
- package/lib/util/make-link.js +2 -2
- package/lib/util/make-link.js.map +1 -1
- package/lib/util/parse-workspace-id.d.ts +10 -0
- package/lib/util/parse-workspace-id.d.ts.map +1 -1
- package/lib/util/parse-workspace-id.js +31 -7
- package/lib/util/parse-workspace-id.js.map +1 -1
- package/lib/util/parse-workspace-id.spec.d.ts +4 -0
- package/lib/util/parse-workspace-id.spec.d.ts.map +1 -1
- package/lib/util/parse-workspace-id.spec.js +123 -84
- package/lib/util/parse-workspace-id.spec.js.map +1 -1
- package/lib/util/queue.js +16 -55
- package/lib/util/queue.js.map +1 -1
- package/lib/util/queue.spec.js +144 -288
- package/lib/util/queue.spec.js.map +1 -1
- package/lib/util/repeat.d.ts +15 -0
- package/lib/util/repeat.d.ts.map +1 -0
- package/lib/util/repeat.js +55 -0
- package/lib/util/repeat.js.map +1 -0
- package/lib/util/safe-promise.js +9 -12
- package/lib/util/safe-promise.js.map +1 -1
- package/lib/util/semaphore.js +15 -46
- package/lib/util/semaphore.js.map +1 -1
- package/lib/util/skip-if.js +6 -6
- package/lib/util/skip-if.js.map +1 -1
- package/lib/util/timeutil.js +16 -16
- package/lib/util/timeutil.js.map +1 -1
- package/lib/util/timeutil.spec.js +21 -24
- package/lib/util/timeutil.spec.js.map +1 -1
- package/lib/util/tracing.d.ts +51 -5
- package/lib/util/tracing.d.ts.map +1 -1
- package/lib/util/tracing.js +193 -62
- package/lib/util/tracing.js.map +1 -1
- package/lib/util/tracing.spec.d.ts +7 -0
- package/lib/util/tracing.spec.d.ts.map +1 -0
- package/lib/util/tracing.spec.js +121 -0
- package/lib/util/tracing.spec.js.map +1 -0
- package/lib/util/workspace-port-authentication.js +2 -2
- package/lib/util/workspace-port-authentication.js.map +1 -1
- package/lib/workspace-cluster.d.ts +11 -1
- package/lib/workspace-cluster.d.ts.map +1 -1
- package/lib/workspace-cluster.js +3 -3
- package/lib/workspace-cluster.js.map +1 -1
- package/lib/workspace-instance.d.ts +4 -2
- package/lib/workspace-instance.d.ts.map +1 -1
- package/lib/wsready.js +1 -1
- package/package.json +24 -13
- package/pkg-yarn.lock +14 -7
- package/provenance-bundle.jsonl +2 -0
- package/src/accounting-protocol.ts +1 -3
- package/src/admin-protocol.ts +9 -3
- package/src/analytics.ts +16 -1
- package/src/email-protocol.ts +1 -1
- package/src/env.ts +10 -9
- package/src/gitpod-service.ts +53 -14
- package/src/ide-protocol.ts +92 -0
- package/src/index.ts +2 -0
- package/src/messaging/browser/connection.ts +176 -10
- package/src/messaging/client-call-metrics.ts +97 -0
- package/src/messaging/error.ts +2 -2
- package/src/messaging/handler.ts +12 -0
- package/src/messaging/node/connection.ts +3 -47
- package/src/messaging/proxy-factory.ts +13 -5
- package/src/oss-allowlist.ts +15 -0
- package/src/permission.ts +0 -1
- package/src/protocol.ts +21 -46
- package/src/snapshot-url.spec.ts +25 -0
- package/src/snapshot-url.ts +27 -0
- package/src/team-subscription-protocol.ts +1 -1
- package/src/teams-projects-protocol.ts +37 -5
- package/src/util/analytics.ts +17 -1
- package/src/util/garbage-collected-cache.ts +7 -1
- package/src/util/generate-workspace-id.spec.ts +17 -0
- package/src/util/generate-workspace-id.ts +20 -2
- package/src/util/gitpod-cookie.ts +39 -0
- package/src/util/gitpod-host-url.ts +10 -10
- package/src/util/grpc.ts +15 -0
- package/src/util/jaeger-client-types.ts +102 -0
- package/src/util/logging.ts +102 -38
- package/src/util/parse-workspace-id.spec.ts +21 -1
- package/src/util/parse-workspace-id.ts +32 -6
- package/src/util/repeat.ts +45 -0
- package/src/util/tracing.spec.ts +83 -0
- package/src/util/tracing.ts +180 -18
- package/src/workspace-cluster.ts +8 -1
- package/src/workspace-instance.ts +12 -6
- package/src/wsready.ts +1 -1
- package/lib/util/repeater.d.ts +0 -22
- package/lib/util/repeater.d.ts.map +0 -1
- package/lib/util/repeater.js +0 -118
- package/lib/util/repeater.js.map +0 -1
- package/src/util/jaeger-client.d.ts +0 -105
- package/src/util/repeater.ts +0 -49
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2021 Gitpod GmbH. All rights reserved.
|
|
3
|
+
* Licensed under the GNU Affero General Public License (AGPL).
|
|
4
|
+
* See License-AGPL.txt in the project root for license information.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* `IDEServer` provides a list of available IDEs.
|
|
9
|
+
*/
|
|
10
|
+
export interface IDEServer {
|
|
11
|
+
/**
|
|
12
|
+
* Returns the IDE preferences.
|
|
13
|
+
*/
|
|
14
|
+
getIDEOptions(): Promise<IDEOptions>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface IDEOptions {
|
|
18
|
+
/**
|
|
19
|
+
* A list of available IDEs.
|
|
20
|
+
*/
|
|
21
|
+
options: { [key: string]: IDEOption };
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The default (browser) IDE when the user has not specified one.
|
|
25
|
+
*/
|
|
26
|
+
defaultIde: string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The default desktop IDE when the user has not specified one.
|
|
30
|
+
*/
|
|
31
|
+
defaultDesktopIde: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface IDEOption {
|
|
35
|
+
/**
|
|
36
|
+
* To ensure a stable order one can set an `orderKey`.
|
|
37
|
+
*/
|
|
38
|
+
orderKey?: string;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Human readable title text of the IDE (plain text only).
|
|
42
|
+
*/
|
|
43
|
+
title: string;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The type of the IDE, currently 'browser' or 'desktop'.
|
|
47
|
+
*/
|
|
48
|
+
type: 'browser' | 'desktop';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The logo for the IDE. That could be a key in (see
|
|
52
|
+
* components/dashboard/src/images/ideLogos.ts) or a URL.
|
|
53
|
+
*/
|
|
54
|
+
logo: string;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Text of an optional tooltip (plain text only).
|
|
58
|
+
*/
|
|
59
|
+
tooltip?: string;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Text of an optional label next to the IDE option like “Insiders” (plain
|
|
63
|
+
* text only).
|
|
64
|
+
*/
|
|
65
|
+
label?: string;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Notes to the IDE option that are renderd in the preferences when a user
|
|
69
|
+
* chooses this IDE.
|
|
70
|
+
*/
|
|
71
|
+
notes?: string[];
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* If `true` this IDE option is not visible in the IDE preferences.
|
|
75
|
+
*/
|
|
76
|
+
hidden?: boolean;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The image ref to the IDE image.
|
|
80
|
+
*/
|
|
81
|
+
image: string;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* When this is `true`, the tag of this image is resolved to the latest
|
|
85
|
+
* image digest regularly.
|
|
86
|
+
*
|
|
87
|
+
* This is useful if this image points to a tag like `nightly` that will be
|
|
88
|
+
* updated regularly. When `resolveImageDigest` is `true`, we make sure that
|
|
89
|
+
* we resolve the tag regularly to the most recent image version.
|
|
90
|
+
*/
|
|
91
|
+
resolveImageDigest?: boolean;
|
|
92
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -5,10 +5,13 @@
|
|
|
5
5
|
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { Logger, ConsoleLogger, toSocket, IWebSocket } from "vscode-ws-jsonrpc";
|
|
9
|
+
import { createMessageConnection } from "vscode-jsonrpc";
|
|
10
|
+
import { AbstractMessageWriter } from "vscode-jsonrpc/lib/messageWriter";
|
|
11
|
+
import { AbstractMessageReader } from "vscode-jsonrpc/lib/messageReader";
|
|
9
12
|
import { JsonRpcProxyFactory, JsonRpcProxy } from "../proxy-factory";
|
|
10
|
-
import { ConnectionHandler } from "../handler";
|
|
11
|
-
import ReconnectingWebSocket from 'reconnecting-websocket';
|
|
13
|
+
import { ConnectionEventHandler, ConnectionHandler } from "../handler";
|
|
14
|
+
import ReconnectingWebSocket, { Event } from 'reconnecting-websocket';
|
|
12
15
|
|
|
13
16
|
export interface WebSocketOptions {
|
|
14
17
|
onerror?: (event: Event) => void;
|
|
@@ -29,7 +32,10 @@ export class WebSocketConnectionProvider {
|
|
|
29
32
|
const startListening = (path: string) => {
|
|
30
33
|
const socket = this.listen({
|
|
31
34
|
path,
|
|
32
|
-
onConnection: c => factory.listen(c)
|
|
35
|
+
onConnection: c => factory.listen(c),
|
|
36
|
+
}, {
|
|
37
|
+
onTransportDidClose: () => factory.fireConnectionClosed(),
|
|
38
|
+
onTransportDidOpen: () => factory.fireConnectionOpened(),
|
|
33
39
|
},
|
|
34
40
|
options
|
|
35
41
|
);
|
|
@@ -49,7 +55,7 @@ export class WebSocketConnectionProvider {
|
|
|
49
55
|
/**
|
|
50
56
|
* Install a connection handler for the given path.
|
|
51
57
|
*/
|
|
52
|
-
listen(handler: ConnectionHandler, options?: WebSocketOptions): WebSocket {
|
|
58
|
+
listen(handler: ConnectionHandler, eventHandler: ConnectionEventHandler, options?: WebSocketOptions): WebSocket {
|
|
53
59
|
const url = handler.path;
|
|
54
60
|
const webSocket = this.createWebSocket(url);
|
|
55
61
|
|
|
@@ -64,11 +70,12 @@ export class WebSocketConnectionProvider {
|
|
|
64
70
|
logger.error(JSON.stringify(error));
|
|
65
71
|
});
|
|
66
72
|
}
|
|
67
|
-
doListen(
|
|
68
|
-
webSocket,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
doListen(
|
|
74
|
+
webSocket as any as ReconnectingWebSocket,
|
|
75
|
+
handler,
|
|
76
|
+
eventHandler,
|
|
77
|
+
logger,
|
|
78
|
+
);
|
|
72
79
|
return webSocket;
|
|
73
80
|
}
|
|
74
81
|
|
|
@@ -91,3 +98,162 @@ export class WebSocketConnectionProvider {
|
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
}
|
|
101
|
+
|
|
102
|
+
// The following was extracted from vscode-ws-jsonrpc to make these changes:
|
|
103
|
+
// - switch from WebSocket to ReconnectingWebSocket
|
|
104
|
+
// - webSocket.onopen: making sure it's only ever called once so we're re-using MessageConnection
|
|
105
|
+
// - WebSocketMessageWriter: buffer and re-try messages instead of throwing an error immidiately
|
|
106
|
+
// - WebSocketMessageReader: don't close MessageConnection on 'socket.onclose'
|
|
107
|
+
function doListen(resocket: ReconnectingWebSocket, handler: ConnectionHandler, eventHandler: ConnectionEventHandler, logger: Logger) {
|
|
108
|
+
resocket.addEventListener("close", () => eventHandler.onTransportDidClose());
|
|
109
|
+
|
|
110
|
+
let alreadyOpened = false;
|
|
111
|
+
resocket.onopen = () => {
|
|
112
|
+
// trigerr "open" every time we re-open the underlying websocket
|
|
113
|
+
eventHandler.onTransportDidOpen();
|
|
114
|
+
|
|
115
|
+
// make sure we're only ever creating one MessageConnection, irregardless of how many times we have to re-open the underlying (reconnecting) websocket
|
|
116
|
+
if (alreadyOpened) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
alreadyOpened = true;
|
|
120
|
+
|
|
121
|
+
const connection = createWebSocketConnection(resocket, logger);
|
|
122
|
+
handler.onConnection(connection);
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function createWebSocketConnection(resocket: ReconnectingWebSocket, logger: Logger) {
|
|
127
|
+
const socket = toSocket(resocket as any);
|
|
128
|
+
const messageReader = new NonClosingWebSocketMessageReader(socket);
|
|
129
|
+
const messageWriter = new BufferingWebSocketMessageWriter(resocket, logger);
|
|
130
|
+
const connection = createMessageConnection(messageReader, messageWriter, logger);
|
|
131
|
+
connection.onClose(() => connection.dispose());
|
|
132
|
+
return connection;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* This takes vscode-ws-jsonrpc/lib/socket/writer/WebSocketMessageWriter and adds a buffer
|
|
137
|
+
*/
|
|
138
|
+
class BufferingWebSocketMessageWriter extends AbstractMessageWriter {
|
|
139
|
+
protected readonly socket: ReconnectingWebSocket;
|
|
140
|
+
protected readonly logger: Logger;
|
|
141
|
+
protected errorCount: number = 0;
|
|
142
|
+
|
|
143
|
+
protected buffer: any[] = [];
|
|
144
|
+
|
|
145
|
+
constructor(socket: ReconnectingWebSocket, logger: Logger) {
|
|
146
|
+
super();
|
|
147
|
+
this.socket = socket;
|
|
148
|
+
this.logger = logger;
|
|
149
|
+
|
|
150
|
+
socket.addEventListener("open", (event: Event) => this.flushBuffer());
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
write(msg: any) {
|
|
154
|
+
if (this.socket.readyState !== ReconnectingWebSocket.OPEN) {
|
|
155
|
+
this.bufferMsg(msg);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
const content = JSON.stringify(msg);
|
|
161
|
+
this.socket.send(content);
|
|
162
|
+
} catch (e) {
|
|
163
|
+
this.errorCount++;
|
|
164
|
+
this.fireError(e, msg, this.errorCount);
|
|
165
|
+
|
|
166
|
+
this.bufferMsg(msg);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
protected flushBuffer() {
|
|
171
|
+
if (this.buffer.length === 0) {
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const buffer = [...this.buffer];
|
|
176
|
+
this.buffer = [];
|
|
177
|
+
for (const msg of buffer) {
|
|
178
|
+
this.write(msg);
|
|
179
|
+
}
|
|
180
|
+
//this.logger.info(`flushed buffer (${this.buffer.length})`)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
protected bufferMsg(msg: any) {
|
|
184
|
+
this.buffer.push(msg);
|
|
185
|
+
//this.logger.info(`buffered message (${this.buffer.length})`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* This takes vscode-ws-jsonrpc/lib/socket/reader/WebSocketMessageReader and removes the "onClose -> fireClose" connection
|
|
192
|
+
*/
|
|
193
|
+
class NonClosingWebSocketMessageReader extends AbstractMessageReader {
|
|
194
|
+
protected readonly socket: IWebSocket;
|
|
195
|
+
protected readonly events: any[] = [];
|
|
196
|
+
protected state: 'initial' | 'listening' | 'closed' = 'initial';
|
|
197
|
+
protected callback: (message: any) => void = () => {};
|
|
198
|
+
|
|
199
|
+
constructor(socket: IWebSocket) {
|
|
200
|
+
super();
|
|
201
|
+
this.socket = socket;
|
|
202
|
+
this.socket.onMessage(message => this.readMessage(message));
|
|
203
|
+
this.socket.onError(error => this.fireError(error));
|
|
204
|
+
this.socket.onClose((code, reason) => {
|
|
205
|
+
if (code !== 1000) {
|
|
206
|
+
const error = {
|
|
207
|
+
name: '' + code,
|
|
208
|
+
message: `Error during socket reconnect: code = ${code}, reason = ${reason}`
|
|
209
|
+
};
|
|
210
|
+
this.fireError(error);
|
|
211
|
+
}
|
|
212
|
+
// this.fireClose(); // <-- reason for this class to be copied over
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
listen(callback: (message: any) => void) {
|
|
216
|
+
if (this.state === 'initial') {
|
|
217
|
+
this.state = 'listening';
|
|
218
|
+
this.callback = callback;
|
|
219
|
+
while (this.events.length !== 0) {
|
|
220
|
+
const event = this.events.pop();
|
|
221
|
+
if (event.message) {
|
|
222
|
+
this.readMessage(event.message);
|
|
223
|
+
}
|
|
224
|
+
else if (event.error) {
|
|
225
|
+
this.fireError(event.error);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
this.fireClose();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
readMessage(message: any) {
|
|
234
|
+
if (this.state === 'initial') {
|
|
235
|
+
this.events.splice(0, 0, { message });
|
|
236
|
+
}
|
|
237
|
+
else if (this.state === 'listening') {
|
|
238
|
+
const data = JSON.parse(message);
|
|
239
|
+
this.callback(data);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
fireError(error: any) {
|
|
243
|
+
if (this.state === 'initial') {
|
|
244
|
+
this.events.splice(0, 0, { error });
|
|
245
|
+
}
|
|
246
|
+
else if (this.state === 'listening') {
|
|
247
|
+
super.fireError(error);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
fireClose() {
|
|
251
|
+
if (this.state === 'initial') {
|
|
252
|
+
this.events.splice(0, 0, {});
|
|
253
|
+
}
|
|
254
|
+
else if (this.state === 'listening') {
|
|
255
|
+
super.fireClose();
|
|
256
|
+
}
|
|
257
|
+
this.state = 'closed';
|
|
258
|
+
}
|
|
259
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2021 Gitpod GmbH. All rights reserved.
|
|
3
|
+
* Licensed under the GNU Affero General Public License (AGPL).
|
|
4
|
+
* See License-AGPL.txt in the project root for license information.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { injectable } from 'inversify';
|
|
8
|
+
import * as prometheusClient from 'prom-client';
|
|
9
|
+
|
|
10
|
+
type GrpcMethodType = 'unary' | 'client_stream' | 'server_stream' | 'bidi_stream';
|
|
11
|
+
export interface IGrpcCallMetricsLabels {
|
|
12
|
+
service: string,
|
|
13
|
+
method: string,
|
|
14
|
+
type: GrpcMethodType,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface IGrpcCallMetricsLabelsWithCode extends IGrpcCallMetricsLabels {
|
|
18
|
+
code: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const IClientCallMetrics = Symbol("IClientCallMetrics");
|
|
22
|
+
|
|
23
|
+
export interface IClientCallMetrics {
|
|
24
|
+
started(labels: IGrpcCallMetricsLabels) : void;
|
|
25
|
+
sent(labels: IGrpcCallMetricsLabels) : void;
|
|
26
|
+
received(labels: IGrpcCallMetricsLabels) : void;
|
|
27
|
+
handled(labels: IGrpcCallMetricsLabelsWithCode) : void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@injectable()
|
|
31
|
+
export class PrometheusClientCallMetrics implements IClientCallMetrics {
|
|
32
|
+
|
|
33
|
+
readonly startedCounter: prometheusClient.Counter<string>;
|
|
34
|
+
readonly sentCounter: prometheusClient.Counter<string>;
|
|
35
|
+
readonly receivedCounter: prometheusClient.Counter<string>;
|
|
36
|
+
readonly handledCounter: prometheusClient.Counter<string>;
|
|
37
|
+
|
|
38
|
+
constructor() {
|
|
39
|
+
this.startedCounter = new prometheusClient.Counter({
|
|
40
|
+
name: 'grpc_client_started_total',
|
|
41
|
+
help: 'Total number of RPCs started on the client.',
|
|
42
|
+
labelNames: ['grpc_service', 'grpc_method', 'grpc_type'],
|
|
43
|
+
registers: [prometheusClient.register]
|
|
44
|
+
});
|
|
45
|
+
this.sentCounter = new prometheusClient.Counter({
|
|
46
|
+
name: 'grpc_client_msg_sent_total',
|
|
47
|
+
help: ' Total number of gRPC stream messages sent by the client.',
|
|
48
|
+
labelNames: ['grpc_service', 'grpc_method', 'grpc_type'],
|
|
49
|
+
registers: [prometheusClient.register]
|
|
50
|
+
});
|
|
51
|
+
this.receivedCounter = new prometheusClient.Counter({
|
|
52
|
+
name: 'grpc_client_msg_received_total',
|
|
53
|
+
help: 'Total number of RPC stream messages received by the client.',
|
|
54
|
+
labelNames: ['grpc_service', 'grpc_method', 'grpc_type'],
|
|
55
|
+
registers: [prometheusClient.register]
|
|
56
|
+
});
|
|
57
|
+
this.handledCounter = new prometheusClient.Counter({
|
|
58
|
+
name: 'grpc_client_handled_total',
|
|
59
|
+
help: 'Total number of RPCs completed by the client, regardless of success or failure.',
|
|
60
|
+
labelNames: ['grpc_service', 'grpc_method', 'grpc_type', 'grpc_code'],
|
|
61
|
+
registers: [prometheusClient.register]
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
started(labels: IGrpcCallMetricsLabels): void {
|
|
66
|
+
this.startedCounter.inc({
|
|
67
|
+
grpc_service: labels.service,
|
|
68
|
+
grpc_method: labels.method,
|
|
69
|
+
grpc_type: labels.type
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
sent(labels: IGrpcCallMetricsLabels): void {
|
|
74
|
+
this.sentCounter.inc({
|
|
75
|
+
grpc_service: labels.service,
|
|
76
|
+
grpc_method: labels.method,
|
|
77
|
+
grpc_type: labels.type
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
received(labels: IGrpcCallMetricsLabels): void {
|
|
82
|
+
this.receivedCounter.inc({
|
|
83
|
+
grpc_service: labels.service,
|
|
84
|
+
grpc_method: labels.method,
|
|
85
|
+
grpc_type: labels.type
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
handled(labels: IGrpcCallMetricsLabelsWithCode): void {
|
|
90
|
+
this.handledCounter.inc({
|
|
91
|
+
grpc_service: labels.service,
|
|
92
|
+
grpc_method: labels.method,
|
|
93
|
+
grpc_type: labels.type,
|
|
94
|
+
grpc_code: labels.code
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
package/src/messaging/error.ts
CHANGED
|
@@ -76,6 +76,6 @@ export namespace ErrorCodes {
|
|
|
76
76
|
// 620 Team Subscription Assignment Failed
|
|
77
77
|
export const TEAM_SUBSCRIPTION_ASSIGNMENT_FAILED = 620;
|
|
78
78
|
|
|
79
|
-
//
|
|
80
|
-
export const
|
|
79
|
+
// 630 Snapshot Error
|
|
80
|
+
export const SNAPSHOT_ERROR = 630;
|
|
81
81
|
}
|
package/src/messaging/handler.ts
CHANGED
|
@@ -13,3 +13,15 @@ export interface ConnectionHandler {
|
|
|
13
13
|
readonly path: string;
|
|
14
14
|
onConnection(connection: MessageConnection, session?: object): void;
|
|
15
15
|
}
|
|
16
|
+
|
|
17
|
+
export interface ConnectionEventHandler {
|
|
18
|
+
/**
|
|
19
|
+
* Called when the transport underpinning the connection got closed
|
|
20
|
+
*/
|
|
21
|
+
onTransportDidClose(): void;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Called when the transport underpinning the connection is (re-)opened
|
|
25
|
+
*/
|
|
26
|
+
onTransportDidOpen(): void;
|
|
27
|
+
}
|
|
@@ -7,71 +7,27 @@
|
|
|
7
7
|
|
|
8
8
|
import * as ws from "ws";
|
|
9
9
|
import * as http from "http";
|
|
10
|
-
import * as https from "https";
|
|
11
|
-
import * as url from "url";
|
|
12
10
|
import * as net from "net";
|
|
13
|
-
import {
|
|
14
|
-
import { createWebSocketConnection, IWebSocket } from "vscode-ws-jsonrpc";
|
|
11
|
+
import { IWebSocket } from "vscode-ws-jsonrpc";
|
|
15
12
|
import { log } from '../../util/logging';
|
|
16
13
|
|
|
17
|
-
export interface IServerOptions {
|
|
18
|
-
readonly server: http.Server | https.Server;
|
|
19
|
-
readonly path?: string;
|
|
20
|
-
matches?(request: http.IncomingMessage): boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function createServerWebSocketConnection(options: IServerOptions, onConnect: (connection: MessageConnection) => void): void {
|
|
24
|
-
openJsonRpcSocket(options, socket => {
|
|
25
|
-
onConnect(createWebSocketConnection(socket, console));
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function openJsonRpcSocket(options: IServerOptions, onOpen: (socket: IWebSocket) => void): void {
|
|
30
|
-
openSocket(options, socket => {
|
|
31
|
-
const webSocket = toIWebSocket(socket);
|
|
32
|
-
onOpen(webSocket);
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
14
|
export interface OnOpen {
|
|
37
15
|
(webSocket: ws, request: http.IncomingMessage, socket: net.Socket, head: Buffer): void;
|
|
38
16
|
}
|
|
39
17
|
|
|
40
|
-
export function openSocket(options: IServerOptions, onOpen: OnOpen): void {
|
|
41
|
-
const wss = new ws.Server({
|
|
42
|
-
noServer: true,
|
|
43
|
-
perMessageDeflate: {
|
|
44
|
-
// don't compress if a message is less than 256kb
|
|
45
|
-
threshold: 256 * 1024
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
options.server.on('upgrade', (request: http.IncomingMessage, socket: net.Socket, head: Buffer) => {
|
|
49
|
-
const pathname = request.url ? url.parse(request.url).pathname : undefined;
|
|
50
|
-
if (options.path && pathname === options.path || options.matches && options.matches(request)) {
|
|
51
|
-
wss.handleUpgrade(request, socket, head, webSocket => {
|
|
52
|
-
if (webSocket.readyState === webSocket.OPEN) {
|
|
53
|
-
onOpen(webSocket, request, socket, head);
|
|
54
|
-
} else {
|
|
55
|
-
webSocket.on('open', () => onOpen(webSocket, request, socket, head));
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
|
|
62
18
|
export function toIWebSocket(webSocket: ws) {
|
|
63
19
|
let sendsAfterOpen = 0;
|
|
64
20
|
return <IWebSocket>{
|
|
65
21
|
send: content => {
|
|
66
22
|
if (webSocket.readyState !== ws.OPEN) {
|
|
67
23
|
if (sendsAfterOpen++ > 3) {
|
|
68
|
-
log.
|
|
24
|
+
//log.debug(`Repeated try to send on closed web socket (readyState was ${webSocket.readyState})`, { ws });
|
|
69
25
|
}
|
|
70
26
|
return;
|
|
71
27
|
}
|
|
72
28
|
webSocket.send(content, err => {
|
|
73
29
|
if (err) {
|
|
74
|
-
log.error('
|
|
30
|
+
log.error('error in ws.send()', err, { ws });
|
|
75
31
|
}
|
|
76
32
|
})
|
|
77
33
|
},
|
|
@@ -105,13 +105,19 @@ export class JsonRpcProxyFactory<T extends object> implements ProxyHandler<T> {
|
|
|
105
105
|
this.connectionPromiseResolve = resolve
|
|
106
106
|
);
|
|
107
107
|
this.connectionPromise.then(connection => {
|
|
108
|
-
connection.onClose(() =>
|
|
109
|
-
|
|
110
|
-
);
|
|
111
|
-
this.onDidOpenConnectionEmitter.fire(undefined);
|
|
108
|
+
connection.onClose(() => this.fireConnectionClosed());
|
|
109
|
+
this.fireConnectionOpened();
|
|
112
110
|
});
|
|
113
111
|
}
|
|
114
112
|
|
|
113
|
+
fireConnectionClosed() {
|
|
114
|
+
this.onDidCloseConnectionEmitter.fire(undefined)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
fireConnectionOpened() {
|
|
118
|
+
this.onDidOpenConnectionEmitter.fire(undefined);
|
|
119
|
+
}
|
|
120
|
+
|
|
115
121
|
/**
|
|
116
122
|
* Connect a MessageConnection to the factory.
|
|
117
123
|
*
|
|
@@ -158,7 +164,9 @@ export class JsonRpcProxyFactory<T extends object> implements ProxyHandler<T> {
|
|
|
158
164
|
* methods calls.
|
|
159
165
|
*/
|
|
160
166
|
protected onNotification(method: string, ...args: any[]): void {
|
|
161
|
-
this.target[method]
|
|
167
|
+
if (this.target[method]) {
|
|
168
|
+
this.target[method](...args);
|
|
169
|
+
}
|
|
162
170
|
}
|
|
163
171
|
|
|
164
172
|
/**
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2021 Gitpod GmbH. All rights reserved.
|
|
3
|
+
* Licensed under the GNU Affero General Public License (AGPL).
|
|
4
|
+
* See License-AGPL.txt in the project root for license information.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface OssAllowList {
|
|
8
|
+
/**
|
|
9
|
+
* A string that identifies a GitHub/GitLab/Bitbucket identity of the form "<host>/<profilename>"
|
|
10
|
+
* E.g., "github.com/geropl"
|
|
11
|
+
*/
|
|
12
|
+
identity: string,
|
|
13
|
+
|
|
14
|
+
deleted?: boolean,
|
|
15
|
+
}
|
package/src/permission.ts
CHANGED
|
@@ -16,7 +16,6 @@ export const Permissions = {
|
|
|
16
16
|
"admin-api": undefined,
|
|
17
17
|
"ide-settings": undefined,
|
|
18
18
|
"new-workspace-cluster": undefined,
|
|
19
|
-
"teams-and-projects": undefined,
|
|
20
19
|
};
|
|
21
20
|
export type PermissionName = keyof (typeof Permissions);
|
|
22
21
|
export const Roles = {"devops": undefined, "viewer": undefined, "admin": undefined };
|