From bd8656c5e55c7f7c0c92fcefdc8e6d34ce122097 Mon Sep 17 00:00:00 2001 From: erabii Date: Fri, 4 Feb 2022 17:29:44 +0200 Subject: [PATCH] Nested split (#962) --- .../client/ActuatorDisabledHealthTest.java | 59 ++++ .../client/ActuatorEnabledHealthTest.java | 56 ++++ .../ApiClientUserAgentDefaultHeader.java | 59 ++++ .../ApiClientUserAgentNonDefaultHeader.java | 63 ++++ .../kubernetes/client/default_api/App.java | 24 ++ .../DefaultApiClientNotSameAsApiClient.java | 55 ++++ ...KubernetesClientDefaultApiClientTests.java | 127 -------- .../kubernetes/client/config/Application.java | 24 ++ ...etesClientBootstrapConfigurationTests.java | 175 ----------- ...figMapPropertySourceLocatorRetryTests.java | 282 ----------------- ...ecretsPropertySourceLocatorRetryTests.java | 284 ------------------ ...ClientBootstrapConfigurationInsideK8s.java | 48 +++ ...entBootstrapConfigurationNotInsideK8s.java | 45 +++ .../KubernetesDisabled.java | 47 +++ .../KubernetesEnabled.java | 43 +++ .../KubernetesEnabledConfigDisabled.java | 46 +++ .../KubernetesEnabledOnPurpose.java | 47 +++ ...rnetesEnabledSecretsAndConfigDisabled.java | 47 +++ .../KubernetesEnabledSecretsDisabled.java | 47 +++ .../client/config/configmap_retry/App.java | 24 ++ .../ConfigFailFastDisabled.java | 103 +++++++ ...ConfigFailFastEnabledButRetryDisabled.java | 114 +++++++ ...igRetryDisabledButSecretsRetryEnabled.java | 126 ++++++++ .../configmap_retry/ConfigRetryEnabled.java | 173 +++++++++++ .../config/secrets_retry/Application.java | 24 ++ .../SecretsFailFastDisabled.java | 105 +++++++ ...ecretsFailFastEnabledButRetryDisabled.java | 120 ++++++++ ...etsRetryDisabledButConfigRetryEnabled.java | 127 ++++++++ .../secrets_retry/SecretsRetryEnabled.java | 173 +++++++++++ .../cloud/kubernetes/commons/config/App.java | 24 ++ ...tEnabledWithDefaultRetryConfiguration.java | 79 +++++ .../bootstrap/ConfigFailFastEnabled.java | 65 ++++ ...ConfigFailFastEnabledButRetryDisabled.java | 44 +++ ...stEnabledWithCustomRetryConfiguration.java | 53 ++++ .../config/bootstrap/FailFastDisabled.java | 43 +++ ...tEnabledWithoutSpringRetryOnClasspath.java | 61 ++++ .../bootstrap/SecretsFailFastEnabled.java | 65 ++++ ...ecretsFailFastEnabledButRetryDisabled.java | 44 +++ ...stEnabledWithCustomRetryConfiguration.java | 53 ++++ ...erAutoConfigurationKubernetesDisabled.java | 44 +++ ...ationKubernetesEnabledProfileIncluded.java | 45 +++ ...abledProfileIncludedConfigApiDisabled.java | 45 +++ ...abledProfileIncludedConfigMapDisabled.java | 44 +++ ...bledProfileIncludedSecretsApiDisabled.java | 47 +++ ...abledProfileIncludedSecretsApiEnabled.java | 45 +++ ...ConfigurationKubernetesProfileMissing.java | 44 +++ .../ConfigServerIntegrationTest.java | 2 +- ...tesConfigServerAutoConfigurationTests.java | 176 ----------- .../kubernetes/configserver/MockConfig.java | 35 +++ .../Fabric8AutoConfigurationTests.java | 3 - .../fabric8/Fabric8ClientUserAgentTests.java | 70 ----- ...ic8UserAgentDefaultConfigurationTests.java | 43 +++ ...bric8UserAgentPropertiesConfiguration.java | 44 +++ .../fabric8/config/Fabric8ActuatorTests.java | 95 ------ .../Fabric8BootstrapConfigurationTests.java | 167 ---------- ...ecretsPropertySourceLocatorRetryTests.java | 241 --------------- .../config/actuator/DisabledHealthTest.java | 61 ++++ .../config/actuator/EnabledHealthTest.java | 60 ++++ ...abric8BootstrapConfigurationInsideK8s.java | 48 +++ ...ic8BootstrapConfigurationNotInsideK8s.java | 44 +++ .../config/bootstrap/KubernetesDisabled.java | 46 +++ .../config/bootstrap/KubernetesEnabled.java | 46 +++ .../KubernetesEnabledConfigDisabled.java | 46 +++ .../bootstrap/KubernetesEnabledOnPurpose.java | 47 +++ ...rnetesEnabledSecretsAndConfigDisabled.java | 43 +++ .../KubernetesEnabledSecretsDisabled.java | 47 +++ .../locator_retry/ConfigFailFastDisabled.java | 75 +++++ ...ConfigFailFastEnabledButRetryDisabled.java | 87 ++++++ ...igRetryDisabledButSecretsRetryEnabled.java | 94 ++++++ .../locator_retry/ConfigRetryEnabled.java | 132 ++++++++ .../config/retry/SecretsFailFastDisabled.java | 83 +++++ ...ecretsFailFastEnabledButRetryDisabled.java | 94 ++++++ ...etsRetryDisabledButConfigRetryEnabled.java | 101 +++++++ .../config/retry/SecretsRetryEnabled.java | 139 +++++++++ ...tionClientNotPresentWhenIstioDisabled.java | 43 +++ ...lientNotPresentWhenKubernetesDisabled.java | 43 +++ ...toConfigurationClientPresentByDefault.java | 43 +++ ...gurationClientPresentWhenIstioEnabled.java | 43 +++ .../istio/IstioAutoConfigurationTests.java | 93 ------ 79 files changed, 4232 insertions(+), 1714 deletions(-) create mode 100644 spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/ActuatorDisabledHealthTest.java create mode 100644 spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/ActuatorEnabledHealthTest.java create mode 100644 spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/ApiClientUserAgentDefaultHeader.java create mode 100644 spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/ApiClientUserAgentNonDefaultHeader.java create mode 100644 spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/App.java create mode 100644 spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/DefaultApiClientNotSameAsApiClient.java delete 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-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/Application.java delete mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientBootstrapConfigurationTests.java delete mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorRetryTests.java delete mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocatorRetryTests.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesClientBootstrapConfigurationInsideK8s.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesClientBootstrapConfigurationNotInsideK8s.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesDisabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledConfigDisabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledOnPurpose.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledSecretsAndConfigDisabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledSecretsDisabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/App.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigFailFastDisabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigFailFastEnabledButRetryDisabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigRetryDisabledButSecretsRetryEnabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigRetryEnabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/Application.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsFailFastDisabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsFailFastEnabledButRetryDisabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsRetryDisabledButConfigRetryEnabled.java create mode 100644 spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsRetryEnabled.java create mode 100644 spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/App.java create mode 100644 spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigAndSecretsFailFastEnabledWithDefaultRetryConfiguration.java create mode 100644 spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabled.java create mode 100644 spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabledButRetryDisabled.java create mode 100644 spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabledWithCustomRetryConfiguration.java create mode 100644 spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/FailFastDisabled.java create mode 100644 spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/FailFastEnabledWithoutSpringRetryOnClasspath.java create mode 100644 spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabled.java create mode 100644 spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabledButRetryDisabled.java create mode 100644 spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabledWithCustomRetryConfiguration.java create mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesDisabled.java create mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncluded.java create mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedConfigApiDisabled.java create mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedConfigMapDisabled.java create mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedSecretsApiDisabled.java create mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedSecretsApiEnabled.java create mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesProfileMissing.java delete mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerAutoConfigurationTests.java create mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/MockConfig.java delete mode 100644 spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentTests.java create mode 100644 spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8UserAgentDefaultConfigurationTests.java create mode 100644 spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8UserAgentPropertiesConfiguration.java delete mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ActuatorTests.java delete mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8BootstrapConfigurationTests.java delete mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceLocatorRetryTests.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/actuator/DisabledHealthTest.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/actuator/EnabledHealthTest.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/Fabric8BootstrapConfigurationInsideK8s.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/Fabric8BootstrapConfigurationNotInsideK8s.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesDisabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledConfigDisabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledOnPurpose.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledSecretsAndConfigDisabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledSecretsDisabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigFailFastDisabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigFailFastEnabledButRetryDisabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigRetryDisabledButSecretsRetryEnabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigRetryEnabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsFailFastDisabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsFailFastEnabledButRetryDisabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsRetryDisabledButConfigRetryEnabled.java create mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsRetryEnabled.java create mode 100644 spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientNotPresentWhenIstioDisabled.java create mode 100644 spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientNotPresentWhenKubernetesDisabled.java create mode 100644 spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientPresentByDefault.java create mode 100644 spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientPresentWhenIstioEnabled.java delete mode 100644 spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationTests.java diff --git a/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/ActuatorDisabledHealthTest.java b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/ActuatorDisabledHealthTest.java new file mode 100644 index 00000000..428666bf --- /dev/null +++ b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/ActuatorDisabledHealthTest.java @@ -0,0 +1,59 @@ +/* + * 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.client; + +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.kubernetes.client.example.App; +import org.springframework.http.MediaType; +import org.springframework.test.web.reactive.server.WebTestClient; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, + properties = { "management.health.kubernetes.enabled=false", "management.endpoint.health.show-details=always", + "management.endpoint.health.show-components=always", + "management.endpoints.web.exposure.include=health" }) +class ActuatorDisabledHealthTest { + + @Autowired + private ReactiveHealthContributorRegistry registry; + + @Autowired + private WebTestClient webClient; + + @Value("${local.server.port}") + private int port; + + @Test + void healthEndpointShouldContainKubernetes() { + this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port) + .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class) + .value(Matchers.not(Matchers.containsString("kubernetes"))); + + Assertions.assertNull(registry.getContributor("kubernetes"), + "reactive kubernetes contributor must NOT be present when 'management.health.kubernetes.enabled=false'"); + } + +} diff --git a/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/ActuatorEnabledHealthTest.java b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/ActuatorEnabledHealthTest.java new file mode 100644 index 00000000..72bf4b03 --- /dev/null +++ b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/ActuatorEnabledHealthTest.java @@ -0,0 +1,56 @@ +/* + * 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.client; + +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.kubernetes.client.example.App; +import org.springframework.http.MediaType; +import org.springframework.test.web.reactive.server.WebTestClient; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, + properties = { "management.health.kubernetes.enabled=true", "management.endpoint.health.show-details=always", + "management.endpoint.health.show-components=always", "management.endpoints.web.exposure.include=health", + "spring.main.cloud-platform=KUBERNETES" }) +class ActuatorEnabledHealthTest { + + @Autowired + private WebTestClient webClient; + + @Autowired + private ReactiveHealthContributorRegistry registry; + + @Value("${local.server.port}") + private int port; + + @Test + void healthEndpointShouldContainKubernetes() { + this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port) + .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class) + .value(Matchers.containsString("kubernetes")); + + Assertions.assertNotNull(registry.getContributor("kubernetes"), + "reactive kubernetes contributor must be present when 'management.health.kubernetes.enabled=true'"); + } + +} diff --git a/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/ApiClientUserAgentDefaultHeader.java b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/ApiClientUserAgentDefaultHeader.java new file mode 100644 index 00000000..788d2180 --- /dev/null +++ b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/ApiClientUserAgentDefaultHeader.java @@ -0,0 +1,59 @@ +/* + * 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.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.Test; + +import org.springframework.beans.factory.annotation.Autowired; +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. + * + * kubernetes informer is disabled because KubernetesInformerAutoConfiguration creates a + * defaultApiClient that will be autowired instead of the ApiClient created in + * KubernetesClientAutoConfiguration + */ +@SpringBootTest(classes = App.class, + properties = { "kubernetes.informer.enabled=false", "spring.main.cloud-platform=KUBERNETES" }) +class ApiClientUserAgentDefaultHeader { + + @Autowired + private ApiClient apiClient; + + @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"); + } + +} diff --git a/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/ApiClientUserAgentNonDefaultHeader.java b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/ApiClientUserAgentNonDefaultHeader.java new file mode 100644 index 00000000..24b2a95d --- /dev/null +++ b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/ApiClientUserAgentNonDefaultHeader.java @@ -0,0 +1,63 @@ +/* + * 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.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.Test; + +import org.springframework.beans.factory.annotation.Autowired; +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 + */ +@SpringBootTest(classes = App.class, properties = { "kubernetes.informer.enabled=false", + "spring.cloud.kubernetes.client.userAgent=non-default", "spring.main.cloud-platform=KUBERNETES" }) +class ApiClientUserAgentNonDefaultHeader { + + @Autowired + private ApiClient apiClient; + + @Autowired + private 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"); + } + +} diff --git a/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/App.java b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/App.java new file mode 100644 index 00000000..20263cbb --- /dev/null +++ b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/App.java @@ -0,0 +1,24 @@ +/* + * 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.client.default_api; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +class App { + +} diff --git a/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/DefaultApiClientNotSameAsApiClient.java b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/DefaultApiClientNotSameAsApiClient.java new file mode 100644 index 00000000..e0f7a008 --- /dev/null +++ b/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/DefaultApiClientNotSameAsApiClient.java @@ -0,0 +1,55 @@ +/* + * 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.client.default_api; + +import io.kubernetes.client.openapi.ApiClient; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +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. + * + * kubernetes informer is disabled because KubernetesInformerAutoConfiguration creates a + * defaultApiClient that will be autowired instead of the ApiClient created in + * KubernetesClientAutoConfiguration + */ +@SpringBootTest(classes = App.class, + properties = { "kubernetes.informer.enabled=false", "spring.main.cloud-platform=KUBERNETES" }) +class DefaultApiClientNotSameAsApiClient { + + @Autowired + private ApiClient apiClient; + + @Test + void testCreatedApiClientIsNotDefault() { + assertThat(apiClient).isNotNull(); + + ApiClient defaultApiClient = io.kubernetes.client.openapi.Configuration.getDefaultApiClient(); + assertThat(defaultApiClient).isNotNull(); + + assertThat(defaultApiClient).isNotSameAs(apiClient); + } + +} 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 deleted file mode 100644 index 0d4eaf57..00000000 --- a/spring-cloud-kubernetes-client-autoconfig/src/test/java/org/springframework/cloud/kubernetes/client/default_api/KubernetesClientDefaultApiClientTests.java +++ /dev/null @@ -1,127 +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.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"; - - private static final String ENABLED_K8S = "spring.main.cloud-platform=KUBERNETES"; - - @SpringBootTest(classes = KubernetesClientDefaultApiClientTests.App.class, - properties = { DISABLE_INFORMER, ENABLED_K8S }) - @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, ENABLED_K8S }) - @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, ENABLED_K8S }) - @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-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/Application.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/Application.java new file mode 100644 index 00000000..39e6ce9a --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/Application.java @@ -0,0 +1,24 @@ +/* + * 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.client.config; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientBootstrapConfigurationTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientBootstrapConfigurationTests.java deleted file mode 100644 index 0d66f80a..00000000 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientBootstrapConfigurationTests.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2013-2020 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.config; - -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 wind57 - */ -public class KubernetesClientBootstrapConfigurationTests { - - @SpringBootApplication - static class Application { - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "kubernetes.informer.enabled=false", "kubernetes.manifests.enabled=false" }) - @Nested - class KubernetesDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void configAndSecretsBeansAreNotPresent() { - assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(0); - assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(0); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.cloud.kubernetes.secrets.enabled=true", - "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }) - @Nested - class KubernetesEnabledOnPurpose { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void configAndSecretsBeansArePresent() { - assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(1); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.cloud.kubernetes.client.namespace=default", - "spring.main.cloud-platform=KUBERNETES" }) - @Nested - class KubernetesEnabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void configAndSecretsBeansArePresent() { - assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(1); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.cloud.kubernetes.config.enabled=false", "spring.main.cloud-platform=KUBERNETES" }) - @Nested - class KubernetesEnabledConfigDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void secretsOnlyPresent() { - assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(0); - assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(1); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.cloud.kubernetes.secrets.enabled=false", - "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }) - @Nested - class KubernetesEnabledSecretsDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void secretsOnlyPresent() { - assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(0); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.cloud.kubernetes.secrets.enabled=false", - "spring.cloud.kubernetes.config.enabled=false", "spring.main.cloud-platform=KUBERNETES" }) - @Nested - class KubernetesEnabledSecretsAndConfigDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void secretsOnlyPresent() { - assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(0); - assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(0); - } - - } - - // tests that @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) has the desired - // effect, meaning when it is enabled, both property sources are present - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=abc" }) - @Nested - class KubernetesClientBootstrapConfigurationInsideK8s { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void bothPresent() { - assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(1); - } - - } - - // tests that @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) has the desired - // effect, meaning when it is disabled, no property source bean is present - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "kubernetes.manifests.enabled=false" }) - @Nested - class KubernetesClientBootstrapConfigurationNotInsideK8s { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void bothMissing() { - assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(0); - assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(0); - } - - } - -} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorRetryTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorRetryTests.java deleted file mode 100644 index 31aee7ce..00000000 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorRetryTests.java +++ /dev/null @@ -1,282 +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.config; - -import java.util.HashMap; -import java.util.Map; - -import com.github.tomakehurst.wiremock.WireMockServer; -import com.github.tomakehurst.wiremock.client.WireMock; -import io.kubernetes.client.openapi.JSON; -import io.kubernetes.client.openapi.models.V1ConfigMap; -import io.kubernetes.client.openapi.models.V1ConfigMapList; -import io.kubernetes.client.openapi.models.V1ObjectMeta; -import io.kubernetes.client.openapi.models.V1SecretList; -import io.kubernetes.client.util.ClientBuilder; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; -import org.springframework.context.ApplicationContext; -import org.springframework.core.env.PropertySource; -import org.springframework.mock.env.MockEnvironment; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; -import static com.github.tomakehurst.wiremock.stubbing.Scenario.STARTED; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -/** - * @author Isik Erhan - */ -public class KubernetesClientConfigMapPropertySourceLocatorRetryTests { - - private static final String API = "/api/v1/namespaces/default/configmaps"; - - private static final String SECRETS_API = "/api/v1/namespaces/default/secrets"; - - private static WireMockServer wireMockServer; - - private static MockedStatic clientUtilsMock; - - @BeforeAll - public static void setup() { - wireMockServer = new WireMockServer(options().dynamicPort()); - wireMockServer.start(); - WireMock.configureFor(wireMockServer.port()); - - clientUtilsMock = mockStatic(KubernetesClientUtils.class); - clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient) - .thenReturn(new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build()); - stubConfigMapAndSecretsDefaults(); - } - - private static void stubConfigMapAndSecretsDefaults() { - // return empty config map / secret list to not fail context creation - stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1ConfigMapList())))); - stubFor(get(SECRETS_API) - .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1SecretList())))); - } - - @AfterAll - public static void teardown() { - wireMockServer.stop(); - clientUtilsMock.close(); - } - - @AfterEach - public void afterEach() { - WireMock.reset(); - stubConfigMapAndSecretsDefaults(); - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = { "spring.cloud.kubernetes.client.namespace=default", - "spring.cloud.kubernetes.config.fail-fast=true", - "spring.cloud.kubernetes.config.retry.max-attempts=5", "spring.main.cloud-platform=KUBERNETES" }, - classes = App.class) - class ConfigRetryEnabled { - - @SpyBean - private KubernetesClientConfigMapPropertySourceLocator propertySourceLocator; - - @Test - public void locateShouldNotRetryWhenThereIsNoFailure() { - - Map data = new HashMap<>(); - data.put("some.prop", "theValue"); - data.put("some.number", "0"); - - V1ConfigMapList configMapList = new V1ConfigMapList() - .addItemsItem(new V1ConfigMap().metadata(new V1ObjectMeta().name("application")).data(data)); - - stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList)))); - - PropertySource propertySource = Assertions - .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); - - // verify locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - - // validate the contents of the property source - assertThat(propertySource.getProperty("some.prop")).isEqualTo("theValue"); - assertThat(propertySource.getProperty("some.number")).isEqualTo("0"); - } - - @Test - public void locateShouldRetryAndRecover() { - Map data = new HashMap<>(); - data.put("some.prop", "theValue"); - data.put("some.number", "0"); - - V1ConfigMapList configMapList = new V1ConfigMapList() - .addItemsItem(new V1ConfigMap().metadata(new V1ObjectMeta().name("application")).data(data)); - - // fail 3 times - stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs(STARTED) - .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed once")); - - stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed once") - .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed twice")); - - stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed twice") - .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed thrice")); - - // then succeed - stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed thrice") - .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList)))); - - PropertySource propertySource = Assertions - .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); - - // verify retried 4 times - verify(propertySourceLocator, times(4)).locate(any()); - - // validate the contents of the property source - assertThat(propertySource.getProperty("some.prop")).isEqualTo("theValue"); - assertThat(propertySource.getProperty("some.number")).isEqualTo("0"); - } - - @Test - public void locateShouldRetryAndFail() { - // fail all the 5 requests - stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - - assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Unable to read ConfigMap with name 'application' in namespace 'default'"); - - // verify retried 5 times until failure - verify(propertySourceLocator, times(5)).locate(any()); - } - - } - - @Nested - @SpringBootTest( - webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = { - "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }, - classes = App.class) - class ConfigFailFastDisabled { - - @SpyBean - private KubernetesClientConfigMapPropertySourceLocator propertySourceLocator; - - @Test - public void locateShouldNotRetry() { - - stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - - Assertions.assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); - - // verify locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - } - - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = { "spring.cloud.kubernetes.client.namespace=default", - "spring.cloud.kubernetes.config.fail-fast=true", - "spring.cloud.kubernetes.config.retry.enabled=false", - "spring.cloud.kubernetes.secrets.fail-fast=true", "spring.main.cloud-platform=KUBERNETES" }, - classes = App.class) - class ConfigRetryDisabledButSecretsRetryEnabled { - - @SpyBean - private KubernetesClientConfigMapPropertySourceLocator propertySourceLocator; - - @Autowired - private ApplicationContext context; - - @Test - public void locateShouldFailWithoutRetrying() { - - /* - * Enabling secrets retry causes Spring Retry to be enabled and a - * RetryOperationsInterceptor bean with NeverRetryPolicy for config maps to be - * defined. ConfigMapPropertySourceLocator should not retry even Spring Retry - * is enabled. - */ - - stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - - assertThat(context.containsBean("kubernetesConfigRetryInterceptor")).isTrue(); - assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Unable to read ConfigMap with name 'application' in namespace 'default'"); - - // verify that propertySourceLocator.locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - } - - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = { "spring.cloud.kubernetes.client.namespace=default", - "spring.cloud.kubernetes.config.fail-fast=true", - "spring.cloud.kubernetes.config.retry.enabled=false", "spring.main.cloud-platform=KUBERNETES" }, - classes = App.class) - class ConfigFailFastEnabledButRetryDisabled { - - @SpyBean - private KubernetesClientConfigMapPropertySourceLocator propertySourceLocator; - - @Autowired - private ApplicationContext context; - - @Test - public void locateShouldFailWithoutRetrying() { - - stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - - assertThat(context.containsBean("kubernetesConfigRetryInterceptor")).isFalse(); - assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Unable to read ConfigMap with name 'application' in namespace 'default'"); - - // verify that propertySourceLocator.locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - } - - } - - @SpringBootApplication - static class App { - - } - -} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocatorRetryTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocatorRetryTests.java deleted file mode 100644 index a7863e22..00000000 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocatorRetryTests.java +++ /dev/null @@ -1,284 +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.config; - -import java.util.HashMap; -import java.util.Map; - -import com.github.tomakehurst.wiremock.WireMockServer; -import com.github.tomakehurst.wiremock.client.WireMock; -import io.kubernetes.client.openapi.JSON; -import io.kubernetes.client.openapi.models.V1ConfigMapList; -import io.kubernetes.client.openapi.models.V1ObjectMeta; -import io.kubernetes.client.openapi.models.V1Secret; -import io.kubernetes.client.openapi.models.V1SecretList; -import io.kubernetes.client.util.ClientBuilder; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; -import org.springframework.context.ApplicationContext; -import org.springframework.core.env.PropertySource; -import org.springframework.mock.env.MockEnvironment; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; -import static com.github.tomakehurst.wiremock.stubbing.Scenario.STARTED; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -/** - * @author Isik Erhan - */ -public class KubernetesClientSecretsPropertySourceLocatorRetryTests { - - private static final String API = "/api/v1/namespaces/default/secrets"; - - private static final String CONFIG_MAPS_API = "/api/v1/namespaces/default/configmaps"; - - private static WireMockServer wireMockServer; - - private static MockedStatic clientUtilsMock; - - @BeforeAll - public static void setup() { - wireMockServer = new WireMockServer(options().dynamicPort()); - wireMockServer.start(); - WireMock.configureFor(wireMockServer.port()); - - clientUtilsMock = mockStatic(KubernetesClientUtils.class); - clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient) - .thenReturn(new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build()); - stubConfigMapAndSecretsDefaults(); - } - - private static void stubConfigMapAndSecretsDefaults() { - // return empty config map / secret list to not fail context creation - stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1SecretList())))); - stubFor(get(CONFIG_MAPS_API) - .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1ConfigMapList())))); - } - - @AfterAll - public static void teardown() { - wireMockServer.stop(); - clientUtilsMock.close(); - } - - @AfterEach - public void afterEach() { - WireMock.reset(); - stubConfigMapAndSecretsDefaults(); - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = { - "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.kubernetes.secrets.fail-fast=true", - "spring.cloud.kubernetes.secrets.retry.max-attempts=5", "spring.cloud.kubernetes.secrets.name=my-secret", - "spring.cloud.kubernetes.secrets.enable-api=true", "spring.main.cloud-platform=KUBERNETES" }, - classes = App.class) - class SecretsRetryEnabled { - - @SpyBean - private KubernetesClientSecretsPropertySourceLocator propertySourceLocator; - - @Test - public void locateShouldNotRetryWhenThereIsNoFailure() { - - Map data = new HashMap<>(); - data.put("some.sensitive.prop", "theSensitiveValue".getBytes()); - data.put("some.sensitive.number", "1".getBytes()); - - V1SecretList secretList = new V1SecretList() - .addItemsItem(new V1Secret().metadata(new V1ObjectMeta().name("my-secret")).data(data)); - - stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList)))); - - PropertySource propertySource = Assertions - .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); - - // verify locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - - // validate the contents of the property source - assertThat(propertySource.getProperty("some.sensitive.prop")).isEqualTo("theSensitiveValue"); - assertThat(propertySource.getProperty("some.sensitive.number")).isEqualTo("1"); - } - - @Test - public void locateShouldRetryAndRecover() { - Map data = new HashMap<>(); - data.put("some.sensitive.prop", "theSensitiveValue".getBytes()); - data.put("some.sensitive.number", "1".getBytes()); - - V1SecretList secretList = new V1SecretList() - .addItemsItem(new V1Secret().metadata(new V1ObjectMeta().name("my-secret")).data(data)); - - // fail 3 times - stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs(STARTED) - .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed once")); - - stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed once") - .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed twice")); - - stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed twice") - .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed thrice")); - - // then succeed - stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed thrice") - .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList)))); - - PropertySource propertySource = Assertions - .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); - - // verify retried 4 times - verify(propertySourceLocator, times(4)).locate(any()); - - // validate the contents of the property source - assertThat(propertySource.getProperty("some.sensitive.prop")).isEqualTo("theSensitiveValue"); - assertThat(propertySource.getProperty("some.sensitive.number")).isEqualTo("1"); - } - - @Test - public void locateShouldRetryAndFail() { - // fail all the 5 requests - stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - - assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); - - // verify retried 5 times until failure - verify(propertySourceLocator, times(5)).locate(any()); - } - - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = { "spring.cloud.kubernetes.client.namespace=default", - "spring.cloud.kubernetes.secrets.name=my-secret", "spring.cloud.kubernetes.secrets.enable-api=true", - "spring.main.cloud-platform=KUBERNETES" }, - classes = App.class) - class SecretsFailFastDisabled { - - @SpyBean - private KubernetesClientSecretsPropertySourceLocator propertySourceLocator; - - @Test - public void locateShouldNotRetry() { - - stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - - Assertions.assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); - - // verify locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - } - - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = { "spring.cloud.kubernetes.client.namespace=default", - "spring.cloud.kubernetes.secrets.fail-fast=true", - "spring.cloud.kubernetes.secrets.retry.enabled=false", - "spring.cloud.kubernetes.config.fail-fast=true", "spring.cloud.kubernetes.secrets.name=my-secret", - "spring.cloud.kubernetes.secrets.enable-api=true", "spring.main.cloud-platform=KUBERNETES" }, - classes = App.class) - class SecretsRetryDisabledButConfigRetryEnabled { - - @SpyBean - private KubernetesClientSecretsPropertySourceLocator propertySourceLocator; - - @Autowired - private ApplicationContext context; - - @Test - public void locateShouldFailWithoutRetrying() { - - /* - * Enabling config retry causes Spring Retry to be enabled and a - * RetryOperationsInterceptor bean with NeverRetryPolicy for secrets to be - * defined. SecretsPropertySourceLocator should not retry even Spring Retry is - * enabled. - */ - - stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - - assertThat(context.containsBean("kubernetesSecretsRetryInterceptor")).isTrue(); - assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); - - // verify that propertySourceLocator.locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - } - - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = { - "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.kubernetes.secrets.fail-fast=true", - "spring.cloud.kubernetes.secrets.retry.enabled=false", "spring.cloud.kubernetes.secrets.name=my-secret", - "spring.cloud.kubernetes.secrets.enable-api=true", "spring.main.cloud-platform=KUBERNETES" }, - classes = App.class) - class SecretsFailFastEnabledButRetryDisabled { - - @SpyBean - private KubernetesClientSecretsPropertySourceLocator propertySourceLocator; - - @Autowired - private ApplicationContext context; - - @Test - public void locateShouldFailWithoutRetrying() { - - stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - - assertThat(context.containsBean("kubernetesSecretsRetryInterceptor")).isFalse(); - assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); - - // verify that propertySourceLocator.locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - } - - } - - @SpringBootApplication - static class App { - - } - -} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesClientBootstrapConfigurationInsideK8s.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesClientBootstrapConfigurationInsideK8s.java new file mode 100644 index 00000000..eaa61f0f --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesClientBootstrapConfigurationInsideK8s.java @@ -0,0 +1,48 @@ +/* + * 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.client.config.boostrap_configuration; + +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.client.config.Application; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=abc" }) +class KubernetesClientBootstrapConfigurationInsideK8s { + + @Autowired + private ConfigurableApplicationContext context; + + // tests that @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) has the desired + // effect, meaning when it is enabled, both property sources are present + @Test + public void bothPresent() { + assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(1); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesClientBootstrapConfigurationNotInsideK8s.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesClientBootstrapConfigurationNotInsideK8s.java new file mode 100644 index 00000000..b84ef3c7 --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesClientBootstrapConfigurationNotInsideK8s.java @@ -0,0 +1,45 @@ +/* + * 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.client.config.boostrap_configuration; + +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.client.config.Application; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "kubernetes.manifests.enabled=false" }) +class KubernetesClientBootstrapConfigurationNotInsideK8s { + + @Autowired + private ConfigurableApplicationContext context; + + // tests that @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) has the desired + // effect, meaning when it is disabled, no property source bean is present + @Test + void bothMissing() { + assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(0); + assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesDisabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesDisabled.java new file mode 100644 index 00000000..c930a7bc --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesDisabled.java @@ -0,0 +1,47 @@ +/* + * 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.client.config.boostrap_configuration; + +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.client.config.Application; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.cloud.kubernetes.enabled=false", "kubernetes.informer.enabled=false", + "kubernetes.manifests.enabled=false" }) +class KubernetesDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void configAndSecretsBeansAreNotPresent() { + assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(0); + assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabled.java new file mode 100644 index 00000000..0006a5b6 --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabled.java @@ -0,0 +1,43 @@ +/* + * 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.client.config.boostrap_configuration; + +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.client.config.Application; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }) +class KubernetesEnabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void configAndSecretsBeansArePresent() { + assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(1); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledConfigDisabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledConfigDisabled.java new file mode 100644 index 00000000..36dd39a9 --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledConfigDisabled.java @@ -0,0 +1,46 @@ +/* + * 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.client.config.boostrap_configuration; + +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.client.config.Application; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.cloud.kubernetes.config.enabled=false", "spring.main.cloud-platform=KUBERNETES" }) +class KubernetesEnabledConfigDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void secretsOnlyPresent() { + assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(0); + assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(1); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledOnPurpose.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledOnPurpose.java new file mode 100644 index 00000000..bae93bdb --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledOnPurpose.java @@ -0,0 +1,47 @@ +/* + * 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.client.config.boostrap_configuration; + +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.client.config.Application; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.cloud.kubernetes.secrets.enabled=true", + "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }) +class KubernetesEnabledOnPurpose { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void configAndSecretsBeansArePresent() { + assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(1); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledSecretsAndConfigDisabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledSecretsAndConfigDisabled.java new file mode 100644 index 00000000..52c8f9a5 --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledSecretsAndConfigDisabled.java @@ -0,0 +1,47 @@ +/* + * 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.client.config.boostrap_configuration; + +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.client.config.Application; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.cloud.kubernetes.secrets.enabled=false", "spring.cloud.kubernetes.config.enabled=false", + "spring.main.cloud-platform=KUBERNETES" }) +class KubernetesEnabledSecretsAndConfigDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void secretsOnlyPresent() { + assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(0); + assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledSecretsDisabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledSecretsDisabled.java new file mode 100644 index 00000000..5e7e8470 --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/boostrap_configuration/KubernetesEnabledSecretsDisabled.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013-2020 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.config.boostrap_configuration; + +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.client.config.Application; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.cloud.kubernetes.secrets.enabled=false", + "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }) +class KubernetesEnabledSecretsDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void secretsOnlyPresent() { + assertThat(context.getBeanNamesForType(KubernetesClientConfigMapPropertySourceLocator.class)).hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesClientSecretsPropertySourceLocator.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/App.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/App.java new file mode 100644 index 00000000..a0bf1df1 --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/App.java @@ -0,0 +1,24 @@ +/* + * 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.client.config.configmap_retry; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +class App { + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigFailFastDisabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigFailFastDisabled.java new file mode 100644 index 00000000..7bdab621 --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigFailFastDisabled.java @@ -0,0 +1,103 @@ +/* + * 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.client.config.configmap_retry; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import io.kubernetes.client.openapi.JSON; +import io.kubernetes.client.openapi.models.V1ConfigMapList; +import io.kubernetes.client.util.ClientBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.mock.env.MockEnvironment; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }, + classes = App.class) +class ConfigFailFastDisabled { + + private static final String API = "/api/v1/namespaces/default/configmaps"; + + private static WireMockServer wireMockServer; + + private static MockedStatic clientUtilsMock; + + @BeforeAll + static void setup() { + wireMockServer = new WireMockServer(options().dynamicPort()); + wireMockServer.start(); + WireMock.configureFor(wireMockServer.port()); + + clientUtilsMock = mockStatic(KubernetesClientUtils.class); + clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient) + .thenReturn(new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build()); + stubConfigMapAndSecretsDefaults(); + } + + private static void stubConfigMapAndSecretsDefaults() { + // return empty config map / secret list to not fail context creation + stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1ConfigMapList())))); + } + + @AfterAll + static void teardown() { + wireMockServer.stop(); + clientUtilsMock.close(); + } + + @AfterEach + void afterEach() { + WireMock.reset(); + stubConfigMapAndSecretsDefaults(); + } + + @SpyBean + private KubernetesClientConfigMapPropertySourceLocator propertySourceLocator; + + @Test + void locateShouldNotRetry() { + + stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); + + Assertions.assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigFailFastEnabledButRetryDisabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigFailFastEnabledButRetryDisabled.java new file mode 100644 index 00000000..a5abe60c --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigFailFastEnabledButRetryDisabled.java @@ -0,0 +1,114 @@ +/* + * 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.client.config.configmap_retry; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import io.kubernetes.client.openapi.JSON; +import io.kubernetes.client.openapi.models.V1ConfigMapList; +import io.kubernetes.client.util.ClientBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.context.ApplicationContext; +import org.springframework.mock.env.MockEnvironment; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.config.fail-fast=true", "spring.cloud.kubernetes.config.retry.enabled=false", + "spring.main.cloud-platform=KUBERNETES" }, + classes = App.class) +class ConfigFailFastEnabledButRetryDisabled { + + private static final String API = "/api/v1/namespaces/default/configmaps"; + + private static WireMockServer wireMockServer; + + private static MockedStatic clientUtilsMock; + + @BeforeAll + static void setup() { + wireMockServer = new WireMockServer(options().dynamicPort()); + wireMockServer.start(); + WireMock.configureFor(wireMockServer.port()); + + clientUtilsMock = mockStatic(KubernetesClientUtils.class); + clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient) + .thenReturn(new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build()); + stubConfigMapAndSecretsDefaults(); + } + + private static void stubConfigMapAndSecretsDefaults() { + // return empty config map / secret list to not fail context creation + stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1ConfigMapList())))); + } + + @AfterAll + static void teardown() { + wireMockServer.stop(); + clientUtilsMock.close(); + } + + @AfterEach + void afterEach() { + WireMock.reset(); + stubConfigMapAndSecretsDefaults(); + } + + @SpyBean + private KubernetesClientConfigMapPropertySourceLocator propertySourceLocator; + + @Autowired + private ApplicationContext context; + + @Test + void locateShouldFailWithoutRetrying() { + + stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); + + assertThat(context.containsBean("kubernetesConfigRetryInterceptor")).isFalse(); + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read ConfigMap with name 'application' in namespace 'default'"); + + // verify that propertySourceLocator.locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigRetryDisabledButSecretsRetryEnabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigRetryDisabledButSecretsRetryEnabled.java new file mode 100644 index 00000000..90c37aab --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigRetryDisabledButSecretsRetryEnabled.java @@ -0,0 +1,126 @@ +/* + * 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.client.config.configmap_retry; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import io.kubernetes.client.openapi.JSON; +import io.kubernetes.client.openapi.models.V1ConfigMapList; +import io.kubernetes.client.openapi.models.V1SecretList; +import io.kubernetes.client.util.ClientBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.context.ApplicationContext; +import org.springframework.mock.env.MockEnvironment; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.config.fail-fast=true", "spring.cloud.kubernetes.config.retry.enabled=false", + "spring.cloud.kubernetes.secrets.fail-fast=true", "spring.main.cloud-platform=KUBERNETES" }, + classes = App.class) +class ConfigRetryDisabledButSecretsRetryEnabled { + + private static final String API = "/api/v1/namespaces/default/configmaps"; + + private static final String SECRETS_API = "/api/v1/namespaces/default/secrets"; + + private static WireMockServer wireMockServer; + + private static MockedStatic clientUtilsMock; + + @BeforeAll + static void setup() { + wireMockServer = new WireMockServer(options().dynamicPort()); + wireMockServer.start(); + WireMock.configureFor(wireMockServer.port()); + + clientUtilsMock = mockStatic(KubernetesClientUtils.class); + clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient) + .thenReturn(new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build()); + stubConfigMapAndSecretsDefaults(); + } + + private static void stubConfigMapAndSecretsDefaults() { + // return empty config map / secret list to not fail context creation + stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1ConfigMapList())))); + stubFor(get(SECRETS_API) + .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1SecretList())))); + } + + @AfterAll + static void teardown() { + wireMockServer.stop(); + clientUtilsMock.close(); + } + + @AfterEach + void afterEach() { + WireMock.reset(); + stubConfigMapAndSecretsDefaults(); + } + + @SpyBean + private KubernetesClientConfigMapPropertySourceLocator propertySourceLocator; + + @Autowired + private ApplicationContext context; + + @Test + void locateShouldFailWithoutRetrying() { + + /* + * Enabling secrets retry causes Spring Retry to be enabled and a + * RetryOperationsInterceptor bean with NeverRetryPolicy for config maps to be + * defined. ConfigMapPropertySourceLocator should not retry even Spring Retry is + * enabled. + */ + + stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); + + assertThat(context.containsBean("kubernetesConfigRetryInterceptor")).isTrue(); + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read ConfigMap with name 'application' in namespace 'default'"); + + // verify that propertySourceLocator.locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigRetryEnabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigRetryEnabled.java new file mode 100644 index 00000000..4c3339c9 --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/configmap_retry/ConfigRetryEnabled.java @@ -0,0 +1,173 @@ +/* + * 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.client.config.configmap_retry; + +import java.util.HashMap; +import java.util.Map; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import io.kubernetes.client.openapi.JSON; +import io.kubernetes.client.openapi.models.V1ConfigMap; +import io.kubernetes.client.openapi.models.V1ConfigMapList; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.util.ClientBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySourceLocator; +import org.springframework.core.env.PropertySource; +import org.springframework.mock.env.MockEnvironment; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static com.github.tomakehurst.wiremock.stubbing.Scenario.STARTED; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.config.fail-fast=true", "spring.cloud.kubernetes.config.retry.max-attempts=5", + "spring.main.cloud-platform=KUBERNETES" }, + classes = App.class) +class ConfigRetryEnabled { + + private static final String API = "/api/v1/namespaces/default/configmaps"; + + private static WireMockServer wireMockServer; + + private static MockedStatic clientUtilsMock; + + @BeforeAll + static void setup() { + wireMockServer = new WireMockServer(options().dynamicPort()); + wireMockServer.start(); + WireMock.configureFor(wireMockServer.port()); + + clientUtilsMock = mockStatic(KubernetesClientUtils.class); + clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient) + .thenReturn(new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build()); + stubConfigMapAndSecretsDefaults(); + } + + private static void stubConfigMapAndSecretsDefaults() { + // return empty config map / secret list to not fail context creation + stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1ConfigMapList())))); + } + + @AfterAll + static void teardown() { + wireMockServer.stop(); + clientUtilsMock.close(); + } + + @AfterEach + void afterEach() { + WireMock.reset(); + stubConfigMapAndSecretsDefaults(); + } + + @SpyBean + private KubernetesClientConfigMapPropertySourceLocator propertySourceLocator; + + @Test + void locateShouldNotRetryWhenThereIsNoFailure() { + + Map data = new HashMap<>(); + data.put("some.prop", "theValue"); + data.put("some.number", "0"); + + V1ConfigMapList configMapList = new V1ConfigMapList() + .addItemsItem(new V1ConfigMap().metadata(new V1ObjectMeta().name("application")).data(data)); + + stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList)))); + + PropertySource propertySource = Assertions + .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + + // validate the contents of the property source + assertThat(propertySource.getProperty("some.prop")).isEqualTo("theValue"); + assertThat(propertySource.getProperty("some.number")).isEqualTo("0"); + } + + @Test + void locateShouldRetryAndRecover() { + Map data = new HashMap<>(); + data.put("some.prop", "theValue"); + data.put("some.number", "0"); + + V1ConfigMapList configMapList = new V1ConfigMapList() + .addItemsItem(new V1ConfigMap().metadata(new V1ObjectMeta().name("application")).data(data)); + + // fail 3 times + stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs(STARTED) + .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed once")); + + stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed once") + .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed twice")); + + stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed twice") + .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed thrice")); + + // then succeed + stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed thrice") + .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList)))); + + PropertySource propertySource = Assertions + .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify retried 4 times + verify(propertySourceLocator, times(4)).locate(any()); + + // validate the contents of the property source + assertThat(propertySource.getProperty("some.prop")).isEqualTo("theValue"); + assertThat(propertySource.getProperty("some.number")).isEqualTo("0"); + } + + @Test + void locateShouldRetryAndFail() { + // fail all the 5 requests + stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); + + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read ConfigMap with name 'application' in namespace 'default'"); + + // verify retried 5 times until failure + verify(propertySourceLocator, times(5)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/Application.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/Application.java new file mode 100644 index 00000000..7f3b7731 --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/Application.java @@ -0,0 +1,24 @@ +/* + * 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.client.config.secrets_retry; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +class Application { + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsFailFastDisabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsFailFastDisabled.java new file mode 100644 index 00000000..24e9e20a --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsFailFastDisabled.java @@ -0,0 +1,105 @@ +/* + * 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.client.config.secrets_retry; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import io.kubernetes.client.openapi.JSON; +import io.kubernetes.client.openapi.models.V1SecretList; +import io.kubernetes.client.util.ClientBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.mock.env.MockEnvironment; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.secrets.name=my-secret", "spring.cloud.kubernetes.secrets.enable-api=true", + "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +class SecretsFailFastDisabled { + + private static final String API = "/api/v1/namespaces/default/secrets"; + + private static WireMockServer wireMockServer; + + private static MockedStatic clientUtilsMock; + + @BeforeAll + static void setup() { + wireMockServer = new WireMockServer(options().dynamicPort()); + wireMockServer.start(); + WireMock.configureFor(wireMockServer.port()); + + clientUtilsMock = mockStatic(KubernetesClientUtils.class); + clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient) + .thenReturn(new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build()); + stubConfigMapAndSecretsDefaults(); + } + + private static void stubConfigMapAndSecretsDefaults() { + // return empty config map / secret list to not fail context creation + stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1SecretList())))); + } + + @AfterAll + static void teardown() { + wireMockServer.stop(); + clientUtilsMock.close(); + } + + @AfterEach + void afterEach() { + WireMock.reset(); + stubConfigMapAndSecretsDefaults(); + } + + @SpyBean + private KubernetesClientSecretsPropertySourceLocator propertySourceLocator; + + @Test + void locateShouldNotRetry() { + + stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); + + Assertions.assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsFailFastEnabledButRetryDisabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsFailFastEnabledButRetryDisabled.java new file mode 100644 index 00000000..e2980ed0 --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsFailFastEnabledButRetryDisabled.java @@ -0,0 +1,120 @@ +/* + * 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.config.secrets_retry; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import io.kubernetes.client.openapi.JSON; +import io.kubernetes.client.openapi.models.V1ConfigMapList; +import io.kubernetes.client.openapi.models.V1SecretList; +import io.kubernetes.client.util.ClientBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.context.ApplicationContext; +import org.springframework.mock.env.MockEnvironment; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.secrets.fail-fast=true", "spring.cloud.kubernetes.secrets.retry.enabled=false", + "spring.cloud.kubernetes.secrets.name=my-secret", "spring.cloud.kubernetes.secrets.enable-api=true", + "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +class SecretsFailFastEnabledButRetryDisabled { + + private static final String API = "/api/v1/namespaces/default/secrets"; + + private static final String CONFIG_MAPS_API = "/api/v1/namespaces/default/configmaps"; + + private static WireMockServer wireMockServer; + + private static MockedStatic clientUtilsMock; + + @BeforeAll + static void setup() { + wireMockServer = new WireMockServer(options().dynamicPort()); + wireMockServer.start(); + WireMock.configureFor(wireMockServer.port()); + + clientUtilsMock = mockStatic(KubernetesClientUtils.class); + clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient) + .thenReturn(new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build()); + stubConfigMapAndSecretsDefaults(); + } + + private static void stubConfigMapAndSecretsDefaults() { + // return empty config map / secret list to not fail context creation + stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1SecretList())))); + stubFor(get(CONFIG_MAPS_API) + .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1ConfigMapList())))); + } + + @AfterAll + static void teardown() { + wireMockServer.stop(); + clientUtilsMock.close(); + } + + @AfterEach + void afterEach() { + WireMock.reset(); + stubConfigMapAndSecretsDefaults(); + } + + @SpyBean + private KubernetesClientSecretsPropertySourceLocator propertySourceLocator; + + @Autowired + private ApplicationContext context; + + @Test + void locateShouldFailWithoutRetrying() { + + stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); + + assertThat(context.containsBean("kubernetesSecretsRetryInterceptor")).isFalse(); + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); + + // verify that propertySourceLocator.locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsRetryDisabledButConfigRetryEnabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsRetryDisabledButConfigRetryEnabled.java new file mode 100644 index 00000000..083d29a1 --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsRetryDisabledButConfigRetryEnabled.java @@ -0,0 +1,127 @@ +/* + * 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.client.config.secrets_retry; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import io.kubernetes.client.openapi.JSON; +import io.kubernetes.client.openapi.models.V1ConfigMapList; +import io.kubernetes.client.openapi.models.V1SecretList; +import io.kubernetes.client.util.ClientBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.context.ApplicationContext; +import org.springframework.mock.env.MockEnvironment; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.secrets.fail-fast=true", "spring.cloud.kubernetes.secrets.retry.enabled=false", + "spring.cloud.kubernetes.config.fail-fast=true", "spring.cloud.kubernetes.secrets.name=my-secret", + "spring.cloud.kubernetes.secrets.enable-api=true", "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +class SecretsRetryDisabledButConfigRetryEnabled { + + private static final String API = "/api/v1/namespaces/default/secrets"; + + private static final String CONFIG_MAPS_API = "/api/v1/namespaces/default/configmaps"; + + private static WireMockServer wireMockServer; + + private static MockedStatic clientUtilsMock; + + @BeforeAll + static void setup() { + wireMockServer = new WireMockServer(options().dynamicPort()); + wireMockServer.start(); + WireMock.configureFor(wireMockServer.port()); + + clientUtilsMock = mockStatic(KubernetesClientUtils.class); + clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient) + .thenReturn(new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build()); + stubConfigMapAndSecretsDefaults(); + } + + private static void stubConfigMapAndSecretsDefaults() { + // return empty config map / secret list to not fail context creation + stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1SecretList())))); + stubFor(get(CONFIG_MAPS_API) + .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1ConfigMapList())))); + } + + @AfterAll + static void teardown() { + wireMockServer.stop(); + clientUtilsMock.close(); + } + + @AfterEach + void afterEach() { + WireMock.reset(); + stubConfigMapAndSecretsDefaults(); + } + + @SpyBean + private KubernetesClientSecretsPropertySourceLocator propertySourceLocator; + + @Autowired + private ApplicationContext context; + + @Test + void locateShouldFailWithoutRetrying() { + + /* + * Enabling config retry causes Spring Retry to be enabled and a + * RetryOperationsInterceptor bean with NeverRetryPolicy for secrets to be + * defined. SecretsPropertySourceLocator should not retry even Spring Retry is + * enabled. + */ + + stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); + + assertThat(context.containsBean("kubernetesSecretsRetryInterceptor")).isTrue(); + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); + + // verify that propertySourceLocator.locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsRetryEnabled.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsRetryEnabled.java new file mode 100644 index 00000000..7a9aa46a --- /dev/null +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/secrets_retry/SecretsRetryEnabled.java @@ -0,0 +1,173 @@ +/* + * 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.client.config.secrets_retry; + +import java.util.HashMap; +import java.util.Map; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import io.kubernetes.client.openapi.JSON; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1Secret; +import io.kubernetes.client.openapi.models.V1SecretList; +import io.kubernetes.client.util.ClientBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySourceLocator; +import org.springframework.core.env.PropertySource; +import org.springframework.mock.env.MockEnvironment; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static com.github.tomakehurst.wiremock.stubbing.Scenario.STARTED; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = { + "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.kubernetes.secrets.fail-fast=true", + "spring.cloud.kubernetes.secrets.retry.max-attempts=5", "spring.cloud.kubernetes.secrets.name=my-secret", + "spring.cloud.kubernetes.secrets.enable-api=true", "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +class SecretsRetryEnabled { + + private static final String API = "/api/v1/namespaces/default/secrets"; + + private static WireMockServer wireMockServer; + + private static MockedStatic clientUtilsMock; + + @BeforeAll + static void setup() { + wireMockServer = new WireMockServer(options().dynamicPort()); + wireMockServer.start(); + WireMock.configureFor(wireMockServer.port()); + + clientUtilsMock = mockStatic(KubernetesClientUtils.class); + clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient) + .thenReturn(new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build()); + stubConfigMapAndSecretsDefaults(); + } + + private static void stubConfigMapAndSecretsDefaults() { + // return empty config map / secret list to not fail context creation + stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1SecretList())))); + } + + @AfterAll + static void teardown() { + wireMockServer.stop(); + clientUtilsMock.close(); + } + + @AfterEach + void afterEach() { + WireMock.reset(); + stubConfigMapAndSecretsDefaults(); + } + + @SpyBean + private KubernetesClientSecretsPropertySourceLocator propertySourceLocator; + + @Test + void locateShouldNotRetryWhenThereIsNoFailure() { + + Map data = new HashMap<>(); + data.put("some.sensitive.prop", "theSensitiveValue".getBytes()); + data.put("some.sensitive.number", "1".getBytes()); + + V1SecretList secretList = new V1SecretList() + .addItemsItem(new V1Secret().metadata(new V1ObjectMeta().name("my-secret")).data(data)); + + stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList)))); + + PropertySource propertySource = Assertions + .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + + // validate the contents of the property source + assertThat(propertySource.getProperty("some.sensitive.prop")).isEqualTo("theSensitiveValue"); + assertThat(propertySource.getProperty("some.sensitive.number")).isEqualTo("1"); + } + + @Test + void locateShouldRetryAndRecover() { + Map data = new HashMap<>(); + data.put("some.sensitive.prop", "theSensitiveValue".getBytes()); + data.put("some.sensitive.number", "1".getBytes()); + + V1SecretList secretList = new V1SecretList() + .addItemsItem(new V1Secret().metadata(new V1ObjectMeta().name("my-secret")).data(data)); + + // fail 3 times + stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs(STARTED) + .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed once")); + + stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed once") + .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed twice")); + + stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed twice") + .willReturn(aResponse().withStatus(500)).willSetStateTo("Failed thrice")); + + // then succeed + stubFor(get(API).inScenario("Retry and Recover").whenScenarioStateIs("Failed thrice") + .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList)))); + + PropertySource propertySource = Assertions + .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify retried 4 times + verify(propertySourceLocator, times(4)).locate(any()); + + // validate the contents of the property source + assertThat(propertySource.getProperty("some.sensitive.prop")).isEqualTo("theSensitiveValue"); + assertThat(propertySource.getProperty("some.sensitive.number")).isEqualTo("1"); + } + + @Test + void locateShouldRetryAndFail() { + // fail all the 5 requests + stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); + + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); + + // verify retried 5 times until failure + verify(propertySourceLocator, times(5)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/App.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/App.java new file mode 100644 index 00000000..c0ec5ecc --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/App.java @@ -0,0 +1,24 @@ +/* + * 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.config; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class App { + +} diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigAndSecretsFailFastEnabledWithDefaultRetryConfiguration.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigAndSecretsFailFastEnabledWithDefaultRetryConfiguration.java new file mode 100644 index 00000000..0d1290b1 --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigAndSecretsFailFastEnabledWithDefaultRetryConfiguration.java @@ -0,0 +1,79 @@ +/* + * 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.config.bootstrap; + +import java.util.Map; + +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.commons.config.AbstractConfigProperties; +import org.springframework.cloud.kubernetes.commons.config.App; +import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties; +import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.retry.interceptor.RetryOperationsInterceptor; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = App.class, + properties = { "spring.cloud.kubernetes.config.fail-fast=true", + "spring.cloud.kubernetes.secrets.fail-fast=true", "spring.main.cloud-platform=KUBERNETES" }) +public class ConfigAndSecretsFailFastEnabledWithDefaultRetryConfiguration { + + @Autowired + private ConfigurableApplicationContext context; + + @Autowired + private ConfigMapConfigProperties configMapConfigProperties; + + @Autowired + private SecretsConfigProperties secretsConfigProperties; + + @Test + void shouldDefineRequiredBeans() { + Map retryInterceptors = context + .getBeansOfType(RetryOperationsInterceptor.class); + assertThat(retryInterceptors.containsKey("kubernetesConfigRetryInterceptor")).isTrue(); + assertThat(retryInterceptors.containsKey("kubernetesSecretsRetryInterceptor")).isTrue(); + } + + @Test + void retryConfigurationShouldBeDefault() { + AbstractConfigProperties.RetryProperties defaultRetryProperties = new AbstractConfigProperties.RetryProperties(); + + AbstractConfigProperties.RetryProperties configMapRetryProperties = configMapConfigProperties.getRetry(); + + assertThat(configMapRetryProperties.getMaxAttempts()).isEqualTo(defaultRetryProperties.getMaxAttempts()); + assertThat(configMapRetryProperties.getInitialInterval()) + .isEqualTo(defaultRetryProperties.getInitialInterval()); + assertThat(configMapRetryProperties.getMaxInterval()).isEqualTo(defaultRetryProperties.getMaxInterval()); + assertThat(configMapRetryProperties.getMultiplier()).isEqualTo(defaultRetryProperties.getMultiplier()); + + AbstractConfigProperties.RetryProperties secretsRetryProperties = secretsConfigProperties.getRetry(); + + assertThat(secretsRetryProperties.getMaxAttempts()).isEqualTo(defaultRetryProperties.getMaxAttempts()); + assertThat(secretsRetryProperties.getInitialInterval()).isEqualTo(defaultRetryProperties.getInitialInterval()); + assertThat(secretsRetryProperties.getMaxInterval()).isEqualTo(defaultRetryProperties.getMaxInterval()); + assertThat(secretsRetryProperties.getMultiplier()).isEqualTo(defaultRetryProperties.getMultiplier()); + } + +} diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabled.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabled.java new file mode 100644 index 00000000..0587b1d4 --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabled.java @@ -0,0 +1,65 @@ +/* + * 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.config.bootstrap; + +import java.util.Map; + +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.commons.config.AbstractConfigProperties; +import org.springframework.cloud.kubernetes.commons.config.App; +import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.retry.interceptor.RetryOperationsInterceptor; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = App.class, + properties = { "spring.cloud.kubernetes.config.fail-fast=true", "spring.main.cloud-platform=KUBERNETES" }) +class ConfigFailFastEnabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Autowired + private ConfigMapConfigProperties configMapConfigProperties; + + @Test + void shouldDefineRequiredBeans() { + Map retryInterceptors = context + .getBeansOfType(RetryOperationsInterceptor.class); + assertThat(retryInterceptors.containsKey("kubernetesConfigRetryInterceptor")).isTrue(); + assertThat(retryInterceptors.containsKey("kubernetesSecretsRetryInterceptor")).isTrue(); + } + + @Test + void retryConfigurationShouldBeDefault() { + AbstractConfigProperties.RetryProperties retryProperties = configMapConfigProperties.getRetry(); + AbstractConfigProperties.RetryProperties defaultRetryProperties = new AbstractConfigProperties.RetryProperties(); + + assertThat(retryProperties.getMaxAttempts()).isEqualTo(defaultRetryProperties.getMaxAttempts()); + assertThat(retryProperties.getInitialInterval()).isEqualTo(defaultRetryProperties.getInitialInterval()); + assertThat(retryProperties.getMaxInterval()).isEqualTo(defaultRetryProperties.getMaxInterval()); + assertThat(retryProperties.getMultiplier()).isEqualTo(defaultRetryProperties.getMultiplier()); + } + +} diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabledButRetryDisabled.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabledButRetryDisabled.java new file mode 100644 index 00000000..84234d29 --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabledButRetryDisabled.java @@ -0,0 +1,44 @@ +/* + * 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.config.bootstrap; + +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.commons.config.App; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.retry.interceptor.RetryOperationsInterceptor; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = App.class, properties = { + "spring.cloud.kubernetes.config.fail-fast=true", "spring.cloud.kubernetes.config.retry.enabled=false" }) +class ConfigFailFastEnabledButRetryDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void shouldNotDefineRetryBeans() { + assertThat(context.getBeansOfType(RetryOperationsInterceptor.class)).isEmpty(); + } + +} diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabledWithCustomRetryConfiguration.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabledWithCustomRetryConfiguration.java new file mode 100644 index 00000000..6644f06f --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/ConfigFailFastEnabledWithCustomRetryConfiguration.java @@ -0,0 +1,53 @@ +/* + * 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.config.bootstrap; + +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.commons.config.AbstractConfigProperties; +import org.springframework.cloud.kubernetes.commons.config.App; +import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = App.class, + properties = { "spring.cloud.kubernetes.config.fail-fast=true", + "spring.cloud.kubernetes.config.retry.max-attempts=3", + "spring.cloud.kubernetes.config.retry.initial-interval=1500", + "spring.cloud.kubernetes.config.retry.max-interval=3000", + "spring.cloud.kubernetes.config.retry.multiplier=1.5", "spring.main.cloud-platform=KUBERNETES" }) +class ConfigFailFastEnabledWithCustomRetryConfiguration { + + @Autowired + private ConfigMapConfigProperties configMapConfigProperties; + + @Test + void retryConfigurationShouldBeCustomized() { + AbstractConfigProperties.RetryProperties retryProperties = configMapConfigProperties.getRetry(); + + assertThat(retryProperties.getMaxAttempts()).isEqualTo(3); + assertThat(retryProperties.getInitialInterval()).isEqualTo(1500L); + assertThat(retryProperties.getMaxInterval()).isEqualTo(3000L); + assertThat(retryProperties.getMultiplier()).isEqualTo(1.5D); + } + +} diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/FailFastDisabled.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/FailFastDisabled.java new file mode 100644 index 00000000..63ab8a0c --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/FailFastDisabled.java @@ -0,0 +1,43 @@ +/* + * 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.config.bootstrap; + +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.commons.config.App; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.retry.interceptor.RetryOperationsInterceptor; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = App.class) +class FailFastDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void shouldNotDefineRetryBeans() { + assertThat(context.getBeansOfType(RetryOperationsInterceptor.class)).isEmpty(); + } + +} diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/FailFastEnabledWithoutSpringRetryOnClasspath.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/FailFastEnabledWithoutSpringRetryOnClasspath.java new file mode 100644 index 00000000..db9ef814 --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/FailFastEnabledWithoutSpringRetryOnClasspath.java @@ -0,0 +1,61 @@ +/* + * 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.commons.config.bootstrap; + +import org.aspectj.lang.annotation.Aspect; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.cloud.kubernetes.commons.config.KubernetesBootstrapConfiguration; +import org.springframework.retry.annotation.Retryable; +import org.springframework.retry.interceptor.RetryOperationsInterceptor; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Isik Erhan + */ +class FailFastEnabledWithoutSpringRetryOnClasspath { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(KubernetesBootstrapConfiguration.class)) + .withClassLoader(new FilteredClassLoader(Retryable.class, Aspect.class, AopAutoConfiguration.class)); + + @Test + void shouldNotDefineRetryBeansWhenConfigMapFailFastEnabled() { + contextRunner.withPropertyValues("spring.cloud.kubernetes.config.fail-fast=true") + .run(context -> assertThat(context.getBeansOfType(RetryOperationsInterceptor.class)).isEmpty()); + } + + @Test + void shouldNotDefineRetryBeansWhenSecretsFailFastEnabled() { + contextRunner.withPropertyValues("spring.cloud.kubernetes.secrets.fail-fast=true") + .run(context -> assertThat(context.getBeansOfType(RetryOperationsInterceptor.class)).isEmpty()); + } + + @Test + void shouldNotDefineRetryBeansWhenConfigMapAndSecretsFailFastEnabled() { + contextRunner + .withPropertyValues("spring.cloud.kubernetes.config.fail-fast=true", + "spring.cloud.kubernetes.secrets.fail-fast=true") + .run(context -> assertThat(context.getBeansOfType(RetryOperationsInterceptor.class)).isEmpty()); + } + +} diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabled.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabled.java new file mode 100644 index 00000000..0e14a8a4 --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabled.java @@ -0,0 +1,65 @@ +/* + * 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.commons.config.bootstrap; + +import java.util.Map; + +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.commons.config.AbstractConfigProperties; +import org.springframework.cloud.kubernetes.commons.config.App; +import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.retry.interceptor.RetryOperationsInterceptor; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = App.class, + properties = { "spring.cloud.kubernetes.secrets.fail-fast=true", "spring.main.cloud-platform=KUBERNETES" }) +class SecretsFailFastEnabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Autowired + private SecretsConfigProperties secretsConfigProperties; + + @Test + void shouldDefineRequiredBeans() { + Map retryInterceptors = context + .getBeansOfType(RetryOperationsInterceptor.class); + assertThat(retryInterceptors.containsKey("kubernetesConfigRetryInterceptor")).isTrue(); + assertThat(retryInterceptors.containsKey("kubernetesSecretsRetryInterceptor")).isTrue(); + } + + @Test + void retryConfigurationShouldBeDefault() { + AbstractConfigProperties.RetryProperties retryProperties = secretsConfigProperties.getRetry(); + AbstractConfigProperties.RetryProperties defaultRetryProperties = new AbstractConfigProperties.RetryProperties(); + + assertThat(retryProperties.getMaxAttempts()).isEqualTo(defaultRetryProperties.getMaxAttempts()); + assertThat(retryProperties.getInitialInterval()).isEqualTo(defaultRetryProperties.getInitialInterval()); + assertThat(retryProperties.getMaxInterval()).isEqualTo(defaultRetryProperties.getMaxInterval()); + assertThat(retryProperties.getMultiplier()).isEqualTo(defaultRetryProperties.getMultiplier()); + } + +} diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabledButRetryDisabled.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabledButRetryDisabled.java new file mode 100644 index 00000000..6925dd8f --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabledButRetryDisabled.java @@ -0,0 +1,44 @@ +/* + * 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.commons.config.bootstrap; + +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.commons.config.App; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.retry.interceptor.RetryOperationsInterceptor; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = App.class, properties = { + "spring.cloud.kubernetes.secrets.fail-fast=true", "spring.cloud.kubernetes.secrets.retry.enabled=false" }) +class SecretsFailFastEnabledButRetryDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void shouldNotDefineRetryBeans() { + assertThat(context.getBeansOfType(RetryOperationsInterceptor.class)).isEmpty(); + } + +} diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabledWithCustomRetryConfiguration.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabledWithCustomRetryConfiguration.java new file mode 100644 index 00000000..9c760185 --- /dev/null +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/bootstrap/SecretsFailFastEnabledWithCustomRetryConfiguration.java @@ -0,0 +1,53 @@ +/* + * 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.commons.config.bootstrap; + +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.commons.config.AbstractConfigProperties; +import org.springframework.cloud.kubernetes.commons.config.App; +import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = App.class, + properties = { "spring.cloud.kubernetes.secrets.fail-fast=true", + "spring.cloud.kubernetes.secrets.retry.max-attempts=3", + "spring.cloud.kubernetes.secrets.retry.initial-interval=1500", + "spring.cloud.kubernetes.secrets.retry.max-interval=3000", + "spring.cloud.kubernetes.secrets.retry.multiplier=1.5", "spring.main.cloud-platform=KUBERNETES" }) +class SecretsFailFastEnabledWithCustomRetryConfiguration { + + @Autowired + private SecretsConfigProperties secretsConfigProperties; + + @Test + void retryConfigurationShouldBeCustomized() { + AbstractConfigProperties.RetryProperties retryProperties = secretsConfigProperties.getRetry(); + + assertThat(retryProperties.getMaxAttempts()).isEqualTo(3); + assertThat(retryProperties.getInitialInterval()).isEqualTo(1500L); + assertThat(retryProperties.getMaxInterval()).isEqualTo(3000L); + assertThat(retryProperties.getMultiplier()).isEqualTo(1.5D); + } + +} diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesDisabled.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesDisabled.java new file mode 100644 index 00000000..9bb21e55 --- /dev/null +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesDisabled.java @@ -0,0 +1,44 @@ +/* + * 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.configserver; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Ryan Baxter + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = { "spring.profiles.include=kubernetes,kubernetesdisabled", "spring.cloud.kubernetes.enabled=false", + "debug=true" }, + classes = { KubernetesConfigServerApplication.class, MockConfig.class }) +class ConfigServerAutoConfigurationKubernetesDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void runTest() { + assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncluded.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncluded.java new file mode 100644 index 00000000..b1d581a2 --- /dev/null +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncluded.java @@ -0,0 +1,45 @@ +/* + * 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.configserver; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Ryan Baxter + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = { KubernetesConfigServerApplication.class }, + properties = { "spring.main.cloud-platform=KUBERNETES", "spring.profiles.include=kubernetes", "debug=true", + "spring.cloud.kubernetes.client.namespace=default" }) +class ConfigServerAutoConfigurationKubernetesEnabledProfileIncluded { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void runTest() { + assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).hasSize(1); + } + +} diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedConfigApiDisabled.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedConfigApiDisabled.java new file mode 100644 index 00000000..9d47e171 --- /dev/null +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedConfigApiDisabled.java @@ -0,0 +1,45 @@ +/* + * 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.configserver; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Ryan Baxter + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = { KubernetesConfigServerApplication.class }, + properties = { "spring.main.cloud-platform=KUBERNETES", "spring.profiles.include=kubernetes", "debug=true", + "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.kubernetes.config.enableApi=false" }) +class ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedConfigApiDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void runTest() { + assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedConfigMapDisabled.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedConfigMapDisabled.java new file mode 100644 index 00000000..aebf99ab --- /dev/null +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedConfigMapDisabled.java @@ -0,0 +1,44 @@ +/* + * 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.configserver; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Ryan Baxter + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = { KubernetesConfigServerApplication.class }, properties = { "spring.main.cloud-platform=KUBERNETES", + "spring.profiles.include=kubernetes", "debug=true", "spring.cloud.kubernetes.config.enabled=false" }) +class ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedConfigMapDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void runTest() { + assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedSecretsApiDisabled.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedSecretsApiDisabled.java new file mode 100644 index 00000000..6ad9e6d0 --- /dev/null +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedSecretsApiDisabled.java @@ -0,0 +1,47 @@ +/* + * 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.configserver; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Ryan Baxter + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = { KubernetesConfigServerApplication.class }, + properties = { "spring.main.cloud-platform=KUBERNETES", "spring.profiles.include=kubernetes", "debug=true", + "spring.cloud.kubernetes.client.namespace=default" }) +class ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedSecretsApiDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void runTest() { + assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)[0]) + .isEqualTo("configMapPropertySourceSupplier"); + } + +} diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedSecretsApiEnabled.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedSecretsApiEnabled.java new file mode 100644 index 00000000..64a4820e --- /dev/null +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedSecretsApiEnabled.java @@ -0,0 +1,45 @@ +/* + * 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.configserver; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Ryan Baxter + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = { KubernetesConfigServerApplication.class }, + properties = { "spring.profiles.include=kubernetes", "debug=true", "spring.main.cloud-platform=KUBERNETES", + "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.kubernetes.secrets.enableApi=true" }) +class ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedSecretsApiEnabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void runTest() { + assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).hasSize(2); + } + +} diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesProfileMissing.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesProfileMissing.java new file mode 100644 index 00000000..7bedf868 --- /dev/null +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesProfileMissing.java @@ -0,0 +1,44 @@ +/* + * 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.configserver; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Ryan Baxter + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = { KubernetesConfigServerApplication.class, MockConfig.class }, + properties = { "spring.cloud.kubernetes.enabled=false", "spring.profiles.include=kubernetes,kubernetesdisabled", + "debug=true" }) +class ConfigServerAutoConfigurationKubernetesProfileMissing { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void runTest() { + assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerIntegrationTest.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerIntegrationTest.java index cdd0787b..8127e07a 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerIntegrationTest.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerIntegrationTest.java @@ -75,7 +75,7 @@ public class ConfigServerIntegrationTest { } @Test - public void enabled() throws Exception { + public void enabled() { Environment env = testRestTemplate.getForObject("/test-cm/default", Environment.class); assertThat(env.getPropertySources().size()).isEqualTo(2); assertThat(env.getPropertySources().get(0).getName().equals("configmap.test-cm.default")).isTrue(); diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerAutoConfigurationTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerAutoConfigurationTests.java deleted file mode 100644 index 6995c7fa..00000000 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerAutoConfigurationTests.java +++ /dev/null @@ -1,176 +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.configserver; - -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.config.server.environment.EnvironmentRepository; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * @author Ryan Baxter - */ -public class KubernetesConfigServerAutoConfigurationTests { - - @Configuration - static class MockConfig { - - @Bean - @Profile("kubernetesdisabled") - public EnvironmentRepository environmentRepository() { - return mock(EnvironmentRepository.class); - } - - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = { "spring.profiles.include=kubernetes,kubernetesdisabled", "debug=true" }, - classes = { KubernetesConfigServerApplication.class, MockConfig.class }) - public class KubernetesDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void runTest() { - assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(0); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = { KubernetesConfigServerApplication.class, MockConfig.class }, - properties = { "spring.profiles.include=kubernetes,kubernetesdisabled", "debug=true" }) - @Nested - class KubernetesProfileMissing { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void runTest() { - assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(0); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = { KubernetesConfigServerApplication.class }, - properties = { "spring.main.cloud-platform=KUBERNETES", "spring.profiles.include=kubernetes", "debug=true", - "spring.cloud.kubernetes.client.namespace=default" }) - @Nested - class KubernetesEnabledProfileIncluded { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void runTest() { - assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).hasSize(1); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = { KubernetesConfigServerApplication.class }, - properties = { "spring.main.cloud-platform=KUBERNETES", // STOPSHIP: 11/10/21 - "spring.profiles.include=kubernetes", "debug=true", - "spring.cloud.kubernetes.config.enabled=false" }) - @Nested - class KubernetesEnabledProfileIncludedConfigMapDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void runTest() { - assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).hasSize(0); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = { KubernetesConfigServerApplication.class }, - properties = { "spring.main.cloud-platform=KUBERNETES", "spring.profiles.include=kubernetes", "debug=true", - "spring.cloud.kubernetes.client.namespace=default" }) - @Nested - class KubernetesEnabledProfileIncludedSecretsApiDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void runTest() { - assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)[0]) - .isEqualTo("configMapPropertySourceSupplier"); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = { KubernetesConfigServerApplication.class }, - properties = { "spring.main.cloud-platform=KUBERNETES", "spring.profiles.include=kubernetes", "debug=true", - "spring.cloud.kubernetes.client.namespace=default", - "spring.cloud.kubernetes.secrets.enableApi=true" }) - @Nested - class KubernetesEnabledProfileIncludedSecretsApiEnabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void runTest() { - assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).hasSize(2); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = { KubernetesConfigServerApplication.class }, - properties = { "spring.main.cloud-platform=KUBERNETES", "spring.profiles.include=kubernetes", "debug=true", - "spring.cloud.kubernetes.client.namespace=default", - "spring.cloud.kubernetes.config.enableApi=false" }) - @Nested - class KubernetesEnabledProfileIncludedConfigApiDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - void runTest() { - assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).hasSize(0); - } - - } - -} diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/MockConfig.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/MockConfig.java new file mode 100644 index 00000000..0fdc0645 --- /dev/null +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/MockConfig.java @@ -0,0 +1,35 @@ +/* + * 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.configserver; + +import org.springframework.cloud.config.server.environment.EnvironmentRepository; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +import static org.mockito.Mockito.mock; + +@Configuration +class MockConfig { + + @Bean + @Profile("kubernetesdisabled") + public EnvironmentRepository environmentRepository() { + return mock(EnvironmentRepository.class); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/Fabric8AutoConfigurationTests.java b/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/Fabric8AutoConfigurationTests.java index 273a500d..58d84bf5 100644 --- a/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/Fabric8AutoConfigurationTests.java +++ b/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/Fabric8AutoConfigurationTests.java @@ -22,7 +22,6 @@ import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -32,11 +31,9 @@ import org.springframework.cloud.kubernetes.fabric8.Fabric8HealthIndicator; import org.springframework.cloud.kubernetes.fabric8.Fabric8InfoContributor; import org.springframework.cloud.kubernetes.fabric8.Fabric8PodUtils; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; -@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.password=mypassword", "spring.cloud.kubernetes.client.proxy-password=myproxypassword" }) 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 deleted file mode 100644 index 6aaf5fdf..00000000 --- a/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8ClientUserAgentTests.java +++ /dev/null @@ -1,70 +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.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"; - - private static final String ENABLED_K8S = "spring.main.cloud-platform=KUBERNETES"; - - @Nested - @SpringBootTest(classes = App.class, properties = ENABLED_K8S) - 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, ENABLED_K8S }) - class PropertiesConfigurationForClient { - - @Autowired - private KubernetesClient client; - - @Test - void testUserAgent() { - String userAgent = client.getConfiguration().getUserAgent(); - assertThat(userAgent).isEqualTo("non-default"); - } - - } - -} diff --git a/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8UserAgentDefaultConfigurationTests.java b/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8UserAgentDefaultConfigurationTests.java new file mode 100644 index 00000000..fad50c4f --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8UserAgentDefaultConfigurationTests.java @@ -0,0 +1,43 @@ +/* + * 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.fabric8; + +import io.fabric8.kubernetes.client.KubernetesClient; +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 + */ +@SpringBootTest(classes = App.class, properties = "spring.main.cloud-platform=KUBERNETES") +class Fabric8UserAgentDefaultConfigurationTests { + + @Autowired + private KubernetesClient client; + + @Test + void testUserAgent() { + String userAgent = client.getConfiguration().getUserAgent(); + assertThat(userAgent).isEqualTo("Spring-Cloud-Kubernetes-Application"); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8UserAgentPropertiesConfiguration.java b/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8UserAgentPropertiesConfiguration.java new file mode 100644 index 00000000..0fd907d2 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-autoconfig/src/test/java/org/springframework/cloud/kubernetes/fabric8/Fabric8UserAgentPropertiesConfiguration.java @@ -0,0 +1,44 @@ +/* + * 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.fabric8; + +import io.fabric8.kubernetes.client.KubernetesClient; +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 + */ +@SpringBootTest(classes = App.class, properties = { "spring.cloud.kubernetes.client.userAgent=non-default", + "spring.main.cloud-platform=KUBERNETES" }) +class Fabric8UserAgentPropertiesConfiguration { + + @Autowired + private KubernetesClient client; + + @Test + void testUserAgent() { + String userAgent = client.getConfiguration().getUserAgent(); + assertThat(userAgent).isEqualTo("non-default"); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ActuatorTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ActuatorTests.java deleted file mode 100644 index 8ec4871b..00000000 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ActuatorTests.java +++ /dev/null @@ -1,95 +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.fabric8.config; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.kubernetes.fabric8.config.example.App; -import org.springframework.http.MediaType; -import org.springframework.test.web.reactive.server.WebTestClient; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; - -/** - * @author wind57 - */ -public class Fabric8ActuatorTests { - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { - "management.health.kubernetes.enabled=false", "management.endpoint.health.show-details=always", - "management.endpoint.health.show-components=always", "management.endpoints.web.exposure.include=health", - "spring.cloud.kubernetes.client.namespace=default" }) - public class DisabledHealthTest { - - @Autowired - private ReactiveHealthContributorRegistry registry; - - @Autowired - private WebTestClient webClient; - - @Value("${local.server.port}") - private int port; - - @Test - public void healthEndpointShouldContainKubernetes() { - this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port) - .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class) - .value(not(containsString("kubernetes"))); - - Assertions.assertNull(registry.getContributor("kubernetes"), - "reactive kubernetes contributor must NOT be present when 'management.health.kubernetes.enabled=false'"); - } - - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { - "spring.main.cloud-platform=KUBERNETES", "management.health.kubernetes.enabled=true", - "management.endpoint.health.show-details=always", "management.endpoint.health.show-components=always", - "management.endpoints.web.exposure.include=health", "spring.cloud.kubernetes.client.namespace=default" }) - public class EnabledHealthTest { - - @Autowired - private WebTestClient webClient; - - @Autowired - private ReactiveHealthContributorRegistry registry; - - @Value("${local.server.port}") - private int port; - - @Test - public void healthEndpointShouldContainKubernetes() { - this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port) - .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class) - .value(containsString("kubernetes")); - - Assertions.assertNotNull(registry.getContributor("kubernetes"), - "reactive kubernetes contributor must be present when 'management.health.kubernetes.enabled=true'"); - } - - } - -} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8BootstrapConfigurationTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8BootstrapConfigurationTests.java deleted file mode 100644 index 3efd8c59..00000000 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8BootstrapConfigurationTests.java +++ /dev/null @@ -1,167 +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.fabric8.config; - -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.context.ConfigurableApplicationContext; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author wind57 - */ -public class Fabric8BootstrapConfigurationTests { - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class) - @Nested - class KubernetesDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void configAndSecretsBeansAreNotPresent() { - assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(0); - assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(0); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.cloud.kubernetes.secrets.enabled=true", - "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }) - @Nested - class KubernetesEnabledOnPurpose { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void configAndSecretsBeansArePresent() { - assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(1); - assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(1); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.cloud.kubernetes.client.namespace=default", - "spring.main.cloud-platform=KUBERNETES" }) - @Nested - class KubernetesEnabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void configAndSecretsBeansArePresent() { - assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(1); - assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(1); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.cloud.kubernetes.config.enabled=false", "spring.main.cloud-platform=KUBERNETES" }) - @Nested - class KubernetesEnabledConfigDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void secretsOnlyPresent() { - assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(0); - assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(1); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.cloud.kubernetes.secrets.enabled=false", - "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }) - @Nested - class KubernetesEnabledSecretsDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void secretsOnlyPresent() { - assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(1); - assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(0); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.cloud.kubernetes.secrets.enabled=false", - "spring.cloud.kubernetes.config.enabled=false" }) - @Nested - class KubernetesEnabledSecretsAndConfigDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void secretsOnlyPresent() { - assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(0); - assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(0); - } - - } - - // tests that @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) has the desired - // effect, meaning when it is enabled, both property sources are present - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, - properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=abc" }) - @Nested - class Fabric8BootstrapConfigurationInsideK8s { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void bothPresent() { - assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(1); - assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(1); - } - - } - - // tests that @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) has the desired - // effect, meaning when it is disabled, no property source bean is present - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class) - @Nested - class Fabric8BootstrapConfigurationNotInsideK8s { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void bothMissing() { - assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(0); - assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(0); - } - - } - -} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceLocatorRetryTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceLocatorRetryTests.java deleted file mode 100644 index a3d4232f..00000000 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceLocatorRetryTests.java +++ /dev/null @@ -1,241 +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.fabric8.config; - -import java.util.Base64; -import java.util.HashMap; -import java.util.Map; - -import io.fabric8.kubernetes.api.model.SecretBuilder; -import io.fabric8.kubernetes.api.model.SecretListBuilder; -import io.fabric8.kubernetes.client.Config; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -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.boot.test.mock.mockito.SpyBean; -import org.springframework.context.ApplicationContext; -import org.springframework.core.env.PropertySource; -import org.springframework.mock.env.MockEnvironment; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -/** - * @author Isik Erhan - */ -@EnableKubernetesMockClient -public class Fabric8SecretsPropertySourceLocatorRetryTests { - - private static final String API = "/api/v1/namespaces/default/secrets/my-secret"; - - private static final String LIST_API = "/api/v1/namespaces/default/secrets"; - - static KubernetesMockServer mockServer; - - static KubernetesClient mockClient; - - @BeforeAll - public static void setup() { - // Configure the kubernetes master url to point to the mock server - System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); - System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); - System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); - System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); - System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); - - // return empty secret list to not fail context creation - mockServer.expect().withPath(LIST_API).andReturn(200, new SecretListBuilder().build()).always(); - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = { - "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.kubernetes.secrets.fail-fast=true", - "spring.cloud.kubernetes.secrets.retry.max-attempts=5", "spring.cloud.kubernetes.secrets.name=my-secret", - "spring.cloud.kubernetes.secrets.enable-api=true", "spring.main.cloud-platform=KUBERNETES" }, - classes = Application.class) - @EnableKubernetesMockClient - class SecretsRetryEnabled { - - @SpyBean - private Fabric8SecretsPropertySourceLocator propertySourceLocator; - - @Test - public void locateShouldNotRetryWhenThereIsNoFailure() { - Map data = new HashMap<>(); - data.put("some.sensitive.prop", Base64.getEncoder().encodeToString("theSensitiveValue".getBytes())); - data.put("some.sensitive.number", Base64.getEncoder().encodeToString("1".getBytes())); - - // return secret without failing - mockServer.expect().withPath(API).andReturn(200, - new SecretBuilder().withNewMetadata().withName("my-secret").endMetadata().addToData(data).build()) - .once(); - - PropertySource propertySource = Assertions - .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); - - // verify locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - - // validate the contents of the property source - assertThat(propertySource.getProperty("some.sensitive.prop")).isEqualTo("theSensitiveValue"); - assertThat(propertySource.getProperty("some.sensitive.number")).isEqualTo("1"); - } - - @Test - public void locateShouldRetryAndRecover() { - Map data = new HashMap<>(); - data.put("some.sensitive.prop", Base64.getEncoder().encodeToString("theSensitiveValue".getBytes())); - data.put("some.sensitive.number", Base64.getEncoder().encodeToString("1".getBytes())); - - // fail 3 times then succeed at the 4th call - mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").times(3); - mockServer.expect().withPath(API).andReturn(200, - new SecretBuilder().withNewMetadata().withName("my-secret").endMetadata().addToData(data).build()) - .once(); - - PropertySource propertySource = Assertions - .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); - - // verify retried 4 times - verify(propertySourceLocator, times(4)).locate(any()); - - // validate the contents of the property source - assertThat(propertySource.getProperty("some.sensitive.prop")).isEqualTo("theSensitiveValue"); - assertThat(propertySource.getProperty("some.sensitive.number")).isEqualTo("1"); - } - - @Test - public void locateShouldRetryAndFail() { - // fail all the 5 requests - mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").times(5); - - assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); - - // verify retried 5 times until failure - verify(propertySourceLocator, times(5)).locate(any()); - } - - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = { "spring.cloud.kubernetes.client.namespace=default", - "spring.cloud.kubernetes.secrets.name=my-secret", "spring.cloud.kubernetes.secrets.enable-api=true", - "spring.main.cloud-platform=KUBERNETES" }, - classes = Application.class) - @EnableKubernetesMockClient - class SecretsFailFastDisabled { - - @SpyBean - private Fabric8SecretsPropertySourceLocator propertySourceLocator; - - @Test - public void locateShouldNotRetry() { - mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").once(); - - Assertions.assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); - - // verify locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - } - - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = { "spring.cloud.kubernetes.client.namespace=default", - "spring.cloud.kubernetes.secrets.fail-fast=true", - "spring.cloud.kubernetes.secrets.retry.enabled=false", - "spring.cloud.kubernetes.config.fail-fast=true", "spring.cloud.kubernetes.secrets.name=my-secret", - "spring.cloud.kubernetes.secrets.enable-api=true", "spring.main.cloud-platform=KUBERNETES" }, - classes = Application.class) - @EnableKubernetesMockClient - class SecretsRetryDisabledButConfigRetryEnabled { - - @SpyBean - private Fabric8SecretsPropertySourceLocator propertySourceLocator; - - @Autowired - private ApplicationContext context; - - @Test - public void locateShouldFailWithoutRetrying() { - - /* - * Enabling config retry causes Spring Retry to be enabled and a - * RetryOperationsInterceptor bean with NeverRetryPolicy for secrets to be - * defined. SecretsPropertySourceLocator should not retry even Spring Retry is - * enabled. - */ - - mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").once(); - - assertThat(context.containsBean("kubernetesSecretsRetryInterceptor")).isTrue(); - assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); - - // verify that propertySourceLocator.locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - } - - } - - @Nested - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = { - "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.kubernetes.secrets.fail-fast=true", - "spring.cloud.kubernetes.secrets.retry.enabled=false", "spring.cloud.kubernetes.secrets.name=my-secret", - "spring.cloud.kubernetes.secrets.enable-api=true", "spring.main.cloud-platform=KUBERNETES" }, - classes = Application.class) - @EnableKubernetesMockClient - class SecretsFailFastEnabledButRetryDisabled { - - @SpyBean - private Fabric8SecretsPropertySourceLocator propertySourceLocator; - - @Autowired - private ApplicationContext context; - - @Test - public void locateShouldFailWithoutRetrying() { - - mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").once(); - - assertThat(context.containsBean("kubernetesSecretsRetryInterceptor")).isFalse(); - assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); - - // verify that propertySourceLocator.locate is called only once - verify(propertySourceLocator, times(1)).locate(any()); - } - - } - -} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/actuator/DisabledHealthTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/actuator/DisabledHealthTest.java new file mode 100644 index 00000000..12b21f20 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/actuator/DisabledHealthTest.java @@ -0,0 +1,61 @@ +/* + * 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.fabric8.config.actuator; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.kubernetes.fabric8.config.example.App; +import org.springframework.http.MediaType; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, + properties = { "management.health.kubernetes.enabled=false", "management.endpoint.health.show-details=always", + "management.endpoint.health.show-components=always", "management.endpoints.web.exposure.include=health", + "spring.cloud.kubernetes.client.namespace=default" }) +class DisabledHealthTest { + + @Autowired + private ReactiveHealthContributorRegistry registry; + + @Autowired + private WebTestClient webClient; + + @Value("${local.server.port}") + private int port; + + @Test + void healthEndpointShouldContainKubernetes() { + this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port) + .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class) + .value(not(containsString("kubernetes"))); + + Assertions.assertNull(registry.getContributor("kubernetes"), + "reactive kubernetes contributor must NOT be present when 'management.health.kubernetes.enabled=false'"); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/actuator/EnabledHealthTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/actuator/EnabledHealthTest.java new file mode 100644 index 00000000..d1ba5a7a --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/actuator/EnabledHealthTest.java @@ -0,0 +1,60 @@ +/* + * 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.fabric8.config.actuator; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.kubernetes.fabric8.config.example.App; +import org.springframework.http.MediaType; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static org.hamcrest.Matchers.containsString; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, + properties = { "management.health.kubernetes.enabled=true", "management.endpoint.health.show-details=always", + "management.endpoint.health.show-components=always", "management.endpoints.web.exposure.include=health", + "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }) +class EnabledHealthTest { + + @Autowired + private WebTestClient webClient; + + @Autowired + private ReactiveHealthContributorRegistry registry; + + @Value("${local.server.port}") + private int port; + + @Test + void healthEndpointShouldContainKubernetes() { + this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port) + .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class) + .value(containsString("kubernetes")); + + Assertions.assertNotNull(registry.getContributor("kubernetes"), + "reactive kubernetes contributor must be present when 'management.health.kubernetes.enabled=true'"); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/Fabric8BootstrapConfigurationInsideK8s.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/Fabric8BootstrapConfigurationInsideK8s.java new file mode 100644 index 00000000..e0014630 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/Fabric8BootstrapConfigurationInsideK8s.java @@ -0,0 +1,48 @@ +/* + * 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.fabric8.config.bootstrap; + +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.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=abc" }) +class Fabric8BootstrapConfigurationInsideK8s { + + @Autowired + private ConfigurableApplicationContext context; + + // tests that @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) has the desired + // effect, meaning when it is enabled, both property sources are present + @Test + void bothPresent() { + assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(1); + assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(1); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/Fabric8BootstrapConfigurationNotInsideK8s.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/Fabric8BootstrapConfigurationNotInsideK8s.java new file mode 100644 index 00000000..7932b24f --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/Fabric8BootstrapConfigurationNotInsideK8s.java @@ -0,0 +1,44 @@ +/* + * 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.fabric8.config.bootstrap; + +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.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class) +class Fabric8BootstrapConfigurationNotInsideK8s { + + @Autowired + private ConfigurableApplicationContext context; + + // tests that @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) has the desired + // effect, meaning when it is disabled, no property source bean is present + @Test + void bothMissing() { + assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(0); + assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesDisabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesDisabled.java new file mode 100644 index 00000000..08b21f19 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesDisabled.java @@ -0,0 +1,46 @@ +/* + * 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.fabric8.config.bootstrap; + +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.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = "spring.cloud.kubernetes.enabled=false") +class KubernetesDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void configAndSecretsBeansAreNotPresent() { + assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(0); + assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabled.java new file mode 100644 index 00000000..c8ba70e0 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabled.java @@ -0,0 +1,46 @@ +/* + * 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.fabric8.config.bootstrap; + +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.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }) +class KubernetesEnabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void configAndSecretsBeansArePresent() { + assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(1); + assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(1); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledConfigDisabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledConfigDisabled.java new file mode 100644 index 00000000..d438ed1e --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledConfigDisabled.java @@ -0,0 +1,46 @@ +/* + * 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.config.bootstrap; + +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.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.cloud.kubernetes.config.enabled=false", "spring.main.cloud-platform=KUBERNETES" }) +class KubernetesEnabledConfigDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void secretsOnlyPresent() { + assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(0); + assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(1); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledOnPurpose.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledOnPurpose.java new file mode 100644 index 00000000..70b75f93 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledOnPurpose.java @@ -0,0 +1,47 @@ +/* + * 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.fabric8.config.bootstrap; + +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.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.cloud.kubernetes.secrets.enabled=true", + "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }) +class KubernetesEnabledOnPurpose { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void configAndSecretsBeansArePresent() { + assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(1); + assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(1); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledSecretsAndConfigDisabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledSecretsAndConfigDisabled.java new file mode 100644 index 00000000..7a50d8e3 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledSecretsAndConfigDisabled.java @@ -0,0 +1,43 @@ +/* + * 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.fabric8.config.bootstrap; + +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.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { + "spring.cloud.kubernetes.secrets.enabled=false", "spring.cloud.kubernetes.config.enabled=false" }) +class KubernetesEnabledSecretsAndConfigDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void secretsOnlyPresent() { + assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(0); + assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledSecretsDisabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledSecretsDisabled.java new file mode 100644 index 00000000..ae4763d5 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/bootstrap/KubernetesEnabledSecretsDisabled.java @@ -0,0 +1,47 @@ +/* + * 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.fabric8.config.bootstrap; + +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.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, + properties = { "spring.cloud.kubernetes.secrets.enabled=false", + "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }) +class KubernetesEnabledSecretsDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void secretsOnlyPresent() { + assertThat(context.getBeanNamesForType(Fabric8ConfigMapPropertySourceLocator.class)).hasSize(1); + assertThat(context.getBeanNamesForType(Fabric8SecretsPropertySourceLocator.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigFailFastDisabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigFailFastDisabled.java new file mode 100644 index 00000000..37b57207 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigFailFastDisabled.java @@ -0,0 +1,75 @@ +/* + * 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.fabric8.config.locator_retry; + +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.mock.env.MockEnvironment; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +@EnableKubernetesMockClient +class ConfigFailFastDisabled { + + private static final String API = "/api/v1/namespaces/default/configmaps/application"; + + private static KubernetesMockServer mockServer; + + private static KubernetesClient mockClient; + + @BeforeAll + static void setup() { + // Configure the kubernetes master url to point to the mock server + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); + System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); + } + + @SpyBean + private Fabric8ConfigMapPropertySourceLocator propertySourceLocator; + + @Test + void locateShouldNotRetry() { + mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").once(); + + Assertions.assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify that propertySourceLocator.locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigFailFastEnabledButRetryDisabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigFailFastEnabledButRetryDisabled.java new file mode 100644 index 00000000..2b90b0ba --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigFailFastEnabledButRetryDisabled.java @@ -0,0 +1,87 @@ +/* + * 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.fabric8.config.locator_retry; + +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +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.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.context.ApplicationContext; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.config.fail-fast=true", "spring.cloud.kubernetes.config.retry.enabled=false", + "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +@EnableKubernetesMockClient +class ConfigFailFastEnabledButRetryDisabled { + + private static final String API = "/api/v1/namespaces/default/configmaps/application"; + + private static KubernetesMockServer mockServer; + + private static KubernetesClient mockClient; + + @BeforeAll + static void setup() { + // Configure the kubernetes master url to point to the mock server + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); + System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); + } + + @SpyBean + private Fabric8ConfigMapPropertySourceLocator propertySourceLocator; + + @Autowired + private ApplicationContext context; + + @Test + void locateShouldFailWithoutRetrying() { + + mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").once(); + + assertThat(context.containsBean("kubernetesConfigRetryInterceptor")).isFalse(); + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read ConfigMap with name 'application' in namespace 'default'"); + + // verify that propertySourceLocator.locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigRetryDisabledButSecretsRetryEnabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigRetryDisabledButSecretsRetryEnabled.java new file mode 100644 index 00000000..a19a6e37 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigRetryDisabledButSecretsRetryEnabled.java @@ -0,0 +1,94 @@ +/* + * 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.fabric8.config.locator_retry; + +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +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.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.context.ApplicationContext; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.config.fail-fast=true", "spring.cloud.kubernetes.config.retry.enabled=false", + "spring.cloud.kubernetes.secrets.fail-fast=true", "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +@EnableKubernetesMockClient +class ConfigRetryDisabledButSecretsRetryEnabled { + + private static final String API = "/api/v1/namespaces/default/configmaps/application"; + + private static KubernetesMockServer mockServer; + + private static KubernetesClient mockClient; + + @BeforeAll + static void setup() { + // Configure the kubernetes master url to point to the mock server + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); + System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); + } + + @SpyBean + private Fabric8ConfigMapPropertySourceLocator propertySourceLocator; + + @Autowired + private ApplicationContext context; + + @Test + void locateShouldFailWithoutRetrying() { + + /* + * Enabling secrets retry causes Spring Retry to be enabled and a + * RetryOperationsInterceptor bean with NeverRetryPolicy for config maps to be + * defined. ConfigMapPropertySourceLocator should not retry even Spring Retry is + * enabled. + */ + + mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").once(); + + assertThat(context.containsBean("kubernetesConfigRetryInterceptor")).isTrue(); + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read ConfigMap with name 'application' in namespace 'default'"); + + // verify that propertySourceLocator.locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigRetryEnabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigRetryEnabled.java new file mode 100644 index 00000000..caea6275 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/ConfigRetryEnabled.java @@ -0,0 +1,132 @@ +/* + * 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.fabric8.config.locator_retry; + +import java.util.HashMap; +import java.util.Map; + +import io.fabric8.kubernetes.api.model.ConfigMapBuilder; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigMapPropertySourceLocator; +import org.springframework.core.env.PropertySource; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.config.fail-fast=true", "spring.cloud.kubernetes.config.retry.max-attempts=5", + "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +@EnableKubernetesMockClient +class ConfigRetryEnabled { + + private static final String API = "/api/v1/namespaces/default/configmaps/application"; + + private static KubernetesMockServer mockServer; + + private static KubernetesClient mockClient; + + @BeforeAll + static void setup() { + // Configure the kubernetes master url to point to the mock server + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); + System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); + } + + @SpyBean + private Fabric8ConfigMapPropertySourceLocator propertySourceLocator; + + @Test + void locateShouldNotRetryWhenThereIsNoFailure() { + Map data = new HashMap<>(); + data.put("some.prop", "theValue"); + data.put("some.number", "0"); + + // return config map without failing + mockServer.expect().withPath(API).andReturn(200, + new ConfigMapBuilder().withNewMetadata().withName("application").endMetadata().addToData(data).build()) + .once(); + + PropertySource propertySource = Assertions + .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + + // validate the contents of the property source + assertThat(propertySource.getProperty("some.prop")).isEqualTo("theValue"); + assertThat(propertySource.getProperty("some.number")).isEqualTo("0"); + } + + @Test + void locateShouldRetryAndRecover() { + Map data = new HashMap<>(); + data.put("some.prop", "theValue"); + data.put("some.number", "0"); + + // fail 3 times then succeed at the 4th call + mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").times(3); + mockServer.expect().withPath(API).andReturn(200, + new ConfigMapBuilder().withNewMetadata().withName("application").endMetadata().addToData(data).build()) + .once(); + + PropertySource propertySource = Assertions + .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify retried 4 times + verify(propertySourceLocator, times(4)).locate(any()); + + // validate the contents of the property source + assertThat(propertySource.getProperty("some.prop")).isEqualTo("theValue"); + assertThat(propertySource.getProperty("some.number")).isEqualTo("0"); + } + + @Test + void locateShouldRetryAndFail() { + // fail all the 5 requests + mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").times(5); + + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read ConfigMap with name 'application' in namespace 'default'"); + + // verify retried 5 times until failure + verify(propertySourceLocator, times(5)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsFailFastDisabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsFailFastDisabled.java new file mode 100644 index 00000000..162722f1 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsFailFastDisabled.java @@ -0,0 +1,83 @@ +/* + * 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.fabric8.config.retry; + +import io.fabric8.kubernetes.api.model.SecretListBuilder; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.mock.env.MockEnvironment; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.secrets.name=my-secret", "spring.cloud.kubernetes.secrets.enable-api=true", + "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +@EnableKubernetesMockClient +class SecretsFailFastDisabled { + + private static final String API = "/api/v1/namespaces/default/secrets/my-secret"; + + private static final String LIST_API = "/api/v1/namespaces/default/secrets"; + + private static KubernetesMockServer mockServer; + + private static KubernetesClient mockClient; + + @BeforeAll + static void setup() { + // Configure the kubernetes master url to point to the mock server + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); + System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); + + // return empty secret list to not fail context creation + mockServer.expect().withPath(LIST_API).andReturn(200, new SecretListBuilder().build()).always(); + } + + @SpyBean + private Fabric8SecretsPropertySourceLocator propertySourceLocator; + + @Test + void locateShouldNotRetry() { + mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").once(); + + Assertions.assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsFailFastEnabledButRetryDisabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsFailFastEnabledButRetryDisabled.java new file mode 100644 index 00000000..9f2bf4fa --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsFailFastEnabledButRetryDisabled.java @@ -0,0 +1,94 @@ +/* + * 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.fabric8.config.retry; + +import io.fabric8.kubernetes.api.model.SecretListBuilder; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +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.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.context.ApplicationContext; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.secrets.fail-fast=true", "spring.cloud.kubernetes.secrets.retry.enabled=false", + "spring.cloud.kubernetes.secrets.name=my-secret", "spring.cloud.kubernetes.secrets.enable-api=true", + "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +@EnableKubernetesMockClient +class SecretsFailFastEnabledButRetryDisabled { + + private static final String API = "/api/v1/namespaces/default/secrets/my-secret"; + + private static final String LIST_API = "/api/v1/namespaces/default/secrets"; + + private static KubernetesMockServer mockServer; + + private static KubernetesClient mockClient; + + @BeforeAll + static void setup() { + // Configure the kubernetes master url to point to the mock server + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); + System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); + + // return empty secret list to not fail context creation + mockServer.expect().withPath(LIST_API).andReturn(200, new SecretListBuilder().build()).always(); + } + + @SpyBean + private Fabric8SecretsPropertySourceLocator propertySourceLocator; + + @Autowired + private ApplicationContext context; + + @Test + void locateShouldFailWithoutRetrying() { + + mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").once(); + + assertThat(context.containsBean("kubernetesSecretsRetryInterceptor")).isFalse(); + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); + + // verify that propertySourceLocator.locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsRetryDisabledButConfigRetryEnabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsRetryDisabledButConfigRetryEnabled.java new file mode 100644 index 00000000..75e7492a --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsRetryDisabledButConfigRetryEnabled.java @@ -0,0 +1,101 @@ +/* + * 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.fabric8.config.retry; + +import io.fabric8.kubernetes.api.model.SecretListBuilder; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +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.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.context.ApplicationContext; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, + properties = { "spring.cloud.kubernetes.client.namespace=default", + "spring.cloud.kubernetes.secrets.fail-fast=true", "spring.cloud.kubernetes.secrets.retry.enabled=false", + "spring.cloud.kubernetes.config.fail-fast=true", "spring.cloud.kubernetes.secrets.name=my-secret", + "spring.cloud.kubernetes.secrets.enable-api=true", "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +@EnableKubernetesMockClient +class SecretsRetryDisabledButConfigRetryEnabled { + + private static final String API = "/api/v1/namespaces/default/secrets/my-secret"; + + private static final String LIST_API = "/api/v1/namespaces/default/secrets"; + + private static KubernetesMockServer mockServer; + + private static KubernetesClient mockClient; + + @BeforeAll + static void setup() { + // Configure the kubernetes master url to point to the mock server + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); + System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); + + // return empty secret list to not fail context creation + mockServer.expect().withPath(LIST_API).andReturn(200, new SecretListBuilder().build()).always(); + } + + @SpyBean + private Fabric8SecretsPropertySourceLocator propertySourceLocator; + + @Autowired + private ApplicationContext context; + + @Test + void locateShouldFailWithoutRetrying() { + + /* + * Enabling config retry causes Spring Retry to be enabled and a + * RetryOperationsInterceptor bean with NeverRetryPolicy for secrets to be + * defined. SecretsPropertySourceLocator should not retry even Spring Retry is + * enabled. + */ + + mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").once(); + + assertThat(context.containsBean("kubernetesSecretsRetryInterceptor")).isTrue(); + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); + + // verify that propertySourceLocator.locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsRetryEnabled.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsRetryEnabled.java new file mode 100644 index 00000000..c7a4dff4 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/retry/SecretsRetryEnabled.java @@ -0,0 +1,139 @@ +/* + * 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.fabric8.config.retry; + +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; + +import io.fabric8.kubernetes.api.model.SecretBuilder; +import io.fabric8.kubernetes.api.model.SecretListBuilder; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.cloud.kubernetes.fabric8.config.Application; +import org.springframework.cloud.kubernetes.fabric8.config.Fabric8SecretsPropertySourceLocator; +import org.springframework.core.env.PropertySource; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Isik Erhan + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = { + "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.kubernetes.secrets.fail-fast=true", + "spring.cloud.kubernetes.secrets.retry.max-attempts=5", "spring.cloud.kubernetes.secrets.name=my-secret", + "spring.cloud.kubernetes.secrets.enable-api=true", "spring.main.cloud-platform=KUBERNETES" }, + classes = Application.class) +@EnableKubernetesMockClient +class SecretsRetryEnabled { + + private static final String API = "/api/v1/namespaces/default/secrets/my-secret"; + + private static final String LIST_API = "/api/v1/namespaces/default/secrets"; + + private static KubernetesMockServer mockServer; + + private static KubernetesClient mockClient; + + @BeforeAll + static void setup() { + // Configure the kubernetes master url to point to the mock server + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); + System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); + + // return empty secret list to not fail context creation + mockServer.expect().withPath(LIST_API).andReturn(200, new SecretListBuilder().build()).always(); + } + + @SpyBean + private Fabric8SecretsPropertySourceLocator propertySourceLocator; + + @Test + void locateShouldNotRetryWhenThereIsNoFailure() { + Map data = new HashMap<>(); + data.put("some.sensitive.prop", Base64.getEncoder().encodeToString("theSensitiveValue".getBytes())); + data.put("some.sensitive.number", Base64.getEncoder().encodeToString("1".getBytes())); + + // return secret without failing + mockServer.expect().withPath(API).andReturn(200, + new SecretBuilder().withNewMetadata().withName("my-secret").endMetadata().addToData(data).build()) + .once(); + + PropertySource propertySource = Assertions + .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify locate is called only once + verify(propertySourceLocator, times(1)).locate(any()); + + // validate the contents of the property source + assertThat(propertySource.getProperty("some.sensitive.prop")).isEqualTo("theSensitiveValue"); + assertThat(propertySource.getProperty("some.sensitive.number")).isEqualTo("1"); + } + + @Test + void locateShouldRetryAndRecover() { + Map data = new HashMap<>(); + data.put("some.sensitive.prop", Base64.getEncoder().encodeToString("theSensitiveValue".getBytes())); + data.put("some.sensitive.number", Base64.getEncoder().encodeToString("1".getBytes())); + + // fail 3 times then succeed at the 4th call + mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").times(3); + mockServer.expect().withPath(API).andReturn(200, + new SecretBuilder().withNewMetadata().withName("my-secret").endMetadata().addToData(data).build()) + .once(); + + PropertySource propertySource = Assertions + .assertDoesNotThrow(() -> propertySourceLocator.locate(new MockEnvironment())); + + // verify retried 4 times + verify(propertySourceLocator, times(4)).locate(any()); + + // validate the contents of the property source + assertThat(propertySource.getProperty("some.sensitive.prop")).isEqualTo("theSensitiveValue"); + assertThat(propertySource.getProperty("some.sensitive.number")).isEqualTo("1"); + } + + @Test + void locateShouldRetryAndFail() { + // fail all the 5 requests + mockServer.expect().withPath(API).andReturn(500, "Internal Server Error").times(5); + + assertThatThrownBy(() -> propertySourceLocator.locate(new MockEnvironment())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unable to read Secret with name 'my-secret' or labels [{}] in namespace 'default'"); + + // verify retried 5 times until failure + verify(propertySourceLocator, times(5)).locate(any()); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientNotPresentWhenIstioDisabled.java b/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientNotPresentWhenIstioDisabled.java new file mode 100644 index 00000000..5284f6ed --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientNotPresentWhenIstioDisabled.java @@ -0,0 +1,43 @@ +/* + * 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.fabric8.istio; + +import me.snowdrop.istio.client.IstioClient; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, + properties = { "spring.cloud.istio.enabled=false" }) +class IstioAutoConfigurationClientNotPresentWhenIstioDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void istioClientNotPresent() { + assertThat(context.getBeanNamesForType(IstioClient.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientNotPresentWhenKubernetesDisabled.java b/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientNotPresentWhenKubernetesDisabled.java new file mode 100644 index 00000000..369923d4 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientNotPresentWhenKubernetesDisabled.java @@ -0,0 +1,43 @@ +/* + * 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.fabric8.istio; + +import me.snowdrop.istio.client.IstioClient; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, + properties = { "spring.cloud.kubernetes.enabled=false" }) +class IstioAutoConfigurationClientNotPresentWhenKubernetesDisabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void istioClientNotPresent() { + assertThat(context.getBeanNamesForType(IstioClient.class)).hasSize(0); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientPresentByDefault.java b/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientPresentByDefault.java new file mode 100644 index 00000000..76b6924d --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientPresentByDefault.java @@ -0,0 +1,43 @@ +/* + * 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.fabric8.istio; + +import me.snowdrop.istio.client.IstioClient; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, + properties = "spring.main.cloud-platform=KUBERNETES") +class IstioAutoConfigurationClientPresentByDefault { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void istioClientIsPresent() { + assertThat(context.getBeanNamesForType(IstioClient.class)).hasSize(1); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientPresentWhenIstioEnabled.java b/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientPresentWhenIstioEnabled.java new file mode 100644 index 00000000..2797164f --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationClientPresentWhenIstioEnabled.java @@ -0,0 +1,43 @@ +/* + * 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.fabric8.istio; + +import me.snowdrop.istio.client.IstioClient; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author wind57 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, + properties = { "spring.cloud.istio.enabled=true", "spring.main.cloud-platform=KUBERNETES" }) +class IstioAutoConfigurationClientPresentWhenIstioEnabled { + + @Autowired + private ConfigurableApplicationContext context; + + @Test + void istioClientIsPresent() { + assertThat(context.getBeanNamesForType(IstioClient.class)).hasSize(1); + } + +} diff --git a/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationTests.java b/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationTests.java deleted file mode 100644 index a9799430..00000000 --- a/spring-cloud-kubernetes-fabric8-istio/src/test/java/org/springframework/cloud/kubernetes/fabric8/istio/IstioAutoConfigurationTests.java +++ /dev/null @@ -1,93 +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.fabric8.istio; - -import me.snowdrop.istio.client.IstioClient; -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.context.ConfigurableApplicationContext; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author wind57 - */ -public class IstioAutoConfigurationTests { - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, - properties = "spring.main.cloud-platform=KUBERNETES") - @Nested - class IstioClientPresentByDefault { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void istioClientIsPresent() { - assertThat(context.getBeanNamesForType(IstioClient.class)).hasSize(1); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class) - @Nested - class IstioClientNotPresentWhenKubernetesDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void istioClientNotPresent() { - assertThat(context.getBeanNamesForType(IstioClient.class)).hasSize(0); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, - properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.istio.enabled=true" }) - @Nested - class IstioClientPresentWhenIstioEnabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void istioClientIsPresent() { - assertThat(context.getBeanNamesForType(IstioClient.class)).hasSize(1); - } - - } - - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, - properties = { "spring.cloud.istio.enabled=false" }) - @Nested - class IstioClientNotPresentPresentWhenIstioDisabled { - - @Autowired - ConfigurableApplicationContext context; - - @Test - public void istioClientNotPresent() { - assertThat(context.getBeanNamesForType(IstioClient.class)).hasSize(0); - } - - } - -}