Add ChannelIndex enumeration, and some documentation (#142)
This commit is contained in:
committed by
Brendan Burns
parent
d90289a094
commit
1c07966d72
37
src/KubernetesClient/ChannelIndex.cs
Normal file
37
src/KubernetesClient/ChannelIndex.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
namespace k8s
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// These values identify the various channels which you can use when interacting with a process running in a container in a Kubernetes
|
||||||
|
/// pod.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso href="https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/server/remotecommand/websocket.go#L29"/>
|
||||||
|
public enum ChannelIndex : byte
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The standard input channel. Use this channel to send input to a process running in a container inside a Kubernetes pod.
|
||||||
|
/// </summary>
|
||||||
|
StdIn,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The standard output channel. Use this channel to read standard output generated by a process running in a container in a Kubernetes pod.
|
||||||
|
/// </summary>
|
||||||
|
StdOut,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The standard error channel. Use this channel to read the error output generated by a process running in a container in a Kubernetes pod.
|
||||||
|
/// </summary>
|
||||||
|
StdErr,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The error channel. This channel is used by Kubernetes to send you error messages, including the exit code of the process.
|
||||||
|
/// </summary>
|
||||||
|
Error,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The resize channel. Use this channel to resize the terminal. You need to send a JSON-formatted object over this channel, which
|
||||||
|
/// has a Width and Height property.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso href="https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/client-go/tools/remotecommand/resize.go"/>
|
||||||
|
Resize
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,12 +3,27 @@ using System.IO;
|
|||||||
|
|
||||||
namespace k8s
|
namespace k8s
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="Stream"/> which reads/writes from a specific channel using a <see cref="StreamDemuxer" />.
|
||||||
|
/// </summary>
|
||||||
public class MuxedStream : Stream
|
public class MuxedStream : Stream
|
||||||
{
|
{
|
||||||
private ByteBuffer inputBuffer;
|
private ByteBuffer inputBuffer;
|
||||||
private byte? outputIndex;
|
private byte? outputIndex;
|
||||||
private StreamDemuxer muxer;
|
private StreamDemuxer muxer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MuxedStream"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="muxer">
|
||||||
|
/// The <see cref="StreamDemuxer"/> to use to read from/write to the underlying stream.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="inputBuffer">
|
||||||
|
/// The <see cref="inputBuffer"/> to read from.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="outputIndex">
|
||||||
|
/// The index of the channel to which to write.
|
||||||
|
/// </param>
|
||||||
public MuxedStream(StreamDemuxer muxer, ByteBuffer inputBuffer, byte? outputIndex)
|
public MuxedStream(StreamDemuxer muxer, ByteBuffer inputBuffer, byte? outputIndex)
|
||||||
{
|
{
|
||||||
this.inputBuffer = inputBuffer;
|
this.inputBuffer = inputBuffer;
|
||||||
@@ -22,20 +37,26 @@ namespace k8s
|
|||||||
this.muxer = muxer ?? throw new ArgumentNullException(nameof(muxer));
|
this.muxer = muxer ?? throw new ArgumentNullException(nameof(muxer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override bool CanRead => this.inputBuffer != null;
|
public override bool CanRead => this.inputBuffer != null;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override bool CanSeek => false;
|
public override bool CanSeek => false;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override bool CanWrite => this.outputIndex != null;
|
public override bool CanWrite => this.outputIndex != null;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override long Length => throw new NotSupportedException();
|
public override long Length => throw new NotSupportedException();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override long Position
|
public override long Position
|
||||||
{
|
{
|
||||||
get => throw new NotSupportedException();
|
get => throw new NotSupportedException();
|
||||||
set => throw new NotSupportedException();
|
set => throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
if (this.outputIndex == null)
|
if (this.outputIndex == null)
|
||||||
@@ -48,6 +69,7 @@ namespace k8s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
if (this.inputBuffer == null)
|
if (this.inputBuffer == null)
|
||||||
@@ -60,16 +82,19 @@ namespace k8s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override void Flush()
|
public override void Flush()
|
||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public override void SetLength(long value)
|
public override void SetLength(long value)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
|
|||||||
@@ -9,6 +9,18 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace k8s
|
namespace k8s
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <para>
|
||||||
|
/// The <see cref="StreamDemuxer"/> allows you to interact with processes running in a container in a Kubernetes pod. You can start an exec or attach command
|
||||||
|
/// by calling <see cref="Kubernetes.WebSocketNamespacedPodExecAsync(string, string, IEnumerable{string}, string, bool, bool, bool, bool, Dictionary{string, List{string}}, CancellationToken)"/>
|
||||||
|
/// or <see cref="Kubernetes.WebSocketNamespacedPodAttachAsync(string, string, string, bool, bool, bool, bool, Dictionary{string, List{string}}, CancellationToken)"/>. These methods
|
||||||
|
/// will return you a <see cref="WebSocket"/> connection.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// Kubernetes 'multiplexes' multiple channels over this <see cref="WebSocket"/> connection, such as standard input, standard output and standard error. The <see cref="StreamDemuxer"/>
|
||||||
|
/// allows you to extract individual <see cref="Stream"/>s from this <see cref="WebSocket"/> class. You can then use these streams to send/receive data from that process.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
public class StreamDemuxer : IDisposable
|
public class StreamDemuxer : IDisposable
|
||||||
{
|
{
|
||||||
private readonly WebSocket webSocket;
|
private readonly WebSocket webSocket;
|
||||||
@@ -16,6 +28,12 @@ namespace k8s
|
|||||||
private readonly CancellationTokenSource cts = new CancellationTokenSource();
|
private readonly CancellationTokenSource cts = new CancellationTokenSource();
|
||||||
private Task runLoop;
|
private Task runLoop;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="StreamDemuxer"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="webSocket">
|
||||||
|
/// A <see cref="WebSocket"/> which contains a multiplexed stream, such as the <see cref="WebSocket"/> returned by the exec or attach commands.
|
||||||
|
/// </param>
|
||||||
public StreamDemuxer(WebSocket webSocket)
|
public StreamDemuxer(WebSocket webSocket)
|
||||||
{
|
{
|
||||||
this.webSocket = webSocket ?? throw new ArgumentNullException(nameof(webSocket));
|
this.webSocket = webSocket ?? throw new ArgumentNullException(nameof(webSocket));
|
||||||
@@ -23,11 +41,15 @@ namespace k8s
|
|||||||
|
|
||||||
public event EventHandler ConnectionClosed;
|
public event EventHandler ConnectionClosed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts reading the data sent by the server.
|
||||||
|
/// </summary>
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
this.runLoop = this.RunLoop(this.cts.Token);
|
this.runLoop = this.RunLoop(this.cts.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -45,6 +67,35 @@ namespace k8s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="Stream"/> which allows you to read to and/or write from a remote channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputIndex">
|
||||||
|
/// The index of the channel from which to read.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="outputIndex">
|
||||||
|
/// The index of the channel to which to write.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="Stream"/> which allows you to read/write to the requested channels.
|
||||||
|
/// </returns>
|
||||||
|
public Stream GetStream(ChannelIndex? inputIndex, ChannelIndex? outputIndex)
|
||||||
|
{
|
||||||
|
return GetStream((byte?)inputIndex, (byte?)outputIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="Stream"/> which allows you to read to and/or write from a remote channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputIndex">
|
||||||
|
/// The index of the channel from which to read.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="outputIndex">
|
||||||
|
/// The index of the channel to which to write.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="Stream"/> which allows you to read/write to the requested channels.
|
||||||
|
/// </returns>
|
||||||
public Stream GetStream(byte? inputIndex, byte? outputIndex)
|
public Stream GetStream(byte? inputIndex, byte? outputIndex)
|
||||||
{
|
{
|
||||||
if (inputIndex != null && !this.buffers.ContainsKey(inputIndex.Value))
|
if (inputIndex != null && !this.buffers.ContainsKey(inputIndex.Value))
|
||||||
@@ -60,6 +111,53 @@ namespace k8s
|
|||||||
return new MuxedStream(this, inputBuffer, outputIndex);
|
return new MuxedStream(this, inputBuffer, outputIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Directly writes data to a channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index">
|
||||||
|
/// The index of the channel to which to write.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="buffer">
|
||||||
|
/// The buffer from which to read data.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="offset">
|
||||||
|
/// The offset at which to start reading.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="count">
|
||||||
|
/// The number of bytes to read.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="cancellationToken">
|
||||||
|
/// A <see cref="CancellationToken"/> which can be used to cancel the asynchronous operation.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="Task"/> which represents the asynchronous operation.
|
||||||
|
/// </returns>
|
||||||
|
public Task Write(ChannelIndex index, byte[] buffer, int offset, int count, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
|
{
|
||||||
|
return Write((byte)index, buffer, offset, count, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Directly writes data to a channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index">
|
||||||
|
/// The index of the channel to which to write.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="buffer">
|
||||||
|
/// The buffer from which to read data.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="offset">
|
||||||
|
/// The offset at which to start reading.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="count">
|
||||||
|
/// The number of bytes to read.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="cancellationToken">
|
||||||
|
/// A <see cref="CancellationToken"/> which can be used to cancel the asynchronous operation.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="Task"/> which represents the asynchronous operation.
|
||||||
|
/// </returns>
|
||||||
public async Task Write(byte index, byte[] buffer, int offset, int count, CancellationToken cancellationToken = default(CancellationToken))
|
public async Task Write(byte index, byte[] buffer, int offset, int count, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
byte[] writeBuffer = ArrayPool<byte>.Shared.Rent(count + 1);
|
byte[] writeBuffer = ArrayPool<byte>.Shared.Rent(count + 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user