From 71087c68beded72363e5845f9b03a8751a9ab6dc Mon Sep 17 00:00:00 2001 From: Djordje Lukic Date: Fri, 5 Jun 2020 16:29:08 +0200 Subject: [PATCH] Add exec.ts for an example of exec over gRPC --- server/proxy/streams_test.go | 3 +- server/proxy/streamwriter.go | 23 --------- tests/node-client/build.sh | 8 +++- tests/node-client/exec.ts | 85 ++++++++++++++++++++++++++++++++++ tests/node-client/package.json | 3 +- tests/node-client/types.d.ts | 1 + tests/node-client/yarn.lock | 5 ++ 7 files changed, 100 insertions(+), 28 deletions(-) delete mode 100644 server/proxy/streamwriter.go create mode 100644 tests/node-client/exec.ts create mode 100644 tests/node-client/types.d.ts diff --git a/server/proxy/streams_test.go b/server/proxy/streams_test.go index 2b5b2212..90c6ae5d 100644 --- a/server/proxy/streams_test.go +++ b/server/proxy/streams_test.go @@ -72,8 +72,7 @@ func getReader(t *testing.T, in []byte, errResult error) reader { } } -func getAny(t *testing.T, data []byte) *any.Any { - in := []byte{104, 101, 108, 108, 111} +func getAny(t *testing.T, in []byte) *any.Any { value, err := ptypes.MarshalAny(&streamsv1.BytesMessage{ Type: streamsv1.IOStream_STDOUT, Value: in, diff --git a/server/proxy/streamwriter.go b/server/proxy/streamwriter.go deleted file mode 100644 index 8cd9718c..00000000 --- a/server/proxy/streamwriter.go +++ /dev/null @@ -1,23 +0,0 @@ -package proxy - -import ( - "io" - - v1 "github.com/docker/api/protos/containers/v1" -) - -type streamWriter struct { - stream v1.Containers_LogsServer -} - -func newStreamWriter(stream v1.Containers_LogsServer) io.Writer { - return &streamWriter{ - stream: stream, - } -} - -func (w *streamWriter) Write(p []byte) (n int, err error) { - return len(p), w.stream.SendMsg(&v1.LogsResponse{ - Logs: p, - }) -} diff --git a/tests/node-client/build.sh b/tests/node-client/build.sh index 44b87408..66e80a56 100755 --- a/tests/node-client/build.sh +++ b/tests/node-client/build.sh @@ -3,8 +3,10 @@ node_modules/.bin/grpc_tools_node_protoc \ --grpc_out=generate_package_definition:./grpc \ -I ../../protos/contexts/v1 \ -I ../../protos/containers/v1 \ + -I ../../protos/streams/v1 \ ../../protos/contexts/v1/*.proto \ - ../../protos/containers/v1/*.proto + ../../protos/containers/v1/*.proto \ + ../../protos/streams/v1/*.proto # generate d.ts codes protoc \ @@ -12,5 +14,7 @@ protoc \ --ts_out=generate_package_definition:./grpc \ -I ../../protos/contexts/v1 \ -I ../../protos/containers/v1 \ + -I ../../protos/streams/v1 \ ../../protos/contexts/v1/*.proto \ - ../../protos/containers/v1/*.proto + ../../protos/containers/v1/*.proto \ + ../../protos/streams/v1/*.proto diff --git a/tests/node-client/exec.ts b/tests/node-client/exec.ts new file mode 100644 index 00000000..9e657f48 --- /dev/null +++ b/tests/node-client/exec.ts @@ -0,0 +1,85 @@ +import * as grpc from "@grpc/grpc-js"; +import * as readline from "readline"; +import * as google_protobuf_any_pb from "google-protobuf/google/protobuf/any_pb.js"; + +import * as continersPb from "./grpc/containers_grpc_pb"; +import { IContainersClient } from "./grpc/containers_grpc_pb"; +import { ExecRequest, ExecResponse, LogsRequest } from "./grpc/containers_pb"; + +import * as streamsPb from "./grpc/streams_grpc_pb"; +import { IStreamingClient } from "./grpc/streams_grpc_pb"; +import { BytesMessage } from "./grpc/streams_pb"; + +let address = process.argv[3] || "unix:///tmp/backend.sock"; + +const ContainersServiceClient = grpc.makeClientConstructor( + continersPb["com.docker.api.protos.containers.v1.Containers"], + "ContainersClient" +); + +const client = (new ContainersServiceClient( + address, + grpc.credentials.createInsecure() +) as unknown) as IContainersClient; + +const StreamsServiceClient = grpc.makeClientConstructor( + streamsPb["com.docker.api.protos.streams.v1.Streaming"], + "StreamsClient" +); + +let streamClient = (new StreamsServiceClient( + address, + grpc.credentials.createInsecure() +) as unknown) as IStreamingClient; + +let backend = process.argv[2] || "moby"; +let containerId = process.argv[3]; +const meta = new grpc.Metadata(); +meta.set("CONTEXT_KEY", backend); + +// Get the stream +const stream = streamClient.newStream(); + +stream.on("metadata", (m: grpc.Metadata) => { + let req = new ExecRequest(); + req.setCommand("/bin/bash"); + req.setStreamId(m.get("id")[0] as string); + req.setId(containerId); + req.setTty(true); + + client.exec(req, meta, (err: any, _: ExecResponse) => { + if (err != null) { + console.error(err); + return; + } + process.exit(); + }); +}); + +readline.emitKeypressEvents(process.stdin); +process.stdin.setRawMode(true); + +process.stdin.on("keypress", (str, key) => { + const mess = new BytesMessage(); + const a = new Uint8Array(key.sequence.length); + for (let i = 0; i <= key.sequence.length; i++) { + a[i] = key.sequence.charCodeAt(i); + } + + mess.setValue(a); + + const any = new google_protobuf_any_pb.Any(); + any.pack( + mess.serializeBinary(), + "type.googleapis.com/com.docker.api.protos.streams.v1.BytesMessage" + ); + stream.write(any); +}); + +stream.on("data", (chunk: any) => { + const m = chunk.unpack( + BytesMessage.deserializeBinary, + "com.docker.api.protos.streams.v1.BytesMessage" + ) as BytesMessage; + process.stdout.write(m.getValue()); +}); diff --git a/tests/node-client/package.json b/tests/node-client/package.json index 91f01166..0da3f59d 100644 --- a/tests/node-client/package.json +++ b/tests/node-client/package.json @@ -6,12 +6,13 @@ "scripts": { "start": "ts-node index.ts", "prestart": "./build.sh" - }, + }, "dependencies": { "@grpc/grpc-js": "^1.0.3", "grpc": "^1.24.2", "grpc-tools": "^1.8.1", "grpc_tools_node_protoc_ts": "^3.0.0", + "readline": "^1.3.0", "ts-node": "^8.9.1", "typescript": "^3.8.3" } diff --git a/tests/node-client/types.d.ts b/tests/node-client/types.d.ts new file mode 100644 index 00000000..bcf05fe0 --- /dev/null +++ b/tests/node-client/types.d.ts @@ -0,0 +1 @@ +declare module "google-protobuf/google/protobuf/any_pb.js"; diff --git a/tests/node-client/yarn.lock b/tests/node-client/yarn.lock index 467f9935..5f0ba9a4 100644 --- a/tests/node-client/yarn.lock +++ b/tests/node-client/yarn.lock @@ -1653,6 +1653,11 @@ readable-stream@^2.0.6, readable-stream@~2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readline@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" + integrity sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw= + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"