in src/Cli/func/Kubernetes/KubectlHelper.cs [92:167]
public static Task<Process> RunKubectlProxy(IKubernetesResource resource, int targetPort, int localPort, TimeSpan? timeout = null)
{
var kubectl = new Executable("kubectl", $"port-forward {GetResourceFullName(resource)} {localPort}:{targetPort}");
var sbError = new StringBuilder();
var sbOutput = new StringBuilder();
var tcs = new TaskCompletionSource<Process>();
var deadline = DateTime.Now.Add(timeout ?? TimeSpan.FromSeconds(20));
var exitCodeTask = kubectl.RunAsync(l => Output(l, false), e => Output(e, true));
Task.Run(() => TimeoutFunc());
return tcs.Task;
void Output(string line, bool isError)
{
if (!isError && line?.Contains("Forwarding from") == true)
{
tcs.TrySetResult(kubectl.Process);
}
else if (!isError)
{
sbOutput.AppendLine(line);
}
else
{
sbError.AppendLine(line);
}
}
async Task TimeoutFunc()
{
while (DateTime.Now < deadline)
{
if (tcs.Task.IsCompleted)
{
return;
}
else if (exitCodeTask.IsFaulted || exitCodeTask.IsCompleted)
{
tcs.TrySetException(new Exception($"Unable to proxy request to kubernetes api-server: exitCode: {exitCodeTask.Result}, {sbOutput}, {sbError}"));
return;
}
await Task.Delay(TimeSpan.FromSeconds(1));
}
if (!tcs.Task.IsCompleted)
{
tcs.TrySetException(new TimeoutException("Timedout trying to establish proxy to kubernetes api-server"));
}
}
static string MaybeNamespace(string @namespace)
{
if (string.IsNullOrWhiteSpace(@namespace) == false)
{
return $" --namespace {@namespace}";
}
return string.Empty;
}
string GetResourceFullName(IKubernetesResource r)
{
switch (r)
{
case DeploymentV1Apps deployment:
return $"deployment/{deployment.Metadata.Name} {MaybeNamespace(deployment.Metadata.Namespace)}";
case ServiceV1 service:
return $"service/{service.Metadata.Name} {MaybeNamespace(service.Metadata.Namespace)}";
case PodTemplateV1 pod:
return $"pod/{pod.Metadata.Name} {MaybeNamespace(pod.Metadata.Namespace)}";
default:
throw new ArgumentException($"type {r.GetType()} is not supported");
}
}
}