public async Task SendMultipleDataRemoteCommand() { using (MockWebSocket ws = new MockWebSocket()) using (StreamDemuxer demuxer = new StreamDemuxer(ws)) { List <byte> sentBuffer = new List <byte>(); ws.MessageSent += (sender, args) => { sentBuffer.AddRange(args.Data.Buffer); }; demuxer.Start(); byte channelIndex = 12; var stream = demuxer.GetStream(channelIndex, channelIndex); var b = GenerateRandomBuffer(100, 0xEF); stream.Write(b, 0, b.Length); b = GenerateRandomBuffer(200, 0xAB); stream.Write(b, 0, b.Length); // Send 300 bytes in 2 messages, expect 1 (channel index) * 2 + 300 (payload) = 302 bytes Assert.True( await WaitForAsync(() => sentBuffer.Count == 302).ConfigureAwait(false), $"Demuxer error: expect to send 302 bytes, but actually send {sentBuffer.Count} bytes."); Assert.True(sentBuffer[0] == channelIndex, "The first sent byte is not channel index!"); Assert.True(sentBuffer[1] == 0xEF, "The first part of payload incorrect!"); Assert.True(sentBuffer[101] == channelIndex, "The second message first byte is not channel index!"); Assert.True(sentBuffer[102] == 0xAB, "The second part of payload incorrect!"); } }
public async Task ReceiveDataPortForward() { using (MockWebSocket ws = new MockWebSocket()) using (StreamDemuxer demuxer = new StreamDemuxer(ws, StreamType.PortForward)) { demuxer.Start(); List <byte> receivedBuffer = new List <byte>(); byte channelIndex = 12; var stream = demuxer.GetStream(channelIndex, channelIndex); // Receive 600 bytes in 3 messages. Exclude 1 channel index byte per message, and 2 port bytes in the first message. // expect 600 - 3 - 2 = 595 bytes payload. int expectedCount = 595; var t = Task.Run(async() => { await ws.InvokeReceiveAsync( new ArraySegment <byte>(GenerateRandomBuffer(100, channelIndex, 0xB1, true)), WebSocketMessageType.Binary, true).ConfigureAwait(false); await ws.InvokeReceiveAsync( new ArraySegment <byte>(GenerateRandomBuffer(200, channelIndex, 0xB2, false)), WebSocketMessageType.Binary, true).ConfigureAwait(false); await ws.InvokeReceiveAsync( new ArraySegment <byte>(GenerateRandomBuffer(300, channelIndex, 0xB3, false)), WebSocketMessageType.Binary, true).ConfigureAwait(false); await WaitForAsync(() => receivedBuffer.Count == expectedCount).ConfigureAwait(false); await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "normal", CancellationToken.None).ConfigureAwait(false); }); var buffer = new byte[50]; while (true) { var cRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (cRead == 0) { break; } for (int i = 0; i < cRead; i++) { receivedBuffer.Add(buffer[i]); } } await t.ConfigureAwait(false); Assert.True( receivedBuffer.Count == expectedCount, $"Demuxer error: expect to receive {expectedCount} bytes, but actually got {receivedBuffer.Count} bytes."); Assert.True(receivedBuffer[0] == 0xB1, "The first payload incorrect!"); Assert.True(receivedBuffer[96] == 0xB1, "The first payload incorrect!"); Assert.True(receivedBuffer[97] == 0xB2, "The second payload incorrect!"); Assert.True(receivedBuffer[295] == 0xB2, "The second payload incorrect!"); Assert.True(receivedBuffer[296] == 0xB3, "The third payload incorrect!"); Assert.True(receivedBuffer[594] == 0xB3, "The third payload incorrect!"); } }
private async static Task Forward(IKubernetes client, V1Pod pod) { // Note this is single-threaded, it won't handle concurrent requests well... var webSocket = await client.WebSocketNamespacedPodPortForwardAsync(pod.Metadata.Name, "default", new int[] { 80 }, "v4.channel.k8s.io"); var demux = new StreamDemuxer(webSocket, StreamType.PortForward); demux.Start(); var stream = demux.GetStream((byte?)0, (byte?)0); IPAddress ipAddress = IPAddress.Loopback; IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 8080); Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); listener.Bind(localEndPoint); listener.Listen(100); Socket handler = null; // Note this will only accept a single connection var accept = Task.Run(() => { while (true) { handler = listener.Accept(); var bytes = new byte[4096]; while (true) { int bytesRec = handler.Receive(bytes); stream.Write(bytes, 0, bytesRec); if (bytesRec == 0 || Encoding.ASCII.GetString(bytes, 0, bytesRec).IndexOf("<EOF>") > -1) { break; } } } }); var copy = Task.Run(() => { var buff = new byte[4096]; while (true) { var read = stream.Read(buff, 0, 4096); handler.Send(buff, read, 0); } }); await accept; await copy; if (handler != null) { handler.Close(); } listener.Close(); }
/// <summary> /// Executes a command in a k8s pod. /// </summary> /// <param name="client"></param> /// <param name="pod"></param> /// <param name="namespace"></param> /// <param name="command"></param> /// <returns></returns> public async static Task <string> ExecInPod(IKubernetes client, V1Pod pod, string @namespace, string[] command) { var webSocket = await client.WebSocketNamespacedPodExecAsync(pod.Metadata.Name, @namespace, command, pod.Spec.Containers[0].Name); var demux = new StreamDemuxer(webSocket); demux.Start(); var buff = new byte[4096]; var stream = demux.GetStream(1, 1); var read = stream.Read(buff, 0, 4096); var str = System.Text.Encoding.Default.GetString(buff.Where(b => b != 0).ToArray()); return(str); }
private async static Task ExecInPod(IKubernetes client, V1Pod pod) { var webSocket = await client.WebSocketNamespacedPodExecAsync(pod.Metadata.Name, "default", "ls", pod.Spec.Containers[0].Name); var demux = new StreamDemuxer(webSocket); demux.Start(); var buff = new byte[4096]; var stream = demux.GetStream(1, 1); var read = stream.Read(buff, 0, 4096); var str = System.Text.Encoding.Default.GetString(buff); Console.WriteLine(str); }
/// <summary> /// Synchronously executes an arbitrary command in the first container of given pod. /// </summary> /// <param name="ops">Kubernetes client</param> /// <param name="pod">Kubernetes pod to execute command in</param> /// <param name="@namespace">Pod's namespace in cluster</param> /// <param name="commands">Shell commands to execute</param> /// <returns>Output of commands</returns> internal async static Task <string> ExecInPodAsync(IKubernetes ops, V1Pod pod, string @namespace, string[] commands) { var webSockTask = ops.WebSocketNamespacedPodExecAsync(pod.Metadata.Name, @namespace, commands, pod.Spec.Containers[0].Name, stderr: true, stdin: false, stdout: true, tty: false); using (var webSock = await webSockTask) using (var demux = new StreamDemuxer(webSock)) { demux.Start(); using (var demuxStream = demux.GetStream(1, 1)) using (StreamReader reader = new StreamReader(demuxStream)) return(await reader.ReadToEndAsync()); } }
public async Task ReceiveDataRemoteCommand() { using (MockWebSocket ws = new MockWebSocket()) { StreamDemuxer demuxer = new StreamDemuxer(ws); Task.Run(() => demuxer.Start()); List <byte> receivedBuffer = new List <byte>(); byte channelIndex = 12; var stream = demuxer.GetStream(channelIndex, channelIndex); // Receive 600 bytes in 3 messages. Exclude 1 channel index byte per message, expect 597 bytes payload. int expectedCount = 597; var t = Task.Run(async() => { await ws.InvokeReceiveAsync(new ArraySegment <byte>(GenerateRandomBuffer(100, channelIndex, 0xAA, false)), WebSocketMessageType.Binary, true); await ws.InvokeReceiveAsync(new ArraySegment <byte>(GenerateRandomBuffer(200, channelIndex, 0xAB, false)), WebSocketMessageType.Binary, true); await ws.InvokeReceiveAsync(new ArraySegment <byte>(GenerateRandomBuffer(300, channelIndex, 0xAC, false)), WebSocketMessageType.Binary, true); await WaitForAsync(() => receivedBuffer.Count == expectedCount); await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "normal", CancellationToken.None); }); var buffer = new byte[50]; while (true) { var cRead = await stream.ReadAsync(buffer, 0, buffer.Length); if (cRead == 0) { break; } for (int i = 0; i < cRead; i++) { receivedBuffer.Add(buffer[i]); } } await t; Assert.True(receivedBuffer.Count == expectedCount, $"Demuxer error: expect to receive {expectedCount} bytes, but actually got {receivedBuffer.Count} bytes."); Assert.True(receivedBuffer[0] == 0xAA, "The first payload incorrect!"); Assert.True(receivedBuffer[98] == 0xAA, "The first payload incorrect!"); Assert.True(receivedBuffer[99] == 0xAB, "The second payload incorrect!"); Assert.True(receivedBuffer[297] == 0xAB, "The second payload incorrect!"); Assert.True(receivedBuffer[298] == 0xAC, "The third payload incorrect!"); Assert.True(receivedBuffer[596] == 0xAC, "The third payload incorrect!"); } }
public async Task SendDataRemoteCommand() { using (MockWebSocket ws = new MockWebSocket()) using (StreamDemuxer demuxer = new StreamDemuxer(ws)) { List <byte> sentBuffer = new List <byte>(); ws.MessageSent += (sender, args) => { sentBuffer.AddRange(args.Data.Buffer); }; demuxer.Start(); byte channelIndex = 12; var stream = demuxer.GetStream(channelIndex, channelIndex); var b = GenerateRandomBuffer(100, 0xEF); stream.Write(b, 0, b.Length); // Send 100 bytes, expect 1 (channel index) + 100 (payload) = 101 bytes Assert.True(await WaitForAsync(() => sentBuffer.Count == 101), $"Demuxer error: expect to send 101 bytes, but actually send {sentBuffer.Count} bytes."); Assert.True(sentBuffer[0] == channelIndex, "The first sent byte is not channel index!"); Assert.True(sentBuffer[1] == 0xEF, "Incorrect payload!"); } }
public async Task ReceiveDataPortForwardMultipleStream() { using (MockWebSocket ws = new MockWebSocket()) using (StreamDemuxer demuxer = new StreamDemuxer(ws, StreamType.PortForward)) { demuxer.Start(); List <byte> receivedBuffer1 = new List <byte>(); byte channelIndex1 = 1; var stream1 = demuxer.GetStream(channelIndex1, channelIndex1); List <byte> receivedBuffer2 = new List <byte>(); byte channelIndex2 = 2; var stream2 = demuxer.GetStream(channelIndex2, channelIndex2); // stream 1: receive 100 + 300 = 400 bytes, exclude 1 channel index per message, exclude port bytes in the first message, // expect 400 - 1 x 2 - 2 = 396 bytes. int expectedCount1 = 396; // stream 2: receive 200 bytes, exclude 1 channel index per message, exclude port bytes in the first message, // expect 200 - 1 - 2 = 197 bytes. int expectedCount2 = 197; var t1 = Task.Run(async() => { // Simulate WebSocket received remote data to multiple streams await ws.InvokeReceiveAsync( new ArraySegment <byte>(GenerateRandomBuffer(100, channelIndex1, 0xE1, true)), WebSocketMessageType.Binary, true).ConfigureAwait(false); await ws.InvokeReceiveAsync( new ArraySegment <byte>(GenerateRandomBuffer(200, channelIndex2, 0xE2, true)), WebSocketMessageType.Binary, true).ConfigureAwait(false); await ws.InvokeReceiveAsync( new ArraySegment <byte>(GenerateRandomBuffer(300, channelIndex1, 0xE3, false)), WebSocketMessageType.Binary, true).ConfigureAwait(false); await WaitForAsync(() => receivedBuffer1.Count == expectedCount1).ConfigureAwait(false); await WaitForAsync(() => receivedBuffer2.Count == expectedCount2).ConfigureAwait(false); await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "normal", CancellationToken.None).ConfigureAwait(false); }); var t2 = Task.Run(async() => { var buffer = new byte[50]; while (true) { var cRead = await stream1.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (cRead == 0) { break; } for (int i = 0; i < cRead; i++) { receivedBuffer1.Add(buffer[i]); } } }); var t3 = Task.Run(async() => { var buffer = new byte[50]; while (true) { var cRead = await stream2.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); if (cRead == 0) { break; } for (int i = 0; i < cRead; i++) { receivedBuffer2.Add(buffer[i]); } } }); await Task.WhenAll(t1, t2, t3).ConfigureAwait(false); Assert.True( receivedBuffer1.Count == expectedCount1, $"Demuxer error: expect to receive {expectedCount1} bytes, but actually got {receivedBuffer1.Count} bytes."); Assert.True( receivedBuffer2.Count == expectedCount2, $"Demuxer error: expect to receive {expectedCount2} bytes, but actually got {receivedBuffer2.Count} bytes."); Assert.True(receivedBuffer1[0] == 0xE1, "The first payload incorrect!"); Assert.True(receivedBuffer1[96] == 0xE1, "The first payload incorrect!"); Assert.True(receivedBuffer1[97] == 0xE3, "The second payload incorrect!"); Assert.True(receivedBuffer1[395] == 0xE3, "The second payload incorrect!"); Assert.True(receivedBuffer2[0] == 0xE2, "The first payload incorrect!"); Assert.True(receivedBuffer2[196] == 0xE2, "The first payload incorrect!"); } }
static async Task Main(string[] args) { if (AnsiConsole.Capabilities.SupportLinks) { AnsiConsole.MarkupLine( $"[link=https://github.com/bovrhovn/]Demo for working with Kubernetes[/]!"); } HorizontalRule("Connecting to cluster using default load via .kube/config and list namespaces"); var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); IKubernetes client = new Kubernetes(config); System.Console.WriteLine($"Listening to master at {config.Host}"); var namespaces = await client.ListNamespaceAsync(); foreach (var ns in namespaces.Items) { System.Console.WriteLine($"{ns.Metadata.Uid} : {ns.Metadata.Name}"); } System.Console.Read(); //break for continue HorizontalRule("List pods in namespace - app"); var listPodInNamespace = await client.ListNamespacedPodAsync("app"); var table = new Table(); table.Border(TableBorder.Rounded); table.AddColumn("Pod name"); table.AddColumn(new TableColumn("Labels").Centered()); foreach (var currentPod in listPodInNamespace.Items) { string labels = string.Empty; foreach (var labelPair in currentPod.Metadata.Labels) { labels += $" {labelPair.Key}:{labelPair.Value} "; } table.AddRow(currentPod.Metadata.Name, labels); } AnsiConsole.Render(table); System.Console.Read(); //break for continue HorizontalRule("Creating namespace and pod"); var namespaceNameForTest = "test"; var newNamespace = new V1Namespace { Metadata = new V1ObjectMeta { Name = namespaceNameForTest } }; var resultNamespaceCreated = await client.CreateNamespaceAsync(newNamespace); System.Console.WriteLine( $"Namespace {resultNamespaceCreated.Metadata.Name} has been created and it is in {resultNamespaceCreated.Status.Phase} state"); var pod = new V1Pod { Metadata = new V1ObjectMeta { Name = "nginx-test" }, Spec = new V1PodSpec { Containers = new List <V1Container> { new V1Container { Image = "nginx:1.7.9", Name = "image-nginx-test", Ports = new List <V1ContainerPort> { new V1ContainerPort { ContainerPort = 80 } } } } } }; var createdPodInNamespaceTest = await client.CreateNamespacedPodAsync(pod, namespaceNameForTest); System.Console.WriteLine($"Pod in namespace {namespaceNameForTest} has been created with state {createdPodInNamespaceTest.Status.Phase}"); System.Console.Read(); //break for continue HorizontalRule("Exec into pod"); var webSocket = await client.WebSocketNamespacedPodExecAsync(pod.Metadata.Name, namespaceNameForTest, "env", pod.Spec.Containers[0].Name); var demux = new StreamDemuxer(webSocket); demux.Start(); var buff = new byte[4096]; var stream = demux.GetStream(1, 1); await stream.ReadAsync(buff, 0, 4096); var str = System.Text.Encoding.Default.GetString(buff); System.Console.WriteLine(str); //ouput ls command System.Console.Read(); //break for continue HorizontalRule($"Delete namespace {namespaceNameForTest}"); var status = await client.DeleteNamespaceAsync(namespaceNameForTest, new V1DeleteOptions()); System.Console.WriteLine($"Namespace {namespaceNameForTest} has been deleted - status {status.Message} - {status.Status}"); System.Console.Read(); //break for continue HorizontalRule("Load objects from yaml file"); var typeMap = new Dictionary <string, Type> { { "v1/Pod", typeof(V1Pod) }, { "v1/Service", typeof(V1Service) }, { "apps/v1/Deployment", typeof(V1Deployment) } }; string yamlPath = Path.Join(Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location), "my.yaml"); var objects = await Yaml.LoadAllFromFileAsync(yamlPath, typeMap); foreach (var obj in objects) { System.Console.WriteLine(obj); } System.Console.Read(); //stop and press key to continue HorizontalRule("Watching pods - watch pods"); var podlistResp = client.ListNamespacedPodWithHttpMessagesAsync("default", watch: true); using (podlistResp.Watch <V1Pod, V1PodList>((type, item) => { System.Console.WriteLine("==on watch event=="); System.Console.WriteLine(type); System.Console.WriteLine(item.Metadata.Name); System.Console.WriteLine("==on watch event=="); })) { System.Console.WriteLine("press ctrl + c to stop watching"); var ctrlc = new ManualResetEventSlim(false); System.Console.CancelKeyPress += (sender, eventArgs) => ctrlc.Set(); ctrlc.Wait(); } System.Console.Read(); //press any key to continue }