httpclient to support different timeout for watch and regular api (#725)

* api for httpclient timeout

* testcases for global timeout

* update timeout to honor token

* generated files
This commit is contained in:
Boshi Lian
2021-10-11 12:55:02 -07:00
committed by GitHub
parent 78387dc44f
commit bc11d3aec2
5 changed files with 3435 additions and 2 deletions

View File

@@ -319,6 +319,16 @@ namespace k8s
Dictionary<string, List<string>> customHeaders = null, Dictionary<string, List<string>> customHeaders = null,
CancellationToken cancellationToken = default(CancellationToken)) CancellationToken cancellationToken = default(CancellationToken))
{ {
var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
cts.CancelAfter(HttpClientTimeout);
{{#IfParamCotains operation "watch"}}
if (watch == true)
{
cts.CancelAfter(Timeout.InfiniteTimeSpan);
}
{{/IfParamCotains operation "watch"}}
cancellationToken = cts.Token;
{{#operation.parameters}} {{#operation.parameters}}
{{#isRequired}} {{#isRequired}}
if ({{GetDotNetName name}} == null) if ({{GetDotNetName name}} == null)

View File

@@ -8,6 +8,7 @@ using System.Net.Sockets;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Threading;
using k8s.Exceptions; using k8s.Exceptions;
using k8s.Models; using k8s.Models;
using Microsoft.Rest; using Microsoft.Rest;
@@ -16,6 +17,13 @@ namespace k8s
{ {
public partial class Kubernetes public partial class Kubernetes
{ {
/// <summary>
/// Timeout of REST calls to Kubernetes server
/// Does not apply to watch related api
/// </summary>
/// <value>timeout</value>
public TimeSpan HttpClientTimeout { get; set; } = TimeSpan.FromSeconds(100);
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Kubernetes" /> class. /// Initializes a new instance of the <see cref="Kubernetes" /> class.
/// </summary> /// </summary>
@@ -69,6 +77,7 @@ namespace k8s
SkipTlsVerify = config.SkipTlsVerify; SkipTlsVerify = config.SkipTlsVerify;
CreateHttpClient(handlers, config); CreateHttpClient(handlers, config);
InitializeFromConfig(config); InitializeFromConfig(config);
HttpClientTimeout = config.HttpClientTimeout;
} }
private void ValidateConfig(KubernetesClientConfiguration config) private void ValidateConfig(KubernetesClientConfiguration config)
@@ -247,7 +256,10 @@ namespace k8s
} }
} }
HttpClient = new HttpClient(FirstMessageHandler, false); HttpClient = new HttpClient(FirstMessageHandler, false)
{
Timeout = Timeout.InfiniteTimeSpan,
};
} }
/// <summary> /// <summary>

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
@@ -79,8 +80,25 @@ namespace k8s
/// <value>The access token.</value> /// <value>The access token.</value>
public string AccessToken { get; set; } public string AccessToken { get; set; }
/// <summary>
/// Gets or sets the TokenProvider for authentication.
/// </summary>
/// <value>The access token.</value>
public ITokenProvider TokenProvider { get; set; } public ITokenProvider TokenProvider { get; set; }
/// <summary>
/// Set true to enable tcp keep alive
/// You have to set https://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html as well
/// </summary>
/// <value>true or false</value>
public bool TcpKeepAlive { get; set; } = true; public bool TcpKeepAlive { get; set; } = true;
/// <summary>
/// Timeout of REST calls to Kubernetes server
/// Does not apply to watch related api
/// </summary>
/// <value>timeout</value>
public TimeSpan HttpClientTimeout { get; set; } = TimeSpan.FromSeconds(100);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -552,9 +552,42 @@ namespace k8s.Tests
} }
} }
[Fact]
public async Task EnsureTimeoutWorks()
{
using var server = new MockKubeApiServer(testOutput, async httpContext =>
{
await Task.Delay(TimeSpan.FromSeconds(120)).ConfigureAwait(false); // The default timeout is 100 seconds
await WriteStreamLine(httpContext, MockKubeApiServer.MockPodResponse).ConfigureAwait(false);
return false;
});
[Fact(Skip = "https://github.com/kubernetes-client/csharp/issues/165")] // raw timeout
await Assert.ThrowsAsync<TaskCanceledException>(async () =>
{
var client = new Kubernetes(new KubernetesClientConfiguration
{
Host = server.Uri.ToString(),
HttpClientTimeout = TimeSpan.FromSeconds(5),
});
await client.ListNamespacedPodWithHttpMessagesAsync("default").ConfigureAwait(false);
}).ConfigureAwait(false);
// cts
await Assert.ThrowsAsync<TaskCanceledException>(async () =>
{
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(5));
var client = new Kubernetes(new KubernetesClientConfiguration
{
Host = server.Uri.ToString(),
});
await client.ListNamespacedPodWithHttpMessagesAsync("default", cancellationToken: cts.Token).ConfigureAwait(false);
}).ConfigureAwait(false);
}
[Fact]
public async Task DirectWatchEventsWithTimeout() public async Task DirectWatchEventsWithTimeout()
{ {
var eventsReceived = new AsyncCountdownEvent(4); var eventsReceived = new AsyncCountdownEvent(4);