Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### 7.8-SNAPSHOT

#### Bugs
* Fix #7962: (kubernetes-client) Pod directory copy now rejects sparse tar entries and enforces configured per-file and total extracted-byte limits so pod-controlled tar output cannot expand into unexpectedly large local files
* Fix #7953: (httpclient-jdk) bodyless requests now preserve the requested HTTP method instead of silently defaulting to `GET`. `JdkHttpClientImpl.requestBuilder` only called `HttpRequest.Builder.method(...)` inside the `body != null` branch, so a bodyless `DELETE`/`POST`/`PUT`/`PATCH` (such as `client.raw(uri, "DELETE", null)`) was sent as `GET` on the JDK backend; the method is now set with `BodyPublishers.noBody()` when there is no body, matching the OkHttp, Jetty and Vert.x backends
* Fix #7435: (kubernetes-client) A `SharedIndexInformer`'s periodic resync no longer stops permanently and silently when a single resync cycle throws. `DefaultSharedIndexInformer.scheduleResync` runs the resync through `Utils.scheduleAtFixedRate`, whose self-rescheduling chain re-arms the next cycle only when the previous one completes normally; an uncaught exception completed the (unobserved) `resyncFuture` exceptionally and the resync was never scheduled again, with no log, while the independent watch kept `isWatching()` reporting `true` (a restart was required to recover). The resync command now catches and `WARN`-logs the failure so the schedule fires again at the next interval
* Fix #7933: (kubernetes-client-api) Deterministic TLS trust failures (untrusted cert, expired cert, hostname mismatch) are now classified as terminal and fail fast instead of being retried by the shared `StandardHttpClient.shouldRetry` backoff loop (~19 s drain). The classifier walks both `getCause()` and `getSuppressed()` trees for `CertificateException`, `CertPathValidatorException`, `CertPathBuilderException`, and `SSLPeerUnverifiedException`. Affects all five HTTP client modules (jdk, jetty, okhttp, vertx-4, vertx-5) on both the HTTP request and WebSocket connect paths
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ public class Config extends SundrioConfig {
public static final String KUBERNETES_REQUEST_RETRY_BACKOFFLIMIT_SYSTEM_PROPERTY = "kubernetes.request.retry.backoffLimit";
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_POD_COPY_MAX_FILE_BYTES_SYSTEM_PROPERTY = "kubernetes.pod.copy.max.file.bytes";
public static final String KUBERNETES_POD_COPY_MAX_TOTAL_BYTES_SYSTEM_PROPERTY = "kubernetes.pod.copy.max.total.bytes";
public static final String KUBERNETES_SCALE_TIMEOUT_SYSTEM_PROPERTY = "kubernetes.scale.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";
Expand Down Expand Up @@ -127,6 +129,8 @@ public class Config extends SundrioConfig {
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_POD_COPY_MAX_FILE_BYTES = -1L;
public static final Long DEFAULT_POD_COPY_MAX_TOTAL_BYTES = -1L;
public static final Long DEFAULT_WEBSOCKET_PING_INTERVAL = 30 * 1000L;

public static final Integer DEFAULT_MAX_CONCURRENT_REQUESTS = 64;
Expand All @@ -145,7 +149,7 @@ public class Config extends SundrioConfig {
private static final int DEFAULT_CONNECTION_TIMEOUT = 10 * 1000;
private static final String DEFAULT_CLIENT_KEY_PASSPHRASE = "changeit";

private RequestConfig requestConfig = new RequestConfig(null, null, null, null, null, null, null, null);
private RequestConfig requestConfig = new RequestConfig(null, null, null, null, null, null, null, null, null, null);

protected static boolean disableAutoConfig() {
return Utils.getSystemPropertyOrEnvVar(KUBERNETES_DISABLE_AUTO_CONFIG_SYSTEM_PROPERTY, false);
Expand Down Expand Up @@ -265,6 +269,8 @@ protected Config(SundrioConfig config, Boolean shouldSetDefaultValues) {
this.setRequestTimeout(DEFAULT_REQUEST_TIMEOUT);
this.setScaleTimeout(DEFAULT_SCALE_TIMEOUT);
this.setLoggingInterval(DEFAULT_LOGGING_INTERVAL);
this.setPodCopyMaxFileBytes(DEFAULT_POD_COPY_MAX_FILE_BYTES);
this.setPodCopyMaxTotalBytes(DEFAULT_POD_COPY_MAX_TOTAL_BYTES);
this.setUserAgent("fabric8-kubernetes-client/" + Version.clientVersion());
this.setTlsVersions(new TlsVersion[] { TlsVersion.TLS_1_3, TlsVersion.TLS_1_2 });
}
Expand Down Expand Up @@ -353,6 +359,12 @@ protected Config(SundrioConfig config, Boolean shouldSetDefaultValues) {
if (config.getUploadRequestTimeout() != null) {
setUploadRequestTimeout(config.getUploadRequestTimeout());
}
if (config.getPodCopyMaxFileBytes() != null) {
setPodCopyMaxFileBytes(config.getPodCopyMaxFileBytes());
}
if (config.getPodCopyMaxTotalBytes() != null) {
setPodCopyMaxTotalBytes(config.getPodCopyMaxTotalBytes());
}
if (Utils.isNotNullOrEmpty(config.getImpersonateUsername())) {
setImpersonateUsername(config.getImpersonateUsername());
}
Expand Down Expand Up @@ -512,6 +524,10 @@ public static void configFromSysPropsOrEnvVars(Config config) {
config.getRequestRetryBackoffLimit()));
config.setRequestRetryBackoffInterval(Utils.getSystemPropertyOrEnvVar(
KUBERNETES_REQUEST_RETRY_BACKOFFINTERVAL_SYSTEM_PROPERTY, config.getRequestRetryBackoffInterval()));
config.setPodCopyMaxFileBytes(parseByteLimit(KUBERNETES_POD_COPY_MAX_FILE_BYTES_SYSTEM_PROPERTY,
config.getPodCopyMaxFileBytes()));
config.setPodCopyMaxTotalBytes(parseByteLimit(KUBERNETES_POD_COPY_MAX_TOTAL_BYTES_SYSTEM_PROPERTY,
config.getPodCopyMaxTotalBytes()));

String configuredWebsocketPingInterval = Utils.getSystemPropertyOrEnvVar(KUBERNETES_WEBSOCKET_PING_INTERVAL_SYSTEM_PROPERTY,
String.valueOf(config.getWebsocketPingInterval()));
Expand Down Expand Up @@ -564,6 +580,23 @@ public static void configFromSysPropsOrEnvVars(Config config) {
}
}

private static Long parseByteLimit(String propertyName, Long defaultValue) {
String value = Utils.getSystemPropertyOrEnvVar(propertyName,
defaultValue == null ? null : String.valueOf(defaultValue));
if (value == null) {
return null;
}
try {
long byteLimit = Long.parseLong(value);
if (byteLimit < -1L) {
throw new IllegalArgumentException(propertyName + " must be -1 or greater");
}
return byteLimit;
} catch (NumberFormatException e) {
throw new IllegalArgumentException(propertyName + " must be a byte count", e);
}
}

private static boolean tryServiceAccount(Config config) {
logger.debug("Trying to configure client from service account...");
String masterHost = Utils.getSystemPropertyOrEnvVar(KUBERNETES_SERVICE_HOST_PROPERTY, (String) null);
Expand Down Expand Up @@ -998,6 +1031,28 @@ public void setLoggingInterval(Integer loggingInterval) {
this.requestConfig.setLoggingInterval(loggingInterval);
}

@Override
@JsonProperty("podCopyMaxFileBytes")
public Long getPodCopyMaxFileBytes() {
return getRequestConfig().getPodCopyMaxFileBytes();
}

@Override
public void setPodCopyMaxFileBytes(Long podCopyMaxFileBytes) {
this.requestConfig.setPodCopyMaxFileBytes(podCopyMaxFileBytes);
}

@Override
@JsonProperty("podCopyMaxTotalBytes")
public Long getPodCopyMaxTotalBytes() {
return getRequestConfig().getPodCopyMaxTotalBytes();
}

@Override
public void setPodCopyMaxTotalBytes(Long podCopyMaxTotalBytes) {
this.requestConfig.setPodCopyMaxTotalBytes(podCopyMaxTotalBytes);
}

@JsonProperty("http2Disable")
public boolean isHttp2Disable() {
return Optional.ofNullable(getHttp2Disable()).orElse(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ public A withLoggingInterval(int loggingInterval) {
return this.withLoggingInterval(Integer.valueOf(loggingInterval));
}

public A withPodCopyMaxFileBytes(long podCopyMaxFileBytes) {
return this.withPodCopyMaxFileBytes(Long.valueOf(podCopyMaxFileBytes));
}

public A withPodCopyMaxTotalBytes(long podCopyMaxTotalBytes) {
return this.withPodCopyMaxTotalBytes(Long.valueOf(podCopyMaxTotalBytes));
}

public A withHttp2Disable(boolean http2Disable) {
return this.withHttp2Disable(Boolean.valueOf(http2Disable));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import java.util.Map;

import static io.fabric8.kubernetes.client.Config.DEFAULT_LOGGING_INTERVAL;
import static io.fabric8.kubernetes.client.Config.DEFAULT_POD_COPY_MAX_FILE_BYTES;
import static io.fabric8.kubernetes.client.Config.DEFAULT_POD_COPY_MAX_TOTAL_BYTES;
import static io.fabric8.kubernetes.client.Config.DEFAULT_REQUEST_RETRY_BACKOFFINTERVAL;
import static io.fabric8.kubernetes.client.Config.DEFAULT_REQUEST_RETRY_BACKOFFLIMIT;
import static io.fabric8.kubernetes.client.Config.DEFAULT_REQUEST_TIMEOUT;
Expand All @@ -46,14 +48,24 @@ public class RequestConfig {
private Integer requestTimeout = DEFAULT_REQUEST_TIMEOUT;
private Long scaleTimeout = DEFAULT_SCALE_TIMEOUT;
private Integer loggingInterval = DEFAULT_LOGGING_INTERVAL;
private Long podCopyMaxFileBytes = DEFAULT_POD_COPY_MAX_FILE_BYTES;
private Long podCopyMaxTotalBytes = DEFAULT_POD_COPY_MAX_TOTAL_BYTES;

RequestConfig() {
}

@Buildable(builderPackage = "io.fabric8.kubernetes.api.builder", editableEnabled = false)
public RequestConfig(Integer watchReconnectLimit, Integer watchReconnectInterval, Integer requestTimeout,
Long scaleTimeout, Integer loggingInterval, Integer requestRetryBackoffLimit,
Integer requestRetryBackoffInterval, Integer uploadRequestTimeout) {
this(watchReconnectLimit, watchReconnectInterval, requestTimeout, scaleTimeout, loggingInterval,
requestRetryBackoffLimit, requestRetryBackoffInterval, uploadRequestTimeout, null, null);
}

@Buildable(builderPackage = "io.fabric8.kubernetes.api.builder", editableEnabled = false)
public RequestConfig(Integer watchReconnectLimit, Integer watchReconnectInterval, Integer requestTimeout,
Long scaleTimeout, Integer loggingInterval, Integer requestRetryBackoffLimit,
Integer requestRetryBackoffInterval, Integer uploadRequestTimeout, Long podCopyMaxFileBytes,
Long podCopyMaxTotalBytes) {
this.watchReconnectLimit = watchReconnectLimit;
this.watchReconnectInterval = watchReconnectInterval;
this.requestTimeout = requestTimeout;
Expand All @@ -62,6 +74,8 @@ public RequestConfig(Integer watchReconnectLimit, Integer watchReconnectInterval
this.requestRetryBackoffLimit = requestRetryBackoffLimit;
this.requestRetryBackoffInterval = requestRetryBackoffInterval;
this.uploadRequestTimeout = uploadRequestTimeout;
this.podCopyMaxFileBytes = podCopyMaxFileBytes;
this.podCopyMaxTotalBytes = podCopyMaxTotalBytes;
}

public Integer getWatchReconnectInterval() {
Expand Down Expand Up @@ -128,6 +142,22 @@ public void setLoggingInterval(Integer loggingInterval) {
this.loggingInterval = loggingInterval;
}

public Long getPodCopyMaxFileBytes() {
return podCopyMaxFileBytes;
}

public void setPodCopyMaxFileBytes(Long podCopyMaxFileBytes) {
this.podCopyMaxFileBytes = podCopyMaxFileBytes;
}

public Long getPodCopyMaxTotalBytes() {
return podCopyMaxTotalBytes;
}

public void setPodCopyMaxTotalBytes(Long podCopyMaxTotalBytes) {
this.podCopyMaxTotalBytes = podCopyMaxTotalBytes;
}

public void setImpersonateUsername(String impersonateUsername) {
this.impersonateUsername = impersonateUsername;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ public class SundrioConfig {
private Integer requestTimeout;
private Long scaleTimeout;
private Integer loggingInterval;
private Long podCopyMaxFileBytes;
private Long podCopyMaxTotalBytes;
private String impersonateUsername;
private String[] impersonateGroups;
private Map<String, List<String>> impersonateExtras;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ void withPrimitiveValues() {
.withRequestTimeout(133709)
.withScaleTimeout(133710)
.withLoggingInterval(133711)
.withPodCopyMaxFileBytes(133712)
.withPodCopyMaxTotalBytes(133713)
.withHttp2Disable(true)
.withOnlyHttpWatches(true);
assertThat(configBuilder.build())
Expand All @@ -55,6 +57,8 @@ void withPrimitiveValues() {
.hasFieldOrPropertyWithValue("requestTimeout", 133709)
.hasFieldOrPropertyWithValue("scaleTimeout", 133710L)
.hasFieldOrPropertyWithValue("loggingInterval", 133711)
.hasFieldOrPropertyWithValue("podCopyMaxFileBytes", 133712L)
.hasFieldOrPropertyWithValue("podCopyMaxTotalBytes", 133713L)
.hasFieldOrPropertyWithValue("http2Disable", Boolean.TRUE)
.hasFieldOrPropertyWithValue("onlyHttpWatches", Boolean.TRUE);
}
Expand All @@ -76,6 +80,8 @@ void withBoxedValues() {
.withRequestTimeout(Integer.valueOf(133709))
.withScaleTimeout(Long.valueOf(133710))
.withLoggingInterval(Integer.valueOf(133711))
.withPodCopyMaxFileBytes(Long.valueOf(133712))
.withPodCopyMaxTotalBytes(Long.valueOf(133713))
.withHttp2Disable(Boolean.TRUE)
.withOnlyHttpWatches(Boolean.TRUE);
assertThat(configBuilder.build())
Expand All @@ -93,6 +99,8 @@ void withBoxedValues() {
.hasFieldOrPropertyWithValue("requestTimeout", 133709)
.hasFieldOrPropertyWithValue("scaleTimeout", 133710L)
.hasFieldOrPropertyWithValue("loggingInterval", 133711)
.hasFieldOrPropertyWithValue("podCopyMaxFileBytes", 133712L)
.hasFieldOrPropertyWithValue("podCopyMaxTotalBytes", 133713L)
.hasFieldOrPropertyWithValue("http2Disable", true)
.hasFieldOrPropertyWithValue("onlyHttpWatches", true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
"kubernetes.max.concurrent.requests",
"kubernetes.max.concurrent.requests.per.host",
"kubernetes.namespace",
"kubernetes.pod.copy.max.file.bytes",
"kubernetes.pod.copy.max.total.bytes",
"kubernetes.request.timeout",
"kubernetes.scale.timeout",
"kubernetes.tls.versions",
Expand Down Expand Up @@ -160,6 +162,8 @@ void setUp() {
System.setProperty("kubernetes.max.concurrent.requests.per.host", "20");
System.setProperty("kubernetes.watch.reconnectInterval", "5000");
System.setProperty("kubernetes.watch.reconnectLimit", "5");
System.setProperty("kubernetes.pod.copy.max.file.bytes", "1234");
System.setProperty("kubernetes.pod.copy.max.total.bytes", "5678");
System.setProperty("kubernetes.request.timeout", "5000");
System.setProperty("http.proxy", "httpProxy");
System.setProperty("kubernetes.tls.versions", "TLSv1.2,TLSv1.1");
Expand Down Expand Up @@ -200,6 +204,8 @@ void defaultConfig_whenInvoked_shouldLoadFromProperties() {
.hasFieldOrPropertyWithValue("httpProxy", "httpProxy")
.hasFieldOrPropertyWithValue("watchReconnectInterval", 5000)
.hasFieldOrPropertyWithValue("watchReconnectLimit", 5)
.hasFieldOrPropertyWithValue("podCopyMaxFileBytes", 1234L)
.hasFieldOrPropertyWithValue("podCopyMaxTotalBytes", 5678L)
.hasFieldOrPropertyWithValue("requestTimeout", 5000)
.hasFieldOrPropertyWithValue("requestConfig.uploadRequestTimeout", 600000)
.hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_2, TlsVersion.TLS_1_1 })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ void hasExpectedNumberOfFields() {
.filter(f -> !Modifier.isStatic(f.getModifiers()))
.collect(Collectors.toList()))
.withFailMessage("You've probably modified SundrioConfig, please update the Config copy constructor as well")
.hasSize(55);
.hasSize(57);
}
}
Loading
Loading