From fd9be003296120223f581887c930049fa28d01ae Mon Sep 17 00:00:00 2001 From: erabii Date: Mon, 8 Nov 2021 13:54:06 -0500 Subject: [PATCH] User Agent Functionality (#898) * change in user agent for fabric8 --- docs/src/main/asciidoc/_configprops.adoc | 5 +- .../KubernetesClientAutoConfiguration.java | 4 +- ...KubernetesClientDefaultApiClientTests.java | 61 --------- ...KubernetesClientDefaultApiClientTests.java | 123 ++++++++++++++++++ .../commons/KubernetesClientProperties.java | 15 +++ .../fabric8/Fabric8AutoConfiguration.java | 11 +- ...abric8ClientUserAgentEnvPropertyTests.java | 58 +++++++++ .../fabric8/Fabric8ClientUserAgentTests.java | 68 ++++++++++ 8 files changed, 279 insertions(+), 66 deletions(-) delete mode 100644 spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/KubernetesClientDefaultApiClientTests.java create mode 100644 spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/KubernetesClientDefaultApiClientTests.java create mode 100644 spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentEnvPropertyTests.java create mode 100644 spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentTests.java diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index 7863d867..924fd661 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -95,6 +95,7 @@ |spring.cloud.kubernetes.secrets.name | | |spring.cloud.kubernetes.secrets.namespace | | |spring.cloud.kubernetes.secrets.paths | | -|spring.cloud.kubernetes.secrets.sources | | +|spring.cloud.kubernetes.secrets.sources | | +|spring.cloud.kubernetes.userAgent | `Spring-Cloud-Kubernetes-Application` | `User-Agent` header -|=== \ No newline at end of file +|=== 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 39a7dbb4..a652f037 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 @@ -22,6 +22,7 @@ import io.kubernetes.client.openapi.apis.CoreV1Api; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.kubernetes.commons.ConditionalOnKubernetesEnabled; +import org.springframework.cloud.kubernetes.commons.KubernetesClientProperties; import org.springframework.cloud.kubernetes.commons.KubernetesCommonsAutoConfiguration; import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; import org.springframework.context.annotation.Bean; @@ -40,8 +41,9 @@ public class KubernetesClientAutoConfiguration { @Bean @ConditionalOnMissingBean - public ApiClient apiClient() { + public ApiClient apiClient(KubernetesClientProperties properties) { ApiClient apiClient = kubernetesApiClient(); + apiClient.setUserAgent(properties.getUserAgent()); return apiClient; } diff --git a/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/KubernetesClientDefaultApiClientTests.java b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/KubernetesClientDefaultApiClientTests.java deleted file mode 100644 index 7258e62d..00000000 --- a/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/KubernetesClientDefaultApiClientTests.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2013-2021 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.client; - -import io.kubernetes.client.openapi.ApiClient; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.test.context.SpringBootTest; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Robert McNees - * - * This tests that the apiClient created in KubernetesClientAutoConfiguration will not set - * itself as the default apiClient. This is to avoid overwriting the user's - * defaultApiClient if they include this project. - */ -@SpringBootTest(classes = KubernetesClientDefaultApiClientTests.App.class, - properties = { "kubernetes.informer.enabled=false" }) -// kubernetes.informer is disabled because -// io.kubernetes...KubernetesInformerAutoConfiguration -// creates a defaultApiClient that will be autowired instead of the ApiClient -// created in KubernetesClientAutoConfiguration -public class KubernetesClientDefaultApiClientTests { - - @Autowired - private ApiClient apiClient; - - @Test - public void testCreatedApiClientIsNotDefault() { - assertThat(apiClient).isNotNull(); - - ApiClient defaultApiClient = io.kubernetes.client.openapi.Configuration.getDefaultApiClient(); - assertThat(defaultApiClient).isNotNull(); - - assertThat(defaultApiClient).isNotSameAs(apiClient); - } - - @SpringBootApplication - static class App { - - } - -} diff --git a/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/KubernetesClientDefaultApiClientTests.java b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/KubernetesClientDefaultApiClientTests.java new file mode 100644 index 00000000..e83ebc16 --- /dev/null +++ b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/KubernetesClientDefaultApiClientTests.java @@ -0,0 +1,123 @@ +/* + * Copyright 2013-2021 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.client.default_api; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; + +import io.kubernetes.client.openapi.ApiClient; +import okhttp3.Request; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Robert McNees + * + * This tests that the apiClient created in KubernetesClientAutoConfiguration will not set + * itself as the default apiClient. This is to avoid overwriting the user's + * defaultApiClient if they include this project. + * + * kubernetes informer is disabled because KubernetesInformerAutoConfiguration creates a + * defaultApiClient that will be autowired instead of the ApiClient created in + * KubernetesClientAutoConfiguration + */ + +class KubernetesClientDefaultApiClientTests { + + private static final String DISABLE_INFORMER = "kubernetes.informer.enabled=false"; + + private static final String USER_AGENT = "spring.cloud.kubernetes.client.userAgent=non-default"; + + @SpringBootTest(classes = KubernetesClientDefaultApiClientTests.App.class, properties = DISABLE_INFORMER) + @Nested + class DefaultApiClientNotSameAsApiClient { + + @Autowired + private ApiClient apiClient; + + @Autowired + ConfigurableApplicationContext context; + + @Test + void testCreatedApiClientIsNotDefault() { + assertThat(apiClient).isNotNull(); + + ApiClient defaultApiClient = io.kubernetes.client.openapi.Configuration.getDefaultApiClient(); + assertThat(defaultApiClient).isNotNull(); + + assertThat(defaultApiClient).isNotSameAs(apiClient); + } + + } + + @SpringBootTest(classes = KubernetesClientDefaultApiClientTests.App.class, properties = DISABLE_INFORMER) + @Nested + class ApiClientUserAgentDefaultHeader { + + @Autowired + private ApiClient apiClient; + + @Autowired + ConfigurableApplicationContext context; + + @Test + void testApiClientUserAgentDefaultHeader() throws MalformedURLException { + assertThat(apiClient).isNotNull(); + Request.Builder builder = new Request.Builder(); + apiClient.processHeaderParams(Collections.emptyMap(), builder); + assertThat(builder.url(new URL("http://example.com")).build().headers().get("User-Agent")) + .isEqualTo("Spring-Cloud-Kubernetes-Application"); + } + + } + + @SpringBootTest(classes = KubernetesClientDefaultApiClientTests.App.class, + properties = { DISABLE_INFORMER, USER_AGENT }) + @Nested + class ApiClientUserAgentNonDefaultHeader { + + @Autowired + private ApiClient apiClient; + + @Autowired + ConfigurableApplicationContext context; + + @Test + void testApiClientUserAgentDefaultHeader() throws MalformedURLException { + assertThat(apiClient).isNotNull(); + Request.Builder builder = new Request.Builder(); + apiClient.processHeaderParams(Collections.emptyMap(), builder); + assertThat(builder.url(new URL("http://example.com")).build().headers().get("User-Agent")) + .isEqualTo("non-default"); + } + + } + + @SpringBootApplication + static class App { + + } + +} 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 6da9468e..b31a7c1d 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 @@ -28,6 +28,11 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties("spring.cloud.kubernetes.client") public class KubernetesClientProperties { + /** + * Default user-agent for kubernetes client. + */ + public static final String DEFAULT_USER_AGENT = "Spring-Cloud-Kubernetes-Application"; + /** * Default path for namespace file. */ @@ -87,6 +92,8 @@ public class KubernetesClientProperties { private String serviceAccountNamespacePath = SERVICE_ACCOUNT_NAMESPACE_PATH; + private String userAgent = DEFAULT_USER_AGENT; + public String getServiceAccountNamespacePath() { return serviceAccountNamespacePath; } @@ -307,4 +314,12 @@ public class KubernetesClientProperties { this.oauthToken = oauthToken; } + public String getUserAgent() { + return userAgent; + } + + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + } 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 8697a8d8..2c731fe8 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 @@ -63,7 +63,7 @@ public class Fabric8AutoConfiguration { @ConditionalOnMissingBean(Config.class) public Config kubernetesClientConfig(KubernetesClientProperties kubernetesClientProperties) { Config base = Config.autoConfigure(null); - Config properties = new ConfigBuilder(base) + 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())) @@ -96,7 +96,14 @@ public class Fabric8AutoConfiguration { .withHttpsProxy(or(kubernetesClientProperties.getHttpsProxy(), base.getHttpsProxy())) .withProxyUsername(or(kubernetesClientProperties.getProxyUsername(), base.getProxyUsername())) .withProxyPassword(or(kubernetesClientProperties.getProxyPassword(), base.getProxyPassword())) - .withNoProxy(or(kubernetesClientProperties.getNoProxy(), base.getNoProxy())).build(); + .withNoProxy(or(kubernetesClientProperties.getNoProxy(), base.getNoProxy())); + + String userAgent = or(base.getUserAgent(), KubernetesClientProperties.DEFAULT_USER_AGENT); + if (!kubernetesClientProperties.getUserAgent().equals(KubernetesClientProperties.DEFAULT_USER_AGENT)) { + userAgent = kubernetesClientProperties.getUserAgent(); + } + + Config properties = builder.withUserAgent(userAgent).build(); return properties; } 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 new file mode 100644 index 00000000..cac53ff4 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentEnvPropertyTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2021 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.fabric8; + +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +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 static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + * + * test "User-Agent" functionality via system properties + */ +@SpringBootTest(classes = App.class) +class Fabric8ClientUserAgentEnvPropertyTests { + + @Autowired + private KubernetesClient client; + + @BeforeAll + static void beforeAll() { + System.setProperty(Config.KUBERNETES_USER_AGENT, "spring-k8s"); + } + + @AfterAll + static void afterAll() { + System.clearProperty(Config.KUBERNETES_USER_AGENT); + } + + @Test + void testUserAgent() { + String userAgent = client.getConfiguration().getUserAgent(); + assertThat(userAgent).isEqualTo("spring-k8s"); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentTests.java b/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentTests.java new file mode 100644 index 00000000..b9bd96dd --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentTests.java @@ -0,0 +1,68 @@ +/* + * Copyright 2013-2021 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.fabric8; + +import io.fabric8.kubernetes.client.KubernetesClient; +import org.junit.jupiter.api.Nested; +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 static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + * + * test "User-Agent" functionality + */ +class Fabric8ClientUserAgentTests { + + private static final String USER_AGENT = "spring.cloud.kubernetes.client.userAgent=non-default"; + + @Nested + @SpringBootTest(classes = App.class) + class DefaultConfigurationForClient { + + @Autowired + private KubernetesClient client; + + @Test + void testUserAgent() { + String userAgent = client.getConfiguration().getUserAgent(); + assertThat(userAgent).isEqualTo("Spring-Cloud-Kubernetes-Application"); + } + + } + + @Nested + @SpringBootTest(classes = App.class, properties = USER_AGENT) + class PropertiesConfigurationForClient { + + @Autowired + private KubernetesClient client; + + @Test + void testUserAgent() { + String userAgent = client.getConfiguration().getUserAgent(); + assertThat(userAgent).isEqualTo("non-default"); + } + + } + +}