diff --git a/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java index f9b839d4..79ba73cd 100644 --- a/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-client-autoconfig/src/main/java/org/springframework/cloud/kubernetes/client/KubernetesClientAutoConfiguration.java @@ -42,9 +42,12 @@ public class KubernetesClientAutoConfiguration { @Bean @ConditionalOnMissingBean - public ApiClient apiClient(KubernetesClientProperties properties) { + public ApiClient apiClient(Environment environment) { ApiClient apiClient = kubernetesApiClient(); - apiClient.setUserAgent(properties.getUserAgent()); + // it's too early to inject KubernetesClientProperties here, all its properties + // are missing. For the time being work-around with reading from the environment. + apiClient.setUserAgent(environment.getProperty("spring.cloud.kubernetes.client.user-agent", + KubernetesClientProperties.DEFAULT_USER_AGENT)); return apiClient; } diff --git a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolver.java b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolver.java index 10360a45..cd22c50a 100644 --- a/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolver.java +++ b/spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigDataLocationResolver.java @@ -128,7 +128,7 @@ public class KubernetesClientConfigDataLocationResolver extends KubernetesConfig protected ApiClient apiClient(KubernetesClientProperties properties) { ApiClient apiClient = kubernetesApiClient(); - apiClient.setUserAgent(properties.getUserAgent()); + apiClient.setUserAgent(properties.userAgent()); return apiClient; } diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorTests.java index a385fe3f..0ec6e336 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorTests.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorTests.java @@ -35,7 +35,6 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties; import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties; import org.springframework.cloud.kubernetes.commons.config.NamespaceResolutionFailedException; @@ -119,8 +118,6 @@ class KubernetesClientConfigMapPropertySourceLocatorTests { ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(source), Map.of(), true, "fake-name", null, false, false, false, RetryProperties.DEFAULT); - KubernetesClientProperties kubernetesClientProperties = new KubernetesClientProperties(); - kubernetesClientProperties.setNamespace("dev"); PropertySource propertySource = new KubernetesClientConfigMapPropertySourceLocator(api, configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())).locate(ENV); assertThat(propertySource.containsProperty("spring.cloud.kubernetes.configuration.watcher.refreshDelay")) @@ -139,10 +136,10 @@ class KubernetesClientConfigMapPropertySourceLocatorTests { CoreV1Api api = new CoreV1Api(); stubFor(get("/api/v1/namespaces/default/configmaps") .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(PROPERTIES_CONFIGMAP_LIST)))); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), Map.of(), true, "bootstrap-640", null, false, false, false, RetryProperties.DEFAULT); - KubernetesClientProperties kubernetesClientProperties = new KubernetesClientProperties(); - kubernetesClientProperties.setNamespace(""); // empty on purpose + assertThatThrownBy(() -> new KubernetesClientConfigMapPropertySourceLocator(api, configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())).locate(ENV)) .isInstanceOf(NamespaceResolutionFailedException.class); @@ -162,8 +159,6 @@ class KubernetesClientConfigMapPropertySourceLocatorTests { .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(PROPERTIES_CONFIGMAP_LIST)))); ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), Map.of(), true, "bootstrap-640", null, false, false, false, RetryProperties.DEFAULT); - KubernetesClientProperties kubernetesClientProperties = new KubernetesClientProperties(); - kubernetesClientProperties.setNamespace(""); // empty on purpose assertThatThrownBy(() -> new KubernetesClientConfigMapPropertySourceLocator(api, configMapConfigProperties, new KubernetesNamespaceProvider(ENV)).locate(ENV)) .isInstanceOf(NamespaceResolutionFailedException.class); diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigReloadAutoConfigurationTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigReloadAutoConfigurationTest.java index a7ddd275..f5ec8257 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigReloadAutoConfigurationTest.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigReloadAutoConfigurationTest.java @@ -201,9 +201,9 @@ public class KubernetesClientConfigReloadAutoConfigurationTest { @ConditionalOnMissingBean(KubernetesClientProperties.class) @Bean KubernetesClientProperties kubernetesClientProperties() { - KubernetesClientProperties properties = new KubernetesClientProperties(); - properties.setNamespace("default"); - return properties; + return new KubernetesClientProperties(null, null, null, "default", null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null); } @Bean diff --git a/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplier.java b/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplier.java index c4522df9..d9606855 100644 --- a/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplier.java +++ b/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplier.java @@ -57,7 +57,7 @@ public class KubernetesClientServicesListSupplier extends KubernetesServicesList private String getNamespace() { return kubernetesNamespaceProvider != null ? kubernetesNamespaceProvider.getNamespace() - : kubernetesClientProperties.getNamespace(); + : kubernetesClientProperties.namespace(); } @Override diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/KubernetesClientProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/KubernetesClientProperties.java index ee62df6d..d367217c 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/KubernetesClientProperties.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/KubernetesClientProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2020 the original author or authors. + * Copyright 2013-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ package org.springframework.cloud.kubernetes.commons; import java.time.Duration; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.bind.DefaultValue; import static org.springframework.cloud.kubernetes.commons.KubernetesClientProperties.PREFIX; @@ -28,7 +29,14 @@ import static org.springframework.cloud.kubernetes.commons.KubernetesClientPrope * @author Ioannis Canellos */ @ConfigurationProperties(PREFIX) -public class KubernetesClientProperties { +public record KubernetesClientProperties(Boolean trustCerts, String masterUrl, String apiVersion, String namespace, + String caCertFile, String caCertData, String clientCertFile, String clientCertData, String clientKeyFile, + String clientKeyData, String clientKeyAlgo, String clientKeyPassphrase, String username, String password, + Duration watchReconnectInterval, Duration watchReconnectLimit, Duration connectionTimeout, + Duration requestTimeout, Duration rollingTimeout, Duration loggingInterval, String httpProxy, String httpsProxy, + String proxyUsername, String proxyPassword, String oauthToken, String[] noProxy, + @DefaultValue(SERVICE_ACCOUNT_NAMESPACE_PATH) String serviceAccountNamespacePath, + @DefaultValue(DEFAULT_USER_AGENT) String userAgent) { /** * Configuration properties prefix. @@ -45,288 +53,17 @@ public class KubernetesClientProperties { */ public static final String SERVICE_ACCOUNT_NAMESPACE_PATH = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"; - private Boolean trustCerts; - - private String masterUrl; - - private String apiVersion; - - private String namespace; - - private String caCertFile; - - private String caCertData; - - private String clientCertFile; - - private String clientCertData; - - private String clientKeyFile; - - private String clientKeyData; - - private String clientKeyAlgo; - - private String clientKeyPassphrase; - - private String username; - - private String password; - - private Duration watchReconnectInterval; - - private Duration watchReconnectLimit; - - private Duration connectionTimeout; - - private Duration requestTimeout; - - private Duration rollingTimeout; - - private Duration loggingInterval; - - private String httpProxy; - - private String httpsProxy; - - private String proxyUsername; - - private String proxyPassword; - - private String oauthToken; - - private String[] noProxy; - - private String serviceAccountNamespacePath = SERVICE_ACCOUNT_NAMESPACE_PATH; - - private String userAgent = DEFAULT_USER_AGENT; - - public String getServiceAccountNamespacePath() { - return serviceAccountNamespacePath; - } - - public void setServiceAccountNamespacePath(String serviceAccountNamespacePath) { - this.serviceAccountNamespacePath = serviceAccountNamespacePath; - } - - public String getClientCertData() { - return this.clientCertData; - } - - public void setClientCertData(String clientCertData) { - this.clientCertData = clientCertData; - } - - public Boolean isTrustCerts() { - return this.trustCerts; - } - - public String getMasterUrl() { - return this.masterUrl; - } - - public void setMasterUrl(String masterUrl) { - this.masterUrl = masterUrl; - } - - public String getApiVersion() { - return this.apiVersion; - } - - public void setApiVersion(String apiVersion) { - this.apiVersion = apiVersion; - } - - public String getNamespace() { - return this.namespace; - } - - public void setNamespace(String namespace) { - this.namespace = namespace; - } - - public String getCaCertFile() { - return this.caCertFile; - } - - public void setCaCertFile(String caCertFile) { - this.caCertFile = caCertFile; - } - - public String getCaCertData() { - return this.caCertData; - } - - public void setCaCertData(String caCertData) { - this.caCertData = caCertData; - } - - public String getClientCertFile() { - return this.clientCertFile; - } - - public void setClientCertFile(String clientCertFile) { - this.clientCertFile = clientCertFile; - } - - public String getClientKeyFile() { - return this.clientKeyFile; - } - - public void setClientKeyFile(String clientKeyFile) { - this.clientKeyFile = clientKeyFile; - } - - public String getClientKeyData() { - return this.clientKeyData; - } - - public void setClientKeyData(String clientKeyData) { - this.clientKeyData = clientKeyData; - } - - public String getClientKeyAlgo() { - return this.clientKeyAlgo; - } - - public void setClientKeyAlgo(String clientKeyAlgo) { - this.clientKeyAlgo = clientKeyAlgo; - } - - public String getClientKeyPassphrase() { - return this.clientKeyPassphrase; - } - - public void setClientKeyPassphrase(String clientKeyPassphrase) { - this.clientKeyPassphrase = clientKeyPassphrase; - } - - public String getUsername() { - return this.username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return this.password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Duration getWatchReconnectInterval() { - return this.watchReconnectInterval; - } - - public void setWatchReconnectInterval(Duration watchReconnectInterval) { - this.watchReconnectInterval = watchReconnectInterval; - } - - public Duration getWatchReconnectLimit() { - return this.watchReconnectLimit; - } - - public void setWatchReconnectLimit(Duration watchReconnectLimit) { - this.watchReconnectLimit = watchReconnectLimit; - } - - public Duration getConnectionTimeout() { - return this.connectionTimeout; - } - - public void setConnectionTimeout(Duration connectionTimeout) { - this.connectionTimeout = connectionTimeout; - } - - public Duration getRequestTimeout() { - return this.requestTimeout; - } - - public void setRequestTimeout(Duration requestTimeout) { - this.requestTimeout = requestTimeout; - } - - public Duration getRollingTimeout() { - return this.rollingTimeout; - } - - public void setRollingTimeout(Duration rollingTimeout) { - this.rollingTimeout = rollingTimeout; - } - - public Duration getLoggingInterval() { - return this.loggingInterval; - } - - public void setLoggingInterval(Duration loggingInterval) { - this.loggingInterval = loggingInterval; - } - - public Boolean getTrustCerts() { - return this.trustCerts; - } - - public void setTrustCerts(Boolean trustCerts) { - this.trustCerts = trustCerts; - } - - public String getHttpProxy() { - return this.httpProxy; - } - - public void setHttpProxy(String httpProxy) { - this.httpProxy = httpProxy; - } - - public String getHttpsProxy() { - return this.httpsProxy; - } - - public void setHttpsProxy(String httpsProxy) { - this.httpsProxy = httpsProxy; - } - - public String getProxyUsername() { - return this.proxyUsername; - } - - public void setProxyUsername(String proxyUsername) { - this.proxyUsername = proxyUsername; - } - - public String getProxyPassword() { - return this.proxyPassword; - } - - public void setProxyPassword(String proxyPassword) { - this.proxyPassword = proxyPassword; - } - - public String[] getNoProxy() { - return this.noProxy; - } - - public void setNoProxy(String[] noProxy) { - this.noProxy = noProxy; - } - - public String getOauthToken() { - return this.oauthToken; - } - - public void setOauthToken(String oauthToken) { - this.oauthToken = oauthToken; - } - - public String getUserAgent() { - return userAgent; - } - - public void setUserAgent(String userAgent) { - this.userAgent = userAgent; + /** + * copy constructor that only changes the namespace. + */ + public KubernetesClientProperties withNamespace(String namespace) { + return new KubernetesClientProperties(this.trustCerts(), this.masterUrl(), this.apiVersion(), namespace, + this.caCertFile(), this.caCertData(), this.clientCertFile(), this.clientCertData(), + this.clientKeyFile(), this.clientKeyData(), this.clientKeyAlgo(), this.clientKeyPassphrase(), + this.username(), this.password(), this.watchReconnectInterval(), this.watchReconnectLimit(), + this.connectionTimeout(), this.requestTimeout(), this.rollingTimeout(), this.loggingInterval(), + this.httpProxy(), this.httpsProxy(), this.proxyUsername(), this.proxyPassword(), this.oauthToken(), + this.noProxy(), this.serviceAccountNamespacePath(), this.userAgent()); } } diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java index 1fc53040..ce1f552f 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolver.java @@ -42,7 +42,6 @@ import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.core.env.StandardEnvironment; -import static org.springframework.beans.BeanUtils.copyProperties; import static org.springframework.boot.cloud.CloudPlatform.KUBERNETES; import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.registerSingle; import static org.springframework.util.ClassUtils.isPresent; @@ -95,7 +94,7 @@ public abstract class KubernetesConfigDataLocationResolver registerProperties(resolverContext, clientProperties, configMapProperties, secretsProperties); HashMap kubernetesConfigData = new HashMap<>(); - kubernetesConfigData.put("spring.cloud.kubernetes.client.namespace", clientProperties.getNamespace()); + kubernetesConfigData.put("spring.cloud.kubernetes.client.namespace", clientProperties.namespace()); if (propertyHolder.applicationName() != null) { // If its null it means sprig.application.name was not set so don't add it to // the property source @@ -170,25 +169,25 @@ public abstract class KubernetesConfigDataLocationResolver String namespace = binder.bind("spring.cloud.kubernetes.client.namespace", String.class) .orElse(binder.bind("kubernetes.namespace", String.class).orElse("")); - KubernetesClientProperties kubernetesClientProperties = clientProperties(context); - kubernetesClientProperties.setNamespace(namespace); - + KubernetesClientProperties kubernetesClientProperties = clientProperties(context, namespace); ConfigMapAndSecrets both = ConfigMapAndSecrets.of(binder); + return new PropertyHolder(kubernetesClientProperties, both.configMapProperties(), both.secretsConfigProperties(), applicationName); } - private static KubernetesClientProperties clientProperties(ConfigDataLocationResolverContext context) { + private static KubernetesClientProperties clientProperties(ConfigDataLocationResolverContext context, + String namespace) { KubernetesClientProperties kubernetesClientProperties; if (context.getBootstrapContext().isRegistered(KubernetesClientProperties.class)) { - kubernetesClientProperties = new KubernetesClientProperties(); - copyProperties(context.getBootstrapContext().get(KubernetesClientProperties.class), - kubernetesClientProperties); + kubernetesClientProperties = context.getBootstrapContext().get(KubernetesClientProperties.class) + .withNamespace(namespace); } else { - kubernetesClientProperties = context.getBinder().bindOrCreate(KubernetesClientProperties.PREFIX, - Bindable.of(KubernetesClientProperties.class)); + kubernetesClientProperties = context.getBinder() + .bindOrCreate(KubernetesClientProperties.PREFIX, Bindable.of(KubernetesClientProperties.class)) + .withNamespace(namespace); } return kubernetesClientProperties; diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/KubernetesClientPropertiesTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/KubernetesClientPropertiesTests.java new file mode 100644 index 00000000..c7b36045 --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/KubernetesClientPropertiesTests.java @@ -0,0 +1,206 @@ +/* + * Copyright 2013-2022 the original author or authors. + * + * 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 + * + * https://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 org.springframework.cloud.kubernetes.commons; + +import java.time.Duration; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +class KubernetesClientPropertiesTests { + + @Test + void testDefaults() { + new ApplicationContextRunner().withUserConfiguration(Config.class).run(context -> { + KubernetesClientProperties properties = context.getBean(KubernetesClientProperties.class); + assertThat(properties).isNotNull(); + assertThat(properties.trustCerts()).isNull(); + assertThat(properties.masterUrl()).isNull(); + assertThat(properties.apiVersion()).isNull(); + assertThat(properties.namespace()).isNull(); + assertThat(properties.caCertFile()).isNull(); + assertThat(properties.caCertData()).isNull(); + assertThat(properties.clientCertFile()).isNull(); + assertThat(properties.clientCertData()).isNull(); + assertThat(properties.clientKeyFile()).isNull(); + assertThat(properties.clientKeyData()).isNull(); + assertThat(properties.clientKeyAlgo()).isNull(); + assertThat(properties.clientKeyPassphrase()).isNull(); + assertThat(properties.username()).isNull(); + assertThat(properties.password()).isNull(); + assertThat(properties.watchReconnectInterval()).isNull(); + assertThat(properties.watchReconnectLimit()).isNull(); + assertThat(properties.connectionTimeout()).isNull(); + assertThat(properties.requestTimeout()).isNull(); + assertThat(properties.rollingTimeout()).isNull(); + assertThat(properties.loggingInterval()).isNull(); + assertThat(properties.httpProxy()).isNull(); + assertThat(properties.httpsProxy()).isNull(); + assertThat(properties.proxyUsername()).isNull(); + assertThat(properties.proxyPassword()).isNull(); + assertThat(properties.oauthToken()).isNull(); + assertThat(properties.noProxy()).isNull(); + assertThat(properties.serviceAccountNamespacePath()) + .isEqualTo("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); + assertThat(properties.userAgent()).isEqualTo("Spring-Cloud-Kubernetes-Application"); + }); + } + + @Test + void testNonDefaults() { + new ApplicationContextRunner().withUserConfiguration(Config.class).withPropertyValues( + "spring.cloud.kubernetes.client.trust-certs=true", + "spring.cloud.kubernetes.client.master-url=master-url", "spring.cloud.kubernetes.client.api-version=1", + "spring.cloud.kubernetes.client.namespace=namespace", + "spring.cloud.kubernetes.client.ca-cert-file=ca-cert-file", + "spring.cloud.kubernetes.client.ca-cert-data=ca-cert-data", + "spring.cloud.kubernetes.client.client-cert-file=client-cert-file", + "spring.cloud.kubernetes.client.client-cert-data=client-cert-data", + "spring.cloud.kubernetes.client.client-key-file=client-key-file", + "spring.cloud.kubernetes.client.client-key-data=client-key-data", + "spring.cloud.kubernetes.client.client-key-algo=client-key-algo", + "spring.cloud.kubernetes.client.client-key-passphrase=client-key-passphrase", + "spring.cloud.kubernetes.client.username=username", "spring.cloud.kubernetes.client.password=password", + "spring.cloud.kubernetes.client.watch-reconnect-interval=200ms", + "spring.cloud.kubernetes.client.watch-reconnect-limit=300ms", + "spring.cloud.kubernetes.client.connection-timeout=400ms", + "spring.cloud.kubernetes.client.request-timeout=500ms", + "spring.cloud.kubernetes.client.rolling-timeout=600ms", + "spring.cloud.kubernetes.client.logging-interval=700ms", + "spring.cloud.kubernetes.client.http-proxy=http-proxy", + "spring.cloud.kubernetes.client.https-proxy=https-proxy", + "spring.cloud.kubernetes.client.proxy-username=proxy-username", + "spring.cloud.kubernetes.client.proxy-password=proxy-password", + "spring.cloud.kubernetes.client.oauth-token=oauth-token", + "spring.cloud.kubernetes.client.no-proxy[0]=a", "spring.cloud.kubernetes.client.no-proxy[1]=b", + "spring.cloud.kubernetes.client.service-account-namespace-path=path", + "spring.cloud.kubernetes.client.user-agent=user-agent").run(context -> { + KubernetesClientProperties properties = context.getBean(KubernetesClientProperties.class); + assertThat(properties).isNotNull(); + assertThat(properties.trustCerts()).isTrue(); + assertThat(properties.masterUrl()).isEqualTo("master-url"); + assertThat(properties.apiVersion()).isEqualTo("1"); + assertThat(properties.namespace()).isEqualTo("namespace"); + assertThat(properties.caCertFile()).isEqualTo("ca-cert-file"); + assertThat(properties.caCertData()).isEqualTo("ca-cert-data"); + assertThat(properties.clientCertFile()).isEqualTo("client-cert-file"); + assertThat(properties.clientCertData()).isEqualTo("client-cert-data"); + assertThat(properties.clientKeyFile()).isEqualTo("client-key-file"); + assertThat(properties.clientKeyData()).isEqualTo("client-key-data"); + assertThat(properties.clientKeyAlgo()).isEqualTo("client-key-algo"); + assertThat(properties.clientKeyPassphrase()).isEqualTo("client-key-passphrase"); + assertThat(properties.username()).isEqualTo("username"); + assertThat(properties.password()).isEqualTo("password"); + assertThat(properties.watchReconnectInterval()).isEqualTo(Duration.ofMillis(200)); + assertThat(properties.watchReconnectLimit()).isEqualTo(Duration.ofMillis(300)); + assertThat(properties.connectionTimeout()).isEqualTo(Duration.ofMillis(400)); + assertThat(properties.requestTimeout()).isEqualTo(Duration.ofMillis(500)); + assertThat(properties.rollingTimeout()).isEqualTo(Duration.ofMillis(600)); + assertThat(properties.loggingInterval()).isEqualTo(Duration.ofMillis(700)); + assertThat(properties.httpProxy()).isEqualTo("http-proxy"); + assertThat(properties.httpsProxy()).isEqualTo("https-proxy"); + assertThat(properties.proxyUsername()).isEqualTo("proxy-username"); + assertThat(properties.proxyPassword()).isEqualTo("proxy-password"); + assertThat(properties.oauthToken()).isEqualTo("oauth-token"); + assertThat(properties.noProxy().length).isEqualTo(2); + assertThat(properties.noProxy()[0]).isEqualTo("a"); + assertThat(properties.noProxy()[1]).isEqualTo("b"); + assertThat(properties.serviceAccountNamespacePath()).isEqualTo("path"); + assertThat(properties.userAgent()).isEqualTo("user-agent"); + }); + } + + @Test + void testCopyWithNamespaceConstructor() { + new ApplicationContextRunner().withUserConfiguration(Config.class).withPropertyValues( + "spring.cloud.kubernetes.client.trust-certs=true", + "spring.cloud.kubernetes.client.master-url=master-url", "spring.cloud.kubernetes.client.api-version=1", + "spring.cloud.kubernetes.client.namespace=namespace", + "spring.cloud.kubernetes.client.ca-cert-file=ca-cert-file", + "spring.cloud.kubernetes.client.ca-cert-data=ca-cert-data", + "spring.cloud.kubernetes.client.client-cert-file=client-cert-file", + "spring.cloud.kubernetes.client.client-cert-data=client-cert-data", + "spring.cloud.kubernetes.client.client-key-file=client-key-file", + "spring.cloud.kubernetes.client.client-key-data=client-key-data", + "spring.cloud.kubernetes.client.client-key-algo=client-key-algo", + "spring.cloud.kubernetes.client.client-key-passphrase=client-key-passphrase", + "spring.cloud.kubernetes.client.username=username", "spring.cloud.kubernetes.client.password=password", + "spring.cloud.kubernetes.client.watch-reconnect-interval=200ms", + "spring.cloud.kubernetes.client.watch-reconnect-limit=300ms", + "spring.cloud.kubernetes.client.connection-timeout=400ms", + "spring.cloud.kubernetes.client.request-timeout=500ms", + "spring.cloud.kubernetes.client.rolling-timeout=600ms", + "spring.cloud.kubernetes.client.logging-interval=700ms", + "spring.cloud.kubernetes.client.http-proxy=http-proxy", + "spring.cloud.kubernetes.client.https-proxy=https-proxy", + "spring.cloud.kubernetes.client.proxy-username=proxy-username", + "spring.cloud.kubernetes.client.proxy-password=proxy-password", + "spring.cloud.kubernetes.client.oauth-token=oauth-token", + "spring.cloud.kubernetes.client.no-proxy[0]=a", "spring.cloud.kubernetes.client.no-proxy[1]=b", + "spring.cloud.kubernetes.client.service-account-namespace-path=path", + "spring.cloud.kubernetes.client.user-agent=user-agent").run(context -> { + KubernetesClientProperties properties = context.getBean(KubernetesClientProperties.class) + .withNamespace("non-default"); + assertThat(properties).isNotNull(); + assertThat(properties.trustCerts()).isTrue(); + assertThat(properties.masterUrl()).isEqualTo("master-url"); + assertThat(properties.apiVersion()).isEqualTo("1"); + assertThat(properties.namespace()).isEqualTo("non-default"); + assertThat(properties.caCertFile()).isEqualTo("ca-cert-file"); + assertThat(properties.caCertData()).isEqualTo("ca-cert-data"); + assertThat(properties.clientCertFile()).isEqualTo("client-cert-file"); + assertThat(properties.clientCertData()).isEqualTo("client-cert-data"); + assertThat(properties.clientKeyFile()).isEqualTo("client-key-file"); + assertThat(properties.clientKeyData()).isEqualTo("client-key-data"); + assertThat(properties.clientKeyAlgo()).isEqualTo("client-key-algo"); + assertThat(properties.clientKeyPassphrase()).isEqualTo("client-key-passphrase"); + assertThat(properties.username()).isEqualTo("username"); + assertThat(properties.password()).isEqualTo("password"); + assertThat(properties.watchReconnectInterval()).isEqualTo(Duration.ofMillis(200)); + assertThat(properties.watchReconnectLimit()).isEqualTo(Duration.ofMillis(300)); + assertThat(properties.connectionTimeout()).isEqualTo(Duration.ofMillis(400)); + assertThat(properties.requestTimeout()).isEqualTo(Duration.ofMillis(500)); + assertThat(properties.rollingTimeout()).isEqualTo(Duration.ofMillis(600)); + assertThat(properties.loggingInterval()).isEqualTo(Duration.ofMillis(700)); + assertThat(properties.httpProxy()).isEqualTo("http-proxy"); + assertThat(properties.httpsProxy()).isEqualTo("https-proxy"); + assertThat(properties.proxyUsername()).isEqualTo("proxy-username"); + assertThat(properties.proxyPassword()).isEqualTo("proxy-password"); + assertThat(properties.oauthToken()).isEqualTo("oauth-token"); + assertThat(properties.noProxy().length).isEqualTo(2); + assertThat(properties.noProxy()[0]).isEqualTo("a"); + assertThat(properties.noProxy()[1]).isEqualTo("b"); + assertThat(properties.serviceAccountNamespacePath()).isEqualTo("path"); + assertThat(properties.userAgent()).isEqualTo("user-agent"); + }); + } + + @EnableConfigurationProperties(KubernetesClientProperties.class) + @Configuration + static class Config { + + } + +} diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/KubernetesCommonsAutoConfigurationTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/KubernetesCommonsAutoConfigurationTests.java index a49e85b1..15e35eb7 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/KubernetesCommonsAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/KubernetesCommonsAutoConfigurationTests.java @@ -46,8 +46,8 @@ public class KubernetesCommonsAutoConfigurationTests { KubernetesClientProperties properties = context.getBeansOfType(KubernetesClientProperties.class).values() .stream().findFirst().get(); - assertThat(properties.getPassword()).isEqualTo("mypassword"); - assertThat(properties.getProxyPassword()).isEqualTo("myproxypassword"); + assertThat(properties.password()).isEqualTo("mypassword"); + assertThat(properties.proxyPassword()).isEqualTo("myproxypassword"); } @SpringBootApplication diff --git a/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java b/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java index fcafa620..a54fb7af 100644 --- a/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-autoconfig/src/main/java/org/springframework/cloud/kubernetes/fabric8/Fabric8AutoConfiguration.java @@ -22,8 +22,6 @@ import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.ConfigBuilder; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; @@ -46,8 +44,6 @@ import org.springframework.context.annotation.Configuration; @AutoConfigureAfter(KubernetesCommonsAutoConfiguration.class) public class Fabric8AutoConfiguration { - private static final Log LOG = LogFactory.getLog(Fabric8AutoConfiguration.class); - private static D or(D left, D right) { return left != null ? left : right; } @@ -66,47 +62,46 @@ public class Fabric8AutoConfiguration { Config base = Config.autoConfigure(null); ConfigBuilder builder = new ConfigBuilder(base) // Only set values that have been explicitly specified - .withMasterUrl(or(kubernetesClientProperties.getMasterUrl(), base.getMasterUrl())) - .withApiVersion(or(kubernetesClientProperties.getApiVersion(), base.getApiVersion())) - .withNamespace(or(kubernetesClientProperties.getNamespace(), base.getNamespace())) - .withUsername(or(kubernetesClientProperties.getUsername(), base.getUsername())) - .withPassword(or(kubernetesClientProperties.getPassword(), base.getPassword())) + .withMasterUrl(or(kubernetesClientProperties.masterUrl(), base.getMasterUrl())) + .withApiVersion(or(kubernetesClientProperties.apiVersion(), base.getApiVersion())) + .withNamespace(or(kubernetesClientProperties.namespace(), base.getNamespace())) + .withUsername(or(kubernetesClientProperties.username(), base.getUsername())) + .withPassword(or(kubernetesClientProperties.password(), base.getPassword())) - .withOauthToken(or(kubernetesClientProperties.getOauthToken(), base.getOauthToken())) - .withCaCertFile(or(kubernetesClientProperties.getCaCertFile(), base.getCaCertFile())) - .withCaCertData(or(kubernetesClientProperties.getCaCertData(), base.getCaCertData())) + .withOauthToken(or(kubernetesClientProperties.oauthToken(), base.getOauthToken())) + .withCaCertFile(or(kubernetesClientProperties.caCertFile(), base.getCaCertFile())) + .withCaCertData(or(kubernetesClientProperties.caCertData(), base.getCaCertData())) - .withClientKeyFile(or(kubernetesClientProperties.getClientKeyFile(), base.getClientKeyFile())) - .withClientKeyData(or(kubernetesClientProperties.getClientKeyData(), base.getClientKeyData())) + .withClientKeyFile(or(kubernetesClientProperties.clientKeyFile(), base.getClientKeyFile())) + .withClientKeyData(or(kubernetesClientProperties.clientKeyData(), base.getClientKeyData())) - .withClientCertFile(or(kubernetesClientProperties.getClientCertFile(), base.getClientCertFile())) - .withClientCertData(or(kubernetesClientProperties.getClientCertData(), base.getClientCertData())) + .withClientCertFile(or(kubernetesClientProperties.clientCertFile(), base.getClientCertFile())) + .withClientCertData(or(kubernetesClientProperties.clientCertData(), base.getClientCertData())) // No magic is done for the properties below so we leave them as is. - .withClientKeyAlgo(or(kubernetesClientProperties.getClientKeyAlgo(), base.getClientKeyAlgo())) + .withClientKeyAlgo(or(kubernetesClientProperties.clientKeyAlgo(), base.getClientKeyAlgo())) .withClientKeyPassphrase( - or(kubernetesClientProperties.getClientKeyPassphrase(), base.getClientKeyPassphrase())) + or(kubernetesClientProperties.clientKeyPassphrase(), base.getClientKeyPassphrase())) .withConnectionTimeout( - orDurationInt(kubernetesClientProperties.getConnectionTimeout(), base.getConnectionTimeout())) + orDurationInt(kubernetesClientProperties.connectionTimeout(), base.getConnectionTimeout())) .withRequestTimeout( - orDurationInt(kubernetesClientProperties.getRequestTimeout(), base.getRequestTimeout())) + orDurationInt(kubernetesClientProperties.requestTimeout(), base.getRequestTimeout())) .withRollingTimeout( - orDurationLong(kubernetesClientProperties.getRollingTimeout(), base.getRollingTimeout())) - .withTrustCerts(or(kubernetesClientProperties.isTrustCerts(), base.isTrustCerts())) - .withHttpProxy(or(kubernetesClientProperties.getHttpProxy(), base.getHttpProxy())) - .withHttpsProxy(or(kubernetesClientProperties.getHttpsProxy(), base.getHttpsProxy())) - .withProxyUsername(or(kubernetesClientProperties.getProxyUsername(), base.getProxyUsername())) - .withProxyPassword(or(kubernetesClientProperties.getProxyPassword(), base.getProxyPassword())) - .withNoProxy(or(kubernetesClientProperties.getNoProxy(), base.getNoProxy())); + orDurationLong(kubernetesClientProperties.rollingTimeout(), base.getRollingTimeout())) + .withTrustCerts(or(kubernetesClientProperties.trustCerts(), base.isTrustCerts())) + .withHttpProxy(or(kubernetesClientProperties.httpProxy(), base.getHttpProxy())) + .withHttpsProxy(or(kubernetesClientProperties.httpsProxy(), base.getHttpsProxy())) + .withProxyUsername(or(kubernetesClientProperties.proxyUsername(), base.getProxyUsername())) + .withProxyPassword(or(kubernetesClientProperties.proxyPassword(), base.getProxyPassword())) + .withNoProxy(or(kubernetesClientProperties.noProxy(), base.getNoProxy())); String userAgent = or(base.getUserAgent(), KubernetesClientProperties.DEFAULT_USER_AGENT); - if (!kubernetesClientProperties.getUserAgent().equals(KubernetesClientProperties.DEFAULT_USER_AGENT)) { - userAgent = kubernetesClientProperties.getUserAgent(); + if (!kubernetesClientProperties.userAgent().equals(KubernetesClientProperties.DEFAULT_USER_AGENT)) { + userAgent = kubernetesClientProperties.userAgent(); } - Config properties = builder.withUserAgent(userAgent).build(); + return builder.withUserAgent(userAgent).build(); - return properties; } @Bean diff --git a/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentEnvPropertyTests.java b/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentEnvPropertyTests.java index 83896b9b..7194d436 100644 --- a/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentEnvPropertyTests.java +++ b/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentEnvPropertyTests.java @@ -25,6 +25,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.kubernetes.example.App; +import org.springframework.test.annotation.DirtiesContext; import static org.assertj.core.api.Assertions.assertThat; @@ -34,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; * test "User-Agent" functionality via system properties */ @SpringBootTest(classes = App.class, properties = "spring.main.cloud-platform=KUBERNETES") +@DirtiesContext class Fabric8ClientUserAgentEnvPropertyTests { @Autowired