diff --git a/CHANGELOG.md b/CHANGELOG.md index 95cfeaf3c91..ff653d59990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ #### New Features #### _**Note**_: Breaking changes +* Fix #4911: Config/RequestConfig.scaleTimeout has been deprectated along with Scalable.scale(count, wait) and DeployableScalableResource.deployLatest(wait). withTimeout may be called before the operation to control the timeout. +* Fix #4911: Config/RequestConfig.websocketTimeout has been removed. Config/RequestConfig.requestTimeout will be used for websocket connection timeouts. +* Fix #4911: HttpClient api/building changes - writeTimeout has been removed, readTimeout has moved to the HttpRequest ### 6.6.2 (2023-05-15) @@ -20,7 +23,7 @@ Fix #5121: RequestConfig is propagated to derived HttpClient instances ### 6.6.1 (2023-05-11) #### Bugs -* Fix #5095: moving the enforcement to requestTimeout +* Fix #5095: moving the enforcement of requestTimeout * Fix #5100: lessened the level of the non-conflicting httpclient implementation warning * Fix #5102: wait on scale to 0 was not completing * Fix #5112: Expose put method with InputStream argument in HttpRequest class diff --git a/httpclient-jdk/src/main/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientImpl.java b/httpclient-jdk/src/main/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientImpl.java index 30160218b30..1c48c7fa2a8 100644 --- a/httpclient-jdk/src/main/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientImpl.java +++ b/httpclient-jdk/src/main/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientImpl.java @@ -60,7 +60,6 @@ /** * TODO: * - Mapping to a Reader is always UTF-8 - * - determine if write timeout should be implemented */ public class JdkHttpClientImpl extends StandardHttpClient { @@ -259,7 +258,7 @@ public CompletableFuture> consumeBytesDirect(StandardHtt java.net.http.HttpRequest.Builder requestBuilder(StandardHttpRequest request) { java.net.http.HttpRequest.Builder requestBuilder = java.net.http.HttpRequest.newBuilder(); - Duration readTimeout = this.builder.getReadTimeout(); + Duration readTimeout = request.getReadTimeout(); if (readTimeout != null && !java.time.Duration.ZERO.equals(readTimeout)) { requestBuilder.timeout(readTimeout); } @@ -306,15 +305,13 @@ public long contentLength() { @Override public CompletableFuture buildWebSocketDirect( StandardWebSocketBuilder standardWebSocketBuilder, Listener listener) { - final StandardHttpRequest request = standardWebSocketBuilder.asHttpRequest(); + StandardHttpRequest request = standardWebSocketBuilder.asHttpRequest(); java.net.http.WebSocket.Builder newBuilder = this.getHttpClient().newWebSocketBuilder(); request.headers().forEach((k, v) -> v.forEach(s -> newBuilder.header(k, s))); if (standardWebSocketBuilder.getSubprotocol() != null) { newBuilder.subprotocols(standardWebSocketBuilder.getSubprotocol()); } - // the Watch logic sets a websocketTimeout as the readTimeout - // TODO: this should probably be made clearer in the docs - Duration readTimeout = this.builder.getReadTimeout(); + Duration readTimeout = request.getReadTimeout(); if (readTimeout != null && !java.time.Duration.ZERO.equals(readTimeout)) { newBuilder.connectTimeout(readTimeout); } diff --git a/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientBuilderTest.java b/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientBuilderTest.java index e2bacc73635..c5991b34573 100644 --- a/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientBuilderTest.java +++ b/httpclient-jdk/src/test/java/io/fabric8/kubernetes/client/jdkhttp/JdkHttpClientBuilderTest.java @@ -30,10 +30,7 @@ void testZeroTimeouts() { JdkHttpClientBuilderImpl builder = factory.newBuilder(); // should build and be usable without an issue - try (HttpClient client = builder.readTimeout(0, TimeUnit.MILLISECONDS).connectTimeout(0, TimeUnit.MILLISECONDS) - .writeTimeout(0, - TimeUnit.MILLISECONDS) - .build();) { + try (HttpClient client = builder.connectTimeout(0, TimeUnit.MILLISECONDS).build();) { assertNotNull(client.newHttpRequestBuilder().uri("http://localhost").build()); } } diff --git a/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClient.java b/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClient.java index a98c2a2813f..1ac87314e05 100644 --- a/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClient.java +++ b/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClient.java @@ -18,7 +18,6 @@ import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.http.AsyncBody; import io.fabric8.kubernetes.client.http.AsyncBody.Consumer; -import io.fabric8.kubernetes.client.http.HttpRequest; import io.fabric8.kubernetes.client.http.HttpResponse; import io.fabric8.kubernetes.client.http.StandardHttpClient; import io.fabric8.kubernetes.client.http.StandardHttpClientBuilder; @@ -100,7 +99,9 @@ private Request newRequest(StandardHttpRequest originalRequest) { final var request = requestBuilder.build(); var jettyRequest = jetty.newRequest(request.uri()).method(request.method()); - jettyRequest.timeout(builder.getReadTimeout().toMillis() + builder.getWriteTimeout().toMillis(), TimeUnit.MILLISECONDS); + if (originalRequest.getReadTimeout() != null) { + jettyRequest.timeout(originalRequest.getReadTimeout().toMillis(), TimeUnit.MILLISECONDS); + } jettyRequest.headers(m -> request.headers().forEach((k, l) -> l.forEach(v -> m.add(k, v)))); final var contentType = Optional.ofNullable(request.getContentType()); @@ -136,14 +137,14 @@ public CompletableFuture buildWebSocketDirect(StandardWebSock Listener listener) { try { jettyWs.start(); - final HttpRequest request = standardWebSocketBuilder.asHttpRequest(); + StandardHttpRequest request = standardWebSocketBuilder.asHttpRequest(); final ClientUpgradeRequest cur = new ClientUpgradeRequest(); if (Utils.isNotNullOrEmpty(standardWebSocketBuilder.getSubprotocol())) { cur.setSubProtocols(standardWebSocketBuilder.getSubprotocol()); } cur.setHeaders(request.headers()); - if (builder.getReadTimeout() != null) { - cur.setTimeout(builder.getReadTimeout().toMillis(), TimeUnit.MILLISECONDS); + if (request.getReadTimeout() != null) { + cur.setTimeout(request.getReadTimeout().toMillis(), TimeUnit.MILLISECONDS); } // Extra-future required because we can't Map the UpgradeException to a WebSocketHandshakeException easily final CompletableFuture future = new CompletableFuture<>(); diff --git a/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientBuilder.java b/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientBuilder.java index 32a48b605e8..753831e9609 100644 --- a/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientBuilder.java +++ b/httpclient-jetty/src/main/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientBuilder.java @@ -111,16 +111,6 @@ protected JettyHttpClientBuilder newInstance(JettyHttpClientFactory clientFactor return new JettyHttpClientBuilder(clientFactory); } - @Override - public Duration getReadTimeout() { - return Optional.ofNullable(readTimeout).orElse(Duration.ZERO); - } - - @Override - public Duration getWriteTimeout() { - return Optional.ofNullable(writeTimeout).orElse(Duration.ZERO); - } - @Override public Duration getConnectTimeout() { return Optional.ofNullable(connectTimeout).orElse(Duration.ZERO); diff --git a/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientTest.java b/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientTest.java index 13a5a9b1c85..c21aa98fa39 100644 --- a/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientTest.java +++ b/httpclient-jetty/src/test/java/io/fabric8/kubernetes/client/jetty/JettyHttpClientTest.java @@ -68,14 +68,12 @@ void newBuilderInstantiatesJettyHttpClientBuilderWithSameSettings() throws Excep final var originalBuilder = new JettyHttpClientBuilder(null); originalBuilder .connectTimeout(1337, TimeUnit.SECONDS) - .readTimeout(1337, TimeUnit.SECONDS) .tlsVersions(TlsVersion.SSL_3_0) .followAllRedirects(); try (var firstClient = new JettyHttpClient( originalBuilder, httpClient, webSocketClient)) { // When - final var result = firstClient.newBuilder() - .readTimeout(313373, TimeUnit.SECONDS); + final var result = firstClient.newBuilder(); // Then assertThat(result) .isNotNull() @@ -90,11 +88,11 @@ void newBuilderInstantiatesJettyHttpClientBuilderWithSameSettings() throws Excep .isEqualTo(method.invoke(originalBuilder)) .isEqualTo(entry.getValue()); } - var readTimeout = StandardHttpClientBuilder.class.getDeclaredField("readTimeout"); - readTimeout.setAccessible(true); - assertThat(readTimeout.get(result)).isEqualTo(Duration.ofSeconds(313373)); - assertThat(readTimeout.get(originalBuilder)).isEqualTo(Duration.ofSeconds(1337)); - readTimeout.setAccessible(false); + var connectTimeout = StandardHttpClientBuilder.class.getDeclaredField("connectTimeout"); + connectTimeout.setAccessible(true); + assertThat(connectTimeout.get(result)).isEqualTo(Duration.ofSeconds(1337)); + assertThat(connectTimeout.get(originalBuilder)).isEqualTo(Duration.ofSeconds(1337)); + connectTimeout.setAccessible(false); } } diff --git a/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientBuilderImpl.java b/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientBuilderImpl.java index cbf9d705314..ce029866683 100644 --- a/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientBuilderImpl.java +++ b/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientBuilderImpl.java @@ -91,18 +91,9 @@ public OkHttpClientImpl initialBuild(okhttp3.OkHttpClient.Builder builder) { } private OkHttpClientImpl derivedBuild(okhttp3.OkHttpClient.Builder builder) { - if (readTimeout != null) { - builder.readTimeout(this.readTimeout); - } - if (writeTimeout != null) { - builder.writeTimeout(this.writeTimeout); - } if (authenticatorNone) { builder.authenticator(Authenticator.NONE); } - if (forStreaming) { - builder.cache(null); - } OkHttpClient client = builder.build(); return new OkHttpClientImpl(client, this); diff --git a/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientImpl.java b/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientImpl.java index c4e4d9eec6f..ee0bee754a2 100644 --- a/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientImpl.java +++ b/httpclient-okhttp/src/main/java/io/fabric8/kubernetes/client/okhttp/OkHttpClientImpl.java @@ -291,10 +291,24 @@ public void close() { } } - private CompletableFuture> sendAsync(HttpRequest request, + private CompletableFuture> sendAsync(StandardHttpRequest request, Function handler) { CompletableFuture> future = new CompletableFuture<>(); - Call call = httpClient.newCall(requestBuilder((StandardHttpRequest) request).build()); + + okhttp3.OkHttpClient.Builder clientBuilder = null; + if (request.getReadTimeout() != null) { + clientBuilder = httpClient.newBuilder(); + clientBuilder.readTimeout(request.getReadTimeout()); + } + if (request.isForStreaming()) { + if (clientBuilder == null) { + clientBuilder = httpClient.newBuilder(); + } + clientBuilder.cache(null); + } + + Call call = Optional.ofNullable(clientBuilder).map(okhttp3.OkHttpClient.Builder::build).orElse(httpClient) + .newCall(requestBuilder(request).build()); try { call.enqueue(new Callback() { diff --git a/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClient.java b/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClient.java index 26272875f8b..9a5a2c613a9 100644 --- a/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClient.java +++ b/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClient.java @@ -63,16 +63,16 @@ public CompletableFuture buildWebSocketDirect(StandardWebSock WebSocket.Listener listener) { WebSocketConnectOptions options = new WebSocketConnectOptions(); - if (builder.getReadTimeout() != null) { - options.setTimeout(builder.getReadTimeout().toMillis()); - } - if (standardWebSocketBuilder.getSubprotocol() != null) { options.setSubProtocols(Collections.singletonList(standardWebSocketBuilder.getSubprotocol())); } final StandardHttpRequest request = standardWebSocketBuilder.asHttpRequest(); + if (request.getReadTimeout() != null) { + options.setTimeout(request.getReadTimeout().toMillis()); + } + request.headers().entrySet().stream() .forEach(e -> e.getValue().stream().forEach(v -> options.addHeader(e.getKey(), v))); options.setAbsoluteURI(request.uri().toString()); @@ -107,6 +107,10 @@ public CompletableFuture> consumeBytesDirect(StandardHtt options.setAbsoluteURI(request.uri().toString()); options.setMethod(HttpMethod.valueOf(request.method())); + if (request.getReadTimeout() != null) { + options.setTimeout(request.getReadTimeout().toMillis()); + } + // Proxy authorization is handled manually since the proxyAuthorization value is the actual header if (proxyAuthorization != null) { options.putHeader(HttpHeaders.PROXY_AUTHORIZATION, proxyAuthorization); diff --git a/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java b/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java index 628effc16d7..19ca5b344d9 100644 --- a/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java +++ b/httpclient-vertx/src/main/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilder.java @@ -61,10 +61,6 @@ public VertxHttpClient build() { options.setConnectTimeout((int) this.connectTimeout.toMillis()); } - if (this.writeTimeout != null) { - options.setWriteIdleTimeout((int) this.writeTimeout.getSeconds()); - } - if (this.followRedirects) { options.setFollowRedirects(followRedirects); } diff --git a/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilderTest.java b/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilderTest.java index 3e212073c24..1662bd1ad90 100644 --- a/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilderTest.java +++ b/httpclient-vertx/src/test/java/io/fabric8/kubernetes/client/vertx/VertxHttpClientBuilderTest.java @@ -30,10 +30,7 @@ void testZeroTimeouts() { HttpClient.Builder builder = factory.newBuilder(); // should build and be usable without an issue - try (HttpClient client = builder.readTimeout(0, TimeUnit.MILLISECONDS).connectTimeout(0, TimeUnit.MILLISECONDS) - .writeTimeout(0, - TimeUnit.MILLISECONDS) - .build();) { + try (HttpClient client = builder.connectTimeout(0, TimeUnit.MILLISECONDS).build();) { assertNotNull(client.newHttpRequestBuilder().uri("http://localhost").build()); } } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java index 4c86131aef5..47269765479 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/Config.java @@ -98,7 +98,6 @@ public class Config { public static final String KUBERNETES_REQUEST_RETRY_BACKOFFINTERVAL_SYSTEM_PROPERTY = "kubernetes.request.retry.backoffInterval"; public static final String KUBERNETES_LOGGING_INTERVAL_SYSTEM_PROPERTY = "kubernetes.logging.interval"; public static final String KUBERNETES_SCALE_TIMEOUT_SYSTEM_PROPERTY = "kubernetes.scale.timeout"; - public static final String KUBERNETES_WEBSOCKET_TIMEOUT_SYSTEM_PROPERTY = "kubernetes.websocket.timeout"; public static final String KUBERNETES_WEBSOCKET_PING_INTERVAL_SYSTEM_PROPERTY = "kubernetes.websocket.ping.interval"; public static final String KUBERNETES_MAX_CONCURRENT_REQUESTS = "kubernetes.max.concurrent.requests"; public static final String KUBERNETES_MAX_CONCURRENT_REQUESTS_PER_HOST = "kubernetes.max.concurrent.requests.per.host"; @@ -136,7 +135,6 @@ public class Config { public static final Long DEFAULT_SCALE_TIMEOUT = 10 * 60 * 1000L; public static final int DEFAULT_REQUEST_TIMEOUT = 10 * 1000; public static final int DEFAULT_LOGGING_INTERVAL = 20 * 1000; - public static final Long DEFAULT_WEBSOCKET_TIMEOUT = 5 * 1000L; public static final Long DEFAULT_WEBSOCKET_PING_INTERVAL = 30 * 1000L; public static final Integer DEFAULT_MAX_CONCURRENT_REQUESTS = 64; @@ -197,7 +195,6 @@ public class Config { private int requestTimeout = DEFAULT_REQUEST_TIMEOUT; private long scaleTimeout = DEFAULT_SCALE_TIMEOUT; private int loggingInterval = DEFAULT_LOGGING_INTERVAL; - private long websocketTimeout = DEFAULT_WEBSOCKET_TIMEOUT; private String impersonateUsername; /** @@ -321,14 +318,14 @@ public Config(String masterUrl, String apiVersion, String namespace, boolean tru String oauthToken, int watchReconnectInterval, int watchReconnectLimit, int connectionTimeout, int requestTimeout, long rollingTimeout, long scaleTimeout, int loggingInterval, int maxConcurrentRequests, int maxConcurrentRequestsPerHost, String httpProxy, String httpsProxy, String[] noProxy, Map errorMessages, String userAgent, - TlsVersion[] tlsVersions, long websocketTimeout, long websocketPingInterval, String proxyUsername, String proxyPassword, + TlsVersion[] tlsVersions, long websocketPingInterval, String proxyUsername, String proxyPassword, String trustStoreFile, String trustStorePassphrase, String keyStoreFile, String keyStorePassphrase, String impersonateUsername, String[] impersonateGroups, Map> impersonateExtras) { this(masterUrl, apiVersion, namespace, trustCerts, disableHostnameVerification, caCertFile, caCertData, clientCertFile, clientCertData, clientKeyFile, clientKeyData, clientKeyAlgo, clientKeyPassphrase, username, password, oauthToken, watchReconnectInterval, watchReconnectLimit, connectionTimeout, requestTimeout, scaleTimeout, loggingInterval, maxConcurrentRequests, maxConcurrentRequestsPerHost, false, httpProxy, httpsProxy, noProxy, - errorMessages, userAgent, tlsVersions, websocketTimeout, websocketPingInterval, proxyUsername, proxyPassword, + errorMessages, userAgent, tlsVersions, websocketPingInterval, proxyUsername, proxyPassword, trustStoreFile, trustStorePassphrase, keyStoreFile, keyStorePassphrase, impersonateUsername, impersonateGroups, impersonateExtras, null, null, DEFAULT_REQUEST_RETRY_BACKOFFLIMIT, DEFAULT_REQUEST_RETRY_BACKOFFINTERVAL, DEFAULT_UPLOAD_REQUEST_TIMEOUT); @@ -341,7 +338,7 @@ public Config(String masterUrl, String apiVersion, String namespace, boolean tru String oauthToken, int watchReconnectInterval, int watchReconnectLimit, int connectionTimeout, int requestTimeout, long scaleTimeout, int loggingInterval, int maxConcurrentRequests, int maxConcurrentRequestsPerHost, boolean http2Disable, String httpProxy, String httpsProxy, String[] noProxy, Map errorMessages, - String userAgent, TlsVersion[] tlsVersions, long websocketTimeout, long websocketPingInterval, String proxyUsername, + String userAgent, TlsVersion[] tlsVersions, long websocketPingInterval, String proxyUsername, String proxyPassword, String trustStoreFile, String trustStorePassphrase, String keyStoreFile, String keyStorePassphrase, String impersonateUsername, String[] impersonateGroups, Map> impersonateExtras, OAuthTokenProvider oauthTokenProvider, Map customHeaders, int requestRetryBackoffLimit, @@ -365,7 +362,7 @@ public Config(String masterUrl, String apiVersion, String namespace, boolean tru this.connectionTimeout = connectionTimeout; this.requestConfig = new RequestConfig(watchReconnectLimit, watchReconnectInterval, - requestTimeout, scaleTimeout, loggingInterval, websocketTimeout, + requestTimeout, scaleTimeout, loggingInterval, requestRetryBackoffLimit, requestRetryBackoffInterval, uploadRequestTimeout); this.requestConfig.setImpersonateUsername(impersonateUsername); this.requestConfig.setImpersonateGroups(impersonateGroups); @@ -473,12 +470,6 @@ public static void configFromSysPropsOrEnvVars(Config config) { config.setRequestRetryBackoffInterval(Utils.getSystemPropertyOrEnvVar( KUBERNETES_REQUEST_RETRY_BACKOFFINTERVAL_SYSTEM_PROPERTY, config.getRequestRetryBackoffInterval())); - String configuredWebsocketTimeout = Utils.getSystemPropertyOrEnvVar(KUBERNETES_WEBSOCKET_TIMEOUT_SYSTEM_PROPERTY, - String.valueOf(config.getWebsocketTimeout())); - if (configuredWebsocketTimeout != null) { - config.setWebsocketTimeout(Long.parseLong(configuredWebsocketTimeout)); - } - String configuredWebsocketPingInterval = Utils.getSystemPropertyOrEnvVar(KUBERNETES_WEBSOCKET_PING_INTERVAL_SYSTEM_PROPERTY, String.valueOf(config.getWebsocketPingInterval())); if (configuredWebsocketPingInterval != null) { @@ -1299,15 +1290,6 @@ public void setTlsVersions(TlsVersion[] tlsVersions) { this.tlsVersions = tlsVersions; } - @JsonProperty("websocketTimeout") - public long getWebsocketTimeout() { - return getRequestConfig().getWebsocketTimeout(); - } - - public void setWebsocketTimeout(long websocketTimeout) { - this.requestConfig.setWebsocketTimeout(websocketTimeout); - } - @JsonProperty("websocketPingInterval") public long getWebsocketPingInterval() { return websocketPingInterval; diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/RequestConfig.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/RequestConfig.java index d8ca0b549d3..91eb1a9b9bc 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/RequestConfig.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/RequestConfig.java @@ -29,7 +29,6 @@ import static io.fabric8.kubernetes.client.Config.DEFAULT_REQUEST_TIMEOUT; import static io.fabric8.kubernetes.client.Config.DEFAULT_SCALE_TIMEOUT; import static io.fabric8.kubernetes.client.Config.DEFAULT_UPLOAD_REQUEST_TIMEOUT; -import static io.fabric8.kubernetes.client.Config.DEFAULT_WEBSOCKET_TIMEOUT; public class RequestConfig { @@ -46,20 +45,18 @@ public class RequestConfig { private int requestTimeout = DEFAULT_REQUEST_TIMEOUT; private long scaleTimeout = DEFAULT_SCALE_TIMEOUT; private int loggingInterval = DEFAULT_LOGGING_INTERVAL; - private long websocketTimeout = DEFAULT_WEBSOCKET_TIMEOUT; RequestConfig() { } @Buildable(builderPackage = "io.fabric8.kubernetes.api.builder", editableEnabled = false) public RequestConfig(int watchReconnectLimit, int watchReconnectInterval, int requestTimeout, - long scaleTimeout, int loggingInterval, long websocketTimeout, int requestRetryBackoffLimit, + long scaleTimeout, int loggingInterval, int requestRetryBackoffLimit, int requestRetryBackoffInterval, int uploadRequestTimeout) { this.watchReconnectLimit = watchReconnectLimit; this.watchReconnectInterval = watchReconnectInterval; this.requestTimeout = requestTimeout; this.scaleTimeout = scaleTimeout; - this.websocketTimeout = websocketTimeout; this.loggingInterval = loggingInterval; this.requestRetryBackoffLimit = requestRetryBackoffLimit; this.requestRetryBackoffInterval = requestRetryBackoffInterval; @@ -130,14 +127,6 @@ public void setLoggingInterval(int loggingInterval) { this.loggingInterval = loggingInterval; } - public long getWebsocketTimeout() { - return websocketTimeout; - } - - public void setWebsocketTimeout(long websocketTimeout) { - this.websocketTimeout = websocketTimeout; - } - public void setImpersonateUsername(String impersonateUsername) { this.impersonateUsername = impersonateUsername; } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Deletable.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Deletable.java index b1c72b0bd2b..88d1abfa872 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Deletable.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Deletable.java @@ -18,8 +18,9 @@ import io.fabric8.kubernetes.api.model.StatusDetails; import java.util.List; +import java.util.concurrent.TimeUnit; -public interface Deletable { +public interface Deletable extends Timeoutable { /** * Deletes the resources at this context and returns the {@link StatusDetails} of resources marked for deletion @@ -32,4 +33,16 @@ public interface Deletable { */ List delete(); + /** + * Perform the delete operation as blocking, waiting for finalizers, for up to the given timeout + */ + @Override + Deletable withTimeout(long timeout, TimeUnit unit); + + /** + * Perform the delete operation as blocking, waiting for finalizers, for up to the given timeout + */ + @Override + Deletable withTimeoutInMillis(long timeoutInMillis); + } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/DeletableWithOptions.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/DeletableWithOptions.java index 3227c322651..c6b3bcf5b8e 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/DeletableWithOptions.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/DeletableWithOptions.java @@ -19,15 +19,7 @@ import io.fabric8.kubernetes.client.GracePeriodConfigurable; import io.fabric8.kubernetes.client.PropagationPolicyConfigurable; -import java.util.concurrent.TimeUnit; - public interface DeletableWithOptions extends GracePeriodConfigurable>, - PropagationPolicyConfigurable>, Timeoutable { - - @Override - DeletableWithOptions withTimeout(long timeout, TimeUnit unit); - - @Override - DeletableWithOptions withTimeoutInMillis(long timeoutInMillis); + PropagationPolicyConfigurable> { } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Scalable.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Scalable.java index be7e484d56c..c55877ebfb3 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Scalable.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Scalable.java @@ -35,7 +35,9 @@ public interface Scalable { * @param wait if true, wait for the number of instances to exist - no guarantee is made * as to readiness * @return the resource + * @deprecated use {@link TimeoutableScalable} instead */ + @Deprecated T scale(int count, boolean wait); default Scale scale() { diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ScalableResource.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ScalableResource.java index 2b320809179..a52865bb09c 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ScalableResource.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ScalableResource.java @@ -18,6 +18,6 @@ public interface ScalableResource extends Resource, Loggable, Containerable, - TimestampBytesLimitTerminateTimeTailPrettyLoggable { + TimestampBytesLimitTerminateTimeTailPrettyLoggable, TimeoutableScalable { } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/TimeoutableScalable.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/TimeoutableScalable.java new file mode 100644 index 00000000000..e0f7942c7c2 --- /dev/null +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/TimeoutableScalable.java @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.client.dsl; + +import java.util.concurrent.TimeUnit; + +public interface TimeoutableScalable extends Deletable { + + /** + * Scale the resource to given count + * + * @param count the desired instance count + * @return the resource + */ + T scale(int count); + + @Override + TimeoutableScalable withTimeout(long timeout, TimeUnit unit); + + @Override + TimeoutableScalable withTimeoutInMillis(long timeoutInMillis); + +} diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResource.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResource.java index 443a6f17d09..56b95598c93 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResource.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResource.java @@ -18,9 +18,10 @@ import io.fabric8.kubernetes.api.model.DeletionPropagation; import io.fabric8.kubernetes.client.Client; +import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.dsl.Nameable; import io.fabric8.kubernetes.client.dsl.Resource; -import io.fabric8.kubernetes.client.dsl.WritableOperation; +import io.fabric8.kubernetes.client.dsl.TimeoutableScalable; import java.util.List; import java.util.Map; @@ -31,7 +32,7 @@ * Provides an interface that is usable by the {@link ExtensibleResourceAdapter} that returns * a non-specialized value */ -public interface ExtensibleResource extends Resource { +public interface ExtensibleResource extends Resource, TimeoutableScalable { @Override ExtensibleResource lockResourceVersion(String resourceVersion); @@ -90,8 +91,13 @@ public interface ExtensibleResource extends Resource { ExtensibleResource withTimeout(long timeout, TimeUnit unit); @Override - default WritableOperation withTimeoutInMillis(long timeoutInMillis) { + default ExtensibleResource withTimeoutInMillis(long timeoutInMillis) { return withTimeout(timeoutInMillis, TimeUnit.MILLISECONDS); } + @Override + default T scale(int count) { + throw new KubernetesClientException("not implemented"); + } + } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ResourceAdapter.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ResourceAdapter.java index 08e7c7860c2..836e241ad84 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ResourceAdapter.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ResourceAdapter.java @@ -27,7 +27,6 @@ import io.fabric8.kubernetes.client.Watch; import io.fabric8.kubernetes.client.Watcher; import io.fabric8.kubernetes.client.dsl.Deletable; -import io.fabric8.kubernetes.client.dsl.DeletableWithOptions; import io.fabric8.kubernetes.client.dsl.Gettable; import io.fabric8.kubernetes.client.dsl.Informable; import io.fabric8.kubernetes.client.dsl.NonDeletingOperation; @@ -332,12 +331,12 @@ public T item() { } @Override - public DeletableWithOptions withTimeout(long timeout, TimeUnit unit) { + public Deletable withTimeout(long timeout, TimeUnit unit) { return resource.withTimeout(timeout, unit); } @Override - public DeletableWithOptions withTimeoutInMillis(long timeoutInMillis) { + public Deletable withTimeoutInMillis(long timeoutInMillis) { return withTimeout(timeoutInMillis, TimeUnit.MILLISECONDS); } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/HttpClient.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/HttpClient.java index 751fa6d63e0..b87b890bd73 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/HttpClient.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/HttpClient.java @@ -64,22 +64,6 @@ interface DerivedClientBuilder { HttpClient build(); - /** - * Sets the read timeout for normal http requests. Will also - * be used as the connection timeout for {@link WebSocket}s - */ - DerivedClientBuilder readTimeout(long readTimeout, TimeUnit unit); - - DerivedClientBuilder writeTimeout(long writeTimeout, TimeUnit unit); - - /** - * Sets the HttpClient to be used to perform HTTP requests whose responses - * will be streamed. - * - * @return this Builder instance. - */ - DerivedClientBuilder forStreaming(); - DerivedClientBuilder addOrReplaceInterceptor(String name, Interceptor interceptor); /** @@ -105,26 +89,8 @@ interface Builder extends DerivedClientBuilder { @Override HttpClient build(); - /** - * {@inheritDoc} - */ - @Override - Builder readTimeout(long readTimeout, TimeUnit unit); - - /** - * {@inheritDoc} - */ - @Override - Builder writeTimeout(long writeTimeout, TimeUnit unit); - Builder connectTimeout(long connectTimeout, TimeUnit unit); - /** - * {@inheritDoc} - */ - @Override - Builder forStreaming(); - /** * {@inheritDoc} */ diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/HttpRequest.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/HttpRequest.java index 91b0951c971..c9a0b7fd154 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/HttpRequest.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/HttpRequest.java @@ -24,6 +24,7 @@ import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.UUID; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; public interface HttpRequest extends HttpHeaders { @@ -97,6 +98,18 @@ default Builder post(Map formData) { Builder expectContinue(); + /** + * Sets the read timeout for normal http requests. + */ + Builder readTimeout(long readTimeout, TimeUnit unit); + + /** + * Sets the request to be used for streaming. + * + * @return this Builder instance. + */ + Builder forStreaming(); + } static String formURLEncode(String value) { @@ -109,7 +122,7 @@ static String formURLEncode(String value) { /** * The unique id for this HTTP request, used for logging and debugging - * + * * @return a UUID. */ UUID id(); diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClient.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClient.java index 88d4c01feb6..486fd30e554 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClient.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClient.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.net.URI; import java.nio.ByteBuffer; +import java.time.Duration; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -43,6 +44,7 @@ public abstract class StandardHttpClient> implements HttpClient, RequestTags { + // pads the fail-safe timeout to ensure we don't inadvertently timeout a request private static final long ADDITIONAL_REQEUST_TIMEOUT = TimeUnit.SECONDS.toMillis(5); private static final Logger LOG = LoggerFactory.getLogger(StandardHttpClient.class); @@ -80,15 +82,16 @@ public CompletableFuture> sendAsync(HttpRequest request, Cla @Override public CompletableFuture> consumeBytes(HttpRequest request, Consumer> consumer) { CompletableFuture> result = new CompletableFuture<>(); + StandardHttpRequest standardHttpRequest = (StandardHttpRequest) request; - retryWithExponentialBackoff(result, () -> consumeBytesOnce(request, consumer), request.uri(), HttpResponse::code, - r -> r.body().cancel()); + retryWithExponentialBackoff(result, () -> consumeBytesOnce(standardHttpRequest, consumer), request.uri(), + HttpResponse::code, + r -> r.body().cancel(), standardHttpRequest.getReadTimeout()); return result; } - private CompletableFuture> consumeBytesOnce(HttpRequest request, + private CompletableFuture> consumeBytesOnce(StandardHttpRequest standardHttpRequest, Consumer> consumer) { - StandardHttpRequest standardHttpRequest = (StandardHttpRequest) request; StandardHttpRequest.Builder copy = standardHttpRequest.newBuilder(); for (Interceptor interceptor : builder.getInterceptors().values()) { interceptor.before(copy, standardHttpRequest, this); @@ -140,11 +143,12 @@ private CompletableFuture> consumeBytesOnce(HttpRequest }; } - public CompletableFuture orTimeout(CompletableFuture future, RequestConfig requestConfig) { - int timeout = Optional.ofNullable(requestConfig).map(RequestConfig::getRequestTimeout).orElse(0); - if (timeout > 0) { + public CompletableFuture orTimeout(CompletableFuture future, Duration timeout) { + if (timeout != null && !timeout.isNegative() && !timeout.isZero()) { + long millis = timeout.toMillis(); + millis += (Math.min(millis, ADDITIONAL_REQEUST_TIMEOUT)); Future scheduled = Utils.schedule(Runnable::run, () -> future.completeExceptionally(new TimeoutException()), - timeout + ADDITIONAL_REQEUST_TIMEOUT, TimeUnit.MILLISECONDS); + millis, TimeUnit.MILLISECONDS); future.whenComplete((v, t) -> scheduled.cancel(true)); } return future; @@ -156,9 +160,9 @@ public CompletableFuture orTimeout(CompletableFuture future, RequestCo protected void retryWithExponentialBackoff(CompletableFuture result, Supplier> action, URI uri, Function codeExtractor, java.util.function.Consumer cancel, ExponentialBackoffIntervalCalculator retryIntervalCalculator, - RequestConfig requestConfig) { + Duration timeout) { - orTimeout(action.get(), requestConfig) + orTimeout(action.get(), timeout) .whenComplete((response, throwable) -> { if (retryIntervalCalculator.shouldRetry() && !result.isDone()) { long retryInterval = retryIntervalCalculator.nextReconnectInterval(); @@ -184,7 +188,7 @@ protected void retryWithExponentialBackoff(CompletableFuture result, if (retry) { Utils.schedule(Runnable::run, () -> retryWithExponentialBackoff(result, action, uri, codeExtractor, cancel, retryIntervalCalculator, - requestConfig), + timeout), retryInterval, TimeUnit.MILLISECONDS); return; @@ -196,10 +200,10 @@ protected void retryWithExponentialBackoff(CompletableFuture result, protected void retryWithExponentialBackoff(CompletableFuture result, Supplier> action, URI uri, Function codeExtractor, - java.util.function.Consumer cancel) { + java.util.function.Consumer cancel, Duration timeout) { RequestConfig requestConfig = getTag(RequestConfig.class); retryWithExponentialBackoff(result, action, uri, codeExtractor, cancel, - ExponentialBackoffIntervalCalculator.from(requestConfig), requestConfig); + ExponentialBackoffIntervalCalculator.from(requestConfig), timeout); } @Override @@ -217,11 +221,12 @@ final CompletableFuture buildWebSocket(StandardWebSocketBuilder stand Listener listener) { CompletableFuture intermediate = new CompletableFuture<>(); + StandardHttpRequest request = standardWebSocketBuilder.asHttpRequest(); retryWithExponentialBackoff(intermediate, () -> buildWebSocketOnce(standardWebSocketBuilder, listener), - standardWebSocketBuilder.asHttpRequest().uri(), + request.uri(), r -> Optional.of(r.webSocketUpgradeResponse).map(HttpResponse::code).orElse(null), - r -> Optional.ofNullable(r.webSocket).ifPresent(w -> w.sendClose(1000, null))); + r -> Optional.ofNullable(r.webSocket).ifPresent(w -> w.sendClose(1000, null)), request.getReadTimeout()); CompletableFuture result = new CompletableFuture<>(); diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClientBuilder.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClientBuilder.java index f136238f151..5721d50bd4d 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClientBuilder.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpClientBuilder.java @@ -37,15 +37,12 @@ public abstract class StandardHttpClientBuilder interceptors = new LinkedHashMap<>(); protected Duration connectTimeout; - protected Duration readTimeout; - protected Duration writeTimeout; protected SSLContext sslContext; protected String proxyAuthorization; protected InetSocketAddress proxyAddress; protected boolean followRedirects; protected boolean preferHttp11; protected TlsVersion[] tlsVersions; - protected boolean forStreaming; protected boolean authenticatorNone; protected C client; protected F clientFactory; @@ -61,30 +58,12 @@ protected StandardHttpClientBuilder(F clientFactory) { } } - @Override - public T readTimeout(long readTimeout, TimeUnit unit) { - this.readTimeout = Duration.ofNanos(unit.toNanos(readTimeout)); - return (T) this; - } - - @Override - public T writeTimeout(long writeTimeout, TimeUnit unit) { - this.writeTimeout = Duration.ofNanos(unit.toNanos(writeTimeout)); - return (T) this; - } - @Override public T connectTimeout(long connectTimeout, TimeUnit unit) { this.connectTimeout = Duration.ofNanos(unit.toNanos(connectTimeout)); return (T) this; } - @Override - public T forStreaming() { - this.forStreaming = true; - return (T) this; - } - @Override public T addOrReplaceInterceptor(String name, Interceptor interceptor) { if (interceptor == null) { @@ -157,7 +136,6 @@ public DerivedClientBuilder tag(Object value) { public T copy(C client) { T copy = newInstance(clientFactory); copy.connectTimeout = this.connectTimeout; - copy.readTimeout = this.readTimeout; copy.sslContext = this.sslContext; copy.trustManagers = this.trustManagers; copy.keyManagers = this.keyManagers; @@ -168,7 +146,6 @@ public T copy(C client) { copy.preferHttp11 = this.preferHttp11; copy.followRedirects = this.followRedirects; copy.authenticatorNone = this.authenticatorNone; - copy.writeTimeout = this.writeTimeout; copy.client = client; copy.tags = new LinkedHashMap<>(this.tags); return copy; diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpRequest.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpRequest.java index f504584dbaa..0c95c3d682f 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpRequest.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardHttpRequest.java @@ -21,10 +21,12 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.time.Duration; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; +import java.util.concurrent.TimeUnit; /** * Standard representation of a request. HttpClient implementations need to handle the special fields, @@ -93,6 +95,8 @@ public long getLength() { private final String bodyString; private final BodyContent body; private final boolean expectContinue; + private final Duration readTimeout; + private final boolean forStreaming; /** * Constructor that provides the public information @@ -103,11 +107,11 @@ public long getLength() { * @param bodyString */ public StandardHttpRequest(Map> headers, URI uri, String method, String bodyString) { - this(headers, uri, method, bodyString, null, false, null); + this(headers, uri, method, bodyString, null, false, null, null, false); } StandardHttpRequest(Map> headers, URI uri, String method, String bodyString, - BodyContent body, boolean expectContinue, String contentType) { + BodyContent body, boolean expectContinue, String contentType, Duration readTimeout, boolean forStreaming) { super(headers); this.id = UUID.randomUUID(); this.uri = uri; @@ -116,6 +120,8 @@ public StandardHttpRequest(Map> headers, URI uri, String me this.body = body; this.expectContinue = expectContinue; this.contentType = contentType; + this.readTimeout = readTimeout; + this.forStreaming = forStreaming; } @Override @@ -157,6 +163,14 @@ public Builder newBuilder() { return new Builder(this); } + public boolean isForStreaming() { + return forStreaming; + } + + public Duration getReadTimeout() { + return readTimeout; + } + public static final class Builder extends AbstractBasicBuilder implements HttpRequest.Builder { private String method = "GET"; @@ -164,6 +178,8 @@ public static final class Builder extends AbstractBasicBuilder implemen private String bodyAsString; private boolean expectContinue; private String contentType; + protected Duration readTimeout; + protected boolean forStreaming; public Builder() { } @@ -176,12 +192,26 @@ public Builder(StandardHttpRequest original) { body = original.body; expectContinue = original.expectContinue; contentType = original.contentType; + readTimeout = original.readTimeout; + forStreaming = original.forStreaming; } @Override public StandardHttpRequest build() { - return new StandardHttpRequest( - getHeaders(), Objects.requireNonNull(getUri()), method, bodyAsString, body, expectContinue, contentType); + return new StandardHttpRequest(getHeaders(), Objects.requireNonNull(getUri()), method, bodyAsString, body, expectContinue, + contentType, readTimeout, forStreaming); + } + + @Override + public HttpRequest.Builder readTimeout(long readTimeout, TimeUnit unit) { + this.readTimeout = Duration.ofNanos(unit.toNanos(readTimeout)); + return this; + } + + @Override + public HttpRequest.Builder forStreaming() { + this.forStreaming = true; + return this; } @Override diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardWebSocketBuilder.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardWebSocketBuilder.java index 4be46eba502..618d550a9ee 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardWebSocketBuilder.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/StandardWebSocketBuilder.java @@ -16,11 +16,13 @@ package io.fabric8.kubernetes.client.http; +import io.fabric8.kubernetes.client.http.WebSocket.Builder; import io.fabric8.kubernetes.client.http.WebSocket.Listener; import lombok.Getter; import java.net.URI; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; @Getter public class StandardWebSocketBuilder implements WebSocket.Builder { @@ -75,4 +77,10 @@ public StandardHttpRequest asHttpRequest() { return this.builder.build(); } + @Override + public Builder connectTimeout(long timeout, TimeUnit timeUnit) { + this.builder.readTimeout(timeout, timeUnit); + return this; + } + } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/WebSocket.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/WebSocket.java index f57fc82ecdf..2b651a61fc4 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/WebSocket.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/http/WebSocket.java @@ -19,6 +19,7 @@ import java.net.URI; import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; public interface WebSocket { @@ -101,6 +102,8 @@ interface Builder extends BasicBuilder { @Override Builder uri(URI uri); + Builder connectTimeout(long timeout, TimeUnit timeUnit); + } /** diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java index 8ebc0d2b1d5..e2a84386b0f 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/HttpClientUtils.java @@ -181,10 +181,6 @@ public static void applyCommonConfiguration(Config config, HttpClient.Builder bu builder.connectTimeout(config.getConnectionTimeout(), TimeUnit.MILLISECONDS); } - if (config.getRequestTimeout() > 0) { - builder.readTimeout(config.getRequestTimeout(), TimeUnit.MILLISECONDS); - } - if (config.isHttp2Disable()) { builder.preferHttp11(); } diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java index ffde9029b01..4967ddde509 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigTest.java @@ -594,7 +594,6 @@ void testEmptyConfig() { assertEquals(10000, emptyConfig.getRequestTimeout()); assertEquals(600000, emptyConfig.getScaleTimeout()); assertEquals(20000, emptyConfig.getLoggingInterval()); - assertEquals(5000, emptyConfig.getWebsocketTimeout()); assertEquals(30000, emptyConfig.getWebsocketPingInterval()); assertEquals(120000, emptyConfig.getUploadRequestTimeout()); assertTrue(emptyConfig.getImpersonateExtras().isEmpty()); diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractSimultaneousConnectionsTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractSimultaneousConnectionsTest.java index 7515bbad592..0c6914bbcb4 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractSimultaneousConnectionsTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractSimultaneousConnectionsTest.java @@ -80,8 +80,7 @@ void prepareServerAndBuilder() throws IOException { httpServer.setExecutor(httpExecutor); httpServer.start(); clientBuilder = getHttpClientFactory().newBuilder() - .connectTimeout(60, TimeUnit.SECONDS) - .readTimeout(60, TimeUnit.SECONDS); + .connectTimeout(60, TimeUnit.SECONDS); } @AfterEach @@ -246,6 +245,7 @@ final long activeConnections() { return connections.stream().filter(Socket::isConnected).filter(s -> !s.isClosed()).count(); } + @Override public final void close() { for (Socket socket : connections) { try { diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractWebSocketSendTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractWebSocketSendTest.java index 2f5eaa453ed..9095812ad2d 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractWebSocketSendTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/AbstractWebSocketSendTest.java @@ -63,9 +63,8 @@ void sendEmitsMessageToWebSocketServer() throws Exception { .always(); final BlockingQueue receivedText = new ArrayBlockingQueue<>(1); final WebSocket ws = client - // ensure that both a derived builder and a 0, or no, timeout works - // as that is a common logic path in the client - .newBuilder().readTimeout(0, TimeUnit.SECONDS).build().newWebSocketBuilder() + // ensure that a derived builder works + .newBuilder().build().newWebSocketBuilder() // TODO: JDK HttpClient implementation doesn't work with ws URIs // - Currently we are using an HttpRequest.Builder which is then // mapped to a WebSocket.Builder. We should probably user the WebSocket.Builder diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/StandardHttpClientTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/StandardHttpClientTest.java index 3800ed478dd..64ec1be2c35 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/StandardHttpClientTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/http/StandardHttpClientTest.java @@ -215,12 +215,8 @@ void testClosePreviousBeforeRetry() throws Exception { @Test void testRequestTimeout() throws Exception { - client = client.newBuilder().tag(new RequestConfigBuilder() - .withRequestTimeout(1).build()) - .build(); - CompletableFuture> consumeFuture = client.consumeBytes( - client.newHttpRequestBuilder().uri("http://localhost").build(), + client.newHttpRequestBuilder().uri("http://localhost").readTimeout(1, TimeUnit.MILLISECONDS).build(), (value, asyncBody) -> { }); diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java index 44760ace0fd..0bcd1d6f60a 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java @@ -45,7 +45,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; import static java.net.HttpURLConnection.HTTP_GONE; @@ -115,7 +114,7 @@ public static class WatchRequestState { AbstractWatchManager( Watcher watcher, BaseOperation baseOperation, ListOptions listOptions, int reconnectLimit, - int reconnectInterval, Supplier clientSupplier) throws MalformedURLException { + int reconnectInterval, HttpClient client) throws MalformedURLException { // prevent the callbacks from happening in the httpclient thread this.watcher = new SerialWatcher<>(watcher, new SerialExecutor(baseOperation.getOperationContext().getExecutor())); this.reconnectLimit = reconnectLimit; @@ -130,7 +129,7 @@ public static class WatchRequestState { this.baseOperation = baseOperation; this.requestUrl = baseOperation.getNamespacedUrl(); this.listOptions = listOptions; - this.client = clientSupplier.get(); + this.client = client; startWatch(); } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperation.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperation.java index 20b5a4eb1df..66df22703ab 100755 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperation.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperation.java @@ -401,7 +401,7 @@ public L list(Integer limitVal, String continueVal) { public CompletableFuture submitList(ListOptions listOptions) { try { URL fetchListUrl = fetchListUrl(getNamespacedUrl(), defaultListOptions(listOptions, null)); - HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder().url(fetchListUrl); + HttpRequest.Builder requestBuilder = withReadTimeout(httpClient.newHttpRequestBuilder()).url(fetchListUrl); Type refinedType = listType.equals(DefaultKubernetesResourceList.class) ? Serialization.jsonMapper().getTypeFactory().constructParametricType(listType, type) : listType; @@ -629,7 +629,7 @@ public CompletableFuture> submitWatch(ListOptions option watcherToggle, getRequestConfig().getWatchReconnectInterval(), getRequestConfig().getWatchReconnectLimit(), - getRequestConfig().getWebsocketTimeout()); + getRequestConfig().getRequestTimeout()); } catch (MalformedURLException e) { throw KubernetesClientException.launderThrowable(forOperationType(WATCH), e); } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/HasMetadataOperation.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/HasMetadataOperation.java index 39a73dcc83b..2e7ec581b2b 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/HasMetadataOperation.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/HasMetadataOperation.java @@ -25,6 +25,7 @@ import io.fabric8.kubernetes.api.model.autoscaling.v1.ScaleBuilder; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.dsl.Resource; +import io.fabric8.kubernetes.client.dsl.Scalable; import io.fabric8.kubernetes.client.dsl.base.PatchContext; import io.fabric8.kubernetes.client.dsl.base.PatchType; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; @@ -284,23 +285,27 @@ public HasMetadataOperation newInstance(OperationContext context) { @Override public T scale(int count) { - return scale(count, false); - } - - @Override - public T scale(int count, boolean wait) { // TODO: this could be a simple patch, rather than an edit // we're also not giving the user the option here of doing this as a locked operation // kubectl does support specifying the resourceVersion scale(new ScaleBuilder(scale()).editOrNewMetadata().withResourceVersion(null).endMetadata().editOrNewSpec() .withReplicas(count) .endSpec().build()); - if (wait) { + if (context.getTimeout() > 0) { waitUntilScaled(count); } return get(); } + @Override + public T scale(int count, boolean wait) { + Scalable scalable = this; + if (wait) { + scalable = this.withTimeoutInMillis(getRequestConfig().getScaleTimeout()); + } + return scalable.scale(count); + } + @Override public Scale scale(Scale scaleParam) { return handleScale(scaleParam, Scale.class); @@ -323,7 +328,7 @@ protected void waitUntilScaled(final int count) { int specReplicas = Optional.ofNullable(scale.getSpec().getReplicas()).orElse(0); if (count == statusReplicas && count == specReplicas) { completion.complete(null); - } else { + } else if (LOGGER.isDebugEnabled()) { LOGGER.debug("Only {}/{} replicas scheduled for {}: {} in namespace: {} seconds so waiting...", specReplicas, count, getKind(), getName(), namespace); } @@ -332,12 +337,12 @@ protected void waitUntilScaled(final int count) { } }, 0, () -> 1, TimeUnit.SECONDS); - if (!Utils.waitUntilReady(completion, getRequestConfig().getScaleTimeout(), TimeUnit.MILLISECONDS)) { + if (!Utils.waitUntilReady(completion, this.context.getTimeout(), this.context.getTimeoutUnit())) { completion.complete(null); throw new KubernetesClientException( String.format("%s/%s pod(s) ready for %s: %s in namespace: %s after waiting for %s seconds so giving up", replicasRef.get(), count, getType().getSimpleName(), name, namespace, - TimeUnit.MILLISECONDS.toSeconds(getRequestConfig().getScaleTimeout()))); + this.context.getTimeoutUnit().toSeconds(this.context.getTimeout()))); } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/LogWatchCallback.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/LogWatchCallback.java index 2ca97a9289f..8e9dd609b86 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/LogWatchCallback.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/LogWatchCallback.java @@ -16,7 +16,6 @@ package io.fabric8.kubernetes.client.dsl.internal; import io.fabric8.kubernetes.client.KubernetesClientException; -import io.fabric8.kubernetes.client.RequestConfigBuilder; import io.fabric8.kubernetes.client.dsl.LogWatch; import io.fabric8.kubernetes.client.http.AsyncBody; import io.fabric8.kubernetes.client.http.HttpClient; @@ -32,9 +31,7 @@ import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.WritableByteChannel; -import java.util.Optional; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; public class LogWatchCallback implements LogWatch, AutoCloseable { @@ -43,7 +40,6 @@ public class LogWatchCallback implements LogWatch, AutoCloseable { private final OutputStream out; private WritableByteChannel outChannel; - private final OperationContext context; private volatile InputStream output; private final AtomicBoolean closed = new AtomicBoolean(false); @@ -55,7 +51,6 @@ public LogWatchCallback(OutputStream out, OperationContext context) { if (out != null) { outChannel = Channels.newChannel(out); } - this.context = context; this.serialExecutor = new SerialExecutor(context.getExecutor()); } @@ -74,14 +69,10 @@ private void cleanUp() { public LogWatchCallback callAndWait(HttpClient client, URL url) { HttpRequest request = client.newHttpRequestBuilder().url(url).build(); - HttpClient clone = client.newBuilder() - .tag(Optional.ofNullable(context.getRequestConfig()).map(RequestConfigBuilder::new).orElse(new RequestConfigBuilder()) - .withRequestTimeout(0).build()) - .readTimeout(0, TimeUnit.MILLISECONDS).build(); if (out == null) { // we can pass the input stream directly to the consumer - clone.sendAsync(request, InputStream.class).whenComplete((r, e) -> { + client.sendAsync(request, InputStream.class).whenComplete((r, e) -> { if (e != null) { onFailure(e); } @@ -92,7 +83,7 @@ public LogWatchCallback callAndWait(HttpClient client, URL url) { } else { // we need to write the bytes to the given output // we don't know if the write will be blocking, so hand it off to another thread - clone.consumeBytes(request, (buffers, a) -> CompletableFuture.runAsync(() -> { + client.consumeBytes(request, (buffers, a) -> CompletableFuture.runAsync(() -> { for (ByteBuffer byteBuffer : buffers) { try { outChannel.write(byteBuffer); diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/OperationSupport.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/OperationSupport.java index 43494560a1c..c5d226df306 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/OperationSupport.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/OperationSupport.java @@ -59,6 +59,7 @@ import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; public class OperationSupport { @@ -488,6 +489,10 @@ protected T handleRawGet(URL resourceUrl, Class type) throws IOException return handleRaw(type, resourceUrl.toString(), "GET", null); } + HttpRequest.Builder withReadTimeout(HttpRequest.Builder builder) { + return builder.readTimeout(getRequestConfig().getRequestTimeout(), TimeUnit.MILLISECONDS); + } + /** * Waits for the provided {@link CompletableFuture} to complete and returns the result in case of success. * @@ -531,7 +536,7 @@ protected T waitForResult(CompletableFuture future) throws IOException { * @throws IOException IOException */ protected T handleResponse(HttpRequest.Builder requestBuilder, Class type) throws IOException { - return waitForResult(handleResponse(httpClient, requestBuilder, new TypeReference() { + return waitForResult(handleResponse(httpClient, withReadTimeout(requestBuilder), new TypeReference() { @Override public Type getType() { return type; diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/PortForwarder.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/PortForwarder.java deleted file mode 100644 index ab8aac58a73..00000000000 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/PortForwarder.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (C) 2015 Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.fabric8.kubernetes.client.dsl.internal; - -import io.fabric8.kubernetes.client.LocalPortForward; -import io.fabric8.kubernetes.client.PortForward; - -import java.net.InetAddress; -import java.net.URL; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; - -/** - * Allows to forward local ports (or nio channels) to remote ports in Kubernetes pods. - */ -public interface PortForwarder { - - LocalPortForward forward(URL resourceBaseUrl, int port); - - LocalPortForward forward(URL resourceBaseUrl, int port, int localPort); - - LocalPortForward forward(URL resourceBaseUrl, int port, InetAddress localHost, int localPort); - - PortForward forward(URL resourceBaseUrl, int port, ReadableByteChannel in, WritableByteChannel out); - -} diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/PortForwarderWebsocket.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/PortForwarderWebsocket.java index 1e9d8a4eb06..14c2a960691 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/PortForwarderWebsocket.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/PortForwarderWebsocket.java @@ -40,35 +40,27 @@ import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; /** * A port-forwarder using the websocket protocol. * It requires Kubernetes 1.6+ (previous versions support the SPDY protocol only). */ -public class PortForwarderWebsocket implements PortForwarder { +public class PortForwarderWebsocket { private static final Logger LOG = LoggerFactory.getLogger(PortForwarderWebsocket.class); private final HttpClient client; private final Executor executor; + private final long connectTimeoutMills; - public PortForwarderWebsocket(HttpClient client, Executor executor) { + public PortForwarderWebsocket(HttpClient client, Executor executor, long connectTimeoutMillis) { this.client = client; this.executor = executor; + this.connectTimeoutMills = connectTimeoutMillis; } - @Override - public LocalPortForward forward(URL resourceBaseUrl, int port) { - return forward(resourceBaseUrl, port, 0); - } - - @Override - public LocalPortForward forward(URL resourceBaseUrl, int port, int localPort) { - return forward(resourceBaseUrl, port, null, localPort); - } - - @Override public LocalPortForward forward(final URL resourceBaseUrl, final int port, final InetAddress localHost, final int localPort) { try { InetSocketAddress inetSocketAddress = createNewInetSocketAddress(localHost, localPort); @@ -167,12 +159,12 @@ public Collection getServerThrowables() { } } - @Override public PortForward forward(URL resourceBaseUrl, int port, final ReadableByteChannel in, final WritableByteChannel out) { final PortForwarderWebsocketListener listener = new PortForwarderWebsocketListener(in, out, executor); CompletableFuture socket = client .newWebSocketBuilder() .uri(URI.create(URLUtils.join(resourceBaseUrl.toString(), "portforward?ports=" + port))) + .connectTimeout(connectTimeoutMills, TimeUnit.MILLISECONDS) .subprotocol("v4.channel.k8s.io") .buildAsync(listener); diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchConnectionManager.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchConnectionManager.java index 64f4b20a673..70fb73658c7 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchConnectionManager.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchConnectionManager.java @@ -20,7 +20,6 @@ import io.fabric8.kubernetes.api.model.ListOptions; import io.fabric8.kubernetes.api.model.Status; import io.fabric8.kubernetes.client.KubernetesClientException; -import io.fabric8.kubernetes.client.RequestConfigBuilder; import io.fabric8.kubernetes.client.Watcher; import io.fabric8.kubernetes.client.http.HttpClient; import io.fabric8.kubernetes.client.http.HttpResponse; @@ -47,10 +46,9 @@ public class WatchConnectionManager> extends AbstractWatchManager { - public static final int BACKOFF_MAX_EXPONENT = 5; - private static final Logger logger = LoggerFactory.getLogger(WatchConnectionManager.class); + private final long connectTimeoutMillis; protected WatcherWebSocketListener listener; private volatile CompletableFuture websocketFuture; @@ -72,10 +70,8 @@ static void closeWebSocket(WebSocket webSocket) { public WatchConnectionManager(final HttpClient client, final BaseOperation baseOperation, final ListOptions listOptions, final Watcher watcher, final int reconnectInterval, final int reconnectLimit, long websocketTimeout) throws MalformedURLException { - super(watcher, baseOperation, listOptions, reconnectLimit, reconnectInterval, () -> client.newBuilder() - .tag(new RequestConfigBuilder(baseOperation.getRequestConfig()).withRequestTimeout(0).build()) - .readTimeout(websocketTimeout, TimeUnit.MILLISECONDS) - .build()); + super(watcher, baseOperation, listOptions, reconnectLimit, reconnectInterval, client); + this.connectTimeoutMillis = websocketTimeout; } @Override @@ -99,7 +95,7 @@ protected void start(URL url, Map headers, WatchRequestState sta this.listener = new WatcherWebSocketListener<>(this, state); Builder builder = client.newWebSocketBuilder(); headers.forEach(builder::header); - builder.uri(URI.create(url.toString())); + builder.uri(URI.create(url.toString())).connectTimeout(connectTimeoutMillis, TimeUnit.MILLISECONDS); this.websocketFuture = builder.buildAsync(this.listener).handle((w, t) -> { if (t != null) { diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchHTTPManager.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchHTTPManager.java index d1d3b685ef5..9f453cca26b 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchHTTPManager.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchHTTPManager.java @@ -18,7 +18,6 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.KubernetesResourceList; import io.fabric8.kubernetes.api.model.ListOptions; -import io.fabric8.kubernetes.client.RequestConfigBuilder; import io.fabric8.kubernetes.client.Watcher; import io.fabric8.kubernetes.client.http.AsyncBody; import io.fabric8.kubernetes.client.http.HttpClient; @@ -34,7 +33,6 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; public class WatchHTTPManager> extends AbstractWatchManager { private static final Logger logger = LoggerFactory.getLogger(WatchHTTPManager.class); @@ -46,18 +44,12 @@ public WatchHTTPManager(final HttpClient client, final ListOptions listOptions, final Watcher watcher, final int reconnectInterval, final int reconnectLimit) throws MalformedURLException { - super( - watcher, baseOperation, listOptions, reconnectLimit, reconnectInterval, - () -> client.newBuilder() - .tag(new RequestConfigBuilder(baseOperation.getRequestConfig()).withRequestTimeout(0).build()) - .readTimeout(0, TimeUnit.MILLISECONDS) - .forStreaming() - .build()); + super(watcher, baseOperation, listOptions, reconnectLimit, reconnectInterval, client); } @Override protected synchronized void start(URL url, Map headers, WatchRequestState state) { - HttpRequest.Builder builder = client.newHttpRequestBuilder().url(url); + HttpRequest.Builder builder = client.newHttpRequestBuilder().url(url).forStreaming(); headers.forEach(builder::header); StringBuffer buffer = new StringBuffer(); call = client.consumeBytes(builder.build(), (b, a) -> { diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/batch/v1/JobOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/batch/v1/JobOperationsImpl.java index e178c55bfeb..73c29ad4aaa 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/batch/v1/JobOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/batch/v1/JobOperationsImpl.java @@ -41,7 +41,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; @@ -69,13 +68,8 @@ public JobOperationsImpl newInstance(OperationContext context) { @Override public Job scale(int count) { - return scale(count, false); - } - - @Override - public Job scale(int count, boolean wait) { Job res = accept(b -> b.getSpec().setParallelism(count)); - if (wait) { + if (context.getTimeout() > 0) { waitUntilJobIsScaled(); res = getItemOrRequireFromServer(); } @@ -97,10 +91,10 @@ private void waitUntilJobIsScaled() { if (Objects.equals(job.getSpec().getParallelism(), activeJobs)) { return true; } - LOG.debug("Only {}/{} pods scheduled for Job: {} in namespace: {} seconds so waiting...", + LOG.debug("Only {}/{} pods scheduled for Job: {} in namespace: {} so waiting...", job.getStatus().getActive(), job.getSpec().getParallelism(), job.getMetadata().getName(), namespace); return false; - }, getRequestConfig().getScaleTimeout(), TimeUnit.MILLISECONDS); + }, context.getTimeout(), context.getTimeoutUnit()); } @Override diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java index f090cff2c5b..ddc8bfa9566 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java @@ -28,7 +28,6 @@ import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.LocalPortForward; import io.fabric8.kubernetes.client.PortForward; -import io.fabric8.kubernetes.client.RequestConfigBuilder; import io.fabric8.kubernetes.client.dsl.BytesLimitTerminateTimeTailPrettyLoggable; import io.fabric8.kubernetes.client.dsl.CopyOrReadable; import io.fabric8.kubernetes.client.dsl.EphemeralContainersResource; @@ -55,7 +54,6 @@ import io.fabric8.kubernetes.client.dsl.internal.PodOperationContext.StreamContext; import io.fabric8.kubernetes.client.dsl.internal.PortForwarderWebsocket; import io.fabric8.kubernetes.client.dsl.internal.uploadable.PodUpload; -import io.fabric8.kubernetes.client.http.HttpClient; import io.fabric8.kubernetes.client.http.HttpRequest; import io.fabric8.kubernetes.client.http.WebSocket; import io.fabric8.kubernetes.client.lib.FilenameUtils; @@ -202,7 +200,8 @@ public Loggable withLogWaitTimeout(Integer logWaitTimeout) { @Override public PortForward portForward(int port, ReadableByteChannel in, WritableByteChannel out) { try { - return new PortForwarderWebsocket(httpClient, this.context.getExecutor()).forward(getResourceUrl(), port, in, out); + return new PortForwarderWebsocket(httpClient, this.context.getExecutor(), getRequestConfig().getRequestTimeout()) + .forward(getResourceUrl(), port, in, out); } catch (Exception e) { throw KubernetesClientException.launderThrowable(e); } @@ -210,27 +209,19 @@ public PortForward portForward(int port, ReadableByteChannel in, WritableByteCha @Override public LocalPortForward portForward(int port) { - try { - return new PortForwarderWebsocket(httpClient, this.context.getExecutor()).forward(getResourceUrl(), port); - } catch (Exception e) { - throw KubernetesClientException.launderThrowable(e); - } + return portForward(port, 0); } @Override public LocalPortForward portForward(int port, int localPort) { - try { - return new PortForwarderWebsocket(httpClient, this.context.getExecutor()).forward(getResourceUrl(), port, localPort); - } catch (Exception e) { - throw KubernetesClientException.launderThrowable(e); - } + return portForward(port, null, localPort); } @Override public LocalPortForward portForward(int port, InetAddress localInetAddress, int localPort) { try { - return new PortForwarderWebsocket(httpClient, this.context.getExecutor()).forward(getResourceUrl(), port, - localInetAddress, localPort); + return new PortForwarderWebsocket(httpClient, this.context.getExecutor(), getRequestConfig().getRequestTimeout()) + .forward(getResourceUrl(), port, localInetAddress, localPort); } catch (MalformedURLException ex) { throw KubernetesClientException.launderThrowable(ex); } @@ -376,21 +367,18 @@ private boolean hasEphemeralContainer(List containers, Strin } private ExecWebSocketListener setupConnectionToPod(URI uri) { - HttpClient clone = httpClient.newBuilder() - .tag(new RequestConfigBuilder(getRequestConfig()).withRequestTimeout(0).build()) - .readTimeout(0, TimeUnit.MILLISECONDS) - .build(); ExecWebSocketListener execWebSocketListener = new ExecWebSocketListener(getContext(), this.context.getExecutor()); - CompletableFuture startedFuture = clone.newWebSocketBuilder() + CompletableFuture startedFuture = httpClient.newWebSocketBuilder() .subprotocol("v4.channel.k8s.io") .uri(uri) + .connectTimeout(getRequestConfig().getRequestTimeout(), TimeUnit.MILLISECONDS) .buildAsync(execWebSocketListener); startedFuture.whenComplete((w, t) -> { if (t != null) { execWebSocketListener.onError(w, t, true); } }); - Utils.waitUntilReadyOrFail(startedFuture, getRequestConfig().getWebsocketTimeout(), TimeUnit.MILLISECONDS); + Utils.waitUntilReadyOrFail(startedFuture, getRequestConfig().getRequestTimeout(), TimeUnit.MILLISECONDS); return execWebSocketListener; } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/osgi/ManagedKubernetesClient.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/osgi/ManagedKubernetesClient.java index 4caf4caeebd..be6427bb5c2 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/osgi/ManagedKubernetesClient.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/osgi/ManagedKubernetesClient.java @@ -60,7 +60,6 @@ import static io.fabric8.kubernetes.client.Config.KUBERNETES_WATCH_RECONNECT_INTERVAL_SYSTEM_PROPERTY; import static io.fabric8.kubernetes.client.Config.KUBERNETES_WATCH_RECONNECT_LIMIT_SYSTEM_PROPERTY; import static io.fabric8.kubernetes.client.Config.KUBERNETES_WEBSOCKET_PING_INTERVAL_SYSTEM_PROPERTY; -import static io.fabric8.kubernetes.client.Config.KUBERNETES_WEBSOCKET_TIMEOUT_SYSTEM_PROPERTY; @Component(configurationPid = "io.fabric8.kubernetes.client", policy = ConfigurationPolicy.REQUIRE) @Service({ KubernetesClient.class, NamespacedKubernetesClient.class }) @@ -143,9 +142,6 @@ public void activate(Map properties) { String noProxyProperty = (String) properties.get(KUBERNETES_NO_PROXY); builder.withNoProxy(noProxyProperty.split(",")); } - if (properties.containsKey(KUBERNETES_WEBSOCKET_TIMEOUT_SYSTEM_PROPERTY)) { - builder.withWebsocketTimeout(Long.parseLong((String) properties.get(KUBERNETES_WEBSOCKET_TIMEOUT_SYSTEM_PROPERTY))); - } if (properties.containsKey(KUBERNETES_WEBSOCKET_PING_INTERVAL_SYSTEM_PROPERTY)) { builder.withWebsocketPingInterval( Long.parseLong((String) properties.get(KUBERNETES_WEBSOCKET_PING_INTERVAL_SYSTEM_PROPERTY))); diff --git a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManagerTest.java b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManagerTest.java index 8f1517302d0..c3e6843457a 100644 --- a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManagerTest.java +++ b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManagerTest.java @@ -251,8 +251,7 @@ private static class WatchManager extends AbstractWatchMa public WatchManager(Watcher watcher, ListOptions listOptions, int reconnectLimit, int reconnectInterval) throws MalformedURLException { - super(watcher, mockOperation(), listOptions, reconnectLimit, reconnectInterval, - () -> null); + super(watcher, mockOperation(), listOptions, reconnectLimit, reconnectInterval, null); } @Override diff --git a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/PortForwarderWebsocketTest.java b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/PortForwarderWebsocketTest.java index 61862633492..68ff6d339e9 100644 --- a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/PortForwarderWebsocketTest.java +++ b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/PortForwarderWebsocketTest.java @@ -34,7 +34,7 @@ class PortForwarderWebsocketTest { @BeforeEach void initPortForwarderWebsocket() { - this.portForwarderWebsocket = new PortForwarderWebsocket(mockHttpClient, CommonThreadPool.get()); + this.portForwarderWebsocket = new PortForwarderWebsocket(mockHttpClient, CommonThreadPool.get(), 0); } @Test diff --git a/openshift-client-api/src/main/java/io/fabric8/openshift/client/OpenShiftConfig.java b/openshift-client-api/src/main/java/io/fabric8/openshift/client/OpenShiftConfig.java index bd4daba4d2e..5caf479b72e 100644 --- a/openshift-client-api/src/main/java/io/fabric8/openshift/client/OpenShiftConfig.java +++ b/openshift-client-api/src/main/java/io/fabric8/openshift/client/OpenShiftConfig.java @@ -81,7 +81,6 @@ public OpenShiftConfig(String openShiftUrl, String oapiVersion, String masterUrl int maxConcurrentRequests, int maxConcurrentRequestsPerHost, boolean http2Disable, String httpProxy, String httpsProxy, String[] noProxy, Map errorMessages, String userAgent, TlsVersion[] tlsVersions, - long websocketTimeout, long websocketPingInterval, String proxyUsername, String proxyPassword, String trustStoreFile, String trustStorePassphrase, String keyStoreFile, String keyStorePassphrase, String impersonateUsername, String[] impersonateGroups, Map> impersonateExtras, OAuthTokenProvider oauthTokenProvider, @@ -95,7 +94,7 @@ public OpenShiftConfig(String openShiftUrl, String oapiVersion, String masterUrl watchReconnectInterval, watchReconnectLimit, connectionTimeout, requestTimeout, scaleTimeout, loggingInterval, maxConcurrentRequests, maxConcurrentRequestsPerHost, http2Disable, httpProxy, httpsProxy, noProxy, - errorMessages, userAgent, tlsVersions, websocketTimeout, websocketPingInterval, proxyUsername, proxyPassword, + errorMessages, userAgent, tlsVersions, websocketPingInterval, proxyUsername, proxyPassword, trustStoreFile, trustStorePassphrase, keyStoreFile, keyStorePassphrase, impersonateUsername, impersonateGroups, impersonateExtras, oauthTokenProvider, customHeaders, requestRetryBackoffLimit, requestRetryBackoffInterval, uploadRequestTimeout); @@ -129,7 +128,7 @@ public OpenShiftConfig(Config kubernetesConfig, String openShiftUrl, String oapi kubernetesConfig.getMaxConcurrentRequestsPerHost(), kubernetesConfig.isHttp2Disable(), kubernetesConfig.getHttpProxy(), kubernetesConfig.getHttpsProxy(), kubernetesConfig.getNoProxy(), kubernetesConfig.getErrorMessages(), kubernetesConfig.getUserAgent(), - kubernetesConfig.getTlsVersions(), kubernetesConfig.getWebsocketTimeout(), + kubernetesConfig.getTlsVersions(), kubernetesConfig.getWebsocketPingInterval(), kubernetesConfig.getProxyUsername(), kubernetesConfig.getProxyPassword(), kubernetesConfig.getTrustStoreFile(), kubernetesConfig.getTrustStorePassphrase(), kubernetesConfig.getKeyStoreFile(), diff --git a/openshift-client-api/src/main/java/io/fabric8/openshift/client/dsl/DeployableScalableResource.java b/openshift-client-api/src/main/java/io/fabric8/openshift/client/dsl/DeployableScalableResource.java index 19299ed4ce3..126d57afda6 100644 --- a/openshift-client-api/src/main/java/io/fabric8/openshift/client/dsl/DeployableScalableResource.java +++ b/openshift-client-api/src/main/java/io/fabric8/openshift/client/dsl/DeployableScalableResource.java @@ -17,10 +17,12 @@ import io.fabric8.kubernetes.client.dsl.ScalableResource; -public interface DeployableScalableResource extends ScalableResource { - - T deployLatest(); +public interface DeployableScalableResource extends ScalableResource, TimeoutDeployable { + /** + * @deprecated use {@link TimeoutDeployable} instead to indicate the timeout + */ + @Deprecated T deployLatest(boolean wait); } diff --git a/openshift-client-api/src/main/java/io/fabric8/openshift/client/dsl/TimeoutDeployable.java b/openshift-client-api/src/main/java/io/fabric8/openshift/client/dsl/TimeoutDeployable.java new file mode 100644 index 00000000000..d91b326797b --- /dev/null +++ b/openshift-client-api/src/main/java/io/fabric8/openshift/client/dsl/TimeoutDeployable.java @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fabric8.openshift.client.dsl; + +import io.fabric8.kubernetes.client.dsl.TimeoutableScalable; + +import java.util.concurrent.TimeUnit; + +public interface TimeoutDeployable extends TimeoutableScalable { + + T deployLatest(); + + @Override + TimeoutDeployable withTimeout(long timeout, TimeUnit unit); + + @Override + TimeoutDeployable withTimeoutInMillis(long timeoutInMillis); + +} diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/apps/DeploymentConfigOperationsImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/apps/DeploymentConfigOperationsImpl.java index acf001796da..63971b6d15b 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/apps/DeploymentConfigOperationsImpl.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/apps/DeploymentConfigOperationsImpl.java @@ -43,6 +43,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import static io.fabric8.openshift.client.OpenShiftAPIGroups.APPS; @@ -70,19 +71,23 @@ public DeploymentConfigOperationsImpl newInstance(OperationContext context) { } @Override - public DeploymentConfig deployLatest() { - return deployLatest(false); + public DeploymentConfig deployLatest(boolean wait) { + DeploymentConfigOperationsImpl deployable = this; + if (wait) { + deployable = this.withTimeoutInMillis(getRequestConfig().getScaleTimeout()); + } + return deployable.deployLatest(); } @Override - public DeploymentConfig deployLatest(boolean wait) { + public DeploymentConfig deployLatest() { Long currentVersion = getItemOrRequireFromServer().getStatus().getLatestVersion(); if (currentVersion == null) { currentVersion = 1L; } final Long latestVersion = currentVersion + 1; DeploymentConfig deployment = accept(d -> d.getStatus().setLatestVersion(latestVersion)); - if (wait) { + if (context.getTimeout() > 0) { waitUntilScaled(deployment.getSpec().getReplicas()); deployment = getItemOrRequireFromServer(); } @@ -229,4 +234,15 @@ public TailPrettyLoggable sinceSeconds(int seconds) { public BytesLimitTerminateTimeTailPrettyLoggable usingTimestamps() { return new DeploymentConfigOperationsImpl(rollingOperationContext.withTimestamps(true), context); } + + @Override + public DeploymentConfigOperationsImpl withTimeout(long timeout, TimeUnit unit) { + return new DeploymentConfigOperationsImpl(rollingOperationContext, context.withTimeout(timeout, unit)); + } + + @Override + public DeploymentConfigOperationsImpl withTimeoutInMillis(long timeoutInMillis) { + return withTimeout(timeoutInMillis, TimeUnit.MILLISECONDS); + } + } diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImpl.java index fb8eaa66b75..67a4828121a 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImpl.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImpl.java @@ -27,7 +27,6 @@ import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperationsImpl; import io.fabric8.kubernetes.client.dsl.internal.OperationContext; import io.fabric8.kubernetes.client.dsl.internal.OperationSupport; -import io.fabric8.kubernetes.client.http.HttpClient; import io.fabric8.kubernetes.client.http.HttpRequest; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; import io.fabric8.kubernetes.client.utils.URLUtils; @@ -260,16 +259,12 @@ public Typeable> withSecret(String secret) { protected Build submitToApiServer(InputStream inputStream, long contentLength) { try { - HttpClient newClient = this.httpClient.newBuilder() - .tag(getOperationContext().getRequestConfig()) - .readTimeout(getOperationContext().getTimeout(), getOperationContext().getTimeoutUnit()) - .writeTimeout(getOperationContext().getTimeout(), getOperationContext().getTimeoutUnit()) - .build(); HttpRequest.Builder requestBuilder = this.httpClient.newHttpRequestBuilder() .post("application/octet-stream", inputStream, contentLength) .expectContinue() + .readTimeout(getOperationContext().getTimeout(), getOperationContext().getTimeoutUnit()) .uri(getQueryParameters()); - return waitForResult(handleResponse(newClient, requestBuilder, new TypeReference() { + return waitForResult(handleResponse(this.httpClient, requestBuilder, new TypeReference() { @Override public Type getType() { return Build.class; diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java index 53d6811345b..ec136367778 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java @@ -26,6 +26,7 @@ import io.fabric8.kubernetes.client.VersionInfo; import io.fabric8.kubernetes.client.WithRequestCallable; import io.fabric8.kubernetes.client.dsl.CreateOrDeleteable; +import io.fabric8.kubernetes.client.dsl.Deletable; import io.fabric8.kubernetes.client.dsl.FunctionCallable; import io.fabric8.kubernetes.client.dsl.Gettable; import io.fabric8.kubernetes.client.dsl.InOutCreateable; @@ -173,6 +174,7 @@ import java.text.ParseException; import java.util.List; import java.util.Objects; +import java.util.concurrent.TimeUnit; import java.util.function.Supplier; /** @@ -182,6 +184,42 @@ public class OpenShiftClientImpl extends KubernetesClientImpl implements NamespacedOpenShiftClient { + private static final class NameableCreateOrDeleteableImpl implements NameableCreateOrDeleteable { + private final HasMetadataOperation> nameable; + private final Resource operation; + + private NameableCreateOrDeleteableImpl(HasMetadataOperation> nameable, + Resource operation) { + this.nameable = nameable; + this.operation = operation; + } + + @Override + public List delete() { + return operation.delete(); + } + + @Override + public ImageSignature create(ImageSignature item) { + return operation.create(item); + } + + @Override + public CreateOrDeleteable withName(String name) { + return new NameableCreateOrDeleteableImpl(nameable, nameable.withName(name)); + } + + @Override + public Deletable withTimeout(long timeout, TimeUnit unit) { + return operation.withTimeout(timeout, unit); + } + + @Override + public Deletable withTimeoutInMillis(long timeoutInMillis) { + return operation.withTimeoutInMillis(timeoutInMillis); + } + } + public static final String OPENSHIFT_VERSION_ENDPOINT = "version/openshift"; private URL openShiftUrl; @@ -331,35 +369,7 @@ public Namespaceable>> imageStream public NameableCreateOrDeleteable imageSignatures() { HasMetadataOperation> operation = getHandlers() .getNonListingOperation(ImageSignature.class, this); - return new NameableCreateOrDeleteable() { - - @Override - public List delete() { - return operation.delete(); - } - - @Override - public ImageSignature create(ImageSignature item) { - return operation.create(item); - } - - @Override - public CreateOrDeleteable withName(String name) { - return new CreateOrDeleteable() { - - @Override - public ImageSignature create(ImageSignature item) { - return operation.withName(name).create(item); - } - - @Override - public List delete() { - return operation.withName(name).delete(); - } - - }; - } - }; + return new NameableCreateOrDeleteableImpl(operation, operation); } @Override @@ -702,7 +712,6 @@ protected void setDerivedFields() { HttpClient.DerivedClientBuilder builder = httpClient.newBuilder(); this.httpClient = builder .authenticatorNone() - .tag(config.getRequestConfig()) .addOrReplaceInterceptor(TokenRefreshInterceptor.NAME, new OpenShiftOAuthInterceptor(httpClient, wrapped)) .build(); diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/internal/OpenShiftOAuthInterceptor.java b/openshift-client/src/main/java/io/fabric8/openshift/client/internal/OpenShiftOAuthInterceptor.java index bcd331daf61..81f073ef5bb 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/internal/OpenShiftOAuthInterceptor.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/internal/OpenShiftOAuthInterceptor.java @@ -138,7 +138,6 @@ private boolean setAuthHeader(BasicBuilder builder, String token) { private CompletableFuture authorize() { HttpClient.DerivedClientBuilder builder = client.newBuilder(); - builder.tag(config.getRequestConfig()); builder.addOrReplaceInterceptor(TokenRefreshInterceptor.NAME, null); HttpClient clone = builder.build(); diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/osgi/ManagedOpenShiftClient.java b/openshift-client/src/main/java/io/fabric8/openshift/client/osgi/ManagedOpenShiftClient.java index 691aaa1ce82..06c85fde1e1 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/osgi/ManagedOpenShiftClient.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/osgi/ManagedOpenShiftClient.java @@ -51,7 +51,6 @@ import static io.fabric8.kubernetes.client.Config.KUBERNETES_WATCH_RECONNECT_INTERVAL_SYSTEM_PROPERTY; import static io.fabric8.kubernetes.client.Config.KUBERNETES_WATCH_RECONNECT_LIMIT_SYSTEM_PROPERTY; import static io.fabric8.kubernetes.client.Config.KUBERNETES_WEBSOCKET_PING_INTERVAL_SYSTEM_PROPERTY; -import static io.fabric8.kubernetes.client.Config.KUBERNETES_WEBSOCKET_TIMEOUT_SYSTEM_PROPERTY; import static io.fabric8.openshift.client.OpenShiftConfig.DEFAULT_BUILD_TIMEOUT; import static io.fabric8.openshift.client.OpenShiftConfig.OPENSHIFT_BUILD_TIMEOUT_SYSTEM_PROPERTY; import static io.fabric8.openshift.client.OpenShiftConfig.OPENSHIFT_URL_SYSTEM_PROPERTY; @@ -137,9 +136,6 @@ public void activate(Map properties) { } else { builder.withBuildTimeout(DEFAULT_BUILD_TIMEOUT); } - if (properties.containsKey(KUBERNETES_WEBSOCKET_TIMEOUT_SYSTEM_PROPERTY)) { - builder.withWebsocketTimeout(Long.parseLong((String) properties.get(KUBERNETES_WEBSOCKET_TIMEOUT_SYSTEM_PROPERTY))); - } if (properties.containsKey(KUBERNETES_WEBSOCKET_PING_INTERVAL_SYSTEM_PROPERTY)) { builder.withWebsocketPingInterval( Long.parseLong((String) properties.get(KUBERNETES_WEBSOCKET_PING_INTERVAL_SYSTEM_PROPERTY))); diff --git a/openshift-client/src/test/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImplTest.java b/openshift-client/src/test/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImplTest.java index 498c0803398..be9a2fc1a03 100644 --- a/openshift-client/src/test/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImplTest.java +++ b/openshift-client/src/test/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImplTest.java @@ -55,13 +55,11 @@ public void setUp() { when(response.uri()).thenReturn(URI.create("https://localhost:8443/")); when(httpClient.newBuilder() - .tag(any()) - .readTimeout(anyLong(), any()) - .writeTimeout(anyLong(), any()) .build()).thenReturn(httpClient); when(httpClient.newHttpRequestBuilder() .post(any(), any(), anyLong()) .header(any(), any()) + .readTimeout(anyLong(), any()) .uri(any(String.class)) .build()).thenReturn(response);