diff --git a/CHANGELOG.md b/CHANGELOG.md index 1797f3d2868..35b9de7a945 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ #### Bugs * Fix #6066: Added support for missing `v1.APIVersions` in KubernetesClient * Fix #6110: VolumeSource (and other file mode fields) in Octal are correctly interpreted +* Fix #6137: `ConfigBuilder.withAutoConfigure` is not working * Fix #6197: JettyHttp client error handling improvements. * Fix #6215: Suppressing rejected execution exception for port forwarder * Fix #6212: Improved reliability of file upload to Pod 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 dbf0fd955fc..08da05bfeb1 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 @@ -37,7 +37,6 @@ import io.fabric8.kubernetes.client.utils.IOHelpers; import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.Utils; -import io.sundr.builder.annotations.Buildable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,7 +68,7 @@ public class Config { private static final Logger LOGGER = LoggerFactory.getLogger(Config.class); /** - * Disables auto-configuration based on opinionated defaults in a {@link Config} object in the default constructor + * Disables auto-configuration based on opinionated defaults in a {@link Config} object in the all arguments constructor */ public static final String KUBERNETES_DISABLE_AUTO_CONFIG_SYSTEM_PROPERTY = "kubernetes.disable.autoConfig"; public static final String KUBERNETES_MASTER_SYSTEM_PROPERTY = "kubernetes.master"; @@ -151,21 +150,24 @@ public class Config { private static final String ACCESS_TOKEN = "access-token"; private static final String ID_TOKEN = "id-token"; - - private boolean trustCerts; - private boolean disableHostnameVerification; - private String masterUrl = DEFAULT_MASTER_URL; - private String apiVersion = "v1"; + private static final int DEFAULT_WATCH_RECONNECT_INTERVAL = 1000; + private static final int DEFAULT_CONNECTION_TIMEOUT = 10 * 1000; + private static final String DEFAULT_CLIENT_KEY_PASSPHRASE = "changeit"; + + private Boolean trustCerts; + private Boolean disableHostnameVerification; + private String masterUrl; + private String apiVersion; private String namespace; - private boolean defaultNamespace = true; + private Boolean defaultNamespace; private String caCertFile; private String caCertData; private String clientCertFile; private String clientCertData; private String clientKeyFile; private String clientKeyData; - private String clientKeyAlgo = "RSA"; - private String clientKeyPassphrase = "changeit"; + private String clientKeyAlgo; + private String clientKeyPassphrase; private String trustStoreFile; private String trustStorePassphrase; private String keyStoreFile; @@ -177,27 +179,27 @@ public class Config { @JsonIgnore private volatile String autoOAuthToken; private OAuthTokenProvider oauthTokenProvider; - private long websocketPingInterval = DEFAULT_WEBSOCKET_PING_INTERVAL; - private int connectionTimeout = 10 * 1000; - private int maxConcurrentRequests = DEFAULT_MAX_CONCURRENT_REQUESTS; - private int maxConcurrentRequestsPerHost = DEFAULT_MAX_CONCURRENT_REQUESTS_PER_HOST; + private Long websocketPingInterval; + private Integer connectionTimeout; + private Integer maxConcurrentRequests; + private Integer maxConcurrentRequestsPerHost; - private RequestConfig requestConfig = new RequestConfig(); + private final RequestConfig requestConfig; - private List contexts = new ArrayList<>(); + private List contexts; private NamedContext currentContext = null; /** * fields not used but needed for builder generation. */ - private int watchReconnectInterval = 1000; - private int watchReconnectLimit = -1; - private int uploadRequestTimeout = DEFAULT_UPLOAD_REQUEST_TIMEOUT; - private int requestRetryBackoffLimit; - private int requestRetryBackoffInterval; - private int requestTimeout = DEFAULT_REQUEST_TIMEOUT; - private long scaleTimeout = DEFAULT_SCALE_TIMEOUT; - private int loggingInterval = DEFAULT_LOGGING_INTERVAL; + private Integer watchReconnectInterval; + private Integer watchReconnectLimit; + private Integer uploadRequestTimeout; + private Integer requestRetryBackoffLimit; + private Integer requestRetryBackoffInterval; + private Integer requestTimeout; + private Long scaleTimeout; + private Integer loggingInterval; private String impersonateUsername; /** @@ -211,16 +213,16 @@ public class Config { * end of fields not used but needed for builder generation. */ - private boolean http2Disable; + private Boolean http2Disable; private String httpProxy; private String httpsProxy; private String proxyUsername; private String proxyPassword; private String[] noProxy; - private String userAgent = "fabric8-kubernetes-client/" + Version.clientVersion(); - private TlsVersion[] tlsVersions = new TlsVersion[] { TlsVersion.TLS_1_3, TlsVersion.TLS_1_2 }; + private String userAgent; + private TlsVersion[] tlsVersions; - private boolean onlyHttpWatches; + private Boolean onlyHttpWatches; /** * @deprecated Use Kubernetes Status directly for extracting error messages. @@ -233,12 +235,12 @@ public class Config { */ private Map customHeaders = null; - private boolean autoConfigure; + private Boolean autoConfigure; private File file; @JsonIgnore - protected Map additionalProperties = new HashMap(); + protected Map additionalProperties = new HashMap<>(); /** * @deprecated use {@link #autoConfigure(String)} or {@link ConfigBuilder} instead @@ -248,14 +250,25 @@ public Config() { this(!disableAutoConfig()); } - private static boolean disableAutoConfig() { + static boolean disableAutoConfig() { return Utils.getSystemPropertyOrEnvVar(KUBERNETES_DISABLE_AUTO_CONFIG_SYSTEM_PROPERTY, false); } private Config(boolean autoConfigure) { - if (autoConfigure) { - autoConfigure(this, null); - } + this(null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, + null, + null, null, null, null, + null, null, null, + null, + null, null, null, null, null, + null, null, null, + null, null, null, + null, null, null, null, + null, autoConfigure, true); } /** @@ -321,7 +334,7 @@ private static String ensureHttps(String masterUrl, Config config) { } @Deprecated - public Config(String masterUrl, String apiVersion, String namespace, boolean trustCerts, boolean disableHostnameVerification, + public Config(String masterUrl, String apiVersion, String namespace, Boolean trustCerts, boolean disableHostnameVerification, String caCertFile, String caCertData, String clientCertFile, String clientCertData, String clientKeyFile, String clientKeyData, String clientKeyAlgo, String clientKeyPassphrase, String username, String password, String oauthToken, String autoOAuthToken, int watchReconnectInterval, int watchReconnectLimit, int connectionTimeout, @@ -342,8 +355,8 @@ public Config(String masterUrl, String apiVersion, String namespace, boolean tru DEFAULT_UPLOAD_REQUEST_TIMEOUT, false, null, Collections.emptyList()); } - @Buildable(builderPackage = "io.fabric8.kubernetes.api.builder", editableEnabled = false) - public Config(String masterUrl, String apiVersion, String namespace, boolean trustCerts, boolean disableHostnameVerification, + @Deprecated + public Config(String masterUrl, String apiVersion, String namespace, Boolean trustCerts, boolean disableHostnameVerification, String caCertFile, String caCertData, String clientCertFile, String clientCertData, String clientKeyFile, String clientKeyData, String clientKeyAlgo, String clientKeyPassphrase, String username, String password, String oauthToken, String autoOAuthToken, int watchReconnectInterval, int watchReconnectLimit, int connectionTimeout, @@ -356,57 +369,238 @@ public Config(String masterUrl, String apiVersion, String namespace, boolean tru OAuthTokenProvider oauthTokenProvider, Map customHeaders, int requestRetryBackoffLimit, int requestRetryBackoffInterval, int uploadRequestTimeout, boolean onlyHttpWatches, NamedContext currentContext, List contexts) { - this.apiVersion = apiVersion; - this.namespace = namespace; - this.trustCerts = trustCerts; - this.disableHostnameVerification = disableHostnameVerification; - this.caCertFile = caCertFile; - this.caCertData = caCertData; - this.clientCertFile = clientCertFile; - this.clientCertData = clientCertData; - this.clientKeyFile = clientKeyFile; - this.clientKeyData = clientKeyData; - this.clientKeyAlgo = clientKeyAlgo; - this.clientKeyPassphrase = clientKeyPassphrase; - this.username = username; - this.password = password; - this.oauthToken = oauthToken; - this.websocketPingInterval = websocketPingInterval; - this.connectionTimeout = connectionTimeout; + this(masterUrl, apiVersion, namespace, trustCerts, disableHostnameVerification, caCertFile, caCertData, + clientCertFile, clientCertData, clientKeyFile, clientKeyData, clientKeyAlgo, clientKeyPassphrase, username, + password, oauthToken, autoOAuthToken, watchReconnectInterval, watchReconnectLimit, connectionTimeout, requestTimeout, + scaleTimeout, loggingInterval, maxConcurrentRequests, maxConcurrentRequestsPerHost, http2Disable, + httpProxy, httpsProxy, noProxy, userAgent, tlsVersions, websocketPingInterval, proxyUsername, proxyPassword, + trustStoreFile, trustStorePassphrase, keyStoreFile, keyStorePassphrase, impersonateUsername, impersonateGroups, + impersonateExtras, oauthTokenProvider, customHeaders, requestRetryBackoffLimit, requestRetryBackoffInterval, + uploadRequestTimeout, onlyHttpWatches, currentContext, contexts, false, true); + } - this.requestConfig = new RequestConfig(watchReconnectLimit, watchReconnectInterval, - requestTimeout, scaleTimeout, loggingInterval, - requestRetryBackoffLimit, requestRetryBackoffInterval, uploadRequestTimeout); - this.requestConfig.setImpersonateUsername(impersonateUsername); - this.requestConfig.setImpersonateGroups(impersonateGroups); - this.requestConfig.setImpersonateExtras(impersonateExtras); + public Config(String masterUrl, String apiVersion, String namespace, Boolean trustCerts, Boolean disableHostnameVerification, + String caCertFile, String caCertData, String clientCertFile, String clientCertData, String clientKeyFile, + String clientKeyData, String clientKeyAlgo, String clientKeyPassphrase, String username, String password, + String oauthToken, String autoOAuthToken, Integer watchReconnectInterval, Integer watchReconnectLimit, + Integer connectionTimeout, + Integer requestTimeout, + Long scaleTimeout, Integer loggingInterval, Integer maxConcurrentRequests, Integer maxConcurrentRequestsPerHost, + Boolean http2Disable, String httpProxy, String httpsProxy, String[] noProxy, + 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, Integer requestRetryBackoffLimit, + Integer requestRetryBackoffInterval, Integer uploadRequestTimeout, Boolean onlyHttpWatches, NamedContext currentContext, + List contexts, Boolean autoConfigure) { + this(masterUrl, apiVersion, namespace, trustCerts, disableHostnameVerification, caCertFile, caCertData, + clientCertFile, clientCertData, clientKeyFile, clientKeyData, clientKeyAlgo, clientKeyPassphrase, username, + password, oauthToken, autoOAuthToken, watchReconnectInterval, watchReconnectLimit, connectionTimeout, requestTimeout, + scaleTimeout, loggingInterval, maxConcurrentRequests, maxConcurrentRequestsPerHost, http2Disable, + httpProxy, httpsProxy, noProxy, userAgent, tlsVersions, websocketPingInterval, proxyUsername, proxyPassword, + trustStoreFile, trustStorePassphrase, keyStoreFile, keyStorePassphrase, impersonateUsername, impersonateGroups, + impersonateExtras, oauthTokenProvider, customHeaders, requestRetryBackoffLimit, requestRetryBackoffInterval, + uploadRequestTimeout, onlyHttpWatches, currentContext, contexts, autoConfigure, true); + } - this.http2Disable = http2Disable; - this.httpProxy = httpProxy; - this.httpsProxy = httpsProxy; - this.noProxy = noProxy; - this.proxyUsername = proxyUsername; - this.proxyPassword = proxyPassword; - this.errorMessages = errorMessages; - this.userAgent = userAgent; - this.tlsVersions = tlsVersions; - this.trustStoreFile = trustStoreFile; - this.trustStorePassphrase = trustStorePassphrase; - this.keyStoreFile = keyStoreFile; - this.keyStorePassphrase = keyStorePassphrase; + /* + * The Builder is generated in SundrioConfig, if new fields need to be added here, please make sure to add them there too. + */ + Config(String masterUrl, String apiVersion, String namespace, Boolean trustCerts, Boolean disableHostnameVerification, + String caCertFile, String caCertData, String clientCertFile, String clientCertData, String clientKeyFile, + String clientKeyData, String clientKeyAlgo, String clientKeyPassphrase, String username, String password, + String oauthToken, String autoOAuthToken, Integer watchReconnectInterval, Integer watchReconnectLimit, + Integer connectionTimeout, + Integer requestTimeout, + Long scaleTimeout, Integer loggingInterval, Integer maxConcurrentRequests, Integer maxConcurrentRequestsPerHost, + Boolean http2Disable, String httpProxy, String httpsProxy, String[] noProxy, + 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, Integer requestRetryBackoffLimit, + Integer requestRetryBackoffInterval, Integer uploadRequestTimeout, Boolean onlyHttpWatches, NamedContext currentContext, + List contexts, Boolean autoConfigure, Boolean shouldSetDefaultValues) { + if (Boolean.TRUE.equals(shouldSetDefaultValues)) { + this.masterUrl = DEFAULT_MASTER_URL; + this.apiVersion = "v1"; + this.defaultNamespace = true; + this.trustCerts = false; + this.disableHostnameVerification = false; + this.onlyHttpWatches = false; + this.http2Disable = false; + this.clientKeyAlgo = "RSA"; + this.clientKeyPassphrase = DEFAULT_CLIENT_KEY_PASSPHRASE; + this.websocketPingInterval = DEFAULT_WEBSOCKET_PING_INTERVAL; + this.connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; + this.maxConcurrentRequests = DEFAULT_MAX_CONCURRENT_REQUESTS; + this.maxConcurrentRequestsPerHost = DEFAULT_MAX_CONCURRENT_REQUESTS_PER_HOST; + this.contexts = new ArrayList<>(); + this.watchReconnectInterval = DEFAULT_WATCH_RECONNECT_INTERVAL; + this.watchReconnectLimit = -1; + this.uploadRequestTimeout = DEFAULT_UPLOAD_REQUEST_TIMEOUT; + this.requestRetryBackoffInterval = DEFAULT_REQUEST_RETRY_BACKOFFINTERVAL; + this.requestRetryBackoffLimit = DEFAULT_REQUEST_RETRY_BACKOFFLIMIT; + this.requestTimeout = DEFAULT_REQUEST_TIMEOUT; + this.scaleTimeout = DEFAULT_SCALE_TIMEOUT; + this.loggingInterval = DEFAULT_LOGGING_INTERVAL; + this.userAgent = "fabric8-kubernetes-client/" + Version.clientVersion(); + this.tlsVersions = new TlsVersion[] { TlsVersion.TLS_1_3, TlsVersion.TLS_1_2 }; + this.requestConfig = new RequestConfig(this.watchReconnectLimit, this.watchReconnectInterval, + this.requestTimeout, this.scaleTimeout, this.loggingInterval, + this.requestRetryBackoffLimit, this.requestRetryBackoffInterval, this.uploadRequestTimeout); + } else { + this.requestConfig = new RequestConfig(null, null, null, null, null, null, null, null); + } + + if (Boolean.TRUE.equals(autoConfigure)) { + autoConfigure(this, null); + } + if (Utils.isNotNullOrEmpty(apiVersion)) { + this.apiVersion = apiVersion; + } + if (Utils.isNotNullOrEmpty(masterUrl)) { + this.masterUrl = masterUrl; + } + if (Utils.isNotNullOrEmpty(namespace)) { + this.namespace = namespace; + } + if (Boolean.TRUE.equals(trustCerts)) { + this.trustCerts = true; + } + if (Boolean.TRUE.equals(disableHostnameVerification)) { + this.disableHostnameVerification = true; + } + if (Utils.isNotNullOrEmpty(caCertFile)) { + this.caCertFile = caCertFile; + } + if (Utils.isNotNullOrEmpty(caCertData)) { + this.caCertData = caCertData; + } + if (Utils.isNotNullOrEmpty(clientCertFile)) { + this.clientCertFile = clientCertFile; + } + if (Utils.isNotNullOrEmpty(clientCertData)) { + this.clientCertData = clientCertData; + } + if (Utils.isNotNullOrEmpty(clientKeyFile)) { + this.clientKeyFile = clientKeyFile; + } + if (Utils.isNotNullOrEmpty(clientKeyData)) { + this.clientKeyData = clientKeyData; + } + if (Utils.isNotNullOrEmpty(clientKeyAlgo)) { + this.clientKeyAlgo = clientKeyAlgo; + } + if (Utils.isNotNullOrEmpty(clientKeyPassphrase)) { + this.clientKeyPassphrase = clientKeyPassphrase; + } + if (Utils.isNotNullOrEmpty(username)) { + this.username = username; + } + if (Utils.isNotNullOrEmpty(password)) { + this.password = password; + } + if (Utils.isNotNullOrEmpty(oauthToken)) { + this.oauthToken = oauthToken; + } + if (websocketPingInterval != null) { + this.websocketPingInterval = websocketPingInterval; + } + if (connectionTimeout != null) { + this.connectionTimeout = connectionTimeout; + } + if (watchReconnectLimit != null) { + setWatchReconnectLimit(watchReconnectLimit); + } + if (watchReconnectInterval != null) { + setWatchReconnectInterval(watchReconnectInterval); + } + if (requestTimeout != null) { + setRequestTimeout(requestTimeout); + } + if (scaleTimeout != null) { + setScaleTimeout(scaleTimeout); + } + if (loggingInterval != null) { + setLoggingInterval(loggingInterval); + } + if (requestRetryBackoffLimit != null) { + setRequestRetryBackoffLimit(requestRetryBackoffLimit); + } + if (requestRetryBackoffInterval != null) { + setRequestRetryBackoffInterval(requestRetryBackoffInterval); + } + if (uploadRequestTimeout != null) { + setUploadRequestTimeout(uploadRequestTimeout); + } + if (Utils.isNotNullOrEmpty(impersonateUsername)) { + setImpersonateUsername(impersonateUsername); + } + if (Utils.isNotNullOrEmpty(impersonateGroups)) { + setImpersonateGroups(impersonateGroups); + } + if (Utils.isNotNullOrEmpty(impersonateExtras)) { + setImpersonateExtras(impersonateExtras); + } + if (http2Disable != null) { + this.http2Disable = http2Disable; + } + if (Utils.isNotNullOrEmpty(httpProxy)) { + this.httpProxy = httpProxy; + } + if (Utils.isNotNullOrEmpty(httpsProxy)) { + this.httpsProxy = httpsProxy; + } + if (Utils.isNotNullOrEmpty(noProxy)) { + this.noProxy = noProxy; + } + if (Utils.isNotNullOrEmpty(proxyUsername)) { + this.proxyUsername = proxyUsername; + } + if (Utils.isNotNullOrEmpty(proxyPassword)) { + this.proxyPassword = proxyPassword; + } + if (Utils.isNotNullOrEmpty(userAgent)) { + this.userAgent = userAgent; + } + if (tlsVersions != null && tlsVersions.length > 0) { + this.tlsVersions = tlsVersions; + } + if (Utils.isNotNullOrEmpty(trustStoreFile)) { + this.trustStoreFile = trustStoreFile; + } + if (Utils.isNotNullOrEmpty(trustStorePassphrase)) { + this.trustStorePassphrase = trustStorePassphrase; + } + if (Utils.isNotNullOrEmpty(keyStoreFile)) { + this.keyStoreFile = keyStoreFile; + } + if (Utils.isNotNullOrEmpty(keyStorePassphrase)) { + this.keyStorePassphrase = keyStorePassphrase; + } + if (maxConcurrentRequests != null) { + this.maxConcurrentRequests = maxConcurrentRequests; + } + if (maxConcurrentRequestsPerHost != null) { + this.maxConcurrentRequestsPerHost = maxConcurrentRequestsPerHost; + } + if (Utils.isNotNullOrEmpty(autoOAuthToken)) { + this.autoOAuthToken = autoOAuthToken; + } + if (contexts != null && !contexts.isEmpty()) { + this.contexts = contexts; + } + if (Utils.isNotNull(currentContext)) { + this.currentContext = currentContext; + } + + if (Utils.isNotNullOrEmpty(this.masterUrl)) { + this.masterUrl = ensureEndsWithSlash(ensureHttps(this.masterUrl, this)); + } + this.autoConfigure = autoConfigure; this.oauthTokenProvider = oauthTokenProvider; this.customHeaders = customHeaders; - - //We need to keep this after ssl configuration & masterUrl - //We set the masterUrl because it's needed by ensureHttps - this.masterUrl = masterUrl; - this.masterUrl = ensureEndsWithSlash(ensureHttps(masterUrl, this)); - this.maxConcurrentRequests = maxConcurrentRequests; - this.maxConcurrentRequestsPerHost = maxConcurrentRequestsPerHost; - this.autoOAuthToken = autoOAuthToken; this.onlyHttpWatches = onlyHttpWatches; - this.contexts = contexts; - this.currentContext = currentContext; } public static void configFromSysPropsOrEnvVars(Config config) { @@ -450,7 +644,7 @@ public static void configFromSysPropsOrEnvVars(Config config) { String configuredImpersonateGroups = Utils.getSystemPropertyOrEnvVar(KUBERNETES_IMPERSONATE_GROUP, Arrays .stream(Optional.ofNullable(config.getImpersonateGroups()).orElse(new String[0])).collect(Collectors.joining(","))); - if (configuredImpersonateGroups != null) { + if (Utils.isNotNullOrEmpty(configuredImpersonateGroups)) { config.setImpersonateGroups(configuredImpersonateGroups.split(",")); } @@ -1156,6 +1350,10 @@ public void setMasterUrl(String masterUrl) { @JsonProperty("trustCerts") public boolean isTrustCerts() { + return Optional.ofNullable(trustCerts).orElse(false); + } + + Boolean getTrustCerts() { return trustCerts; } @@ -1165,6 +1363,10 @@ public void setTrustCerts(boolean trustCerts) { @JsonProperty("disableHostnameVerification") public boolean isDisableHostnameVerification() { + return Optional.ofNullable(disableHostnameVerification).orElse(false); + } + + Boolean getDisableHostnameVerification() { return disableHostnameVerification; } @@ -1173,20 +1375,20 @@ public void setDisableHostnameVerification(boolean disableHostnameVerification) } @JsonProperty("watchReconnectInterval") - public int getWatchReconnectInterval() { + public Integer getWatchReconnectInterval() { return requestConfig.getWatchReconnectInterval(); } - public void setWatchReconnectInterval(int watchReconnectInterval) { + public void setWatchReconnectInterval(Integer watchReconnectInterval) { this.requestConfig.setWatchReconnectInterval(watchReconnectInterval); } @JsonProperty("watchReconnectLimit") - public int getWatchReconnectLimit() { + public Integer getWatchReconnectLimit() { return getRequestConfig().getWatchReconnectLimit(); } - public void setWatchReconnectLimit(int watchReconnectLimit) { + public void setWatchReconnectLimit(Integer watchReconnectLimit) { this.requestConfig.setWatchReconnectLimit(watchReconnectLimit); } @@ -1209,74 +1411,78 @@ public static ConfigBuilder builder() { } @JsonProperty("connectionTimeout") - public int getConnectionTimeout() { + public Integer getConnectionTimeout() { return connectionTimeout; } - public void setConnectionTimeout(int connectionTimeout) { + public void setConnectionTimeout(Integer connectionTimeout) { this.connectionTimeout = connectionTimeout; } @JsonProperty("uploadRequestTimeout") - public int getUploadRequestTimeout() { + public Integer getUploadRequestTimeout() { return getRequestConfig().getUploadRequestTimeout(); } - public void setUploadRequestTimeout(int requestTimeout) { + public void setUploadRequestTimeout(Integer requestTimeout) { this.requestConfig.setUploadRequestTimeout(requestTimeout); } @JsonProperty("requestTimeout") - public int getRequestTimeout() { + public Integer getRequestTimeout() { return getRequestConfig().getRequestTimeout(); } - public void setRequestTimeout(int requestTimeout) { + public void setRequestTimeout(Integer requestTimeout) { this.requestConfig.setRequestTimeout(requestTimeout); } @JsonProperty("requestRetryBackoffLimit") - public int getRequestRetryBackoffLimit() { + public Integer getRequestRetryBackoffLimit() { return getRequestConfig().getRequestRetryBackoffLimit(); } - public void setRequestRetryBackoffLimit(int requestRetryBackoffLimit) { + public void setRequestRetryBackoffLimit(Integer requestRetryBackoffLimit) { requestConfig.setRequestRetryBackoffLimit(requestRetryBackoffLimit); } @JsonProperty("requestRetryBackoffInterval") - public int getRequestRetryBackoffInterval() { + public Integer getRequestRetryBackoffInterval() { return getRequestConfig().getRequestRetryBackoffInterval(); } - public void setRequestRetryBackoffInterval(int requestRetryBackoffInterval) { + public void setRequestRetryBackoffInterval(Integer requestRetryBackoffInterval) { requestConfig.setRequestRetryBackoffInterval(requestRetryBackoffInterval); } @JsonProperty("scaleTimeout") - public long getScaleTimeout() { + public Long getScaleTimeout() { return getRequestConfig().getScaleTimeout(); } - public void setScaleTimeout(long scaleTimeout) { + public void setScaleTimeout(Long scaleTimeout) { this.requestConfig.setScaleTimeout(scaleTimeout); } @JsonProperty("loggingInterval") - public int getLoggingInterval() { + public Integer getLoggingInterval() { return getRequestConfig().getLoggingInterval(); } - public void setLoggingInterval(int loggingInterval) { + public void setLoggingInterval(Integer loggingInterval) { this.requestConfig.setLoggingInterval(loggingInterval); } @JsonProperty("http2Disable") public boolean isHttp2Disable() { + return Optional.ofNullable(http2Disable).orElse(false); + } + + Boolean getHttp2Disable() { return http2Disable; } - public void setHttp2Disable(boolean http2Disable) { + public void setHttp2Disable(Boolean http2Disable) { this.http2Disable = http2Disable; } @@ -1318,7 +1524,7 @@ public void setNamespace(String namespace) { @JsonProperty("defaultNamespace") public boolean isDefaultNamespace() { - return defaultNamespace; + return Optional.ofNullable(defaultNamespace).orElse(true); } public void setDefaultNamespace(boolean defaultNamespace) { @@ -1344,27 +1550,27 @@ public void setTlsVersions(TlsVersion[] tlsVersions) { } @JsonProperty("websocketPingInterval") - public long getWebsocketPingInterval() { + public Long getWebsocketPingInterval() { return websocketPingInterval; } - public void setWebsocketPingInterval(long websocketPingInterval) { + public void setWebsocketPingInterval(Long websocketPingInterval) { this.websocketPingInterval = websocketPingInterval; } - public int getMaxConcurrentRequests() { + public Integer getMaxConcurrentRequests() { return maxConcurrentRequests; } - public void setMaxConcurrentRequests(int maxConcurrentRequests) { + public void setMaxConcurrentRequests(Integer maxConcurrentRequests) { this.maxConcurrentRequests = maxConcurrentRequests; } - public int getMaxConcurrentRequestsPerHost() { + public Integer getMaxConcurrentRequestsPerHost() { return maxConcurrentRequestsPerHost; } - public void setMaxConcurrentRequestsPerHost(int maxConcurrentRequestsPerHost) { + public void setMaxConcurrentRequestsPerHost(Integer maxConcurrentRequestsPerHost) { this.maxConcurrentRequestsPerHost = maxConcurrentRequestsPerHost; } @@ -1444,7 +1650,7 @@ public void setCustomHeaders(Map customHeaders) { this.customHeaders = customHeaders; } - public boolean getAutoConfigure() { + public Boolean getAutoConfigure() { return autoConfigure; } @@ -1528,7 +1734,7 @@ public void setAutoOAuthToken(String autoOAuthToken) { } public boolean isOnlyHttpWatches() { - return onlyHttpWatches; + return Optional.ofNullable(onlyHttpWatches).orElse(false); } public void setOnlyHttpWatches(boolean onlyHttpWatches) { diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigBuilder.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigBuilder.java new file mode 100644 index 00000000000..a829b7ac6ed --- /dev/null +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigBuilder.java @@ -0,0 +1,65 @@ +/* + * 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; + +import io.fabric8.kubernetes.api.builder.VisitableBuilder; + +import java.util.Optional; + +import static io.fabric8.kubernetes.client.Config.disableAutoConfig; + +public class ConfigBuilder extends ConfigFluent implements VisitableBuilder { + public ConfigBuilder() { + this.fluent = this; + } + + public ConfigBuilder(ConfigFluent fluent) { + this.fluent = fluent; + } + + public ConfigBuilder(ConfigFluent fluent, Config instance) { + this.fluent = fluent; + fluent.copyInstance(instance); + } + + public ConfigBuilder(Config instance) { + this.fluent = this; + this.copyInstance(instance); + } + + ConfigFluent fluent; + + public Config build() { + Config buildable = new Config(fluent.getMasterUrl(), fluent.getApiVersion(), fluent.getNamespace(), fluent.getTrustCerts(), + fluent.getDisableHostnameVerification(), fluent.getCaCertFile(), fluent.getCaCertData(), fluent.getClientCertFile(), + fluent.getClientCertData(), fluent.getClientKeyFile(), fluent.getClientKeyData(), fluent.getClientKeyAlgo(), + fluent.getClientKeyPassphrase(), fluent.getUsername(), fluent.getPassword(), fluent.getOauthToken(), + fluent.getAutoOAuthToken(), fluent.getWatchReconnectInterval(), fluent.getWatchReconnectLimit(), + fluent.getConnectionTimeout(), fluent.getRequestTimeout(), fluent.getScaleTimeout(), fluent.getLoggingInterval(), + fluent.getMaxConcurrentRequests(), fluent.getMaxConcurrentRequestsPerHost(), fluent.getHttp2Disable(), + fluent.getHttpProxy(), fluent.getHttpsProxy(), fluent.getNoProxy(), fluent.getUserAgent(), fluent.getTlsVersions(), + fluent.getWebsocketPingInterval(), fluent.getProxyUsername(), fluent.getProxyPassword(), fluent.getTrustStoreFile(), + fluent.getTrustStorePassphrase(), fluent.getKeyStoreFile(), fluent.getKeyStorePassphrase(), + fluent.getImpersonateUsername(), fluent.getImpersonateGroups(), fluent.getImpersonateExtras(), + fluent.getOauthTokenProvider(), fluent.getCustomHeaders(), fluent.getRequestRetryBackoffLimit(), + fluent.getRequestRetryBackoffInterval(), fluent.getUploadRequestTimeout(), fluent.getOnlyHttpWatches(), + fluent.getCurrentContext(), fluent.getContexts(), + Optional.ofNullable(fluent.getAutoConfigure()).orElse(!disableAutoConfig()), true); + buildable.setAuthProvider(fluent.getAuthProvider()); + buildable.setFile(fluent.getFile()); + return buildable; + } +} diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigFluent.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigFluent.java new file mode 100644 index 00000000000..73578677970 --- /dev/null +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/ConfigFluent.java @@ -0,0 +1,84 @@ +/* + * 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; + +public class ConfigFluent> extends SundrioConfigFluent { + public ConfigFluent() { + super(); + } + + public ConfigFluent(Config instance) { + super(); + this.copyInstance(instance); + } + + public void copyInstance(Config instance) { + if (instance != null) { + this.withMasterUrl(instance.getMasterUrl()); + this.withApiVersion(instance.getApiVersion()); + this.withNamespace(instance.getNamespace()); + this.withTrustCerts(instance.isTrustCerts()); + this.withDisableHostnameVerification(instance.isDisableHostnameVerification()); + this.withCaCertFile(instance.getCaCertFile()); + this.withCaCertData(instance.getCaCertData()); + this.withClientCertFile(instance.getClientCertFile()); + this.withClientCertData(instance.getClientCertData()); + this.withClientKeyFile(instance.getClientKeyFile()); + this.withClientKeyData(instance.getClientKeyData()); + this.withClientKeyAlgo(instance.getClientKeyAlgo()); + this.withClientKeyPassphrase(instance.getClientKeyPassphrase()); + this.withUsername(instance.getUsername()); + this.withPassword(instance.getPassword()); + this.withOauthToken(instance.getOauthToken()); + this.withAutoOAuthToken(instance.getAutoOAuthToken()); + this.withWatchReconnectInterval(instance.getWatchReconnectInterval()); + this.withWatchReconnectLimit(instance.getWatchReconnectLimit()); + this.withConnectionTimeout(instance.getConnectionTimeout()); + this.withRequestTimeout(instance.getRequestTimeout()); + this.withScaleTimeout(instance.getScaleTimeout()); + this.withLoggingInterval(instance.getLoggingInterval()); + this.withMaxConcurrentRequests(instance.getMaxConcurrentRequests()); + this.withMaxConcurrentRequestsPerHost(instance.getMaxConcurrentRequestsPerHost()); + this.withHttp2Disable(instance.isHttp2Disable()); + this.withHttpProxy(instance.getHttpProxy()); + this.withHttpsProxy(instance.getHttpsProxy()); + this.withNoProxy(instance.getNoProxy()); + this.withUserAgent(instance.getUserAgent()); + this.withTlsVersions(instance.getTlsVersions()); + this.withWebsocketPingInterval(instance.getWebsocketPingInterval()); + this.withProxyUsername(instance.getProxyUsername()); + this.withProxyPassword(instance.getProxyPassword()); + this.withTrustStoreFile(instance.getTrustStoreFile()); + this.withTrustStorePassphrase(instance.getTrustStorePassphrase()); + this.withKeyStoreFile(instance.getKeyStoreFile()); + this.withKeyStorePassphrase(instance.getKeyStorePassphrase()); + this.withImpersonateUsername(instance.getImpersonateUsername()); + this.withImpersonateGroups(instance.getImpersonateGroups()); + this.withImpersonateExtras(instance.getImpersonateExtras()); + this.withOauthTokenProvider(instance.getOauthTokenProvider()); + this.withCustomHeaders(instance.getCustomHeaders()); + this.withRequestRetryBackoffLimit(instance.getRequestRetryBackoffLimit()); + this.withRequestRetryBackoffInterval(instance.getRequestRetryBackoffInterval()); + this.withUploadRequestTimeout(instance.getUploadRequestTimeout()); + this.withOnlyHttpWatches(instance.isOnlyHttpWatches()); + this.withCurrentContext(instance.getCurrentContext()); + this.withContexts(instance.getContexts()); + this.withAutoConfigure(instance.getAutoConfigure()); + this.withAuthProvider(instance.getAuthProvider()); + this.withFile(instance.getFile()); + } + } +} 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 cd0109381b2..92c4a5f31c3 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 @@ -37,22 +37,22 @@ public class RequestConfig { private String[] impersonateGroups = new String[0]; private Map> impersonateExtras = new HashMap<>(); - private int watchReconnectInterval = 1000; - private int watchReconnectLimit = -1; - private int uploadRequestTimeout = DEFAULT_UPLOAD_REQUEST_TIMEOUT; - private int requestRetryBackoffLimit = DEFAULT_REQUEST_RETRY_BACKOFFLIMIT; - private int requestRetryBackoffInterval = DEFAULT_REQUEST_RETRY_BACKOFFINTERVAL; - private int requestTimeout = DEFAULT_REQUEST_TIMEOUT; - private long scaleTimeout = DEFAULT_SCALE_TIMEOUT; - private int loggingInterval = DEFAULT_LOGGING_INTERVAL; + private Integer watchReconnectInterval = 1000; + private Integer watchReconnectLimit = -1; + private Integer uploadRequestTimeout = DEFAULT_UPLOAD_REQUEST_TIMEOUT; + private Integer requestRetryBackoffLimit = DEFAULT_REQUEST_RETRY_BACKOFFLIMIT; + private Integer requestRetryBackoffInterval = DEFAULT_REQUEST_RETRY_BACKOFFINTERVAL; + private Integer requestTimeout = DEFAULT_REQUEST_TIMEOUT; + private Long scaleTimeout = DEFAULT_SCALE_TIMEOUT; + private Integer loggingInterval = DEFAULT_LOGGING_INTERVAL; RequestConfig() { } @Buildable(builderPackage = "io.fabric8.kubernetes.api.builder", editableEnabled = false) - public RequestConfig(int watchReconnectLimit, int watchReconnectInterval, int requestTimeout, - long scaleTimeout, int loggingInterval, int requestRetryBackoffLimit, - int requestRetryBackoffInterval, int uploadRequestTimeout) { + public RequestConfig(Integer watchReconnectLimit, Integer watchReconnectInterval, Integer requestTimeout, + Long scaleTimeout, Integer loggingInterval, Integer requestRetryBackoffLimit, + Integer requestRetryBackoffInterval, Integer uploadRequestTimeout) { this.watchReconnectLimit = watchReconnectLimit; this.watchReconnectInterval = watchReconnectInterval; this.requestTimeout = requestTimeout; @@ -63,67 +63,67 @@ public RequestConfig(int watchReconnectLimit, int watchReconnectInterval, int re this.uploadRequestTimeout = uploadRequestTimeout; } - public int getWatchReconnectInterval() { + public Integer getWatchReconnectInterval() { return watchReconnectInterval; } - public void setWatchReconnectInterval(int watchReconnectInterval) { + public void setWatchReconnectInterval(Integer watchReconnectInterval) { this.watchReconnectInterval = watchReconnectInterval; } - public int getWatchReconnectLimit() { + public Integer getWatchReconnectLimit() { return watchReconnectLimit; } - public void setWatchReconnectLimit(int watchReconnectLimit) { + public void setWatchReconnectLimit(Integer watchReconnectLimit) { this.watchReconnectLimit = watchReconnectLimit; } - public int getRequestTimeout() { + public Integer getRequestTimeout() { return requestTimeout; } - public void setRequestTimeout(int requestTimeout) { + public void setRequestTimeout(Integer requestTimeout) { this.requestTimeout = requestTimeout; } - public int getRequestRetryBackoffLimit() { + public Integer getRequestRetryBackoffLimit() { return requestRetryBackoffLimit; } - public void setRequestRetryBackoffLimit(int requestRetryBackoffLimit) { + public void setRequestRetryBackoffLimit(Integer requestRetryBackoffLimit) { this.requestRetryBackoffLimit = requestRetryBackoffLimit; } - public int getRequestRetryBackoffInterval() { + public Integer getRequestRetryBackoffInterval() { return requestRetryBackoffInterval; } - public void setRequestRetryBackoffInterval(int requestRetryBackoffInterval) { + public void setRequestRetryBackoffInterval(Integer requestRetryBackoffInterval) { this.requestRetryBackoffInterval = requestRetryBackoffInterval; } - public int getUploadRequestTimeout() { + public Integer getUploadRequestTimeout() { return uploadRequestTimeout; } - public void setUploadRequestTimeout(int uploadRequestTimeout) { + public void setUploadRequestTimeout(Integer uploadRequestTimeout) { this.uploadRequestTimeout = uploadRequestTimeout; } - public long getScaleTimeout() { + public Long getScaleTimeout() { return scaleTimeout; } - public void setScaleTimeout(long scaleTimeout) { + public void setScaleTimeout(Long scaleTimeout) { this.scaleTimeout = scaleTimeout; } - public int getLoggingInterval() { + public Integer getLoggingInterval() { return loggingInterval; } - public void setLoggingInterval(int loggingInterval) { + public void setLoggingInterval(Integer loggingInterval) { this.loggingInterval = loggingInterval; } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/SundrioConfig.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/SundrioConfig.java new file mode 100644 index 00000000000..d6c027f3b3a --- /dev/null +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/SundrioConfig.java @@ -0,0 +1,63 @@ +/* + * 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; + +import io.fabric8.kubernetes.api.model.NamedContext; +import io.fabric8.kubernetes.client.http.TlsVersion; +import io.sundr.builder.annotations.Buildable; + +import java.util.List; +import java.util.Map; + +/** + * This class is necessary to be able to autogenerate a builder for the Config class using Sundrio while providing + * specific behavior for the build() method. + * + * This way we can extend the default SundrioConfigBuilder, overriding the build method and enabling autoconfiguration only in + * this case. + * + * The builder is also capable of having a state of the Config with null values (no defaults or autoconfigured). + * + * The end purpose is for users to actually use the builder to override the default values or autoconfigured ones + * by providing their values through the builder withXxx accessors + */ +class SundrioConfig extends Config { + @Buildable(builderPackage = "io.fabric8.kubernetes.api.builder", editableEnabled = false) + public SundrioConfig(String masterUrl, String apiVersion, String namespace, Boolean trustCerts, + Boolean disableHostnameVerification, + String caCertFile, String caCertData, String clientCertFile, String clientCertData, String clientKeyFile, + String clientKeyData, String clientKeyAlgo, String clientKeyPassphrase, String username, String password, + String oauthToken, String autoOAuthToken, Integer watchReconnectInterval, Integer watchReconnectLimit, + Integer connectionTimeout, + Integer requestTimeout, + Long scaleTimeout, Integer loggingInterval, Integer maxConcurrentRequests, Integer maxConcurrentRequestsPerHost, + Boolean http2Disable, String httpProxy, String httpsProxy, String[] noProxy, + 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, Integer requestRetryBackoffLimit, + Integer requestRetryBackoffInterval, Integer uploadRequestTimeout, Boolean onlyHttpWatches, NamedContext currentContext, + List contexts, Boolean autoConfigure) { + super(masterUrl, apiVersion, namespace, trustCerts, disableHostnameVerification, caCertFile, caCertData, + clientCertFile, clientCertData, clientKeyFile, clientKeyData, clientKeyAlgo, clientKeyPassphrase, username, + password, oauthToken, autoOAuthToken, watchReconnectInterval, watchReconnectLimit, connectionTimeout, requestTimeout, + scaleTimeout, loggingInterval, maxConcurrentRequests, maxConcurrentRequestsPerHost, http2Disable, + httpProxy, httpsProxy, noProxy, userAgent, tlsVersions, websocketPingInterval, proxyUsername, proxyPassword, + trustStoreFile, trustStorePassphrase, keyStoreFile, keyStorePassphrase, impersonateUsername, impersonateGroups, + impersonateExtras, oauthTokenProvider, customHeaders, requestRetryBackoffLimit, requestRetryBackoffInterval, + uploadRequestTimeout, onlyHttpWatches, currentContext, contexts, autoConfigure, true); + } +} diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigConstructorTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigConstructorTest.java new file mode 100644 index 00000000000..9caaafed939 --- /dev/null +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigConstructorTest.java @@ -0,0 +1,573 @@ +/* + * 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; + +import io.fabric8.kubernetes.client.http.TlsVersion; +import io.fabric8.kubernetes.client.utils.Utils; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; + +class ConfigConstructorTest { + @Test + @DisplayName("empty configuration, no default values, no auto configured values") + void emptyConfiguration() { + // Given + When + Config config = new Config(null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, + null, + null, null, null, null, + null, null, null, + null, + null, null, null, null, null, + null, null, null, + null, null, null, + null, null, null, null, + null, null, false); + + // Then + assertThat(config) + .isNotNull() + .satisfies(c -> assertThat(c.getTrustCerts()).isNull()) + .satisfies(c -> assertThat(c.getDisableHostnameVerification()).isNull()) + .hasFieldOrPropertyWithValue("masterUrl", null) + .hasFieldOrPropertyWithValue("namespace", null) + .hasFieldOrPropertyWithValue("username", null) + .hasFieldOrPropertyWithValue("password", null) + .hasFieldOrPropertyWithValue("caCertFile", null) + .hasFieldOrPropertyWithValue("caCertData", null) + .hasFieldOrPropertyWithValue("clientCertFile", null) + .hasFieldOrPropertyWithValue("clientCertData", null) + .hasFieldOrPropertyWithValue("clientKeyFile", null) + .hasFieldOrPropertyWithValue("clientKeyData", null) + .hasFieldOrPropertyWithValue("clientKeyAlgo", null) + .hasFieldOrPropertyWithValue("clientKeyPassphrase", null) + .hasFieldOrPropertyWithValue("httpProxy", null) + .hasFieldOrPropertyWithValue("watchReconnectInterval", null) + .hasFieldOrPropertyWithValue("watchReconnectLimit", null) + .hasFieldOrPropertyWithValue("loggingInterval", null) + .hasFieldOrPropertyWithValue("requestTimeout", null) + .hasFieldOrPropertyWithValue("requestConfig.uploadRequestTimeout", null) + .hasFieldOrPropertyWithValue("tlsVersions", null) + .hasFieldOrPropertyWithValue("trustStoreFile", null) + .hasFieldOrPropertyWithValue("trustStorePassphrase", null) + .hasFieldOrPropertyWithValue("keyStoreFile", null) + .hasFieldOrPropertyWithValue("keyStorePassphrase", null) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", null) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", null) + .hasFieldOrPropertyWithValue("websocketPingInterval", null) + .hasFieldOrPropertyWithValue("connectionTimeout", null) + .hasFieldOrPropertyWithValue("scaleTimeout", null) + .hasFieldOrPropertyWithValue("watchReconnectInterval", null) + .hasFieldOrPropertyWithValue("http2Disable", null) + .hasFieldOrPropertyWithValue("httpsProxy", null) + .hasFieldOrPropertyWithValue("proxyUsername", null) + .hasFieldOrPropertyWithValue("proxyPassword", null) + .hasFieldOrPropertyWithValue("noProxy", null) + .hasFieldOrPropertyWithValue("autoOAuthToken", null); + } + + @Nested + @DisplayName("Config default values initialization with system properties for auto configuration") + class DefaultValues { + @BeforeEach + void setUp() { + System.setProperty("kubernetes.master", "http://autoconfigured-master:80"); + System.setProperty("kubernetes.namespace", "autoconfigured-namespace"); + System.setProperty("kubernetes.auth.token", "autoconfigured-token"); + System.setProperty("kubernetes.auth.basic.username", "autoconfigured-user"); + System.setProperty("kubernetes.auth.basic.password", "autoconfigured-pass"); + System.setProperty("kubernetes.trust.certificates", "true"); + System.setProperty("kubernetes.disable.hostname.verification", "true"); + System.setProperty("kubernetes.certs.ca.file", "/autoconfigured-path/to/cert"); + System.setProperty("kubernetes.certs.ca.data", "autoconfigured-cacertdata"); + System.setProperty("kubernetes.certs.client.file", "/autoconfigured-path/to/clientcert"); + System.setProperty("kubernetes.certs.client.data", "autoconfigured-clientcertdata"); + System.setProperty("kubernetes.certs.client.key.file", "/autoconfigured-path/to/clientkey"); + System.setProperty("kubernetes.certs.client.key.data", "autoconfigured-clientkeydata"); + System.setProperty("kubernetes.certs.client.key.algo", "autoconfigured-algo"); + System.setProperty("kubernetes.certs.client.key.passphrase", "autoconfigured-passphrase"); + System.setProperty("kubernetes.certs.client.key.file", "/autoconfigured-path/to/clientkey"); + System.setProperty("kubernetes.max.concurrent.requests", "120"); + System.setProperty("kubernetes.max.concurrent.requests.per.host", "20"); + System.setProperty("kubernetes.watch.reconnectInterval", "5000"); + System.setProperty("kubernetes.watch.reconnectLimit", "5"); + System.setProperty("kubernetes.request.timeout", "5000"); + System.setProperty("http.proxy", "autoconfigured-httpProxy"); + System.setProperty("kubernetes.tls.versions", "TLSv1.2,TLSv1.1"); + System.setProperty("kubernetes.truststore.file", "/autoconfigured-path/to/truststore"); + System.setProperty("kubernetes.truststore.passphrase", "autoconfigured-truststorePassphrase"); + System.setProperty("kubernetes.keystore.file", "/autoconfigured-path/to/keystore"); + System.setProperty("kubernetes.keystore.passphrase", "autoconfigured-keystorePassphrase"); + System.setProperty("kubernetes.upload.request.timeout", "600000"); + System.setProperty("kubernetes.websocket.ping.interval", "1000"); + System.setProperty("kubernetes.connection.timeout", "1000"); + System.setProperty("kubernetes.scale.timeout", "1000"); + System.setProperty("https.proxy", "autoconfigured-httpsProxy"); + System.setProperty("no.proxy", "autoconfigured-no-proxy-url1.io,autoconfigured-no-proxy-url2.io"); + System.setProperty("proxy.username", "autoconfigured-proxyUsername"); + System.setProperty("proxy.password", "autoconfigured-proxyPassword"); + } + + @AfterEach + void tearDown() { + System.clearProperty("kubernetes.master"); + System.clearProperty("kubernetes.namespace"); + System.clearProperty("kubernetes.auth.token"); + System.clearProperty("kubernetes.auth.basic.username"); + System.clearProperty("kubernetes.auth.basic.password"); + System.clearProperty("kubernetes.trust.certificates"); + System.clearProperty("kubernetes.disable.hostname.verification"); + System.clearProperty("kubernetes.certs.ca.file"); + System.clearProperty("kubernetes.certs.ca.data"); + System.clearProperty("kubernetes.certs.client.file"); + System.clearProperty("kubernetes.certs.client.data"); + System.clearProperty("kubernetes.certs.client.key.file"); + System.clearProperty("kubernetes.certs.client.key.data"); + System.clearProperty("kubernetes.certs.client.key.algo"); + System.clearProperty("kubernetes.certs.client.key.passphrase"); + System.clearProperty("kubernetes.certs.client.key.file"); + System.clearProperty("kubernetes.max.concurrent.requests"); + System.clearProperty("kubernetes.max.concurrent.requests.per.host"); + System.clearProperty("kubernetes.watch.reconnectInterval"); + System.clearProperty("kubernetes.watch.reconnectLimit"); + System.clearProperty("kubernetes.request.timeout"); + System.clearProperty("http.proxy"); + System.clearProperty("kubernetes.tls.versions"); + System.clearProperty("kubernetes.truststore.file"); + System.clearProperty("kubernetes.truststore.passphrase"); + System.clearProperty("kubernetes.keystore.file"); + System.clearProperty("kubernetes.keystore.passphrase"); + System.clearProperty("kubernetes.upload.request.timeout"); + System.clearProperty("kubernetes.websocket.ping.interval"); + System.clearProperty("kubernetes.connection.timeout"); + System.clearProperty("kubernetes.scale.timeout"); + System.clearProperty("https.proxy"); + System.clearProperty("no.proxy"); + System.clearProperty("proxy.username"); + System.clearProperty("proxy.password"); + } + + @Test + @DisplayName("when autoConfigure enabled, then auto configured values override default values") + void whenAutoConfigureEnabled_thenUseBothDefaultAndAutoConfiguredValues() { + // Given + // When + Config config = new Config(null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, + null, + null, null, null, null, + null, null, null, + null, + null, null, null, null, null, + null, null, null, + null, null, null, + null, null, null, null, + null, true, true); + + // Then + assertThat(config) + .isNotNull() + // Default values + .hasFieldOrPropertyWithValue("apiVersion", "v1") + .hasFieldOrPropertyWithValue("onlyHttpWatches", false) + .hasFieldOrPropertyWithValue("http2Disable", false) + .hasFieldOrPropertyWithValue("userAgent", "fabric8-kubernetes-client/" + Version.clientVersion()) + // Auto Configured values + .hasFieldOrPropertyWithValue("trustCerts", true) + .hasFieldOrPropertyWithValue("disableHostnameVerification", true) + .hasFieldOrPropertyWithValue("masterUrl", "http://autoconfigured-master:80/") + .hasFieldOrPropertyWithValue("namespace", "autoconfigured-namespace") + .hasFieldOrPropertyWithValue("username", "autoconfigured-user") + .hasFieldOrPropertyWithValue("password", "autoconfigured-pass") + .hasFieldOrPropertyWithValue("caCertFile", "/autoconfigured-path/to/cert") + .hasFieldOrPropertyWithValue("caCertData", "autoconfigured-cacertdata") + .hasFieldOrPropertyWithValue("clientCertFile", "/autoconfigured-path/to/clientcert") + .hasFieldOrPropertyWithValue("clientCertData", "autoconfigured-clientcertdata") + .hasFieldOrPropertyWithValue("clientKeyFile", "/autoconfigured-path/to/clientkey") + .hasFieldOrPropertyWithValue("clientKeyData", "autoconfigured-clientkeydata") + .hasFieldOrPropertyWithValue("clientKeyAlgo", "autoconfigured-algo") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "autoconfigured-passphrase") + .hasFieldOrPropertyWithValue("httpProxy", "autoconfigured-httpProxy") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 5000) + .hasFieldOrPropertyWithValue("watchReconnectLimit", 5) + .hasFieldOrPropertyWithValue("requestTimeout", 5000) + .hasFieldOrPropertyWithValue("requestConfig.uploadRequestTimeout", 600000) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_2, TlsVersion.TLS_1_1 }) + .hasFieldOrPropertyWithValue("trustStoreFile", "/autoconfigured-path/to/truststore") + .hasFieldOrPropertyWithValue("trustStorePassphrase", "autoconfigured-truststorePassphrase") + .hasFieldOrPropertyWithValue("keyStoreFile", "/autoconfigured-path/to/keystore") + .hasFieldOrPropertyWithValue("keyStorePassphrase", "autoconfigured-keystorePassphrase") + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 120) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 20) + .hasFieldOrPropertyWithValue("websocketPingInterval", 1000L) + .hasFieldOrPropertyWithValue("connectionTimeout", 1000) + .hasFieldOrPropertyWithValue("scaleTimeout", 1000L) + .hasFieldOrPropertyWithValue("watchReconnectInterval", 5000) + .hasFieldOrPropertyWithValue("http2Disable", false) + .hasFieldOrPropertyWithValue("httpsProxy", "autoconfigured-httpsProxy") + .hasFieldOrPropertyWithValue("proxyUsername", "autoconfigured-proxyUsername") + .hasFieldOrPropertyWithValue("proxyPassword", "autoconfigured-proxyPassword") + .hasFieldOrPropertyWithValue("noProxy", + new String[] { "autoconfigured-no-proxy-url1.io", "autoconfigured-no-proxy-url2.io" }) + .hasFieldOrPropertyWithValue("autoOAuthToken", "autoconfigured-token"); + } + + @Test + @DisplayName("when autoConfigure disabled, then auto configured values are ignored") + void whenAutoConfigureDisabled_thenOnlyUseDefaultValues() { + Config config = new Config(null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, + null, + null, null, null, null, + null, null, null, + null, + null, null, null, null, null, + null, null, null, + null, null, null, + null, null, null, null, + null, false, true); + + assertThat(config) + .isNotNull() + .hasFieldOrPropertyWithValue("apiVersion", "v1") + .hasFieldOrPropertyWithValue("onlyHttpWatches", false) + .hasFieldOrPropertyWithValue("http2Disable", false) + .hasFieldOrPropertyWithValue("userAgent", "fabric8-kubernetes-client/" + Version.clientVersion()) + .hasFieldOrPropertyWithValue("trustCerts", false) + .hasFieldOrPropertyWithValue("disableHostnameVerification", false) + .hasFieldOrPropertyWithValue("masterUrl", "https://kubernetes.default.svc/") + .hasFieldOrPropertyWithValue("namespace", null) + .hasFieldOrPropertyWithValue("username", null) + .hasFieldOrPropertyWithValue("password", null) + .hasFieldOrPropertyWithValue("caCertFile", null) + .hasFieldOrPropertyWithValue("caCertData", null) + .hasFieldOrPropertyWithValue("clientCertFile", null) + .hasFieldOrPropertyWithValue("clientCertData", null) + .hasFieldOrPropertyWithValue("clientKeyFile", null) + .hasFieldOrPropertyWithValue("clientKeyData", null) + .hasFieldOrPropertyWithValue("clientKeyAlgo", "RSA") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "changeit") + .hasFieldOrPropertyWithValue("httpProxy", null) + .hasFieldOrPropertyWithValue("watchReconnectInterval", 1000) + .hasFieldOrPropertyWithValue("watchReconnectLimit", -1) + .hasFieldOrPropertyWithValue("requestTimeout", 10000) + .hasFieldOrPropertyWithValue("requestConfig.uploadRequestTimeout", 120000) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_3, TlsVersion.TLS_1_2 }) + .hasFieldOrPropertyWithValue("trustStoreFile", null) + .hasFieldOrPropertyWithValue("trustStorePassphrase", null) + .hasFieldOrPropertyWithValue("keyStoreFile", null) + .hasFieldOrPropertyWithValue("keyStorePassphrase", null) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 64) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 5) + .hasFieldOrPropertyWithValue("websocketPingInterval", 30000L) + .hasFieldOrPropertyWithValue("connectionTimeout", 10000) + .hasFieldOrPropertyWithValue("scaleTimeout", 600000L) + .hasFieldOrPropertyWithValue("watchReconnectInterval", 1000) + .hasFieldOrPropertyWithValue("http2Disable", false) + .hasFieldOrPropertyWithValue("httpsProxy", null) + .hasFieldOrPropertyWithValue("proxyUsername", null) + .hasFieldOrPropertyWithValue("proxyPassword", null) + .hasFieldOrPropertyWithValue("noProxy", null) + .hasFieldOrPropertyWithValue("autoOAuthToken", null); + } + } + + @Nested + @DisplayName("Config auto configured values initialization (autoConfigure=true)") + class AutoConfiguredValues { + @Nested + @DisplayName("(defaultValues=true)") + class DefaultValuesTrue { + @Test + @DisplayName("from system properties") + void configLoadedViaSystemProperties() { + try { + // Given + System.setProperty("kubernetes.master", "http://autoconfigured-master:80"); + System.setProperty("kubernetes.namespace", "autoconfigured-namespace"); + System.setProperty("kubernetes.auth.token", "autoconfigured-token"); + System.setProperty("kubernetes.auth.basic.username", "autoconfigured-user"); + System.setProperty("kubernetes.auth.basic.password", "autoconfigured-pass"); + System.setProperty("kubernetes.trust.certificates", "true"); + System.setProperty("kubernetes.disable.hostname.verification", "true"); + System.setProperty("kubernetes.certs.ca.file", "/autoconfigured-path/to/cert"); + System.setProperty("kubernetes.certs.ca.data", "autoconfigured-cacertdata"); + System.setProperty("kubernetes.certs.client.file", "/autoconfigured-path/to/clientcert"); + System.setProperty("kubernetes.certs.client.data", "autoconfigured-clientcertdata"); + System.setProperty("kubernetes.certs.client.key.file", "/autoconfigured-path/to/clientkey"); + System.setProperty("kubernetes.certs.client.key.data", "autoconfigured-clientkeydata"); + System.setProperty("kubernetes.certs.client.key.algo", "autoconfigured-algo"); + System.setProperty("kubernetes.certs.client.key.passphrase", "autoconfigured-passphrase"); + System.setProperty("kubernetes.certs.client.key.file", "/autoconfigured-path/to/clientkey"); + System.setProperty("kubernetes.max.concurrent.requests", "120"); + System.setProperty("kubernetes.max.concurrent.requests.per.host", "20"); + System.setProperty("kubernetes.watch.reconnectInterval", "5000"); + System.setProperty("kubernetes.watch.reconnectLimit", "5"); + System.setProperty("kubernetes.request.timeout", "5000"); + System.setProperty("http.proxy", "autoconfigured-httpProxy"); + System.setProperty("kubernetes.tls.versions", "TLSv1.2,TLSv1.1"); + System.setProperty("kubernetes.truststore.file", "/autoconfigured-path/to/truststore"); + System.setProperty("kubernetes.truststore.passphrase", "autoconfigured-truststorePassphrase"); + System.setProperty("kubernetes.keystore.file", "/autoconfigured-path/to/keystore"); + System.setProperty("kubernetes.keystore.passphrase", "autoconfigured-keystorePassphrase"); + System.setProperty("kubernetes.upload.request.timeout", "600000"); + System.setProperty("kubernetes.websocket.ping.interval", "1000"); + System.setProperty("kubernetes.connection.timeout", "1000"); + System.setProperty("kubernetes.scale.timeout", "1000"); + System.setProperty("https.proxy", "autoconfigured-httpsProxy"); + System.setProperty("no.proxy", "autoconfigured-no-proxy-url1.io,autoconfigured-no-proxy-url2.io"); + System.setProperty("proxy.username", "autoconfigured-proxyUsername"); + System.setProperty("proxy.password", "autoconfigured-proxyPassword"); + + // When + Config config = new Config(null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, + null, + null, null, null, null, + null, null, null, + null, + null, null, null, null, null, + null, null, null, + null, null, null, + null, null, null, null, + null, true, true); + + // Then + assertThat(config) + .isNotNull() + // Default values + .hasFieldOrPropertyWithValue("apiVersion", "v1") + .hasFieldOrPropertyWithValue("onlyHttpWatches", false) + .hasFieldOrPropertyWithValue("http2Disable", false) + .hasFieldOrPropertyWithValue("userAgent", "fabric8-kubernetes-client/" + Version.clientVersion()) + // Auto Configured values + .hasFieldOrPropertyWithValue("trustCerts", true) + .hasFieldOrPropertyWithValue("disableHostnameVerification", true) + .hasFieldOrPropertyWithValue("masterUrl", "http://autoconfigured-master:80/") + .hasFieldOrPropertyWithValue("namespace", "autoconfigured-namespace") + .hasFieldOrPropertyWithValue("username", "autoconfigured-user") + .hasFieldOrPropertyWithValue("password", "autoconfigured-pass") + .hasFieldOrPropertyWithValue("caCertFile", "/autoconfigured-path/to/cert") + .hasFieldOrPropertyWithValue("caCertData", "autoconfigured-cacertdata") + .hasFieldOrPropertyWithValue("clientCertFile", "/autoconfigured-path/to/clientcert") + .hasFieldOrPropertyWithValue("clientCertData", "autoconfigured-clientcertdata") + .hasFieldOrPropertyWithValue("clientKeyFile", "/autoconfigured-path/to/clientkey") + .hasFieldOrPropertyWithValue("clientKeyData", "autoconfigured-clientkeydata") + .hasFieldOrPropertyWithValue("clientKeyAlgo", "autoconfigured-algo") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "autoconfigured-passphrase") + .hasFieldOrPropertyWithValue("httpProxy", "autoconfigured-httpProxy") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 5000) + .hasFieldOrPropertyWithValue("watchReconnectLimit", 5) + .hasFieldOrPropertyWithValue("requestTimeout", 5000) + .hasFieldOrPropertyWithValue("requestConfig.uploadRequestTimeout", 600000) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_2, TlsVersion.TLS_1_1 }) + .hasFieldOrPropertyWithValue("trustStoreFile", "/autoconfigured-path/to/truststore") + .hasFieldOrPropertyWithValue("trustStorePassphrase", "autoconfigured-truststorePassphrase") + .hasFieldOrPropertyWithValue("keyStoreFile", "/autoconfigured-path/to/keystore") + .hasFieldOrPropertyWithValue("keyStorePassphrase", "autoconfigured-keystorePassphrase") + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 120) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 20) + .hasFieldOrPropertyWithValue("websocketPingInterval", 1000L) + .hasFieldOrPropertyWithValue("connectionTimeout", 1000) + .hasFieldOrPropertyWithValue("scaleTimeout", 1000L) + .hasFieldOrPropertyWithValue("watchReconnectInterval", 5000) + .hasFieldOrPropertyWithValue("http2Disable", false) + .hasFieldOrPropertyWithValue("httpsProxy", "autoconfigured-httpsProxy") + .hasFieldOrPropertyWithValue("proxyUsername", "autoconfigured-proxyUsername") + .hasFieldOrPropertyWithValue("proxyPassword", "autoconfigured-proxyPassword") + .hasFieldOrPropertyWithValue("noProxy", + new String[] { "autoconfigured-no-proxy-url1.io", "autoconfigured-no-proxy-url2.io" }) + .hasFieldOrPropertyWithValue("autoOAuthToken", "autoconfigured-token"); + } finally { + System.clearProperty("kubernetes.master"); + System.clearProperty("kubernetes.namespace"); + System.clearProperty("kubernetes.auth.token"); + System.clearProperty("kubernetes.auth.basic.username"); + System.clearProperty("kubernetes.auth.basic.password"); + System.clearProperty("kubernetes.trust.certificates"); + System.clearProperty("kubernetes.disable.hostname.verification"); + System.clearProperty("kubernetes.certs.ca.file"); + System.clearProperty("kubernetes.certs.ca.data"); + System.clearProperty("kubernetes.certs.client.file"); + System.clearProperty("kubernetes.certs.client.data"); + System.clearProperty("kubernetes.certs.client.key.file"); + System.clearProperty("kubernetes.certs.client.key.data"); + System.clearProperty("kubernetes.certs.client.key.algo"); + System.clearProperty("kubernetes.certs.client.key.passphrase"); + System.clearProperty("kubernetes.certs.client.key.file"); + System.clearProperty("kubernetes.max.concurrent.requests"); + System.clearProperty("kubernetes.max.concurrent.requests.per.host"); + System.clearProperty("kubernetes.watch.reconnectInterval"); + System.clearProperty("kubernetes.watch.reconnectLimit"); + System.clearProperty("kubernetes.request.timeout"); + System.clearProperty("http.proxy"); + System.clearProperty("kubernetes.tls.versions"); + System.clearProperty("kubernetes.truststore.file"); + System.clearProperty("kubernetes.truststore.passphrase"); + System.clearProperty("kubernetes.keystore.file"); + System.clearProperty("kubernetes.keystore.passphrase"); + System.clearProperty("kubernetes.upload.request.timeout"); + System.clearProperty("kubernetes.websocket.ping.interval"); + System.clearProperty("kubernetes.connection.timeout"); + System.clearProperty("kubernetes.scale.timeout"); + System.clearProperty("https.proxy"); + System.clearProperty("no.proxy"); + System.clearProperty("proxy.username"); + System.clearProperty("proxy.password"); + } + } + + @Test + @DisplayName("from kube config") + void configLoadedViaKubeConfig() { + try { + // Given + String kubeConfigFilePath = Utils.filePath(ConfigConstructorTest.class.getResource("/test-kubeconfig")); + System.setProperty("kubeconfig", kubeConfigFilePath); + // When + Config config = new Config(null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, + null, + null, null, null, null, + null, null, null, + null, + null, null, null, null, null, + null, null, null, + null, null, null, + null, null, null, null, + null, true, true); + + // Then + assertThat(config) + .isNotNull() + .hasFieldOrPropertyWithValue("masterUrl", "https://172.28.128.4:8443/") + .hasFieldOrPropertyWithValue("trustCerts", true) + .hasFieldOrPropertyWithValue("namespace", "testns") + .hasFieldOrPropertyWithValue("autoOAuthToken", "token") + .satisfies(c -> Assertions.assertThat(c.getCaCertFile()).endsWith("testns/ca.pem".replace("/", File.separator))) + .satisfies(c -> Assertions.assertThat(new File(c.getCaCertFile())).isAbsolute()) + .hasFieldOrPropertyWithValue("file", new File(kubeConfigFilePath)); + } finally { + System.clearProperty("kubeconfig"); + } + } + + @Test + @DisplayName("from Service Account") + void configLoadedViaServiceAccount() { + try { + // Given + System.setProperty("kubeconfig", "/dev/null"); + System.setProperty("kubernetes.auth.serviceAccount.token", + Utils.filePath(ConfigConstructorTest.class.getResource("/config-source-precedence/serviceaccount/token"))); + System.setProperty("kubenamespace", + Utils.filePath(ConfigConstructorTest.class.getResource("/config-source-precedence/serviceaccount/namespace"))); + // When + Config config = new Config(null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, + null, + null, null, null, null, + null, null, null, + null, + null, null, null, null, null, + null, null, null, + null, null, null, + null, null, null, null, + null, true, true); + + // Then + assertThat(config) + .isNotNull() + .hasFieldOrPropertyWithValue("namespace", "namespace-from-mounted-serviceaccount") + .extracting(Config::getAutoOAuthToken) + .asString() + .contains("token-from-mounted-serviceaccount"); + } finally { + System.clearProperty("kubeconfig"); + System.clearProperty("kubernetes.auth.serviceAccount.token"); + System.clearProperty("kubenamespace"); + } + } + } + + /* + * AutoConfiguration requires default values as System Property/Environment variable resolution needs specific defaults for + * property resolution, + * such as connection timeout and so on. + * + * This is not a problem as the Constructor is package private and is not exposed to the users. + */ + @Nested + @DisplayName("(defaultValues=false)") + class DefaultValuesFalse { + @Test + @DisplayName("should throw exception") + void throwsException() { + try { + // Given + String kubeConfigFilePath = Utils.filePath(ConfigConstructorTest.class.getResource("/test-kubeconfig")); + System.setProperty("kubeconfig", kubeConfigFilePath); + // When + // Then + assertThatExceptionOfType(NullPointerException.class) + .isThrownBy(() -> new Config(null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, null, + null, null, null, null, + null, + null, null, null, null, + null, null, null, + null, + null, null, null, null, null, + null, null, null, + null, null, null, + null, null, null, null, + null, true, false)); + } finally { + System.clearProperty("kubeconfig"); + } + } + } + } +} diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigDisableAutoConfigurationTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigDisableAutoConfigurationTest.java new file mode 100644 index 00000000000..36539191841 --- /dev/null +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/ConfigDisableAutoConfigurationTest.java @@ -0,0 +1,579 @@ +/* + * 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; + +import io.fabric8.kubernetes.api.model.NamedContext; +import io.fabric8.kubernetes.api.model.NamedContextBuilder; +import io.fabric8.kubernetes.client.http.TlsVersion; +import io.fabric8.kubernetes.client.utils.Utils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; + +class ConfigDisableAutoConfigurationTest { + private final NamedContext userConfiguredNamedContext = new NamedContextBuilder() + .withName("context1") + .withNewContext() + .withCluster("api-test-openshiftapps-com:6443") + .withUser("testuser/api-test-openshiftapps-com:6443") + .endContext() + .build(); + + @Nested + @DisplayName("via kubernetes.disable.autoConfig=true") + class AutoConfigDisabledViaProperty { + @BeforeEach + void setUp() { + System.setProperty("kubernetes.disable.autoConfig", "true"); + } + + @AfterEach + void tearDown() { + System.clearProperty("kubernetes.disable.autoConfig"); + } + + @Nested + @DisplayName("And inside Kubernetes Cluster with ServiceAccount mounted") + class InsideKubernetesClusterWithMountedServiceAccount { + @BeforeEach + void setUp() { + System.setProperty("kubernetes.auth.serviceAccount.token", + Utils.filePath(ConfigDisableAutoConfigurationTest.class + .getResource("/config-disable-autoconfiguration/serviceaccount/token"))); + System.setProperty("kubenamespace", + Utils.filePath(ConfigDisableAutoConfigurationTest.class + .getResource("/config-disable-autoconfiguration/serviceaccount/namespace"))); + } + + @Test + @DisplayName("then use default values") + void whenConfigDisabledViaPropertyAndUserProvidesNoConfiguration_thenUseConfigDefaultValues() { + assertThat(new ConfigBuilder().build()) + .hasFieldOrPropertyWithValue("autoConfigure", false) + .hasFieldOrPropertyWithValue("masterUrl", "https://kubernetes.default.svc/") + .hasFieldOrPropertyWithValue("contexts", Collections.emptyList()) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 64) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 5) + .hasFieldOrPropertyWithValue("trustCerts", false) + .hasFieldOrPropertyWithValue("disableHostnameVerification", false) + .hasFieldOrPropertyWithValue("clientKeyAlgo", "RSA") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "changeit") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 1000) + .hasFieldOrPropertyWithValue("watchReconnectLimit", -1) + .hasFieldOrPropertyWithValue("connectionTimeout", 10000) + .hasFieldOrPropertyWithValue("requestTimeout", 10000) + .hasFieldOrPropertyWithValue("scaleTimeout", 600000L) + .hasFieldOrPropertyWithValue("loggingInterval", 20000) + .hasFieldOrPropertyWithValue("websocketPingInterval", 30000L) + .hasFieldOrPropertyWithValue("uploadRequestTimeout", 120000) + .hasFieldOrPropertyWithValue("impersonateExtras", Collections.emptyMap()) + .hasFieldOrPropertyWithValue("http2Disable", false) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_3, TlsVersion.TLS_1_2 }) + .satisfies(e -> assertThat(e.getCurrentContext()).isNull()) + .satisfies(e -> assertThat(e.getImpersonateGroups()).isEmpty()) + .satisfies(e -> assertThat(e.getUserAgent()).isNotNull()); + } + + @Test + @DisplayName("And user configuration via builder, then user configuration takes precedence") + void whenConfigDisabledViaPropertyAndUserProvidesConfigurationViaConfigBuilder_thenUseConfigDefaultValues() { + // Given + When + Config config = new ConfigBuilder() + .withMasterUrl("https://api-test.openshiftapps.com:6443") + .withContexts(userConfiguredNamedContext) + .withCurrentContext(userConfiguredNamedContext) + .withMaxConcurrentRequests(30) + .withMaxConcurrentRequestsPerHost(10) + .withTrustCerts() + .withDisableHostnameVerification() + .withClientKeyAlgo("EC") + .withWatchReconnectInterval(500) + .withWatchReconnectLimit(10) + .withConnectionTimeout(1000) + .withRequestTimeout(1000) + .withScaleTimeout(1000L) + .withLoggingInterval(1000) + .withWebsocketPingInterval(10000L) + .withUploadRequestTimeout(1000) + .withImpersonateExtras(Collections.singletonMap("acme%2Fproject", Collections.singletonList("some-project"))) + .withHttp2Disable(true) + .withTlsVersions(new TlsVersion[] { TlsVersion.TLS_1_3 }) + .withCurrentContext(userConfiguredNamedContext) + .withImpersonateGroups("developer", "admin") + .withUserAgent("custom-user-agent") + .build(); + // Then + assertThat(config) + .hasFieldOrPropertyWithValue("autoConfigure", false) + .hasFieldOrPropertyWithValue("masterUrl", "https://api-test.openshiftapps.com:6443/") + .hasFieldOrPropertyWithValue("contexts", Collections.singletonList(userConfiguredNamedContext)) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 30) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 10) + .hasFieldOrPropertyWithValue("trustCerts", true) + .hasFieldOrPropertyWithValue("disableHostnameVerification", true) + .hasFieldOrPropertyWithValue("clientKeyAlgo", "EC") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "changeit") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 500) + .hasFieldOrPropertyWithValue("watchReconnectLimit", 10) + .hasFieldOrPropertyWithValue("connectionTimeout", 1000) + .hasFieldOrPropertyWithValue("requestTimeout", 1000) + .hasFieldOrPropertyWithValue("scaleTimeout", 1000L) + .hasFieldOrPropertyWithValue("loggingInterval", 1000) + .hasFieldOrPropertyWithValue("websocketPingInterval", 10000L) + .hasFieldOrPropertyWithValue("uploadRequestTimeout", 1000) + .hasFieldOrPropertyWithValue("impersonateExtras", + Collections.singletonMap("acme%2Fproject", Collections.singletonList("some-project"))) + .hasFieldOrPropertyWithValue("http2Disable", true) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_3 }) + .satisfies(e -> assertThat(e.getCurrentContext()).isEqualTo(userConfiguredNamedContext)) + .satisfies(e -> assertThat(e.getImpersonateGroups()).containsExactly("developer", "admin")) + .satisfies(e -> assertThat(e.getUserAgent()).isEqualTo("custom-user-agent")); + } + + @AfterEach + void tearDown() { + System.clearProperty("kubernetes.master"); + System.clearProperty("kubernetes.auth.serviceAccount.token"); + System.clearProperty("kubenamespace"); + } + } + + @Nested + @DisplayName("And system properties configured") + class SystemPropertiesConfigured { + @BeforeEach + void setUp() { + System.setProperty("kubernetes.master", "http://somehost:80"); + System.setProperty("kubernetes.namespace", "testns"); + } + + @Test + @DisplayName("then use default values") + void whenConfigDisabledViaPropertyAndUserProvidesNoConfiguration_thenUseConfigDefaultValues() { + assertThat(new ConfigBuilder().build()) + .hasFieldOrPropertyWithValue("autoConfigure", false) + .hasFieldOrPropertyWithValue("masterUrl", "https://kubernetes.default.svc/") + .hasFieldOrPropertyWithValue("contexts", Collections.emptyList()) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 64) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 5) + .hasFieldOrPropertyWithValue("trustCerts", false) + .hasFieldOrPropertyWithValue("disableHostnameVerification", false) + .hasFieldOrPropertyWithValue("clientKeyAlgo", "RSA") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "changeit") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 1000) + .hasFieldOrPropertyWithValue("watchReconnectLimit", -1) + .hasFieldOrPropertyWithValue("connectionTimeout", 10000) + .hasFieldOrPropertyWithValue("requestTimeout", 10000) + .hasFieldOrPropertyWithValue("scaleTimeout", 600000L) + .hasFieldOrPropertyWithValue("loggingInterval", 20000) + .hasFieldOrPropertyWithValue("websocketPingInterval", 30000L) + .hasFieldOrPropertyWithValue("uploadRequestTimeout", 120000) + .hasFieldOrPropertyWithValue("impersonateExtras", Collections.emptyMap()) + .hasFieldOrPropertyWithValue("http2Disable", false) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_3, TlsVersion.TLS_1_2 }) + .satisfies(e -> assertThat(e.getCurrentContext()).isNull()) + .satisfies(e -> assertThat(e.getImpersonateGroups()).isEmpty()) + .satisfies(e -> assertThat(e.getUserAgent()).isNotNull()); + } + + @Test + @DisplayName("And user configuration via builder, then user configuration takes precedence") + void whenConfigDisabledViaPropertyAndUserProvidesConfigurationViaConfigBuilder_thenUseConfigDefaultValues() { + // Given + When + Config config = new ConfigBuilder() + .withMasterUrl("https://api-test.openshiftapps.com:6443") + .withContexts(userConfiguredNamedContext) + .withCurrentContext(userConfiguredNamedContext) + .withMaxConcurrentRequests(30) + .withMaxConcurrentRequestsPerHost(10) + .withTrustCerts() + .withDisableHostnameVerification() + .withClientKeyAlgo("EC") + .withWatchReconnectInterval(500) + .withWatchReconnectLimit(10) + .withConnectionTimeout(1000) + .withRequestTimeout(1000) + .withScaleTimeout(1000L) + .withLoggingInterval(1000) + .withWebsocketPingInterval(10000L) + .withUploadRequestTimeout(1000) + .withImpersonateExtras(Collections.singletonMap("acme%2Fproject", Collections.singletonList("some-project"))) + .withHttp2Disable(true) + .withTlsVersions(new TlsVersion[] { TlsVersion.TLS_1_3 }) + .withCurrentContext(userConfiguredNamedContext) + .withImpersonateGroups("developer", "admin") + .withUserAgent("custom-user-agent") + .build(); + // Then + assertThat(config) + .hasFieldOrPropertyWithValue("autoConfigure", false) + .hasFieldOrPropertyWithValue("masterUrl", "https://api-test.openshiftapps.com:6443/") + .hasFieldOrPropertyWithValue("contexts", Collections.singletonList(userConfiguredNamedContext)) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 30) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 10) + .hasFieldOrPropertyWithValue("trustCerts", true) + .hasFieldOrPropertyWithValue("disableHostnameVerification", true) + .hasFieldOrPropertyWithValue("clientKeyAlgo", "EC") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "changeit") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 500) + .hasFieldOrPropertyWithValue("watchReconnectLimit", 10) + .hasFieldOrPropertyWithValue("connectionTimeout", 1000) + .hasFieldOrPropertyWithValue("requestTimeout", 1000) + .hasFieldOrPropertyWithValue("scaleTimeout", 1000L) + .hasFieldOrPropertyWithValue("loggingInterval", 1000) + .hasFieldOrPropertyWithValue("websocketPingInterval", 10000L) + .hasFieldOrPropertyWithValue("uploadRequestTimeout", 1000) + .hasFieldOrPropertyWithValue("impersonateExtras", + Collections.singletonMap("acme%2Fproject", Collections.singletonList("some-project"))) + .hasFieldOrPropertyWithValue("http2Disable", true) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_3 }) + .satisfies(e -> assertThat(e.getCurrentContext()).isEqualTo(userConfiguredNamedContext)) + .satisfies(e -> assertThat(e.getImpersonateGroups()).containsExactly("developer", "admin")) + .satisfies(e -> assertThat(e.getUserAgent()).isEqualTo("custom-user-agent")); + } + + @AfterEach + void tearDown() { + System.clearProperty("kubernetes.master"); + } + } + + @Nested + @DisplayName("And kubeconfig present") + class KubeConfigPresent { + @BeforeEach + void setUp() { + System.setProperty("kubeconfig", + Utils.filePath(getClass().getResource("/config-disable-autoconfiguration/kube-config"))); + } + + @Test + @DisplayName("then use default values") + void whenConfigDisabledViaPropertyAndUserProvidesNoConfiguration_thenUseConfigDefaultValues() { + assertThat(new ConfigBuilder().build()) + .hasFieldOrPropertyWithValue("autoConfigure", false) + .hasFieldOrPropertyWithValue("masterUrl", "https://kubernetes.default.svc/") + .hasFieldOrPropertyWithValue("contexts", Collections.emptyList()) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 64) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 5) + .hasFieldOrPropertyWithValue("trustCerts", false) + .hasFieldOrPropertyWithValue("disableHostnameVerification", false) + .hasFieldOrPropertyWithValue("clientKeyAlgo", "RSA") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "changeit") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 1000) + .hasFieldOrPropertyWithValue("watchReconnectLimit", -1) + .hasFieldOrPropertyWithValue("connectionTimeout", 10000) + .hasFieldOrPropertyWithValue("requestTimeout", 10000) + .hasFieldOrPropertyWithValue("scaleTimeout", 600000L) + .hasFieldOrPropertyWithValue("loggingInterval", 20000) + .hasFieldOrPropertyWithValue("websocketPingInterval", 30000L) + .hasFieldOrPropertyWithValue("uploadRequestTimeout", 120000) + .hasFieldOrPropertyWithValue("impersonateExtras", Collections.emptyMap()) + .hasFieldOrPropertyWithValue("http2Disable", false) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_3, TlsVersion.TLS_1_2 }) + .satisfies(e -> assertThat(e.getCurrentContext()).isNull()) + .satisfies(e -> assertThat(e.getImpersonateGroups()).isEmpty()) + .satisfies(e -> assertThat(e.getUserAgent()).isNotNull()); + } + + @Test + @DisplayName("And user configuration via builder, then user configuration via builder takes precedence") + void whenConfigDisabledViaPropertyAndUserProvidesConfigurationViaConfigBuilder_thenUseConfigDefaultValues() { + // Given + When + Config config = new ConfigBuilder() + .withMasterUrl("https://api-test.openshiftapps.com:6443") + .withContexts(userConfiguredNamedContext) + .withCurrentContext(userConfiguredNamedContext) + .withMaxConcurrentRequests(30) + .withMaxConcurrentRequestsPerHost(10) + .withTrustCerts() + .withDisableHostnameVerification() + .withClientKeyAlgo("EC") + .withWatchReconnectInterval(500) + .withWatchReconnectLimit(10) + .withConnectionTimeout(1000) + .withRequestTimeout(1000) + .withScaleTimeout(1000L) + .withLoggingInterval(1000) + .withWebsocketPingInterval(10000L) + .withUploadRequestTimeout(1000) + .withImpersonateExtras(Collections.singletonMap("acme%2Fproject", Collections.singletonList("some-project"))) + .withHttp2Disable(true) + .withTlsVersions(new TlsVersion[] { TlsVersion.TLS_1_3 }) + .withCurrentContext(userConfiguredNamedContext) + .withImpersonateGroups("developer", "admin") + .withUserAgent("custom-user-agent") + .build(); + // Then + assertThat(config) + .hasFieldOrPropertyWithValue("autoConfigure", false) + .hasFieldOrPropertyWithValue("masterUrl", "https://api-test.openshiftapps.com:6443/") + .hasFieldOrPropertyWithValue("contexts", Collections.singletonList(userConfiguredNamedContext)) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 30) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 10) + .hasFieldOrPropertyWithValue("trustCerts", true) + .hasFieldOrPropertyWithValue("disableHostnameVerification", true) + .hasFieldOrPropertyWithValue("clientKeyAlgo", "EC") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "changeit") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 500) + .hasFieldOrPropertyWithValue("watchReconnectLimit", 10) + .hasFieldOrPropertyWithValue("connectionTimeout", 1000) + .hasFieldOrPropertyWithValue("requestTimeout", 1000) + .hasFieldOrPropertyWithValue("scaleTimeout", 1000L) + .hasFieldOrPropertyWithValue("loggingInterval", 1000) + .hasFieldOrPropertyWithValue("websocketPingInterval", 10000L) + .hasFieldOrPropertyWithValue("uploadRequestTimeout", 1000) + .hasFieldOrPropertyWithValue("impersonateExtras", + Collections.singletonMap("acme%2Fproject", Collections.singletonList("some-project"))) + .hasFieldOrPropertyWithValue("http2Disable", true) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_3 }) + .satisfies(e -> assertThat(e.getCurrentContext()).isEqualTo(userConfiguredNamedContext)) + .satisfies(e -> assertThat(e.getImpersonateGroups()).containsExactly("developer", "admin")) + .satisfies(e -> assertThat(e.getUserAgent()).isEqualTo("custom-user-agent")); + } + + @AfterEach + void tearDown() { + System.clearProperty("kubeconfig"); + } + } + } + + @Nested + @DisplayName("With autoConfigure(false) in ConfigBuilder") + class AutoConfigDisabledViaBuilder { + private ConfigBuilder configBuilder; + + @BeforeEach + void setUp() { + System.setProperty("kubeconfig", "/dev/null"); + configBuilder = new ConfigBuilder().withAutoConfigure(false); + } + + @AfterEach + void tearDown() { + System.clearProperty("kubeconfig"); + } + + @Nested + @DisplayName("And system properties configured") + class SystemPropertiesConfigured { + @BeforeEach + void setUp() { + System.setProperty("kubernetes.master", "http://somehost:80"); + System.setProperty("kubernetes.namespace", "testns"); + } + + @Test + @DisplayName("then use default values") + void whenConfigDisabledViaPropertyAndUserProvidesNoConfiguration_thenUseConfigDefaultValues() { + assertThat(configBuilder.build()) + .hasFieldOrPropertyWithValue("autoConfigure", false) + .hasFieldOrPropertyWithValue("masterUrl", "https://kubernetes.default.svc/") + .hasFieldOrPropertyWithValue("contexts", Collections.emptyList()) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 64) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 5) + .hasFieldOrPropertyWithValue("trustCerts", false) + .hasFieldOrPropertyWithValue("disableHostnameVerification", false) + .hasFieldOrPropertyWithValue("clientKeyAlgo", "RSA") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "changeit") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 1000) + .hasFieldOrPropertyWithValue("watchReconnectLimit", -1) + .hasFieldOrPropertyWithValue("connectionTimeout", 10000) + .hasFieldOrPropertyWithValue("requestTimeout", 10000) + .hasFieldOrPropertyWithValue("scaleTimeout", 600000L) + .hasFieldOrPropertyWithValue("loggingInterval", 20000) + .hasFieldOrPropertyWithValue("websocketPingInterval", 30000L) + .hasFieldOrPropertyWithValue("uploadRequestTimeout", 120000) + .hasFieldOrPropertyWithValue("impersonateExtras", Collections.emptyMap()) + .hasFieldOrPropertyWithValue("http2Disable", false) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_3, TlsVersion.TLS_1_2 }) + .satisfies(e -> assertThat(e.getCurrentContext()).isNull()) + .satisfies(e -> assertThat(e.getImpersonateGroups()).isEmpty()) + .satisfies(e -> assertThat(e.getUserAgent()).isNotNull()); + } + + @Test + @DisplayName("And user configuration via builder, then user configuration takes precedence") + void whenConfigDisabledViaPropertyAndUserProvidesConfigurationViaConfigBuilder_thenUseConfigDefaultValues() { + // Given + When + Config config = configBuilder.withMasterUrl("https://api-test.openshiftapps.com:6443") + .withContexts(userConfiguredNamedContext) + .withCurrentContext(userConfiguredNamedContext) + .withMaxConcurrentRequests(30) + .withMaxConcurrentRequestsPerHost(10) + .withTrustCerts() + .withDisableHostnameVerification() + .withClientKeyAlgo("EC") + .withWatchReconnectInterval(500) + .withWatchReconnectLimit(10) + .withConnectionTimeout(1000) + .withRequestTimeout(1000) + .withScaleTimeout(1000L) + .withLoggingInterval(1000) + .withWebsocketPingInterval(10000L) + .withUploadRequestTimeout(1000) + .withImpersonateExtras(Collections.singletonMap("acme%2Fproject", Collections.singletonList("some-project"))) + .withHttp2Disable(true) + .withTlsVersions(new TlsVersion[] { TlsVersion.TLS_1_3 }) + .withCurrentContext(userConfiguredNamedContext) + .withImpersonateGroups("developer", "admin") + .withUserAgent("custom-user-agent") + .build(); + // Then + assertThat(config) + .hasFieldOrPropertyWithValue("autoConfigure", false) + .hasFieldOrPropertyWithValue("masterUrl", "https://api-test.openshiftapps.com:6443/") + .hasFieldOrPropertyWithValue("contexts", Collections.singletonList(userConfiguredNamedContext)) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 30) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 10) + .hasFieldOrPropertyWithValue("trustCerts", true) + .hasFieldOrPropertyWithValue("disableHostnameVerification", true) + .hasFieldOrPropertyWithValue("clientKeyAlgo", "EC") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "changeit") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 500) + .hasFieldOrPropertyWithValue("watchReconnectLimit", 10) + .hasFieldOrPropertyWithValue("connectionTimeout", 1000) + .hasFieldOrPropertyWithValue("requestTimeout", 1000) + .hasFieldOrPropertyWithValue("scaleTimeout", 1000L) + .hasFieldOrPropertyWithValue("loggingInterval", 1000) + .hasFieldOrPropertyWithValue("websocketPingInterval", 10000L) + .hasFieldOrPropertyWithValue("uploadRequestTimeout", 1000) + .hasFieldOrPropertyWithValue("impersonateExtras", + Collections.singletonMap("acme%2Fproject", Collections.singletonList("some-project"))) + .hasFieldOrPropertyWithValue("http2Disable", true) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_3 }) + .satisfies(e -> assertThat(e.getCurrentContext()).isEqualTo(userConfiguredNamedContext)) + .satisfies(e -> assertThat(e.getImpersonateGroups()).containsExactly("developer", "admin")) + .satisfies(e -> assertThat(e.getUserAgent()).isEqualTo("custom-user-agent")); + } + + @AfterEach + void tearDown() { + System.clearProperty("kubernetes.master"); + System.clearProperty("kubeconfig"); + System.clearProperty("kubernetes.namespace"); + } + } + + @Nested + @DisplayName("And kubeconfig present") + class KubeConfigPresent { + @BeforeEach + void setUp() throws IOException { + System.setProperty("kubeconfig", + Utils.filePath(getClass().getResource("/config-disable-autoconfiguration/kube-config"))); + } + + @Test + @DisplayName("then use default values") + void whenConfigDisabledViaPropertyAndUserProvidesNoConfiguration_thenUseConfigDefaultValues() { + assertThat(configBuilder.build()) + .hasFieldOrPropertyWithValue("autoConfigure", false) + .hasFieldOrPropertyWithValue("masterUrl", "https://kubernetes.default.svc/") + .hasFieldOrPropertyWithValue("contexts", Collections.emptyList()) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 64) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 5) + .hasFieldOrPropertyWithValue("trustCerts", false) + .hasFieldOrPropertyWithValue("disableHostnameVerification", false) + .hasFieldOrPropertyWithValue("clientKeyAlgo", "RSA") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "changeit") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 1000) + .hasFieldOrPropertyWithValue("watchReconnectLimit", -1) + .hasFieldOrPropertyWithValue("connectionTimeout", 10000) + .hasFieldOrPropertyWithValue("requestTimeout", 10000) + .hasFieldOrPropertyWithValue("scaleTimeout", 600000L) + .hasFieldOrPropertyWithValue("loggingInterval", 20000) + .hasFieldOrPropertyWithValue("websocketPingInterval", 30000L) + .hasFieldOrPropertyWithValue("uploadRequestTimeout", 120000) + .hasFieldOrPropertyWithValue("impersonateExtras", Collections.emptyMap()) + .hasFieldOrPropertyWithValue("http2Disable", false) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_3, TlsVersion.TLS_1_2 }) + .satisfies(e -> assertThat(e.getCurrentContext()).isNull()) + .satisfies(e -> assertThat(e.getImpersonateGroups()).isEmpty()) + .satisfies(e -> assertThat(e.getUserAgent()).isNotNull()); + } + + @Test + @DisplayName("And user configuration via builder, then user configuration via builder takes precedence") + void whenConfigDisabledViaPropertyAndUserProvidesConfigurationViaConfigBuilder_thenUseConfigDefaultValues() { + // Given + When + Config config = configBuilder + .withMasterUrl("https://api-test.openshiftapps.com:6443") + .withContexts(userConfiguredNamedContext) + .withCurrentContext(userConfiguredNamedContext) + .withMaxConcurrentRequests(30) + .withMaxConcurrentRequestsPerHost(10) + .withTrustCerts() + .withDisableHostnameVerification() + .withClientKeyAlgo("EC") + .withWatchReconnectInterval(500) + .withWatchReconnectLimit(10) + .withConnectionTimeout(1000) + .withRequestTimeout(1000) + .withScaleTimeout(1000L) + .withLoggingInterval(1000) + .withWebsocketPingInterval(10000L) + .withUploadRequestTimeout(1000) + .withImpersonateExtras(Collections.singletonMap("acme%2Fproject", Collections.singletonList("some-project"))) + .withHttp2Disable(true) + .withTlsVersions(new TlsVersion[] { TlsVersion.TLS_1_3 }) + .withCurrentContext(userConfiguredNamedContext) + .withImpersonateGroups("developer", "admin") + .withUserAgent("custom-user-agent") + .build(); + // Then + assertThat(config) + .hasFieldOrPropertyWithValue("autoConfigure", false) + .hasFieldOrPropertyWithValue("masterUrl", "https://api-test.openshiftapps.com:6443/") + .hasFieldOrPropertyWithValue("contexts", Collections.singletonList(userConfiguredNamedContext)) + .hasFieldOrPropertyWithValue("maxConcurrentRequests", 30) + .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 10) + .hasFieldOrPropertyWithValue("trustCerts", true) + .hasFieldOrPropertyWithValue("disableHostnameVerification", true) + .hasFieldOrPropertyWithValue("clientKeyAlgo", "EC") + .hasFieldOrPropertyWithValue("clientKeyPassphrase", "changeit") + .hasFieldOrPropertyWithValue("watchReconnectInterval", 500) + .hasFieldOrPropertyWithValue("watchReconnectLimit", 10) + .hasFieldOrPropertyWithValue("connectionTimeout", 1000) + .hasFieldOrPropertyWithValue("requestTimeout", 1000) + .hasFieldOrPropertyWithValue("scaleTimeout", 1000L) + .hasFieldOrPropertyWithValue("loggingInterval", 1000) + .hasFieldOrPropertyWithValue("websocketPingInterval", 10000L) + .hasFieldOrPropertyWithValue("uploadRequestTimeout", 1000) + .hasFieldOrPropertyWithValue("impersonateExtras", + Collections.singletonMap("acme%2Fproject", Collections.singletonList("some-project"))) + .hasFieldOrPropertyWithValue("http2Disable", true) + .hasFieldOrPropertyWithValue("tlsVersions", new TlsVersion[] { TlsVersion.TLS_1_3 }) + .satisfies(e -> assertThat(e.getCurrentContext()).isEqualTo(userConfiguredNamedContext)) + .satisfies(e -> assertThat(e.getImpersonateGroups()).containsExactly("developer", "admin")) + .satisfies(e -> assertThat(e.getUserAgent()).isEqualTo("custom-user-agent")); + } + + @AfterEach + void tearDown() { + System.clearProperty("kubeconfig"); + } + } + } +} 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 780b05aa043..fc9f505c512 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 @@ -835,7 +835,7 @@ void testEmptyConfig() { // Then assertThat(emptyConfig) - .hasFieldOrPropertyWithValue("masterUrl", "https://kubernetes.default.svc") + .hasFieldOrPropertyWithValue("masterUrl", "https://kubernetes.default.svc/") .hasFieldOrPropertyWithValue("contexts", Collections.emptyList()) .hasFieldOrPropertyWithValue("maxConcurrentRequests", 64) .hasFieldOrPropertyWithValue("maxConcurrentRequestsPerHost", 5) @@ -1247,7 +1247,7 @@ private io.fabric8.kubernetes.client.ConfigBuilder createConfigBuilderWithUserCo .withWatchReconnectLimit(10) .withConnectionTimeout(1000) .withRequestTimeout(1000) - .withScaleTimeout(1000) + .withScaleTimeout(1000L) .withLoggingInterval(1000) .withWebsocketPingInterval(10000L) .withUploadRequestTimeout(1000) diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/SundrioConfigBuilderTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/SundrioConfigBuilderTest.java new file mode 100644 index 00000000000..9db91d03b38 --- /dev/null +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/SundrioConfigBuilderTest.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; + +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.stream.Collectors; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +class SundrioConfigBuilderTest { + @Test + void hasExpectedNumberOfFields() { + assertThat(Arrays.stream(SundrioConfigFluent.class.getDeclaredFields()) + .filter(f -> !Modifier.isStatic(f.getModifiers())) + .collect(Collectors.toList())) + .withFailMessage("You've probably modified Config and SundrioConfig constructor annotated with @Buildable," + + "please update the ConfigFluent.copyInstance method too") + .hasSize(53); + } +} diff --git a/kubernetes-itests/src/test/java/io/fabric8/kubernetes/DisableAutoConfigurationIT.java b/kubernetes-itests/src/test/java/io/fabric8/kubernetes/DisableAutoConfigurationIT.java index 4afd7ef4a8e..cdbe8dcafc4 100644 --- a/kubernetes-itests/src/test/java/io/fabric8/kubernetes/DisableAutoConfigurationIT.java +++ b/kubernetes-itests/src/test/java/io/fabric8/kubernetes/DisableAutoConfigurationIT.java @@ -31,6 +31,32 @@ class DisableAutoConfigurationIT { KubernetesClient client; + @Test + @DisplayName("with autoConfigure=false, then client should not load kubeconfig contents") + void givenConfigWithAutoConfigureDisabled_shouldNotLoadLocalKubeConfig() { + // Given + When + client = new KubernetesClientBuilder().withConfig(new ConfigBuilder() + .withAutoConfigure(false) + .withRequestRetryBackoffLimit(0) + .build()).build(); + + // Then + assertThat(client.getConfiguration()) + .hasFieldOrPropertyWithValue("namespace", null) + .hasFieldOrPropertyWithValue("masterUrl", "https://kubernetes.default.svc/") + .hasFieldOrPropertyWithValue("contexts", Collections.emptyList()) + .hasFieldOrPropertyWithValue("currentContext", null) + .hasFieldOrPropertyWithValue("username", null) + .hasFieldOrPropertyWithValue("clientCertFile", null) + .hasFieldOrPropertyWithValue("clientKeyFile", null) + .hasFieldOrPropertyWithValue("clientCertData", null) + .hasFieldOrPropertyWithValue("caCertFile", null) + .hasFieldOrPropertyWithValue("caCertData", null); + assertThatExceptionOfType(KubernetesClientException.class) + .isThrownBy(() -> client.pods().list()) + .withMessageContaining("Operation: [list] for kind: [Pod] with name: [null] in namespace: [null] failed."); + } + @Test @DisplayName("kubernetes.disable.autoConfig=true, then client should not load kubeconfig contents") void givenDisableAutoConfigPropertyTrue_shouldNotLoadLocalKubeConfig() { 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 9c9b39d4ad2..db4e8548d29 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 @@ -52,8 +52,8 @@ public class OpenShiftConfig extends Config { // dummy fields so that Builder is created correctly private String oapiVersion; private String openShiftUrl; - private long buildTimeout; - private boolean disableApiGroupCheck; //If group hasn't been explicitly set. + private Long buildTimeout; + private Boolean disableApiGroupCheck; //If group hasn't been explicitly set. //This is not meant to be used. This constructor is used only by the generated builder. OpenShiftConfig() { @@ -73,35 +73,34 @@ public OpenShiftConfig(Config kubernetesConfig, String openShiftUrl) { @Buildable(builderPackage = "io.fabric8.kubernetes.api.builder", editableEnabled = false, refs = { @BuildableReference(Config.class) }) public OpenShiftConfig(String openShiftUrl, String oapiVersion, String masterUrl, String apiVersion, String namespace, - boolean trustCerts, boolean disableHostnameVerification, String caCertFile, String caCertData, + Boolean trustCerts, Boolean disableHostnameVerification, String caCertFile, String caCertData, String clientCertFile, String clientCertData, String clientKeyFile, String clientKeyData, String clientKeyAlgo, String clientKeyPassphrase, - String username, String password, String oauthToken, String autoOAuthToken, int watchReconnectInterval, - int watchReconnectLimit, - int connectionTimeout, int requestTimeout, long scaleTimeout, int loggingInterval, - int maxConcurrentRequests, int maxConcurrentRequestsPerHost, boolean http2Disable, String httpProxy, + String username, String password, String oauthToken, String autoOAuthToken, Integer watchReconnectInterval, + Integer watchReconnectLimit, + Integer connectionTimeout, Integer requestTimeout, Long scaleTimeout, Integer loggingInterval, + Integer maxConcurrentRequests, Integer maxConcurrentRequestsPerHost, Boolean http2Disable, String httpProxy, String httpsProxy, String[] noProxy, Map errorMessages, String userAgent, TlsVersion[] tlsVersions, - long websocketPingInterval, String proxyUsername, String proxyPassword, String trustStoreFile, + 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, int requestRetryBackoffInterval, - int uploadRequestTimeout, boolean onlyHttpWatches, long buildTimeout, - boolean disableApiGroupCheck, NamedContext currentContext, List contexts) { + Map customHeaders, Integer requestRetryBackoffLimit, Integer requestRetryBackoffInterval, + Integer uploadRequestTimeout, Boolean onlyHttpWatches, Long buildTimeout, + Boolean disableApiGroupCheck, NamedContext currentContext, List contexts, Boolean autoConfigure) { super(masterUrl, apiVersion, namespace, trustCerts, disableHostnameVerification, caCertFile, caCertData, clientCertFile, clientCertData, clientKeyFile, clientKeyData, clientKeyAlgo, clientKeyPassphrase, username, password, oauthToken, autoOAuthToken, watchReconnectInterval, watchReconnectLimit, connectionTimeout, requestTimeout, scaleTimeout, loggingInterval, maxConcurrentRequests, maxConcurrentRequestsPerHost, http2Disable, httpProxy, httpsProxy, - noProxy, - errorMessages, userAgent, tlsVersions, websocketPingInterval, proxyUsername, proxyPassword, + noProxy, userAgent, tlsVersions, websocketPingInterval, proxyUsername, proxyPassword, trustStoreFile, trustStorePassphrase, keyStoreFile, keyStorePassphrase, impersonateUsername, impersonateGroups, impersonateExtras, oauthTokenProvider, customHeaders, requestRetryBackoffLimit, requestRetryBackoffInterval, - uploadRequestTimeout, onlyHttpWatches, currentContext, contexts); + uploadRequestTimeout, onlyHttpWatches, currentContext, contexts, autoConfigure); this.setOapiVersion(oapiVersion); this.setBuildTimeout(buildTimeout); this.setDisableApiGroupCheck(disableApiGroupCheck); @@ -131,9 +130,8 @@ public OpenShiftConfig(Config kubernetesConfig, String openShiftUrl, String oapi kubernetesConfig.getScaleTimeout(), kubernetesConfig.getLoggingInterval(), kubernetesConfig.getMaxConcurrentRequests(), kubernetesConfig.getMaxConcurrentRequestsPerHost(), kubernetesConfig.isHttp2Disable(), - kubernetesConfig.getHttpProxy(), kubernetesConfig.getHttpsProxy(), kubernetesConfig.getNoProxy(), - kubernetesConfig.getErrorMessages(), kubernetesConfig.getUserAgent(), - kubernetesConfig.getTlsVersions(), + kubernetesConfig.getHttpProxy(), kubernetesConfig.getHttpsProxy(), kubernetesConfig.getNoProxy(), null, + kubernetesConfig.getUserAgent(), kubernetesConfig.getTlsVersions(), kubernetesConfig.getWebsocketPingInterval(), kubernetesConfig.getProxyUsername(), kubernetesConfig.getProxyPassword(), kubernetesConfig.getTrustStoreFile(), kubernetesConfig.getTrustStorePassphrase(), kubernetesConfig.getKeyStoreFile(), @@ -146,7 +144,8 @@ public OpenShiftConfig(Config kubernetesConfig, String openShiftUrl, String oapi buildTimeout, false, kubernetesConfig.getCurrentContext(), - kubernetesConfig.getContexts()); + kubernetesConfig.getContexts(), + kubernetesConfig.getAutoConfigure()); } public static OpenShiftConfig wrap(Config config) { 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 73572207ae0..6ed35a139e4 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 @@ -131,7 +131,7 @@ public void activate(Map properties) { builder.withOpenShiftUrl(URLUtils.join(builder.getMasterUrl(), "oapi", builder.getOapiVersion())); } if (properties.containsKey(OPENSHIFT_BUILD_TIMEOUT_SYSTEM_PROPERTY)) { - builder.withBuildTimeout(Integer.parseInt((String) properties.get(OPENSHIFT_BUILD_TIMEOUT_SYSTEM_PROPERTY))); + builder.withBuildTimeout(Long.parseLong((String) properties.get(OPENSHIFT_BUILD_TIMEOUT_SYSTEM_PROPERTY))); } else { builder.withBuildTimeout(DEFAULT_BUILD_TIMEOUT); }