diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/KubernetesClientException.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/KubernetesClientException.java index b838eeca22..b8b7ed27e3 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/KubernetesClientException.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/KubernetesClientException.java @@ -60,7 +60,7 @@ private KubernetesClientException(String message, Throwable t, int code, Status super(message, t); this.code = code; this.status = status; - this.requestMetadata = requestMetadata; + this.requestMetadata = requestMetadata == null ? RequestMetadata.EMPTY : requestMetadata; } /** @@ -230,4 +230,12 @@ static RequestMetadata from(URI request) { } } } + + /** + * Create a new {@link KubernetesClientException} with this exception as the cause + */ + public KubernetesClientException copyAsCause() { + return new KubernetesClientException(this.getMessage(), this, this.getCode(), this.getStatus(), + this.requestMetadata); + } } 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 7c68ff7633..f557baa3e8 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 @@ -83,6 +83,7 @@ public class OperationSupport { protected String apiGroupVersion; protected boolean dryRun; private final int requestRetryBackoffLimit; + private final int requestRetryBackoffInterval; public OperationSupport(Client client) { this(new OperationContext().withClient(client)); @@ -106,8 +107,10 @@ public OperationSupport(OperationContext ctx) { } if (ctx.getConfig() != null) { + requestRetryBackoffInterval = ctx.getConfig().getRequestRetryBackoffInterval(); this.requestRetryBackoffLimit = ctx.getConfig().getRequestRetryBackoffLimit(); } else { + requestRetryBackoffInterval = Config.DEFAULT_REQUEST_RETRY_BACKOFFINTERVAL; this.requestRetryBackoffLimit = Config.DEFAULT_REQUEST_RETRY_BACKOFFLIMIT; } } @@ -508,15 +511,14 @@ protected T waitForResult(CompletableFuture future) throws IOException { if (e.getCause() != null) { t = e.getCause(); } + // throw a new exception to preserve the calling stack trace if (t instanceof IOException) { - throw (IOException) t; + throw new IOException(t.getMessage(), t); } - if (t instanceof RuntimeException) { - throw (RuntimeException) t; + if (t instanceof KubernetesClientException) { + throw ((KubernetesClientException) t).copyAsCause(); } - InterruptedIOException ie = new InterruptedIOException(); - ie.initCause(e); - throw ie; + throw new KubernetesClientException(t.getMessage(), t); } } @@ -568,7 +570,7 @@ protected CompletableFuture handleResponse(HttpClient client, HttpRequest HttpRequest request = requestBuilder.build(); CompletableFuture> futureResponse = new CompletableFuture<>(); retryWithExponentialBackoff(futureResponse, - new ExponentialBackoffIntervalCalculator(requestRetryBackoffLimit, MAX_RETRY_INTERVAL_EXPONENT), + new ExponentialBackoffIntervalCalculator(requestRetryBackoffInterval, MAX_RETRY_INTERVAL_EXPONENT), Utils.getNonNullOrElse(client, httpClient), request); return futureResponse.thenApply(response -> { diff --git a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperationTest.java b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperationTest.java index 37e686edc0..2b209f3b15 100644 --- a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperationTest.java +++ b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperationTest.java @@ -296,6 +296,7 @@ void testNoHttpRetryWithDefaultConfig() { void testHttpRetryWithMoreFailuresThanRetries() { final AtomicInteger httpExecutionCounter = new AtomicInteger(0); HttpClient mockClient = newHttpClientWithSomeFailures(httpExecutionCounter, 1000); + long start = System.currentTimeMillis(); BaseOperation> baseOp = new BaseOperation(new OperationContext() .withClient(mockClient(mockClient, new ConfigBuilder().withMasterUrl("https://172.17.0.2:8443").withNamespace("default") @@ -309,7 +310,10 @@ void testHttpRetryWithMoreFailuresThanRetries() { Pod result = baseOp.get(); }); + long stop = System.currentTimeMillis(); + // Then + assertTrue(stop - start >= 700); //100+200+400 assertTrue(exception.getMessage().contains("Internal Server Error"), "As the last failure, the 3rd one, is not an IOException the message expected to contain: 'Internal Server Error'!"); assertEquals(4, httpExecutionCounter.get(), "Expected 4 calls: one normal try and 3 backoff retries!");