WebSocketNamespacedPodExecAsync: Support specifying command arguments (#123)
* WebSocketNamespacedPodExecAsync: Support specifying command argumets * Address PR feedback * Address PR feedback * Fix unstable test
This commit is contained in:
committed by
Brendan Burns
parent
cf1c9950a0
commit
d20e2597b9
@@ -52,7 +52,54 @@ namespace k8s
|
||||
/// <return>
|
||||
/// A <see cref="ClientWebSocket"/> which can be used to communicate with the process running in the pod.
|
||||
/// </return>
|
||||
Task<WebSocket> WebSocketNamespacedPodExecAsync(string name, string @namespace = "default", string command = "/bin/bash", string container = null, bool stderr = true, bool stdin = true, bool stdout = true, bool tty = true, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
|
||||
Task<WebSocket> WebSocketNamespacedPodExecAsync(string name, string @namespace = "default", string command = null, string container = null, bool stderr = true, bool stdin = true, bool stdout = true, bool tty = true, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Executes a command in a pod.
|
||||
/// </summary>
|
||||
/// <param name='name'>
|
||||
/// name of the Pod
|
||||
/// </param>
|
||||
/// <param name='namespace'>
|
||||
/// object name and auth scope, such as for teams and projects
|
||||
/// </param>
|
||||
/// <param name='command'>
|
||||
/// Command is the remote command to execute. argv array. Not executed within a
|
||||
/// shell.
|
||||
/// </param>
|
||||
/// <param name='container'>
|
||||
/// Container in which to execute the command. Defaults to only container if
|
||||
/// there is only one container in the pod.
|
||||
/// </param>
|
||||
/// <param name='stderr'>
|
||||
/// Redirect the standard error stream of the pod for this call. Defaults to
|
||||
/// <see langword="true"/>.
|
||||
/// </param>
|
||||
/// <param name='stdin'>
|
||||
/// Redirect the standard input stream of the pod for this call. Defaults to
|
||||
/// <see langword="true"/>.
|
||||
/// </param>
|
||||
/// <param name='stdout'>
|
||||
/// Redirect the standard output stream of the pod for this call. Defaults to
|
||||
/// <see langword="true"/>.
|
||||
/// </param>
|
||||
/// <param name='tty'>
|
||||
/// TTY if true indicates that a tty will be allocated for the exec call.
|
||||
/// Defaults to <see langword="true"/>.
|
||||
/// </param>
|
||||
/// <param name='customHeaders'>
|
||||
/// Headers that will be added to request.
|
||||
/// </param>
|
||||
/// <param name='cancellationToken'>
|
||||
/// The cancellation token.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// Thrown when a required parameter is null
|
||||
/// </exception>
|
||||
/// <return>
|
||||
/// A <see cref="ClientWebSocket"/> which can be used to communicate with the process running in the pod.
|
||||
/// </return>
|
||||
Task<WebSocket> WebSocketNamespacedPodExecAsync(string name, string @namespace = "default", IEnumerable<string> command = null, string container = null, bool stderr = true, bool stdin = true, bool stdout = true, bool tty = true, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Start port forwarding one or more ports of a pod.
|
||||
|
||||
@@ -20,7 +20,13 @@ namespace k8s
|
||||
public Func<WebSocketBuilder> CreateWebSocketBuilder { get; set; } = () => new WebSocketBuilder();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<WebSocket> WebSocketNamespacedPodExecAsync(string name, string @namespace = "default", string command = "/bin/sh", string container = null, bool stderr = true, bool stdin = true, bool stdout = true, bool tty = true, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<WebSocket> WebSocketNamespacedPodExecAsync(string name, string @namespace = "default", string command = null, string container = null, bool stderr = true, bool stdin = true, bool stdout = true, bool tty = true, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return WebSocketNamespacedPodExecAsync(name, @namespace, new string[] { command }, container, stderr, stdin, stdout, tty, customHeaders, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<WebSocket> WebSocketNamespacedPodExecAsync(string name, string @namespace = "default", IEnumerable<string> command = null, string container = null, bool stderr = true, bool stdin = true, bool stdout = true, bool tty = true, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
@@ -37,6 +43,11 @@ namespace k8s
|
||||
throw new ArgumentNullException(nameof(command));
|
||||
}
|
||||
|
||||
if (!command.Any())
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(command));
|
||||
}
|
||||
|
||||
// Tracing
|
||||
bool _shouldTrace = ServiceClientTracing.IsEnabled;
|
||||
string _invocationId = null;
|
||||
@@ -67,17 +78,28 @@ namespace k8s
|
||||
|
||||
uriBuilder.Path += $"api/v1/namespaces/{@namespace}/pods/{name}/exec";
|
||||
|
||||
var query = string.Empty;
|
||||
|
||||
uriBuilder.Query = QueryHelpers.AddQueryString(string.Empty, new Dictionary<string, string>
|
||||
foreach (var c in command)
|
||||
{
|
||||
{ "command", command},
|
||||
{ "container", container},
|
||||
{ "stderr", stderr ? "1": "0"},
|
||||
{ "stdin", stdin ? "1": "0"},
|
||||
{ "stdout", stdout ? "1": "0"},
|
||||
{ "tty", tty ? "1": "0"}
|
||||
query = QueryHelpers.AddQueryString(query, "command", c);
|
||||
}
|
||||
|
||||
if (container != null)
|
||||
{
|
||||
query = QueryHelpers.AddQueryString(query, "container", Uri.EscapeDataString(container));
|
||||
}
|
||||
|
||||
query = QueryHelpers.AddQueryString(query, new Dictionary<string, string>
|
||||
{
|
||||
{"stderr", stderr ? "1" : "0"},
|
||||
{"stdin", stdin ? "1" : "0"},
|
||||
{"stdout", stdout ? "1" : "0"},
|
||||
{"tty", tty ? "1" : "0"}
|
||||
}).TrimStart('?');
|
||||
|
||||
uriBuilder.Query = query;
|
||||
|
||||
return this.StreamConnectAsync(uriBuilder.Uri, _invocationId, customHeaders, cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace k8s.Tests
|
||||
WebSocket clientSocket = await client.WebSocketNamespacedPodExecAsync(
|
||||
name: "mypod",
|
||||
@namespace: "mynamespace",
|
||||
command: "/bin/bash",
|
||||
command: new string[] { "/bin/bash" },
|
||||
container: "mycontainer",
|
||||
stderr: false,
|
||||
stdin: false,
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace k8s.tests
|
||||
var webSocket = await client.WebSocketNamespacedPodExecAsync(
|
||||
name: "mypod",
|
||||
@namespace: "mynamespace",
|
||||
command: "/bin/bash",
|
||||
command: new string[] { "/bin/bash", "-c", $"echo Hello, World\nexit 0\n" },
|
||||
container: "mycontainer",
|
||||
stderr: true,
|
||||
stdin: true,
|
||||
@@ -58,7 +58,7 @@ namespace k8s.tests
|
||||
};
|
||||
|
||||
Assert.Equal(mockWebSocketBuilder.PublicWebSocket, webSocket); // Did the method return the correct web socket?
|
||||
Assert.Equal(new Uri("ws://localhost:80/api/v1/namespaces/mynamespace/pods/mypod/exec?command=%2Fbin%2Fbash&container=mycontainer&stderr=1&stdin=1&stdout=1&tty=1"), mockWebSocketBuilder.Uri); // Did we connect to the correct URL?
|
||||
Assert.Equal(new Uri("ws://localhost/api/v1/namespaces/mynamespace/pods/mypod/exec?command=%2Fbin%2Fbash&command=-c&command=echo%20Hello,%20World%0Aexit%200%0A&container=mycontainer&stderr=1&stdin=1&stdout=1&tty=1"), mockWebSocketBuilder.Uri); // Did we connect to the correct URL?
|
||||
Assert.Empty(mockWebSocketBuilder.Certificates); // No certificates were used in this test
|
||||
Assert.Equal(expectedHeaders, mockWebSocketBuilder.RequestHeaders); // Did we use the expected headers
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user