From 5d6dc34e7551cc999d066ba6263f86a0372b85e6 Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 28 Apr 2025 16:05:56 +0300 Subject: [PATCH 1/6] started Signed-off-by: wind57 --- .../it/ConfigServerIntegration.java | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java index 0ec76fce23..613397dca6 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java @@ -32,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.cloud.config.environment.Environment; +import org.springframework.cloud.config.environment.PropertySource; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; @@ -43,6 +44,16 @@ */ abstract class ConfigServerIntegration { + private static final String TEST_CONFIG_MAP_DEV_YAML = "test-cm-dev.yaml"; + private static final String TEST_CONFIG_MAP_DEV_NAME = "configmap.test-cm.default.dev"; + private static final String TEST_CONFIG_MAP_DEV_DATA = """ + dummy: + property: + profile: dev + value: 1 + enabled: false + """; + @Autowired private TestRestTemplate testRestTemplate; @@ -52,8 +63,8 @@ abstract class ConfigServerIntegration { @BeforeEach void beforeEach() { V1ConfigMapList TEST_CONFIGMAP = new V1ConfigMapList().addItemsItem(new V1ConfigMapBuilder().withMetadata( - new V1ObjectMetaBuilder().withName("test-cm").withNamespace("default").withResourceVersion("1").build()) - .addToData("test-cm-dev.yaml", "dummy:\n property:\n string2: \"dev\"\n int2: 1\n bool2: false\n") + new V1ObjectMetaBuilder().withName("test-cm").withNamespace("default").build()) + .addToData(TEST_CONFIG_MAP_DEV_YAML, TEST_CONFIG_MAP_DEV_DATA) .addToData("test-cm-qa.yaml", "dummy:\n property:\n string2: \"qa\"\n int2: 2\n bool2: true\n") .addToData("test-cm-prod.yaml", "dummy:\n property:\n string2: \"prod\"\n int2: 3\n bool2: true\n") @@ -62,7 +73,7 @@ void beforeEach() { .build()); V1SecretList TEST_SECRET = new V1SecretListBuilder() - .withMetadata(new V1ListMetaBuilder().withResourceVersion("1").build()) + .withMetadata(new V1ListMetaBuilder().build()) .addToItems(new V1SecretBuilder() .withMetadata(new V1ObjectMetaBuilder().withName("test-cm") .withResourceVersion("0") @@ -92,16 +103,20 @@ void enabled() { Environment devprod = testRestTemplate.getForObject("/test-cm/dev,prod", Environment.class); assertThat(devprod.getPropertySources().size()).isEqualTo(4); + assertThat(devprod.getPropertySources().get(0).getName().equals("configmap.test-cm.default.prod")).isTrue(); assertThat(devprod.getPropertySources().get(0).getSource().size()).isEqualTo(3); assertThat(devprod.getPropertySources().get(0).getSource().get("dummy.property.int2")).isEqualTo(3); assertThat(devprod.getPropertySources().get(0).getSource().get("dummy.property.bool2")).isEqualTo(true); assertThat(devprod.getPropertySources().get(0).getSource().get("dummy.property.string2")).isEqualTo("prod"); - assertThat(devprod.getPropertySources().get(1).getName().equals("configmap.test-cm.default.dev")).isTrue(); - assertThat(devprod.getPropertySources().get(1).getSource().size()).isEqualTo(3); - assertThat(devprod.getPropertySources().get(1).getSource().get("dummy.property.int2")).isEqualTo(1); - assertThat(devprod.getPropertySources().get(1).getSource().get("dummy.property.bool2")).isEqualTo(false); - assertThat(devprod.getPropertySources().get(1).getSource().get("dummy.property.string2")).isEqualTo("dev"); + + PropertySource testConfigMapDev = devprod.getPropertySources().get(1); + assertThat(testConfigMapDev.getName().equals(TEST_CONFIG_MAP_DEV_NAME)).isTrue(); + assertThat(testConfigMapDev.getSource().size()).isEqualTo(3); + assertThat(testConfigMapDev.getSource().get("dummy.property.value")).isEqualTo(1); + assertThat(testConfigMapDev.getSource().get("dummy.property.enabled")).isEqualTo(false); + assertThat(testConfigMapDev.getSource().get("dummy.property.profile")).isEqualTo("dev"); + assertThat(devprod.getPropertySources().get(2).getName().equals("configmap.test-cm.default.default")).isTrue(); assertThat(devprod.getPropertySources().get(2).getSource().size()).isEqualTo(4); assertThat(devprod.getPropertySources().get(2).getSource().get("app.name")).isEqualTo("test"); From 42961817f00d8715de241a9d61b26681b4026951 Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 28 Apr 2025 16:24:49 +0300 Subject: [PATCH 2/6] started Signed-off-by: wind57 --- .../it/ConfigServerIntegration.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java index 613397dca6..d9030def1d 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java @@ -34,6 +34,8 @@ import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.environment.PropertySource; +import java.util.Map; + 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.urlMatching; @@ -110,12 +112,7 @@ void enabled() { assertThat(devprod.getPropertySources().get(0).getSource().get("dummy.property.bool2")).isEqualTo(true); assertThat(devprod.getPropertySources().get(0).getSource().get("dummy.property.string2")).isEqualTo("prod"); - PropertySource testConfigMapDev = devprod.getPropertySources().get(1); - assertThat(testConfigMapDev.getName().equals(TEST_CONFIG_MAP_DEV_NAME)).isTrue(); - assertThat(testConfigMapDev.getSource().size()).isEqualTo(3); - assertThat(testConfigMapDev.getSource().get("dummy.property.value")).isEqualTo(1); - assertThat(testConfigMapDev.getSource().get("dummy.property.enabled")).isEqualTo(false); - assertThat(testConfigMapDev.getSource().get("dummy.property.profile")).isEqualTo("dev"); + assertTestConfigMapDev(devprod); assertThat(devprod.getPropertySources().get(2).getName().equals("configmap.test-cm.default.default")).isTrue(); assertThat(devprod.getPropertySources().get(2).getSource().size()).isEqualTo(4); @@ -129,4 +126,14 @@ void enabled() { assertThat(devprod.getPropertySources().get(3).getSource().get("username")).isEqualTo("user"); } + private void assertTestConfigMapDev(Environment devAndProd) { + PropertySource testConfigMapDev = devAndProd.getPropertySources().get(1); + assertThat(testConfigMapDev.getName()).isEqualTo(TEST_CONFIG_MAP_DEV_NAME); + + @SuppressWarnings("unchecked") + Map data = (Map) testConfigMapDev.getSource(); + assertThat(data).containsExactlyInAnyOrderEntriesOf( + Map.of("dummy.property.value", "1", "dummy.property.enabled", "false", "dummy.property.profile", "dev")); + } + } From 09c00d06a6ff7872bc07827cde3738665657f4d4 Mon Sep 17 00:00:00 2001 From: wind57 Date: Mon, 28 Apr 2025 17:10:39 +0300 Subject: [PATCH 3/6] started Signed-off-by: wind57 --- .../it/ConfigServerIntegration.java | 87 ++++++++++++++----- 1 file changed, 63 insertions(+), 24 deletions(-) diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java index d9030def1d..1924fd68ea 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java @@ -49,12 +49,41 @@ abstract class ConfigServerIntegration { private static final String TEST_CONFIG_MAP_DEV_YAML = "test-cm-dev.yaml"; private static final String TEST_CONFIG_MAP_DEV_NAME = "configmap.test-cm.default.dev"; private static final String TEST_CONFIG_MAP_DEV_DATA = """ - dummy: - property: - profile: dev - value: 1 - enabled: false - """; + dummy: + property: + profile: dev + value: 1 + enabled: false + """; + + private static final String TEST_CONFIG_MAP_QA_YAML = "test-cm-qa.yaml"; + private static final String TEST_CONFIG_MAP_QA_DATA = """ + dummy: + property: + profile: qa + value: 2 + enabled: true + """; + + private static final String TEST_CONFIG_MAP_PROD_YAML = "test-cm-prod.yaml"; + private static final String TEST_CONFIG_MAP_PROD_NAME = "configmap.test-cm.default.prod"; + private static final String TEST_CONFIG_MAP_PROD_DATA = """ + dummy: + property: + profile: prod + value: 3 + enabled: true + """; + + private static final String TEST_CONFIG_MAP_YAML = "test-cm.yaml"; + private static final String TEST_CONFIG_MAP_NAME = "configmap.test-cm.default.default"; + private static final String TEST_CONFIG_MAP_DATA = """ + dummy: + property: + profile: default + value: 4 + enabled: true + """; @Autowired private TestRestTemplate testRestTemplate; @@ -67,10 +96,9 @@ void beforeEach() { V1ConfigMapList TEST_CONFIGMAP = new V1ConfigMapList().addItemsItem(new V1ConfigMapBuilder().withMetadata( new V1ObjectMetaBuilder().withName("test-cm").withNamespace("default").build()) .addToData(TEST_CONFIG_MAP_DEV_YAML, TEST_CONFIG_MAP_DEV_DATA) - .addToData("test-cm-qa.yaml", "dummy:\n property:\n string2: \"qa\"\n int2: 2\n bool2: true\n") - .addToData("test-cm-prod.yaml", - "dummy:\n property:\n string2: \"prod\"\n int2: 3\n bool2: true\n") - .addToData("test-cm.yaml", "dummy:\n property:\n string2: \"default\"\n int2: 4\n bool2: true\n") + .addToData(TEST_CONFIG_MAP_QA_YAML, TEST_CONFIG_MAP_QA_DATA) + .addToData(TEST_CONFIG_MAP_PROD_YAML, TEST_CONFIG_MAP_PROD_DATA) + .addToData(TEST_CONFIG_MAP_YAML, TEST_CONFIG_MAP_DATA) .addToData("app.name", "test") .build()); @@ -106,20 +134,11 @@ void enabled() { Environment devprod = testRestTemplate.getForObject("/test-cm/dev,prod", Environment.class); assertThat(devprod.getPropertySources().size()).isEqualTo(4); - assertThat(devprod.getPropertySources().get(0).getName().equals("configmap.test-cm.default.prod")).isTrue(); - assertThat(devprod.getPropertySources().get(0).getSource().size()).isEqualTo(3); - assertThat(devprod.getPropertySources().get(0).getSource().get("dummy.property.int2")).isEqualTo(3); - assertThat(devprod.getPropertySources().get(0).getSource().get("dummy.property.bool2")).isEqualTo(true); - assertThat(devprod.getPropertySources().get(0).getSource().get("dummy.property.string2")).isEqualTo("prod"); - + assertTestConfigMapProd(devprod); assertTestConfigMapDev(devprod); + assertTestConfigMapDefault(devprod); + - assertThat(devprod.getPropertySources().get(2).getName().equals("configmap.test-cm.default.default")).isTrue(); - assertThat(devprod.getPropertySources().get(2).getSource().size()).isEqualTo(4); - assertThat(devprod.getPropertySources().get(2).getSource().get("app.name")).isEqualTo("test"); - assertThat(devprod.getPropertySources().get(2).getSource().get("dummy.property.int2")).isEqualTo(4); - assertThat(devprod.getPropertySources().get(2).getSource().get("dummy.property.bool2")).isEqualTo(true); - assertThat(devprod.getPropertySources().get(2).getSource().get("dummy.property.string2")).isEqualTo("default"); assertThat(devprod.getPropertySources().get(3).getName().equals("secret.test-cm.default.default")).isTrue(); assertThat(devprod.getPropertySources().get(3).getSource().size()).isEqualTo(2); assertThat(devprod.getPropertySources().get(3).getSource().get("password")).isEqualTo("p455w0rd"); @@ -131,9 +150,29 @@ private void assertTestConfigMapDev(Environment devAndProd) { assertThat(testConfigMapDev.getName()).isEqualTo(TEST_CONFIG_MAP_DEV_NAME); @SuppressWarnings("unchecked") - Map data = (Map) testConfigMapDev.getSource(); + Map data = (Map) testConfigMapDev.getSource(); + assertThat(data).containsExactlyInAnyOrderEntriesOf( + Map.of("dummy.property.value", 1, "dummy.property.enabled", false, "dummy.property.profile", "dev")); + } + + private void assertTestConfigMapProd(Environment devAndProd) { + PropertySource testConfigMapDev = devAndProd.getPropertySources().get(0); + assertThat(testConfigMapDev.getName()).isEqualTo(TEST_CONFIG_MAP_PROD_NAME); + + @SuppressWarnings("unchecked") + Map data = (Map) testConfigMapDev.getSource(); + assertThat(data).containsExactlyInAnyOrderEntriesOf( + Map.of("dummy.property.value", 3, "dummy.property.enabled", true, "dummy.property.profile", "prod")); + } + + private void assertTestConfigMapDefault(Environment devAndProd) { + PropertySource testConfigMapDev = devAndProd.getPropertySources().get(2); + assertThat(testConfigMapDev.getName()).isEqualTo(TEST_CONFIG_MAP_NAME); + + @SuppressWarnings("unchecked") + Map data = (Map) testConfigMapDev.getSource(); assertThat(data).containsExactlyInAnyOrderEntriesOf( - Map.of("dummy.property.value", "1", "dummy.property.enabled", "false", "dummy.property.profile", "dev")); + Map.of("dummy.property.value", 4, "dummy.property.enabled", true, "dummy.property.profile", "default")); } } From f1f94df17c1d51641d5f839e072d42e39e9f4c1b Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 30 Apr 2025 13:40:05 +0300 Subject: [PATCH 4/6] cleanup Signed-off-by: wind57 --- .../CompositeKubernetesIntegrationTests.java | 97 +++++++------------ ...onfigDataConfigServerIntegrationTests.java | 9 +- .../it/ConfigServerIntegration.java | 95 ++++++++++++------ 3 files changed, 104 insertions(+), 97 deletions(-) diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/CompositeKubernetesIntegrationTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/CompositeKubernetesIntegrationTests.java index 00c0789330..9f1aea8237 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/CompositeKubernetesIntegrationTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/CompositeKubernetesIntegrationTests.java @@ -16,8 +16,6 @@ package org.springframework.cloud.kubernetes.configserver.it; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import io.kubernetes.client.openapi.ApiException; @@ -31,10 +29,10 @@ import io.kubernetes.client.openapi.models.V1SecretList; import io.kubernetes.client.openapi.models.V1SecretListBuilder; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.SpyBean; @@ -42,15 +40,9 @@ import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.environment.PropertySource; import org.springframework.cloud.config.server.environment.NativeEnvironmentRepository; -import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigContext; -import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySource; import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapsCache; import org.springframework.cloud.kubernetes.commons.config.Constants; -import org.springframework.cloud.kubernetes.commons.config.NamedConfigMapNormalizedSource; -import org.springframework.cloud.kubernetes.commons.config.NormalizedSource; import org.springframework.cloud.kubernetes.configserver.KubernetesConfigServerApplication; -import org.springframework.cloud.kubernetes.configserver.KubernetesPropertySourceSupplier; -import org.springframework.core.env.MapPropertySource; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.test.context.ActiveProfiles; @@ -65,14 +57,12 @@ /** * @author Arjav Dongaonkar */ -public class CompositeKubernetesIntegrationTests { - - private static final List KUBERNETES_PROPERTY_SOURCE_SUPPLIER = new ArrayList<>(); +class CompositeKubernetesIntegrationTests { private static V1ConfigMap buildConfigMap(String name, String namespace) { return new V1ConfigMapBuilder() .withMetadata( - new V1ObjectMetaBuilder().withName(name).withNamespace(namespace).withResourceVersion("1").build()) + new V1ObjectMetaBuilder().withName(name).withNamespace(namespace).build()) .addToData(Constants.APPLICATION_YAML, "dummy:\n property:\n string: \"" + name + "\"\n") .build(); } @@ -80,7 +70,7 @@ private static V1ConfigMap buildConfigMap(String name, String namespace) { private static V1Secret buildSecret(String name, String namespace) { return new V1SecretBuilder() .withMetadata( - new V1ObjectMetaBuilder().withName(name).withResourceVersion("0").withNamespace(namespace).build()) + new V1ObjectMetaBuilder().withName(name).withNamespace(namespace).build()) .addToData("password", "p455w0rd".getBytes()) .addToData("username", "user".getBytes()) .build(); @@ -93,22 +83,8 @@ private static V1Secret buildSecret(String name, String namespace) { .addToItems(buildSecret("gateway", "default")) .build(); - @BeforeAll - public static void before() { - KUBERNETES_PROPERTY_SOURCE_SUPPLIER.add((coreApi, applicationName, namespace, springEnv) -> { - List propertySources = new ArrayList<>(); - - NormalizedSource defaultSource = new NamedConfigMapNormalizedSource(applicationName, "default", false, - true); - KubernetesClientConfigContext defaultContext = new KubernetesClientConfigContext(coreApi, defaultSource, - "default", springEnv); - propertySources.add(new KubernetesClientConfigMapPropertySource(defaultContext)); - return propertySources; - }); - } - @AfterEach - public void after() { + void after() { new KubernetesClientConfigMapsCache().discardAll(); } @@ -129,12 +105,12 @@ class KubernetesCompositeConfigServerTest { private CoreV1Api coreV1Api; @Test - public void contextLoads() throws ApiException { - when(coreV1Api.listNamespacedConfigMap(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null), eq(null))) + void contextLoads() throws ApiException { + when(coreV1Api.listNamespacedConfigMap( + "default", null, null, null, null, null, null, null, null, null, null, null)) .thenReturn(CONFIGMAP_DEFAULT_LIST); - when(coreV1Api.listNamespacedSecret(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null), eq(null))) + when(coreV1Api.listNamespacedSecret( + "default", null, null, null, null, null, null, null, null, null, null, null)) .thenReturn(SECRET_DEFAULT_LIST); ResponseEntity response = new RestTemplate().exchange( @@ -155,7 +131,6 @@ public void contextLoads() throws ApiException { properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.config.server.composite[0].type=kubernetes", "spring.cloud.config.server.composite[1].type=native", - "spring.cloud.config.server.composite[1].location=file:./native-config", "spring.cloud.kubernetes.secrets.enableApi=true" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ActiveProfiles({ "test", "composite", "kubernetes", "native" }) @@ -171,12 +146,12 @@ class KubernetesSecretsEnabledCompositeConfigServerTest { private NativeEnvironmentRepository nativeEnvironmentRepository; @Test - public void contextLoads() throws Exception { - when(coreV1Api.listNamespacedConfigMap(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null), eq(null))) + void contextLoads() throws Exception { + when(coreV1Api.listNamespacedConfigMap( + "default", null, null, null, null, null, null, null, null, null, null, null)) .thenReturn(CONFIGMAP_DEFAULT_LIST); - when(coreV1Api.listNamespacedSecret(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null), eq(null))) + when(coreV1Api.listNamespacedSecret( + "default", null, null, null, null, null, null, null, null, null, null, null)) .thenReturn(SECRET_DEFAULT_LIST); Environment mockNativeEnvironment = new Environment("gateway", "default"); @@ -206,7 +181,6 @@ public void contextLoads() throws Exception { properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.config.server.composite[0].type=kubernetes", "spring.cloud.config.server.composite[1].type=native", - "spring.cloud.config.server.composite[1].location=file:./native-config", "spring.cloud.kubernetes.config.enableApi=false", "spring.cloud.kubernetes.secrets.enableApi=true" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -223,12 +197,12 @@ class KubernetesConfigMapDisabledCompositeConfigServerTest { private NativeEnvironmentRepository nativeEnvironmentRepository; @Test - public void contextLoads() throws Exception { - when(coreV1Api.listNamespacedConfigMap(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null), eq(null))) + void contextLoads() throws Exception { + when(coreV1Api.listNamespacedConfigMap( + "default", null, null, null, null, null, null, null, null, null, null, null)) .thenReturn(CONFIGMAP_DEFAULT_LIST); - when(coreV1Api.listNamespacedSecret(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null), eq(null))) + when(coreV1Api.listNamespacedSecret( + "default", null, null, null, null, null, null, null, null, null, null, null)) .thenReturn(SECRET_DEFAULT_LIST); Environment mockNativeEnvironment = new Environment("gateway", "default"); @@ -256,8 +230,7 @@ public void contextLoads() throws Exception { @SpringBootTest(classes = { KubernetesConfigServerApplication.class }, properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.config.server.composite[0].type=kubernetes", - "spring.cloud.config.server.composite[1].type=native", - "spring.cloud.config.server.composite[1].location=file:./native-config" }, + "spring.cloud.config.server.composite[1].type=native" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ActiveProfiles({ "test", "composite", "kubernetes", "native" }) class KubernetesSecretsDisabledCompositeConfigServerTest { @@ -272,12 +245,12 @@ class KubernetesSecretsDisabledCompositeConfigServerTest { private NativeEnvironmentRepository nativeEnvironmentRepository; @Test - public void contextLoads() throws Exception { - when(coreV1Api.listNamespacedConfigMap(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null), eq(null))) + void contextLoads() throws Exception { + when(coreV1Api.listNamespacedConfigMap( + "default", null, null, null, null, null, null, null, null, null, null, null)) .thenReturn(CONFIGMAP_DEFAULT_LIST); - when(coreV1Api.listNamespacedSecret(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null), eq(null))) + when(coreV1Api.listNamespacedSecret( + "default", null, null, null, null, null, null, null, null, null, null, null)) .thenReturn(SECRET_DEFAULT_LIST); Environment mockNativeEnvironment = new Environment("gateway", "default"); @@ -306,7 +279,6 @@ public void contextLoads() throws Exception { @SpringBootTest(classes = { KubernetesConfigServerApplication.class }, properties = { "spring.config.name:compositeconfigserver", "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=default", - "spring.cloud.config.server.native.search-locations=file:./native-config", "spring.cloud.config.server.native.order=1", "spring.cloud.kubernetes.configserver.order=2", "spring.cloud.kubernetes.secrets.enableApi=true" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -323,12 +295,12 @@ class NativeAndKubernetesConfigServerTest { private NativeEnvironmentRepository nativeEnvironmentRepository; @Test - public void contextLoads() throws Exception { - when(coreV1Api.listNamespacedConfigMap(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null), eq(null))) + void contextLoads() throws Exception { + when(coreV1Api.listNamespacedConfigMap( + "default", null, null, null, null, null, null, null, null, null, null, null)) .thenReturn(CONFIGMAP_DEFAULT_LIST); - when(coreV1Api.listNamespacedSecret(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null), eq(null))) + when(coreV1Api.listNamespacedSecret( + "default", null, null, null, null, null, null, null, null, null, null, null)) .thenReturn(SECRET_DEFAULT_LIST); Environment mockNativeEnvironment = new Environment("gateway", "default"); @@ -340,9 +312,14 @@ public void contextLoads() throws Exception { ResponseEntity response = new RestTemplate().exchange( "http://localhost:" + this.port + "/gateway/default", HttpMethod.GET, null, Environment.class); + Mockito.verify(coreV1Api, Mockito.times(1)).listNamespacedConfigMap( + "default", null, null, null, null, null, null, null, null, null, null, null); + + Mockito.verify(coreV1Api, Mockito.times(1)).listNamespacedSecret( + "default", null, null, null, null, null, null, null, null, null, null, null); + Environment environment = response.getBody(); - assert environment != null; assertThat(3).isEqualTo(environment.getPropertySources().size()); assertThat("nativeProperties").isEqualTo(environment.getPropertySources().get(0).getName()); assertThat(environment.getPropertySources().get(1).getName().contains("configmap.gateway.default.default") diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigDataConfigServerIntegrationTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigDataConfigServerIntegrationTests.java index 5f6e81208b..90a3f295a4 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigDataConfigServerIntegrationTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigDataConfigServerIntegrationTests.java @@ -17,6 +17,7 @@ package org.springframework.cloud.kubernetes.configserver.it; import com.github.tomakehurst.wiremock.client.WireMock; +import io.kubernetes.client.openapi.ApiClient; import io.kubernetes.client.util.ClientBuilder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -43,17 +44,13 @@ class ConfigDataConfigServerIntegrationTests extends ConfigServerIntegration { @BeforeEach void setup() { clientUtilsMock = mockStatic(KubernetesClientUtils.class); - clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient) - .thenReturn(new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build()); + ApiClient client = new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build(); + clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient).thenReturn(client); } @AfterEach void teardown() { clientUtilsMock.close(); - } - - @AfterEach - void afterEach() { WireMock.reset(); } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java index 1924fd68ea..c761283402 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java @@ -26,6 +26,7 @@ import io.kubernetes.client.openapi.models.V1SecretBuilder; import io.kubernetes.client.openapi.models.V1SecretList; import io.kubernetes.client.openapi.models.V1SecretListBuilder; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -46,6 +47,10 @@ */ abstract class ConfigServerIntegration { + private static final String SOURCE_NAME = "test-cm"; + + private static final String NAMESPACE = "default"; + private static final String TEST_CONFIG_MAP_DEV_YAML = "test-cm-dev.yaml"; private static final String TEST_CONFIG_MAP_DEV_NAME = "configmap.test-cm.default.dev"; private static final String TEST_CONFIG_MAP_DEV_DATA = """ @@ -85,6 +90,8 @@ abstract class ConfigServerIntegration { enabled: true """; + private static final String TEST_SECRET_NAME = "secret.test-cm.default.default"; + @Autowired private TestRestTemplate testRestTemplate; @@ -94,7 +101,7 @@ abstract class ConfigServerIntegration { @BeforeEach void beforeEach() { V1ConfigMapList TEST_CONFIGMAP = new V1ConfigMapList().addItemsItem(new V1ConfigMapBuilder().withMetadata( - new V1ObjectMetaBuilder().withName("test-cm").withNamespace("default").build()) + new V1ObjectMetaBuilder().withName(SOURCE_NAME).withNamespace(NAMESPACE).build()) .addToData(TEST_CONFIG_MAP_DEV_YAML, TEST_CONFIG_MAP_DEV_DATA) .addToData(TEST_CONFIG_MAP_QA_YAML, TEST_CONFIG_MAP_QA_DATA) .addToData(TEST_CONFIG_MAP_PROD_YAML, TEST_CONFIG_MAP_PROD_DATA) @@ -105,9 +112,8 @@ void beforeEach() { V1SecretList TEST_SECRET = new V1SecretListBuilder() .withMetadata(new V1ListMetaBuilder().build()) .addToItems(new V1SecretBuilder() - .withMetadata(new V1ObjectMetaBuilder().withName("test-cm") - .withResourceVersion("0") - .withNamespace("default") + .withMetadata(new V1ObjectMetaBuilder().withName(SOURCE_NAME) + .withNamespace(NAMESPACE) .build()) .addToData("password", "p455w0rd".getBytes()) .addToData("username", "user".getBytes()) @@ -121,28 +127,25 @@ void beforeEach() { .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(TEST_SECRET)))); } + @AfterEach + void afterEach() { + WireMock.reset(); + WireMock.shutdownServer(); + } + @Test 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.default")).isTrue(); - assertThat(env.getPropertySources().get(0).getSource().get("app.name")).isEqualTo("test"); - assertThat(env.getPropertySources().get(1).getName().equals("secret.test-cm.default.default")).isTrue(); - assertThat(env.getPropertySources().get(1).getSource().get("password")).isEqualTo("p455w0rd"); - assertThat(env.getPropertySources().get(1).getSource().get("username")).isEqualTo("user"); - - Environment devprod = testRestTemplate.getForObject("/test-cm/dev,prod", Environment.class); - assertThat(devprod.getPropertySources().size()).isEqualTo(4); - - assertTestConfigMapProd(devprod); - assertTestConfigMapDev(devprod); - assertTestConfigMapDefault(devprod); - - - assertThat(devprod.getPropertySources().get(3).getName().equals("secret.test-cm.default.default")).isTrue(); - assertThat(devprod.getPropertySources().get(3).getSource().size()).isEqualTo(2); - assertThat(devprod.getPropertySources().get(3).getSource().get("password")).isEqualTo("p455w0rd"); - assertThat(devprod.getPropertySources().get(3).getSource().get("username")).isEqualTo("user"); + Environment defaultEnv = testRestTemplate.getForObject("/test-cm/default", Environment.class); + assertDefaultProfile(defaultEnv); + + Environment devAndProd = testRestTemplate.getForObject("/test-cm/dev,prod", Environment.class); + assertThat(devAndProd.getPropertySources().size()).isEqualTo(4); + + assertTestConfigMapProd(devAndProd); + assertTestConfigMapDev(devAndProd); + assertTestConfigMapDefault(devAndProd); + assertTestSecretDefault(devAndProd); + } private void assertTestConfigMapDev(Environment devAndProd) { @@ -156,23 +159,53 @@ private void assertTestConfigMapDev(Environment devAndProd) { } private void assertTestConfigMapProd(Environment devAndProd) { - PropertySource testConfigMapDev = devAndProd.getPropertySources().get(0); - assertThat(testConfigMapDev.getName()).isEqualTo(TEST_CONFIG_MAP_PROD_NAME); + PropertySource testConfigMapProd = devAndProd.getPropertySources().get(0); + assertThat(testConfigMapProd.getName()).isEqualTo(TEST_CONFIG_MAP_PROD_NAME); @SuppressWarnings("unchecked") - Map data = (Map) testConfigMapDev.getSource(); + Map data = (Map) testConfigMapProd.getSource(); assertThat(data).containsExactlyInAnyOrderEntriesOf( Map.of("dummy.property.value", 3, "dummy.property.enabled", true, "dummy.property.profile", "prod")); } private void assertTestConfigMapDefault(Environment devAndProd) { - PropertySource testConfigMapDev = devAndProd.getPropertySources().get(2); - assertThat(testConfigMapDev.getName()).isEqualTo(TEST_CONFIG_MAP_NAME); + PropertySource testConfigMap = devAndProd.getPropertySources().get(2); + assertThat(testConfigMap.getName()).isEqualTo(TEST_CONFIG_MAP_NAME); @SuppressWarnings("unchecked") - Map data = (Map) testConfigMapDev.getSource(); + Map data = (Map) testConfigMap.getSource(); + assertThat(data).containsExactlyInAnyOrderEntriesOf( + Map.of("dummy.property.value", 4, "dummy.property.enabled", true, "dummy.property.profile", "default", + "app.name", "test")); + } + + private void assertTestSecretDefault(Environment devAndProd) { + + PropertySource testSecret = devAndProd.getPropertySources().get(3); + assertThat(testSecret.getName()).isEqualTo(TEST_SECRET_NAME); + + @SuppressWarnings("unchecked") + Map data = (Map) testSecret.getSource(); assertThat(data).containsExactlyInAnyOrderEntriesOf( - Map.of("dummy.property.value", 4, "dummy.property.enabled", true, "dummy.property.profile", "default")); + Map.of("password", "p455w0rd", "username", "user")); + } + + private void assertDefaultProfile(Environment defaultEnv) { + assertThat(defaultEnv.getPropertySources().size()).isEqualTo(2); + + PropertySource configMapSource = defaultEnv.getPropertySources().get(0); + assertThat(configMapSource.getName()).isEqualTo(TEST_CONFIG_MAP_NAME); + @SuppressWarnings("unchecked") + Map configmapData = (Map) configMapSource.getSource(); + assertThat(configmapData).containsExactlyInAnyOrderEntriesOf( + Map.of("dummy.property.value", 4, "dummy.property.enabled", true, "dummy.property.profile", "default", + "app.name", "test")); + + PropertySource secretSource = defaultEnv.getPropertySources().get(1); + assertThat(secretSource.getName()).isEqualTo(TEST_SECRET_NAME); + @SuppressWarnings("unchecked") + Map secretData = (Map) secretSource.getSource(); + assertThat(secretData).containsExactlyInAnyOrderEntriesOf(Map.of("password", "p455w0rd", "username", "user")); } } From f619f6023dbd09a3a17e9163d65ae6169f792e0a Mon Sep 17 00:00:00 2001 From: wind57 Date: Wed, 30 Apr 2025 18:42:09 +0300 Subject: [PATCH 5/6] cleanup Signed-off-by: wind57 --- .../it/ConfigServerIntegration.java | 56 ++++++++----------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java index c761283402..878c461c4c 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java @@ -51,43 +51,35 @@ abstract class ConfigServerIntegration { private static final String NAMESPACE = "default"; - private static final String TEST_CONFIG_MAP_DEV_YAML = "test-cm-dev.yaml"; + private static final String TEST_CONFIG_MAP_DEV_PROPERTIES = "test-cm-dev.properties"; private static final String TEST_CONFIG_MAP_DEV_NAME = "configmap.test-cm.default.dev"; private static final String TEST_CONFIG_MAP_DEV_DATA = """ - dummy: - property: - profile: dev - value: 1 - enabled: false + dummy.property.profile=dev + dummy.property.value=1 + dummy.property.enabled=false """; - private static final String TEST_CONFIG_MAP_QA_YAML = "test-cm-qa.yaml"; + private static final String TEST_CONFIG_MAP_QA_PROPERTIES = "test-cm-qa.properties"; private static final String TEST_CONFIG_MAP_QA_DATA = """ - dummy: - property: - profile: qa - value: 2 - enabled: true + dummy.property.profile=qa + dummy.property.value=2 + dummy.property.enabled=true """; - private static final String TEST_CONFIG_MAP_PROD_YAML = "test-cm-prod.yaml"; + private static final String TEST_CONFIG_MAP_PROD_PROPERTIES = "test-cm-prod.properties"; private static final String TEST_CONFIG_MAP_PROD_NAME = "configmap.test-cm.default.prod"; private static final String TEST_CONFIG_MAP_PROD_DATA = """ - dummy: - property: - profile: prod - value: 3 - enabled: true + dummy.property.profile=prod + dummy.property.value=3 + dummy.property.enabled=true """; - private static final String TEST_CONFIG_MAP_YAML = "test-cm.yaml"; + private static final String TEST_CONFIG_MAP_PROPERTIES = "test-cm.properties"; private static final String TEST_CONFIG_MAP_NAME = "configmap.test-cm.default.default"; private static final String TEST_CONFIG_MAP_DATA = """ - dummy: - property: - profile: default - value: 4 - enabled: true + dummy.property.profile=default + dummy.property.value=4 + dummy.property.enabled=true """; private static final String TEST_SECRET_NAME = "secret.test-cm.default.default"; @@ -102,10 +94,10 @@ abstract class ConfigServerIntegration { void beforeEach() { V1ConfigMapList TEST_CONFIGMAP = new V1ConfigMapList().addItemsItem(new V1ConfigMapBuilder().withMetadata( new V1ObjectMetaBuilder().withName(SOURCE_NAME).withNamespace(NAMESPACE).build()) - .addToData(TEST_CONFIG_MAP_DEV_YAML, TEST_CONFIG_MAP_DEV_DATA) - .addToData(TEST_CONFIG_MAP_QA_YAML, TEST_CONFIG_MAP_QA_DATA) - .addToData(TEST_CONFIG_MAP_PROD_YAML, TEST_CONFIG_MAP_PROD_DATA) - .addToData(TEST_CONFIG_MAP_YAML, TEST_CONFIG_MAP_DATA) + .addToData(TEST_CONFIG_MAP_DEV_PROPERTIES, TEST_CONFIG_MAP_DEV_DATA) + .addToData(TEST_CONFIG_MAP_QA_PROPERTIES, TEST_CONFIG_MAP_QA_DATA) + .addToData(TEST_CONFIG_MAP_PROD_PROPERTIES, TEST_CONFIG_MAP_PROD_DATA) + .addToData(TEST_CONFIG_MAP_PROPERTIES, TEST_CONFIG_MAP_DATA) .addToData("app.name", "test") .build()); @@ -155,7 +147,7 @@ private void assertTestConfigMapDev(Environment devAndProd) { @SuppressWarnings("unchecked") Map data = (Map) testConfigMapDev.getSource(); assertThat(data).containsExactlyInAnyOrderEntriesOf( - Map.of("dummy.property.value", 1, "dummy.property.enabled", false, "dummy.property.profile", "dev")); + Map.of("dummy.property.value", "1", "dummy.property.enabled", "false", "dummy.property.profile", "dev")); } private void assertTestConfigMapProd(Environment devAndProd) { @@ -165,7 +157,7 @@ private void assertTestConfigMapProd(Environment devAndProd) { @SuppressWarnings("unchecked") Map data = (Map) testConfigMapProd.getSource(); assertThat(data).containsExactlyInAnyOrderEntriesOf( - Map.of("dummy.property.value", 3, "dummy.property.enabled", true, "dummy.property.profile", "prod")); + Map.of("dummy.property.value", "3", "dummy.property.enabled", "true", "dummy.property.profile", "prod")); } private void assertTestConfigMapDefault(Environment devAndProd) { @@ -175,7 +167,7 @@ private void assertTestConfigMapDefault(Environment devAndProd) { @SuppressWarnings("unchecked") Map data = (Map) testConfigMap.getSource(); assertThat(data).containsExactlyInAnyOrderEntriesOf( - Map.of("dummy.property.value", 4, "dummy.property.enabled", true, "dummy.property.profile", "default", + Map.of("dummy.property.value", "4", "dummy.property.enabled", "true", "dummy.property.profile", "default", "app.name", "test")); } @@ -198,7 +190,7 @@ private void assertDefaultProfile(Environment defaultEnv) { @SuppressWarnings("unchecked") Map configmapData = (Map) configMapSource.getSource(); assertThat(configmapData).containsExactlyInAnyOrderEntriesOf( - Map.of("dummy.property.value", 4, "dummy.property.enabled", true, "dummy.property.profile", "default", + Map.of("dummy.property.value", "4", "dummy.property.enabled", "true", "dummy.property.profile", "default", "app.name", "test")); PropertySource secretSource = defaultEnv.getPropertySources().get(1); From 266b806844dbda20d01276f2b7002f1fcabfa428 Mon Sep 17 00:00:00 2001 From: wind57 Date: Fri, 2 May 2025 10:19:13 +0300 Subject: [PATCH 6/6] fix Signed-off-by: wind57 --- ...oConfigurationKubernetesDisabledTests.java | 3 +- ...gurationKubernetesProfileMissingTests.java | 1 + ...etesEnvironmentRepositoryFactoryTests.java | 28 +--- .../KubernetesEnvironmentRepositoryTests.java | 50 +++--- ...KubernetesPropertySourceSupplierTests.java | 95 ++++++----- .../FirstConfig.java} | 12 +- .../{ => configurations}/MockConfig.java | 4 +- .../configurations/SecondConfig.java | 94 +++++++++++ .../configurations/ThirdConfig.java | 42 +++++ ...BootstrapConfigServerIntegrationTests.java | 2 +- .../CompositeKubernetesIntegrationTests.java | 156 ++++-------------- ...onfigDataConfigServerIntegrationTests.java | 32 +--- .../it/ConfigServerIntegration.java | 82 ++++----- .../test/resources/META-INF/spring.factories | 3 +- 14 files changed, 318 insertions(+), 286 deletions(-) rename spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/{TestBootstrapConfig.java => configurations/FirstConfig.java} (76%) rename spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/{ => configurations}/MockConfig.java (91%) create mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/SecondConfig.java create mode 100644 spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/ThirdConfig.java diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesDisabledTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesDisabledTests.java index 1864cdbd2d..ee0385300c 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesDisabledTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesDisabledTests.java @@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.kubernetes.configserver.configurations.MockConfig; import org.springframework.context.ConfigurableApplicationContext; import static org.assertj.core.api.Assertions.assertThat; @@ -28,7 +29,7 @@ * @author Ryan Baxter */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = { "spring.profiles.include=kubernetes,kubernetesdisabled" }, + properties = { "spring.profiles.include=kubernetes,kubernetesdisabled", "test.first.config.enabled=true" }, classes = { KubernetesConfigServerApplication.class, MockConfig.class }) class ConfigServerAutoConfigurationKubernetesDisabledTests { diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesProfileMissingTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesProfileMissingTests.java index 2d507599da..78d4fefe69 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesProfileMissingTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/ConfigServerAutoConfigurationKubernetesProfileMissingTests.java @@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.kubernetes.configserver.configurations.MockConfig; import org.springframework.context.ConfigurableApplicationContext; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesEnvironmentRepositoryFactoryTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesEnvironmentRepositoryFactoryTests.java index e99b83ad88..5df4686912 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesEnvironmentRepositoryFactoryTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesEnvironmentRepositoryFactoryTests.java @@ -18,21 +18,17 @@ 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.MockBean; import org.springframework.cloud.config.server.environment.EnvironmentRepository; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.cloud.kubernetes.configserver.configurations.ThirdConfig; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -@SpringJUnitConfig -@SpringBootTest +@SpringBootTest(classes = ThirdConfig.class, properties = "test.third.config.enabled=true") class KubernetesEnvironmentRepositoryFactoryTests { - @MockBean + @Autowired private KubernetesEnvironmentRepository mockRepository; @Test @@ -47,20 +43,4 @@ void testBuild() { assertThat(repository).isSameAs(mockRepository); } - @Configuration - static class TestConfig { - - @Bean - public KubernetesEnvironmentRepository kubernetesEnvironmentRepository() { - return mock(KubernetesEnvironmentRepository.class); - } - - @Bean - public KubernetesEnvironmentRepositoryFactory kubernetesEnvironmentRepositoryFactory( - KubernetesEnvironmentRepository kubernetesEnvironmentRepository) { - return new KubernetesEnvironmentRepositoryFactory(kubernetesEnvironmentRepository); - } - - } - } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesEnvironmentRepositoryTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesEnvironmentRepositoryTests.java index 0901176e4c..6fb2ec39b9 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesEnvironmentRepositoryTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesEnvironmentRepositoryTests.java @@ -36,6 +36,7 @@ import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigContext; import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySource; import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapsCache; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsCache; import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsPropertySource; import org.springframework.cloud.kubernetes.commons.config.ConfigUtils; import org.springframework.cloud.kubernetes.commons.config.Constants; @@ -89,39 +90,33 @@ class KubernetesEnvironmentRepositoryTests { private static final V1ConfigMapList CONFIGMAP_DEV_LIST = new V1ConfigMapList() .addItemsItem(new V1ConfigMapBuilder() - .withMetadata( - new V1ObjectMetaBuilder().withName("stores").withNamespace("dev").withResourceVersion("1").build()) + .withMetadata(new V1ObjectMetaBuilder().withName("stores").withNamespace("dev").build()) .addToData(Constants.APPLICATION_YAML, "dummy:\n property:\n string2: \"dev\"\n int2: 1\n bool2: true\n") .build()); private static final V1SecretList SECRET_LIST = new V1SecretListBuilder() - .addToItems( - new V1SecretBuilder() - .withMetadata(new V1ObjectMetaBuilder().withName("application") - .withResourceVersion("0") - .withNamespace("default") - .build()) - .addToData("password", "p455w0rd".getBytes()) - .addToData("username", "user".getBytes()) - .build()) - .addToItems(new V1SecretBuilder().withMetadata( - new V1ObjectMetaBuilder().withName("stores").withResourceVersion("0").withNamespace("default").build()) + .addToItems(new V1SecretBuilder() + .withMetadata(new V1ObjectMetaBuilder().withName("application").withNamespace("default").build()) + .addToData("password", "p455w0rd".getBytes()) + .addToData("username", "user".getBytes()) + .build()) + .addToItems(new V1SecretBuilder() + .withMetadata(new V1ObjectMetaBuilder().withName("stores").withNamespace("default").build()) .addToData("password", "password-from-stores".getBytes()) .addToData("username", "stores".getBytes()) .build()) .addToItems(new V1SecretBuilder() - .withMetadata(new V1ObjectMetaBuilder().withName("stores-dev") - .withResourceVersion("0") - .withNamespace("default") - .build()) + .withMetadata(new V1ObjectMetaBuilder().withName("stores-dev").withNamespace("default").build()) .addToData("password", "password-from-stores-dev".getBytes()) .addToData("username", "stores-dev".getBytes()) .build()) .build(); + private static final KubernetesConfigServerProperties PROPERTIES = properties(); + @BeforeAll - public static void before() { + static void before() { KUBERNETES_PROPERTY_SOURCE_SUPPLIER.add((coreApi, applicationName, namespace, springEnv) -> { List propertySources = new ArrayList<>(); @@ -152,8 +147,9 @@ public static void before() { } @AfterEach - public void after() { + void after() { new KubernetesClientConfigMapsCache().discardAll(); + new KubernetesClientSecretsCache().discardAll(); } @Test @@ -169,7 +165,7 @@ public void testApplicationCase() throws ApiException { eq(null), eq(null), eq(null), eq(null), eq(null))) .thenReturn(CONFIGMAP_DEV_LIST); KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, - KUBERNETES_PROPERTY_SOURCE_SUPPLIER, "default"); + KUBERNETES_PROPERTY_SOURCE_SUPPLIER, "default", PROPERTIES); Environment environment = environmentRepository.findOne("application", "", ""); assertThat(environment.getPropertySources().size()).isEqualTo(2); environment.getPropertySources().forEach(propertySource -> { @@ -245,7 +241,7 @@ public void testStoresCase() throws ApiException { eq(null), eq(null), eq(null), eq(null), eq(null))) .thenReturn(SECRET_LIST); KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, - KUBERNETES_PROPERTY_SOURCE_SUPPLIER, "default"); + KUBERNETES_PROPERTY_SOURCE_SUPPLIER, "default", PROPERTIES); Environment environment = environmentRepository.findOne("stores", "", ""); assertThat(environment.getPropertySources().size()).isEqualTo(4); environment.getPropertySources().forEach(propertySource -> { @@ -292,7 +288,7 @@ public void testStoresProfileCase() throws ApiException { eq(null), eq(null), eq(null), eq(null), eq(null))) .thenReturn(CONFIGMAP_DEV_LIST); KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, - KUBERNETES_PROPERTY_SOURCE_SUPPLIER, "default"); + KUBERNETES_PROPERTY_SOURCE_SUPPLIER, "default", PROPERTIES); Environment environment = environmentRepository.findOne("stores", "dev", ""); assertThat(environment.getPropertySources().size()).isEqualTo(6); environment.getPropertySources().forEach(propertySource -> { @@ -356,7 +352,7 @@ public void testApplicationPropertiesAnSecretsOverride() throws ApiException { eq(null), eq(null), eq(null), eq(null), eq(null))) .thenReturn(CONFIGMAP_DEV_LIST); KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, - KUBERNETES_PROPERTY_SOURCE_SUPPLIER, "default"); + KUBERNETES_PROPERTY_SOURCE_SUPPLIER, "default", PROPERTIES); Environment environment = environmentRepository.findOne("stores-dev", "", ""); environment.getPropertySources() .stream() @@ -404,7 +400,7 @@ public void testSingleConfigMapMultipleSources() throws ApiException { return propertySources; }); KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, suppliers, - "default"); + "default", PROPERTIES); Environment environment = environmentRepository.findOne("storessingle", "", ""); assertThat(environment.getPropertySources().size()).isEqualTo(1); assertThat(environment.getPropertySources().get(0).getName()) @@ -434,4 +430,10 @@ public void testSingleConfigMapMultipleSources() throws ApiException { } + private static KubernetesConfigServerProperties properties() { + KubernetesConfigServerProperties properties = new KubernetesConfigServerProperties(); + properties.setOrder(1); + return properties; + } + } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesPropertySourceSupplierTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesPropertySourceSupplierTests.java index 3b2e7a5e03..a6aaba092c 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesPropertySourceSupplierTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesPropertySourceSupplierTests.java @@ -27,15 +27,18 @@ import io.kubernetes.client.openapi.models.V1Secret; import io.kubernetes.client.openapi.models.V1SecretBuilder; import io.kubernetes.client.openapi.models.V1SecretList; -import io.kubernetes.client.openapi.models.V1SecretListBuilder; +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.Mockito; import org.springframework.cloud.config.environment.Environment; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapsCache; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsCache; import org.springframework.cloud.kubernetes.commons.config.Constants; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -47,7 +50,7 @@ */ class KubernetesPropertySourceSupplierTests { - private static final CoreV1Api coreApi = mock(CoreV1Api.class); + private static final CoreV1Api CORE_V1_API = mock(CoreV1Api.class); private static final V1ConfigMapList CONFIGMAP_DEFAULT_LIST = new V1ConfigMapList() .addItemsItem(buildConfigMap("gateway", "default")); @@ -58,41 +61,51 @@ class KubernetesPropertySourceSupplierTests { private static final V1ConfigMapList CONFIGMAP_TEAM_B_LIST = new V1ConfigMapList() .addItemsItem(buildConfigMap("orders", "team-b")); - private static final V1SecretList SECRET_DEFAULT_LIST = new V1SecretListBuilder() - .addToItems(buildSecret("gateway", "default")) - .build(); + private static final V1SecretList SECRET_DEFAULT_LIST = new V1SecretList() + .addItemsItem(buildSecret("gateway", "default")); - private static final V1SecretList SECRET_TEAM_A_LIST = new V1SecretListBuilder() - .addToItems(buildSecret("stores", "team-a")) - .build(); + private static final V1SecretList SECRET_TEAM_A_LIST = new V1SecretList() + .addItemsItem(buildSecret("stores", "team-a")); - private static final V1SecretList SECRET_TEAM_B_LIST = new V1SecretListBuilder() - .addToItems(buildSecret("orders", "team-b")) - .build(); + private static final V1SecretList SECRET_TEAM_B_LIST = new V1SecretList() + .addItemsItem(buildSecret("orders", "team-b")); + + private static final KubernetesConfigServerProperties PROPERTIES = properties(); @BeforeAll - public static void before() throws ApiException { - when(coreApi.listNamespacedConfigMap(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null))) + static void beforeAll() throws ApiException { + when(CORE_V1_API.listNamespacedConfigMap("default", null, null, null, null, null, null, null, null, null, null, + null)) .thenReturn(CONFIGMAP_DEFAULT_LIST); - when(coreApi.listNamespacedConfigMap(eq("team-a"), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null))) + when(CORE_V1_API.listNamespacedConfigMap("team-a", null, null, null, null, null, null, null, null, null, null, + null)) .thenReturn(CONFIGMAP_TEAM_A_LIST); - when(coreApi.listNamespacedConfigMap(eq("team-b"), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null))) + when(CORE_V1_API.listNamespacedConfigMap("team-b", null, null, null, null, null, null, null, null, null, null, + null)) .thenReturn(CONFIGMAP_TEAM_B_LIST); - when(coreApi.listNamespacedSecret(eq("default"), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null))) + when(CORE_V1_API.listNamespacedSecret("default", null, null, null, null, null, null, null, null, null, null, + null)) .thenReturn(SECRET_DEFAULT_LIST); - when(coreApi.listNamespacedSecret(eq("team-a"), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null))) + when(CORE_V1_API.listNamespacedSecret("team-a", null, null, null, null, null, null, null, null, null, null, + null)) .thenReturn(SECRET_TEAM_A_LIST); - when(coreApi.listNamespacedSecret(eq("team-b"), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null), eq(null), eq(null), eq(null))) + when(CORE_V1_API.listNamespacedSecret("team-b", null, null, null, null, null, null, null, null, null, null, + null)) .thenReturn(SECRET_TEAM_B_LIST); } + @AfterAll + static void afterAll() { + Mockito.reset(CORE_V1_API); + } + + @AfterEach + void afterEach() { + new KubernetesClientConfigMapsCache().discardAll(); + new KubernetesClientSecretsCache().discardAll(); + } + @Test void whenCurrentAndExtraNamespacesAddedThenAllConfigMapsAreIncluded() { KubernetesConfigServerProperties kubernetesConfigServerProperties = new KubernetesConfigServerProperties(); @@ -101,8 +114,8 @@ void whenCurrentAndExtraNamespacesAddedThenAllConfigMapsAreIncluded() { KubernetesPropertySourceSupplier kubernetesPropertySourceSupplier = new KubernetesConfigServerAutoConfiguration() .configMapPropertySourceSupplier(kubernetesConfigServerProperties); - KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, - Collections.singletonList(kubernetesPropertySourceSupplier), "default"); + KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(CORE_V1_API, + Collections.singletonList(kubernetesPropertySourceSupplier), "default", PROPERTIES); Environment environmentGateway = environmentRepository.findOne("gateway", "", ""); assertThat(environmentGateway.getPropertySources().size()).isEqualTo(1); @@ -122,8 +135,8 @@ void whenExtraNamespacesAddedThenConfigMapsInCurrentNamespaceAreNotIncluded() { KubernetesPropertySourceSupplier kubernetesPropertySourceSupplier = new KubernetesConfigServerAutoConfiguration() .configMapPropertySourceSupplier(kubernetesConfigServerProperties); - KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, - Collections.singletonList(kubernetesPropertySourceSupplier), "default"); + KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(CORE_V1_API, + Collections.singletonList(kubernetesPropertySourceSupplier), "default", PROPERTIES); Environment environmentGateway = environmentRepository.findOne("gateway", "", ""); assertThat(environmentGateway.getPropertySources().size()).isEqualTo(0); @@ -143,8 +156,8 @@ void whenCurrentAndExtraNamespacesAddedThenAllSecretsAreIncluded() { KubernetesPropertySourceSupplier kubernetesPropertySourceSupplier = new KubernetesConfigServerAutoConfiguration() .secretsPropertySourceSupplier(kubernetesConfigServerProperties); - KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, - Collections.singletonList(kubernetesPropertySourceSupplier), "default"); + KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(CORE_V1_API, + Collections.singletonList(kubernetesPropertySourceSupplier), "default", PROPERTIES); Environment environmentGateway = environmentRepository.findOne("gateway", "", ""); assertThat(environmentGateway.getPropertySources().size()).isEqualTo(1); @@ -164,8 +177,8 @@ void whenExtraNamespacesAddedThenSecretsInCurrentNamespaceAreNotIncluded() { KubernetesPropertySourceSupplier kubernetesPropertySourceSupplier = new KubernetesConfigServerAutoConfiguration() .secretsPropertySourceSupplier(kubernetesConfigServerProperties); - KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, - Collections.singletonList(kubernetesPropertySourceSupplier), "default"); + KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(CORE_V1_API, + Collections.singletonList(kubernetesPropertySourceSupplier), "default", PROPERTIES); Environment environmentGateway = environmentRepository.findOne("gateway", "", ""); assertThat(environmentGateway.getPropertySources().size()).isEqualTo(0); @@ -179,19 +192,25 @@ void whenExtraNamespacesAddedThenSecretsInCurrentNamespaceAreNotIncluded() { private static V1ConfigMap buildConfigMap(String name, String namespace) { return new V1ConfigMapBuilder() - .withMetadata( - new V1ObjectMetaBuilder().withName(name).withNamespace(namespace).withResourceVersion("1").build()) - .addToData(Constants.APPLICATION_YAML, "dummy:\n property:\n string: \"" + name + "\"\n") + .withMetadata(new V1ObjectMetaBuilder().withName(name).withNamespace(namespace).build()) + .addToData(Constants.APPLICATION_PROPERTIES, """ + dummy.property.string=%s + """.formatted(name)) .build(); } private static V1Secret buildSecret(String name, String namespace) { return new V1SecretBuilder() - .withMetadata( - new V1ObjectMetaBuilder().withName(name).withResourceVersion("0").withNamespace(namespace).build()) + .withMetadata(new V1ObjectMetaBuilder().withName(name).withNamespace(namespace).build()) .addToData("password", "p455w0rd".getBytes()) .addToData("username", "user".getBytes()) .build(); } + private static KubernetesConfigServerProperties properties() { + KubernetesConfigServerProperties properties = new KubernetesConfigServerProperties(); + properties.setOrder(1); + return properties; + } + } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/TestBootstrapConfig.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/FirstConfig.java similarity index 76% rename from spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/TestBootstrapConfig.java rename to spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/FirstConfig.java index b93a81ed50..2c3a3348ea 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/TestBootstrapConfig.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/FirstConfig.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.cloud.kubernetes.configserver; +package org.springframework.cloud.kubernetes.configserver.configurations; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; @@ -22,14 +22,18 @@ import io.kubernetes.client.openapi.apis.CoreV1Api; import io.kubernetes.client.util.ClientBuilder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; /** * @author Ryan Baxter */ -public class TestBootstrapConfig { +@Configuration +@ConditionalOnProperty(value = "test.first.config.enabled", havingValue = "true", matchIfMissing = false) +public class FirstConfig { @Bean WireMockServer wireMockServer() { @@ -41,9 +45,7 @@ WireMockServer wireMockServer() { @Bean ApiClient apiClient(WireMockServer wireMockServer) { - ApiClient apiClient = new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build(); - apiClient.setDebugging(true); - return apiClient; + return new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build(); } @Bean 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/configurations/MockConfig.java similarity index 91% rename from spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/MockConfig.java rename to spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/MockConfig.java index 0fdc064537..379640e23d 100644 --- 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/configurations/MockConfig.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.cloud.kubernetes.configserver; +package org.springframework.cloud.kubernetes.configserver.configurations; import org.springframework.cloud.config.server.environment.EnvironmentRepository; import org.springframework.context.annotation.Bean; @@ -24,7 +24,7 @@ import static org.mockito.Mockito.mock; @Configuration -class MockConfig { +public class MockConfig { @Bean @Profile("kubernetesdisabled") diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/SecondConfig.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/SecondConfig.java new file mode 100644 index 0000000000..e3c97ad767 --- /dev/null +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/SecondConfig.java @@ -0,0 +1,94 @@ +/* + * Copyright 2013-2025 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.configurations; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import io.kubernetes.client.openapi.ApiClient; +import io.kubernetes.client.openapi.JSON; +import io.kubernetes.client.openapi.apis.CoreV1Api; +import io.kubernetes.client.openapi.models.V1ConfigMap; +import io.kubernetes.client.openapi.models.V1ConfigMapBuilder; +import io.kubernetes.client.openapi.models.V1ConfigMapList; +import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder; +import io.kubernetes.client.openapi.models.V1Secret; +import io.kubernetes.client.openapi.models.V1SecretBuilder; +import io.kubernetes.client.openapi.models.V1SecretList; +import io.kubernetes.client.util.ClientBuilder; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.kubernetes.commons.config.Constants; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +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.urlMatching; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; + +/** + * @author wind57 + */ +@Configuration +@ConditionalOnProperty(value = "test.second.config.enabled", havingValue = "true", matchIfMissing = false) +public class SecondConfig { + + private static V1ConfigMap buildConfigMap() { + return new V1ConfigMapBuilder() + .withMetadata(new V1ObjectMetaBuilder().withName("gateway").withNamespace("default").build()) + .addToData(Constants.APPLICATION_PROPERTIES, "dummy.property.string=gateway") + .build(); + } + + private static V1Secret buildSecret() { + return new V1SecretBuilder() + .withMetadata(new V1ObjectMetaBuilder().withName("gateway").withNamespace("default").build()) + .addToData("password", "p455w0rd".getBytes()) + .addToData("username", "user".getBytes()) + .build(); + } + + private static final V1ConfigMapList CONFIGMAP_DEFAULT_LIST = new V1ConfigMapList().addItemsItem(buildConfigMap()); + + private static final V1SecretList SECRET_DEFAULT_LIST = new V1SecretList().addItemsItem(buildSecret()); + + @Bean + WireMockServer wireMockServer() { + WireMockServer wireMockServer = new WireMockServer(options().dynamicPort()); + wireMockServer.start(); + WireMock.configureFor(wireMockServer.port()); + + WireMock.stubFor(get(urlMatching("^/api/v1/namespaces/default/configmaps.*")) + .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(CONFIGMAP_DEFAULT_LIST)))); + + WireMock.stubFor(get(urlMatching("^/api/v1/namespaces/default/secrets.*")) + .willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(SECRET_DEFAULT_LIST)))); + + return wireMockServer; + } + + @Bean + ApiClient apiClient(WireMockServer wireMockServer) { + return new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build(); + } + + @Bean + CoreV1Api coreApi(ApiClient apiClient) { + return new CoreV1Api(apiClient); + } + +} diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/ThirdConfig.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/ThirdConfig.java new file mode 100644 index 0000000000..a422aaadef --- /dev/null +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/configurations/ThirdConfig.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013-2025 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.configurations; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.kubernetes.configserver.KubernetesEnvironmentRepository; +import org.springframework.cloud.kubernetes.configserver.KubernetesEnvironmentRepositoryFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.mockito.Mockito.mock; + +@Configuration +@ConditionalOnProperty(value = "test.third.config.enabled", havingValue = "true", matchIfMissing = false) +public class ThirdConfig { + + @Bean + public KubernetesEnvironmentRepository kubernetesEnvironmentRepository() { + return mock(KubernetesEnvironmentRepository.class); + } + + @Bean + public KubernetesEnvironmentRepositoryFactory kubernetesEnvironmentRepositoryFactory( + KubernetesEnvironmentRepository kubernetesEnvironmentRepository) { + return new KubernetesEnvironmentRepositoryFactory(kubernetesEnvironmentRepository); + } + +} diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/BootstrapConfigServerIntegrationTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/BootstrapConfigServerIntegrationTests.java index 67a2250ff7..951061a69b 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/BootstrapConfigServerIntegrationTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/BootstrapConfigServerIntegrationTests.java @@ -25,7 +25,7 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=default", "spring.profiles.include=kubernetes", "spring.cloud.kubernetes.secrets.enableApi=true", - "spring.cloud.bootstrap.enabled=true" }, + "spring.cloud.bootstrap.enabled=true", "test.first.config.enabled=true" }, classes = { KubernetesConfigServerApplication.class }) class BootstrapConfigServerIntegrationTests extends ConfigServerIntegration { diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/CompositeKubernetesIntegrationTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/CompositeKubernetesIntegrationTests.java index 9f1aea8237..fd1d270b51 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/CompositeKubernetesIntegrationTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/CompositeKubernetesIntegrationTests.java @@ -18,30 +18,17 @@ import java.util.Map; -import io.kubernetes.client.openapi.ApiException; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.models.V1ConfigMap; -import io.kubernetes.client.openapi.models.V1ConfigMapBuilder; -import io.kubernetes.client.openapi.models.V1ConfigMapList; -import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder; -import io.kubernetes.client.openapi.models.V1Secret; -import io.kubernetes.client.openapi.models.V1SecretBuilder; -import io.kubernetes.client.openapi.models.V1SecretList; -import io.kubernetes.client.openapi.models.V1SecretListBuilder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.environment.PropertySource; import org.springframework.cloud.config.server.environment.NativeEnvironmentRepository; import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapsCache; -import org.springframework.cloud.kubernetes.commons.config.Constants; import org.springframework.cloud.kubernetes.configserver.KubernetesConfigServerApplication; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; @@ -59,30 +46,6 @@ */ class CompositeKubernetesIntegrationTests { - private static V1ConfigMap buildConfigMap(String name, String namespace) { - return new V1ConfigMapBuilder() - .withMetadata( - new V1ObjectMetaBuilder().withName(name).withNamespace(namespace).build()) - .addToData(Constants.APPLICATION_YAML, "dummy:\n property:\n string: \"" + name + "\"\n") - .build(); - } - - private static V1Secret buildSecret(String name, String namespace) { - return new V1SecretBuilder() - .withMetadata( - new V1ObjectMetaBuilder().withName(name).withNamespace(namespace).build()) - .addToData("password", "p455w0rd".getBytes()) - .addToData("username", "user".getBytes()) - .build(); - } - - private static final V1ConfigMapList CONFIGMAP_DEFAULT_LIST = new V1ConfigMapList() - .addItemsItem(buildConfigMap("gateway", "default")); - - private static final V1SecretList SECRET_DEFAULT_LIST = new V1SecretListBuilder() - .addToItems(buildSecret("gateway", "default")) - .build(); - @AfterEach void after() { new KubernetesClientConfigMapsCache().discardAll(); @@ -91,9 +54,8 @@ void after() { @Nested @SpringBootTest(classes = { KubernetesConfigServerApplication.class }, properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=default", - "spring.config.name=compositeconfigserver", "spring.cloud.config.server.composite[0].type=kubernetes", - "spring.cloud.kubernetes.secrets.enableApi=true" }, + "spring.cloud.kubernetes.secrets.enableApi=true", "test.second.config.enabled=true" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ActiveProfiles({ "test", "composite", "kubernetes" }) class KubernetesCompositeConfigServerTest { @@ -101,27 +63,18 @@ class KubernetesCompositeConfigServerTest { @LocalServerPort private int port; - @MockBean - private CoreV1Api coreV1Api; - @Test - void contextLoads() throws ApiException { - when(coreV1Api.listNamespacedConfigMap( - "default", null, null, null, null, null, null, null, null, null, null, null)) - .thenReturn(CONFIGMAP_DEFAULT_LIST); - when(coreV1Api.listNamespacedSecret( - "default", null, null, null, null, null, null, null, null, null, null, null)) - .thenReturn(SECRET_DEFAULT_LIST); + void contextLoads() { ResponseEntity response = new RestTemplate().exchange( "http://localhost:" + this.port + "/gateway/default", HttpMethod.GET, null, Environment.class); Environment environment = response.getBody(); assertThat(environment).isNotNull(); - assertThat(environment.getPropertySources()).hasSize(4); + assertThat(environment.getPropertySources().size()).isEqualTo(4); assertThat(environment.getPropertySources().get(0).getName()) .isEqualTo("configmap.gateway.default.default"); - assertThat(environment.getPropertySources().get(1).getName()).contains("secret.gateway.default.default"); + assertThat(environment.getPropertySources().get(1).getName()).isEqualTo("secret.gateway.default.default"); } } @@ -131,28 +84,19 @@ void contextLoads() throws ApiException { properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.config.server.composite[0].type=kubernetes", "spring.cloud.config.server.composite[1].type=native", - "spring.cloud.kubernetes.secrets.enableApi=true" }, + "spring.cloud.kubernetes.secrets.enableApi=true", + "spring.profiles.active=test, composite, kubernetes, native", "test.second.config.enabled=true" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) - @ActiveProfiles({ "test", "composite", "kubernetes", "native" }) class KubernetesSecretsEnabledCompositeConfigServerTest { @LocalServerPort private int port; - @MockBean - private CoreV1Api coreV1Api; - @SpyBean private NativeEnvironmentRepository nativeEnvironmentRepository; @Test - void contextLoads() throws Exception { - when(coreV1Api.listNamespacedConfigMap( - "default", null, null, null, null, null, null, null, null, null, null, null)) - .thenReturn(CONFIGMAP_DEFAULT_LIST); - when(coreV1Api.listNamespacedSecret( - "default", null, null, null, null, null, null, null, null, null, null, null)) - .thenReturn(SECRET_DEFAULT_LIST); + void contextLoads() { Environment mockNativeEnvironment = new Environment("gateway", "default"); mockNativeEnvironment.add(new PropertySource("nativeProperties", Map.of("key1", "value1"))); @@ -165,13 +109,12 @@ void contextLoads() throws Exception { Environment environment = response.getBody(); assertThat(environment).isNotNull(); - assertThat(environment.getPropertySources()).hasSizeGreaterThanOrEqualTo(5); + assertThat(environment.getPropertySources().size()).isEqualTo(5); assertThat(environment.getPropertySources().get(0).getName()) .isEqualTo("configmap.gateway.default.default"); assertThat(environment.getPropertySources().get(1).getName()).contains("secret.gateway.default.default"); - assertThat(environment.getPropertySources()).anyMatch(ps -> ps.getName().contains("native")); } } @@ -181,29 +124,19 @@ void contextLoads() throws Exception { properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.config.server.composite[0].type=kubernetes", "spring.cloud.config.server.composite[1].type=native", - "spring.cloud.kubernetes.config.enableApi=false", - "spring.cloud.kubernetes.secrets.enableApi=true" }, + "spring.cloud.kubernetes.config.enableApi=false", "spring.cloud.kubernetes.secrets.enableApi=true", + "spring.profiles.active=test ,composite, kubernetes, native", "test.second.config.enabled=true" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) - @ActiveProfiles({ "test", "composite", "kubernetes", "native" }) class KubernetesConfigMapDisabledCompositeConfigServerTest { @LocalServerPort private int port; - @MockBean - private CoreV1Api coreV1Api; - @SpyBean private NativeEnvironmentRepository nativeEnvironmentRepository; @Test - void contextLoads() throws Exception { - when(coreV1Api.listNamespacedConfigMap( - "default", null, null, null, null, null, null, null, null, null, null, null)) - .thenReturn(CONFIGMAP_DEFAULT_LIST); - when(coreV1Api.listNamespacedSecret( - "default", null, null, null, null, null, null, null, null, null, null, null)) - .thenReturn(SECRET_DEFAULT_LIST); + void contextLoads() { Environment mockNativeEnvironment = new Environment("gateway", "default"); mockNativeEnvironment.add(new PropertySource("nativeProperties", Map.of("key1", "value1"))); @@ -216,12 +149,11 @@ void contextLoads() throws Exception { Environment environment = response.getBody(); assertThat(environment).isNotNull(); - assertThat(environment.getPropertySources()).hasSizeGreaterThanOrEqualTo(3); + assertThat(environment.getPropertySources().size()).isEqualTo(3); assertThat(environment.getPropertySources().get(0).getName()).isEqualTo("secret.gateway.default.default"); - assertThat(environment.getPropertySources().get(1).getName()).contains("nativeProperties"); + assertThat(environment.getPropertySources().get(1).getName()).isEqualTo("nativeProperties"); - assertThat(environment.getPropertySources()).anyMatch(ps -> ps.getName().contains("native")); } } @@ -230,28 +162,19 @@ void contextLoads() throws Exception { @SpringBootTest(classes = { KubernetesConfigServerApplication.class }, properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.config.server.composite[0].type=kubernetes", - "spring.cloud.config.server.composite[1].type=native" }, + "spring.cloud.config.server.composite[1].type=native", + "spring.profiles.active=test, composite, kubernetes, native", "test.second.config.enabled=true" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) - @ActiveProfiles({ "test", "composite", "kubernetes", "native" }) class KubernetesSecretsDisabledCompositeConfigServerTest { @LocalServerPort private int port; - @MockBean - private CoreV1Api coreV1Api; - @SpyBean private NativeEnvironmentRepository nativeEnvironmentRepository; @Test - void contextLoads() throws Exception { - when(coreV1Api.listNamespacedConfigMap( - "default", null, null, null, null, null, null, null, null, null, null, null)) - .thenReturn(CONFIGMAP_DEFAULT_LIST); - when(coreV1Api.listNamespacedSecret( - "default", null, null, null, null, null, null, null, null, null, null, null)) - .thenReturn(SECRET_DEFAULT_LIST); + void contextLoads() { Environment mockNativeEnvironment = new Environment("gateway", "default"); mockNativeEnvironment.add(new PropertySource("nativeProperties", Map.of("key1", "value1"))); @@ -264,68 +187,51 @@ void contextLoads() throws Exception { Environment environment = response.getBody(); assertThat(environment).isNotNull(); - assertThat(environment.getPropertySources()).hasSizeGreaterThanOrEqualTo(3); + assertThat(environment.getPropertySources().size()).isEqualTo(3); assertThat(environment.getPropertySources().get(0).getName()) .isEqualTo("configmap.gateway.default.default"); - assertThat(environment.getPropertySources().get(1).getName()).contains("nativeProperties"); + assertThat(environment.getPropertySources().get(1).getName()).isEqualTo("nativeProperties"); - assertThat(environment.getPropertySources()).anyMatch(ps -> ps.getName().contains("native")); } } @Nested @SpringBootTest(classes = { KubernetesConfigServerApplication.class }, - properties = { "spring.config.name:compositeconfigserver", "spring.main.cloud-platform=KUBERNETES", - "spring.cloud.kubernetes.client.namespace=default", + properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=default", "spring.cloud.config.server.native.order=1", "spring.cloud.kubernetes.configserver.order=2", - "spring.cloud.kubernetes.secrets.enableApi=true" }, + "spring.cloud.kubernetes.secrets.enableApi=true", "test.second.config.enabled=true", + "spring.profiles.active=test, native, kubernetes" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) - @ActiveProfiles({ "test", "native", "kubernetes" }) class NativeAndKubernetesConfigServerTest { @LocalServerPort private int port; - @MockBean - private CoreV1Api coreV1Api; - @SpyBean private NativeEnvironmentRepository nativeEnvironmentRepository; @Test - void contextLoads() throws Exception { - when(coreV1Api.listNamespacedConfigMap( - "default", null, null, null, null, null, null, null, null, null, null, null)) - .thenReturn(CONFIGMAP_DEFAULT_LIST); - when(coreV1Api.listNamespacedSecret( - "default", null, null, null, null, null, null, null, null, null, null, null)) - .thenReturn(SECRET_DEFAULT_LIST); + void contextLoads() { - Environment mockNativeEnvironment = new Environment("gateway", "default"); - mockNativeEnvironment.add(new PropertySource("nativeProperties", Map.of("key1", "value1"))); + Environment nativeEnvironment = new Environment("gateway", "default"); + nativeEnvironment.add(new PropertySource("nativeProperties", Map.of("key1", "value1"))); when(nativeEnvironmentRepository.findOne(anyString(), anyString(), eq(null), anyBoolean())) - .thenReturn(mockNativeEnvironment); + .thenReturn(nativeEnvironment); ResponseEntity response = new RestTemplate().exchange( "http://localhost:" + this.port + "/gateway/default", HttpMethod.GET, null, Environment.class); - Mockito.verify(coreV1Api, Mockito.times(1)).listNamespacedConfigMap( - "default", null, null, null, null, null, null, null, null, null, null, null); - - Mockito.verify(coreV1Api, Mockito.times(1)).listNamespacedSecret( - "default", null, null, null, null, null, null, null, null, null, null, null); - Environment environment = response.getBody(); - assertThat(3).isEqualTo(environment.getPropertySources().size()); - assertThat("nativeProperties").isEqualTo(environment.getPropertySources().get(0).getName()); - assertThat(environment.getPropertySources().get(1).getName().contains("configmap.gateway.default.default") - && !environment.getPropertySources().get(1).getName().contains("nativeProperties")) - .isTrue(); - assertThat(environment.getPropertySources().get(2).getName()).contains("secret.gateway.default.default"); + assertThat(environment.getPropertySources().size()).isEqualTo(3); + assertThat(environment.getPropertySources().get(0).getName()).isEqualTo("nativeProperties"); + assertThat(environment.getPropertySources().get(1).getName()) + .isEqualTo("configmap.gateway.default.default"); + assertThat(environment.getPropertySources().get(2).getName()).isEqualTo("secret.gateway.default.default"); + } } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigDataConfigServerIntegrationTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigDataConfigServerIntegrationTests.java index 90a3f295a4..1547dd463a 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigDataConfigServerIntegrationTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigDataConfigServerIntegrationTests.java @@ -16,42 +16,18 @@ package org.springframework.cloud.kubernetes.configserver.it; -import com.github.tomakehurst.wiremock.client.WireMock; -import io.kubernetes.client.openapi.ApiClient; -import io.kubernetes.client.util.ClientBuilder; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.mockito.MockedStatic; - import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.kubernetes.client.KubernetesClientUtils; import org.springframework.cloud.kubernetes.configserver.KubernetesConfigServerApplication; -import org.springframework.cloud.kubernetes.configserver.TestBootstrapConfig; - -import static org.mockito.Mockito.mockStatic; +import org.springframework.cloud.kubernetes.configserver.configurations.FirstConfig; /** * @author Ryan Baxter */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.client.namespace=default", - "spring.profiles.include=kubernetes", "spring.cloud.kubernetes.secrets.enableApi=true" }, - classes = { KubernetesConfigServerApplication.class, TestBootstrapConfig.class }) + "spring.profiles.include=kubernetes", "spring.cloud.kubernetes.secrets.enableApi=true", + "test.first.config.enabled=true" }, + classes = { KubernetesConfigServerApplication.class, FirstConfig.class }) class ConfigDataConfigServerIntegrationTests extends ConfigServerIntegration { - private MockedStatic clientUtilsMock; - - @BeforeEach - void setup() { - clientUtilsMock = mockStatic(KubernetesClientUtils.class); - ApiClient client = new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build(); - clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient).thenReturn(client); - } - - @AfterEach - void teardown() { - clientUtilsMock.close(); - WireMock.reset(); - } - } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java index 878c461c4c..eea41166af 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/it/ConfigServerIntegration.java @@ -16,6 +16,8 @@ package org.springframework.cloud.kubernetes.configserver.it; +import java.util.Map; + import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; import io.kubernetes.client.openapi.JSON; @@ -34,8 +36,8 @@ import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.environment.PropertySource; - -import java.util.Map; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapsCache; +import org.springframework.cloud.kubernetes.client.config.KubernetesClientSecretsCache; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; @@ -52,35 +54,42 @@ abstract class ConfigServerIntegration { private static final String NAMESPACE = "default"; private static final String TEST_CONFIG_MAP_DEV_PROPERTIES = "test-cm-dev.properties"; + private static final String TEST_CONFIG_MAP_DEV_NAME = "configmap.test-cm.default.dev"; + private static final String TEST_CONFIG_MAP_DEV_DATA = """ - dummy.property.profile=dev - dummy.property.value=1 - dummy.property.enabled=false - """; + dummy.property.profile=dev + dummy.property.value=1 + dummy.property.enabled=false + """; private static final String TEST_CONFIG_MAP_QA_PROPERTIES = "test-cm-qa.properties"; + private static final String TEST_CONFIG_MAP_QA_DATA = """ - dummy.property.profile=qa - dummy.property.value=2 - dummy.property.enabled=true - """; + dummy.property.profile=qa + dummy.property.value=2 + dummy.property.enabled=true + """; private static final String TEST_CONFIG_MAP_PROD_PROPERTIES = "test-cm-prod.properties"; + private static final String TEST_CONFIG_MAP_PROD_NAME = "configmap.test-cm.default.prod"; + private static final String TEST_CONFIG_MAP_PROD_DATA = """ - dummy.property.profile=prod - dummy.property.value=3 - dummy.property.enabled=true - """; + dummy.property.profile=prod + dummy.property.value=3 + dummy.property.enabled=true + """; private static final String TEST_CONFIG_MAP_PROPERTIES = "test-cm.properties"; + private static final String TEST_CONFIG_MAP_NAME = "configmap.test-cm.default.default"; + private static final String TEST_CONFIG_MAP_DATA = """ - dummy.property.profile=default - dummy.property.value=4 - dummy.property.enabled=true - """; + dummy.property.profile=default + dummy.property.value=4 + dummy.property.enabled=true + """; private static final String TEST_SECRET_NAME = "secret.test-cm.default.default"; @@ -92,8 +101,8 @@ abstract class ConfigServerIntegration { @BeforeEach void beforeEach() { - V1ConfigMapList TEST_CONFIGMAP = new V1ConfigMapList().addItemsItem(new V1ConfigMapBuilder().withMetadata( - new V1ObjectMetaBuilder().withName(SOURCE_NAME).withNamespace(NAMESPACE).build()) + V1ConfigMapList TEST_CONFIGMAP = new V1ConfigMapList().addItemsItem(new V1ConfigMapBuilder() + .withMetadata(new V1ObjectMetaBuilder().withName(SOURCE_NAME).withNamespace(NAMESPACE).build()) .addToData(TEST_CONFIG_MAP_DEV_PROPERTIES, TEST_CONFIG_MAP_DEV_DATA) .addToData(TEST_CONFIG_MAP_QA_PROPERTIES, TEST_CONFIG_MAP_QA_DATA) .addToData(TEST_CONFIG_MAP_PROD_PROPERTIES, TEST_CONFIG_MAP_PROD_DATA) @@ -101,12 +110,9 @@ void beforeEach() { .addToData("app.name", "test") .build()); - V1SecretList TEST_SECRET = new V1SecretListBuilder() - .withMetadata(new V1ListMetaBuilder().build()) + V1SecretList TEST_SECRET = new V1SecretListBuilder().withMetadata(new V1ListMetaBuilder().build()) .addToItems(new V1SecretBuilder() - .withMetadata(new V1ObjectMetaBuilder().withName(SOURCE_NAME) - .withNamespace(NAMESPACE) - .build()) + .withMetadata(new V1ObjectMetaBuilder().withName(SOURCE_NAME).withNamespace(NAMESPACE).build()) .addToData("password", "p455w0rd".getBytes()) .addToData("username", "user".getBytes()) .build()) @@ -123,6 +129,11 @@ void beforeEach() { void afterEach() { WireMock.reset(); WireMock.shutdownServer(); + wireMockServer.stop(); + wireMockServer.shutdownServer(); + + new KubernetesClientConfigMapsCache().discardAll(); + new KubernetesClientSecretsCache().discardAll(); } @Test @@ -146,8 +157,8 @@ private void assertTestConfigMapDev(Environment devAndProd) { @SuppressWarnings("unchecked") Map data = (Map) testConfigMapDev.getSource(); - assertThat(data).containsExactlyInAnyOrderEntriesOf( - Map.of("dummy.property.value", "1", "dummy.property.enabled", "false", "dummy.property.profile", "dev")); + assertThat(data).containsExactlyInAnyOrderEntriesOf(Map.of("dummy.property.value", "1", + "dummy.property.enabled", "false", "dummy.property.profile", "dev")); } private void assertTestConfigMapProd(Environment devAndProd) { @@ -156,8 +167,8 @@ private void assertTestConfigMapProd(Environment devAndProd) { @SuppressWarnings("unchecked") Map data = (Map) testConfigMapProd.getSource(); - assertThat(data).containsExactlyInAnyOrderEntriesOf( - Map.of("dummy.property.value", "3", "dummy.property.enabled", "true", "dummy.property.profile", "prod")); + assertThat(data).containsExactlyInAnyOrderEntriesOf(Map.of("dummy.property.value", "3", + "dummy.property.enabled", "true", "dummy.property.profile", "prod")); } private void assertTestConfigMapDefault(Environment devAndProd) { @@ -166,9 +177,8 @@ private void assertTestConfigMapDefault(Environment devAndProd) { @SuppressWarnings("unchecked") Map data = (Map) testConfigMap.getSource(); - assertThat(data).containsExactlyInAnyOrderEntriesOf( - Map.of("dummy.property.value", "4", "dummy.property.enabled", "true", "dummy.property.profile", "default", - "app.name", "test")); + assertThat(data).containsExactlyInAnyOrderEntriesOf(Map.of("dummy.property.value", "4", + "dummy.property.enabled", "true", "dummy.property.profile", "default", "app.name", "test")); } private void assertTestSecretDefault(Environment devAndProd) { @@ -178,8 +188,7 @@ private void assertTestSecretDefault(Environment devAndProd) { @SuppressWarnings("unchecked") Map data = (Map) testSecret.getSource(); - assertThat(data).containsExactlyInAnyOrderEntriesOf( - Map.of("password", "p455w0rd", "username", "user")); + assertThat(data).containsExactlyInAnyOrderEntriesOf(Map.of("password", "p455w0rd", "username", "user")); } private void assertDefaultProfile(Environment defaultEnv) { @@ -189,9 +198,8 @@ private void assertDefaultProfile(Environment defaultEnv) { assertThat(configMapSource.getName()).isEqualTo(TEST_CONFIG_MAP_NAME); @SuppressWarnings("unchecked") Map configmapData = (Map) configMapSource.getSource(); - assertThat(configmapData).containsExactlyInAnyOrderEntriesOf( - Map.of("dummy.property.value", "4", "dummy.property.enabled", "true", "dummy.property.profile", "default", - "app.name", "test")); + assertThat(configmapData).containsExactlyInAnyOrderEntriesOf(Map.of("dummy.property.value", "4", + "dummy.property.enabled", "true", "dummy.property.profile", "default", "app.name", "test")); PropertySource secretSource = defaultEnv.getPropertySources().get(1); assertThat(secretSource.getName()).isEqualTo(TEST_SECRET_NAME); diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/resources/META-INF/spring.factories b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/resources/META-INF/spring.factories index b3e57fd872..615b13bb14 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/resources/META-INF/spring.factories +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/resources/META-INF/spring.factories @@ -1,2 +1,3 @@ org.springframework.cloud.bootstrap.BootstrapConfiguration=\ -org.springframework.cloud.kubernetes.configserver.TestBootstrapConfig +org.springframework.cloud.kubernetes.configserver.configurations.FirstConfig,\ +org.springframework.cloud.kubernetes.configserver.configurations.SecondConfig