diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/main/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerAutoConfiguration.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/main/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerAutoConfiguration.java index 038fac81..09c1e610 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/main/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerAutoConfiguration.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/main/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerAutoConfiguration.java @@ -67,7 +67,7 @@ public class KubernetesConfigServerAutoConfiguration { public KubernetesPropertySourceSupplier configMapPropertySourceSupplier( KubernetesConfigServerProperties properties) { return (coreApi, applicationName, namespace, springEnv) -> { - List namespaces = namespaceSplitter(properties.getSecretsNamespaces(), namespace); + List namespaces = namespaceSplitter(properties.getConfigMapNamespaces(), namespace); List propertySources = new ArrayList<>(); namespaces.forEach(space -> propertySources.add(new KubernetesClientConfigMapPropertySource(coreApi, applicationName, space, springEnv, "", true, false))); diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/main/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerProperties.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/main/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerProperties.java index bbb88b81..1e753994 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/main/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerProperties.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/main/java/org/springframework/cloud/kubernetes/configserver/KubernetesConfigServerProperties.java @@ -25,16 +25,16 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties("spring.cloud.kubernetes.configserver") public class KubernetesConfigServerProperties { - private String conigMapNamespaces = ""; + private String configMapNamespaces = ""; private String secretsNamespaces = ""; - public String getConigMapNamespaces() { - return conigMapNamespaces; + public String getConfigMapNamespaces() { + return configMapNamespaces; } - public void setConigMapNamespaces(String conigMapNamespaces) { - this.conigMapNamespaces = conigMapNamespaces; + public void setConfigMapNamespaces(String configMapNamespaces) { + this.configMapNamespaces = configMapNamespaces; } public String getSecretsNamespaces() { 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 new file mode 100644 index 00000000..51ded3f2 --- /dev/null +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configserver/src/test/java/org/springframework/cloud/kubernetes/configserver/KubernetesPropertySourceSupplierTests.java @@ -0,0 +1,184 @@ +/* + * Copyright 2013-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.kubernetes.configserver; + +import java.util.Collections; + +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.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.springframework.cloud.config.environment.Environment; + +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; + +/** + * Tests for verifying the behavior of the {@link KubernetesPropertySourceSupplier} beans + * for ConfigMaps and Secrets created by the auto-configuration. + * + * @author Thomas Vitale + */ +class KubernetesPropertySourceSupplierTests { + + private static final CoreV1Api coreApi = mock(CoreV1Api.class); + + private static final V1ConfigMapList CONFIGMAP_DEFAULT_LIST = new V1ConfigMapList() + .addItemsItem(buildConfigMap("gateway", "tdefault")); + + private static final V1ConfigMapList CONFIGMAP_TEAM_A_LIST = new V1ConfigMapList() + .addItemsItem(buildConfigMap("stores", "team-a")); + + 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_TEAM_A_LIST = new V1SecretListBuilder() + .addToItems(buildSecret("stores", "team-a")).build(); + + private static final V1SecretList SECRET_TEAM_B_LIST = new V1SecretListBuilder() + .addToItems(buildSecret("orders", "team-b")).build(); + + @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))).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))).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))).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))).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))).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))).thenReturn(SECRET_TEAM_B_LIST); + } + + @Test + void whenCurrentAndExtraNamespacesAddedThenAllConfigMapsAreIncluded() { + KubernetesConfigServerProperties kubernetesConfigServerProperties = new KubernetesConfigServerProperties(); + kubernetesConfigServerProperties.setConfigMapNamespaces("default,team-a,team-b"); + + KubernetesPropertySourceSupplier kubernetesPropertySourceSupplier = new KubernetesConfigServerAutoConfiguration() + .configMapPropertySourceSupplier(kubernetesConfigServerProperties); + + KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, + Collections.singletonList(kubernetesPropertySourceSupplier), "default"); + + Environment environmentGateway = environmentRepository.findOne("gateway", "", ""); + assertThat(environmentGateway.getPropertySources().size()).isEqualTo(1); + + Environment environmentStores = environmentRepository.findOne("stores", "", ""); + assertThat(environmentStores.getPropertySources().size()).isEqualTo(1); + + Environment environmentOrders = environmentRepository.findOne("orders", "", ""); + assertThat(environmentOrders.getPropertySources().size()).isEqualTo(1); + } + + @Test + void whenExtraNamespacesAddedThenConfigMapsInCurrentNamespaceAreNotIncluded() { + KubernetesConfigServerProperties kubernetesConfigServerProperties = new KubernetesConfigServerProperties(); + kubernetesConfigServerProperties.setConfigMapNamespaces("team-a,team-b"); + + KubernetesPropertySourceSupplier kubernetesPropertySourceSupplier = new KubernetesConfigServerAutoConfiguration() + .configMapPropertySourceSupplier(kubernetesConfigServerProperties); + + KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, + Collections.singletonList(kubernetesPropertySourceSupplier), "default"); + + Environment environmentGateway = environmentRepository.findOne("gateway", "", ""); + assertThat(environmentGateway.getPropertySources().size()).isEqualTo(0); + + Environment environmentStores = environmentRepository.findOne("stores", "", ""); + assertThat(environmentStores.getPropertySources().size()).isEqualTo(1); + + Environment environmentOrders = environmentRepository.findOne("orders", "", ""); + assertThat(environmentOrders.getPropertySources().size()).isEqualTo(1); + } + + @Test + void whenCurrentAndExtraNamespacesAddedThenAllSecretsAreIncluded() { + KubernetesConfigServerProperties kubernetesConfigServerProperties = new KubernetesConfigServerProperties(); + kubernetesConfigServerProperties.setSecretsNamespaces("default,team-a,team-b"); + + KubernetesPropertySourceSupplier kubernetesPropertySourceSupplier = new KubernetesConfigServerAutoConfiguration() + .secretsPropertySourceSupplier(kubernetesConfigServerProperties); + + KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, + Collections.singletonList(kubernetesPropertySourceSupplier), "default"); + + Environment environmentGateway = environmentRepository.findOne("gateway", "", ""); + assertThat(environmentGateway.getPropertySources().size()).isEqualTo(1); + + Environment environmentStores = environmentRepository.findOne("stores", "", ""); + assertThat(environmentStores.getPropertySources().size()).isEqualTo(1); + + Environment environmentOrders = environmentRepository.findOne("orders", "", ""); + assertThat(environmentOrders.getPropertySources().size()).isEqualTo(1); + } + + @Test + void whenExtraNamespacesAddedThenSecretsInCurrentNamespaceAreNotIncluded() { + KubernetesConfigServerProperties kubernetesConfigServerProperties = new KubernetesConfigServerProperties(); + kubernetesConfigServerProperties.setSecretsNamespaces("team-a,team-b"); + + KubernetesPropertySourceSupplier kubernetesPropertySourceSupplier = new KubernetesConfigServerAutoConfiguration() + .secretsPropertySourceSupplier(kubernetesConfigServerProperties); + + KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi, + Collections.singletonList(kubernetesPropertySourceSupplier), "default"); + + Environment environmentGateway = environmentRepository.findOne("gateway", "", ""); + assertThat(environmentGateway.getPropertySources().size()).isEqualTo(0); + + Environment environmentStores = environmentRepository.findOne("stores", "", ""); + assertThat(environmentStores.getPropertySources().size()).isEqualTo(1); + + Environment environmentOrders = environmentRepository.findOne("orders", "", ""); + assertThat(environmentOrders.getPropertySources().size()).isEqualTo(1); + } + + private static V1ConfigMap buildConfigMap(String name, String namespace) { + return new V1ConfigMapBuilder() + .withMetadata(new V1ObjectMetaBuilder().withName(name).withNamespace(namespace).withResourceVersion("1") + .build()) + .addToData("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).withResourceVersion("0").withNamespace(namespace) + .build()) + .addToData("password", "p455w0rd".getBytes()).addToData("username", "user".getBytes()).build(); + } + +}