Merge branch '3.2.x'

This commit is contained in:
Ryan Baxter
2025-02-23 07:57:05 -06:00
12 changed files with 710 additions and 6 deletions

View File

@@ -23,12 +23,13 @@ import io.kubernetes.client.openapi.apis.CoreV1Api;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.config.server.config.ConfigServerAutoConfiguration;
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
import org.springframework.cloud.kubernetes.client.KubernetesClientAutoConfiguration;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigContext;
import org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigMapPropertySource;
@@ -59,11 +60,21 @@ public class KubernetesConfigServerAutoConfiguration {
@Bean
@Profile("kubernetes")
public EnvironmentRepository kubernetesEnvironmentRepository(CoreV1Api coreV1Api,
@ConditionalOnMissingBean
public KubernetesEnvironmentRepository kubernetesEnvironmentRepository(CoreV1Api coreV1Api,
List<KubernetesPropertySourceSupplier> kubernetesPropertySourceSuppliers,
KubernetesNamespaceProvider kubernetesNamespaceProvider) {
KubernetesNamespaceProvider kubernetesNamespaceProvider,
KubernetesConfigServerProperties kubernetesConfigServerProperties) {
return new KubernetesEnvironmentRepository(coreV1Api, kubernetesPropertySourceSuppliers,
kubernetesNamespaceProvider.getNamespace());
kubernetesNamespaceProvider.getNamespace(), kubernetesConfigServerProperties);
}
@Bean
@ConditionalOnBean(KubernetesEnvironmentRepository.class)
@ConditionalOnMissingBean
public KubernetesEnvironmentRepositoryFactory kubernetesEnvironmentRepositoryFactory(
KubernetesEnvironmentRepository kubernetesEnvironmentRepository) {
return new KubernetesEnvironmentRepositoryFactory(kubernetesEnvironmentRepository);
}
@Bean

View File

@@ -17,13 +17,16 @@
package org.springframework.cloud.kubernetes.configserver;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties;
/**
* @author Ryan Baxter
*/
@ConfigurationProperties("spring.cloud.kubernetes.configserver")
public class KubernetesConfigServerProperties {
public class KubernetesConfigServerProperties implements EnvironmentRepositoryProperties {
private int order = DEFAULT_ORDER;
private String configMapNamespaces = "";
@@ -45,4 +48,12 @@ public class KubernetesConfigServerProperties {
this.secretsNamespaces = secretsNamespaces;
}
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
}

View File

@@ -28,6 +28,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.config.environment.Environment;
import org.springframework.cloud.config.environment.PropertySource;
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
import org.springframework.core.Ordered;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.StandardEnvironment;
@@ -36,7 +37,7 @@ import org.springframework.util.StringUtils;
/**
* @author Ryan Baxter
*/
public class KubernetesEnvironmentRepository implements EnvironmentRepository {
public class KubernetesEnvironmentRepository implements EnvironmentRepository, Ordered {
private static final Log LOG = LogFactory.getLog(KubernetesEnvironmentRepository.class);
@@ -46,6 +47,9 @@ public class KubernetesEnvironmentRepository implements EnvironmentRepository {
private final String namespace;
private int order = KubernetesConfigServerProperties.DEFAULT_ORDER;
@Deprecated
public KubernetesEnvironmentRepository(CoreV1Api coreApi,
List<KubernetesPropertySourceSupplier> kubernetesPropertySourceSuppliers, String namespace) {
this.coreApi = coreApi;
@@ -53,6 +57,15 @@ public class KubernetesEnvironmentRepository implements EnvironmentRepository {
this.namespace = namespace;
}
public KubernetesEnvironmentRepository(CoreV1Api coreApi,
List<KubernetesPropertySourceSupplier> kubernetesPropertySourceSuppliers, String namespace,
KubernetesConfigServerProperties properties) {
this.coreApi = coreApi;
this.kubernetesPropertySourceSuppliers = kubernetesPropertySourceSuppliers;
this.namespace = namespace;
this.order = properties.getOrder();
}
@Override
public Environment findOne(String application, String profile, String label) {
return findOne(application, profile, label, true);
@@ -118,4 +131,13 @@ public class KubernetesEnvironmentRepository implements EnvironmentRepository {
});
}
@Override
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2013-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.configserver;
import org.springframework.cloud.config.server.environment.EnvironmentRepositoryFactory;
/**
* Factory class for creating instances of {@link KubernetesEnvironmentRepository}.
*
* @author Arjav Dongaonkar
*/
public class KubernetesEnvironmentRepositoryFactory
implements EnvironmentRepositoryFactory<KubernetesEnvironmentRepository, KubernetesConfigServerProperties> {
private final KubernetesEnvironmentRepository kubernetesEnvironmentRepository;
public KubernetesEnvironmentRepositoryFactory(KubernetesEnvironmentRepository kubernetesEnvironmentRepository) {
this.kubernetesEnvironmentRepository = kubernetesEnvironmentRepository;
}
@Override
public KubernetesEnvironmentRepository build(KubernetesConfigServerProperties environmentProperties) {
return kubernetesEnvironmentRepository;
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2013-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.configserver;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.config.server.environment.JGitEnvironmentRepository;
import org.springframework.context.ConfigurableApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Arjav Dongaonkar
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { KubernetesConfigServerApplication.class },
properties = { "spring.main.cloud-platform=KUBERNETES", "spring.profiles.include=kubernetes",
"spring.cloud.kubernetes.client.namespace=default", "spring.profiles.active=composite",
"spring.cloud.config.server.composite[0].type=git",
"spring.cloud.config.server.composite[0].uri=https://github.com/spring-cloud-samples/config-repo",
"spring.cloud.config.server.composite[1].type=kubernetes",
"spring.cloud.config.server.composite[1].config-map-namespace=default",
"spring.cloud.config.server.composite[1].secrets-namespace=default" })
class CompositeProfileWithGitAndKubernetesConfigSourcesTests {
@Autowired
private ConfigurableApplicationContext context;
@Test
void runTest() {
assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(2);
assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepositoryFactory.class)).hasSize(1);
assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).isNotEmpty();
assertThat(context.getBeanNamesForType(JGitEnvironmentRepository.class)).hasSize(1);
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2013-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.configserver;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ConfigurableApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Arjav Dongaonkar
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { KubernetesConfigServerApplication.class },
properties = { "spring.main.cloud-platform=KUBERNETES", "spring.profiles.include=kubernetes",
"spring.cloud.kubernetes.client.namespace=default", "spring.profiles.active=composite",
"spring.cloud.config.server.composite[0].type=kubernetes",
"spring.cloud.config.server.composite[0].config-map-namespace=default",
"spring.cloud.config.server.composite[0].secrets-namespace=default",
"spring.cloud.config.server.composite[1].type=kubernetes",
"spring.cloud.config.server.composite[1].config-map-namespace=another-namespace",
"spring.cloud.config.server.composite[1].secrets-namespace=another-namespace" })
class CompositeProfileWithMultipleKubernetesConfigSourcesTests {
@Autowired
private ConfigurableApplicationContext context;
@Test
void runTest() {
assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(3);
assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepositoryFactory.class)).hasSize(1);
assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).isNotEmpty();
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2013-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.configserver;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ConfigurableApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Arjav Dongaonkar
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { KubernetesConfigServerApplication.class },
properties = { "spring.main.cloud-platform=KUBERNETES", "spring.profiles.include=kubernetes",
"spring.cloud.kubernetes.client.namespace=default", "spring.profiles.active=composite",
"spring.cloud.config.server.composite[0].type=kubernetes",
"spring.cloud.config.server.composite[0].config-map-namespace=default",
"spring.cloud.config.server.composite[0].secrets-namespace=default" })
class CompositeProfileWithOnlyKubernetesConfigSourceTests {
@Autowired
private ConfigurableApplicationContext context;
@Test
void runTest() {
assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(2);
assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepositoryFactory.class)).hasSize(1);
assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).isNotEmpty();
}
}

View File

@@ -38,6 +38,7 @@ class ConfigServerAutoConfigurationKubernetesDisabledTests {
@Test
void runTest() {
assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(0);
assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepositoryFactory.class)).hasSize(0);
}
}

View File

@@ -40,6 +40,7 @@ class ConfigServerAutoConfigurationKubernetesEnabledProfileIncludedConfigApiDisa
void runTest() {
assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepository.class)).hasSize(1);
assertThat(context.getBeanNamesForType(KubernetesPropertySourceSupplier.class)).hasSize(0);
assertThat(context.getBeanNamesForType(KubernetesEnvironmentRepositoryFactory.class)).hasSize(1);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2013-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.configserver;
import org.junit.jupiter.api.Test;
import org.springframework.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 static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@SpringJUnitConfig
@SpringBootTest
class KubernetesEnvironmentRepositoryFactoryTests {
@MockBean
private KubernetesEnvironmentRepository mockRepository;
@Test
void testBuild() {
KubernetesEnvironmentRepositoryFactory factory = new KubernetesEnvironmentRepositoryFactory(mockRepository);
KubernetesConfigServerProperties properties = new KubernetesConfigServerProperties();
EnvironmentRepository repository = factory.build(properties);
assertThat(repository).isNotNull();
assertThat(repository).isInstanceOf(KubernetesEnvironmentRepository.class);
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);
}
}
}

View File

@@ -190,6 +190,48 @@ class KubernetesEnvironmentRepositoryTests {
});
}
@Test
public void testApplicationCaseWithNewConstructor() throws ApiException {
CoreV1Api coreApi = mock(CoreV1Api.class);
KubernetesConfigServerProperties properties = mock(KubernetesConfigServerProperties.class);
when(properties.getOrder()).thenReturn(0);
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)))
.thenReturn(CONFIGMAP_DEFAULT_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)))
.thenReturn(SECRET_LIST);
when(coreApi.listNamespacedConfigMap(eq("dev"), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null),
eq(null), eq(null), eq(null), eq(null), eq(null)))
.thenReturn(CONFIGMAP_DEV_LIST);
KubernetesEnvironmentRepository environmentRepository = new KubernetesEnvironmentRepository(coreApi,
KUBERNETES_PROPERTY_SOURCE_SUPPLIER, "default", properties);
Environment environment = environmentRepository.findOne("application", "", "");
assertThat(environment.getPropertySources().size()).isEqualTo(2);
environment.getPropertySources().forEach(propertySource -> {
assertThat(propertySource.getName().equals("configmap.application.default")
|| propertySource.getName().equals("secret.application.default"))
.isTrue();
if (propertySource.getName().equals("configmap.application.default")) {
assertThat(propertySource.getSource().size()).isEqualTo(3);
assertThat(propertySource.getSource().get("dummy.property.int2")).isEqualTo(1);
assertThat(propertySource.getSource().get("dummy.property.bool2")).isEqualTo(true);
assertThat(propertySource.getSource().get("dummy.property.string2")).isEqualTo("a");
}
if (propertySource.getName().equals("secrets.application.default")) {
assertThat(propertySource.getSource().size()).isEqualTo(2);
assertThat(propertySource.getSource().get("username")).isEqualTo("user");
assertThat(propertySource.getSource().get("password")).isEqualTo("p455w0rd");
}
});
assertThat(environmentRepository.getOrder()).isEqualTo(0);
}
@Test
public void testStoresCase() throws ApiException {
CoreV1Api coreApi = mock(CoreV1Api.class);

View File

@@ -0,0 +1,356 @@
/*
* Copyright 2013-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.kubernetes.configserver.it;
import java.util.ArrayList;
import java.util.List;
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.BeforeAll;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
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.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;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
* @author Arjav Dongaonkar
*/
public class CompositeKubernetesIntegrationTests {
private static final List<KubernetesPropertySourceSupplier> KUBERNETES_PROPERTY_SOURCE_SUPPLIER = new ArrayList<>();
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")
.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();
}
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();
@BeforeAll
public static void before() {
KUBERNETES_PROPERTY_SOURCE_SUPPLIER.add((coreApi, applicationName, namespace, springEnv) -> {
List<MapPropertySource> 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() {
new KubernetesClientConfigMapsCache().discardAll();
}
@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" },
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles({ "test", "composite", "kubernetes" })
class KubernetesCompositeConfigServerTest {
@LocalServerPort
private int port;
@MockBean
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)))
.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)))
.thenReturn(SECRET_DEFAULT_LIST);
ResponseEntity<Environment> 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().get(0).getName())
.isEqualTo("configmap.gateway.default.default");
assertThat(environment.getPropertySources().get(1).getName()).contains("secret.gateway.default.default");
}
}
@Nested
@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.kubernetes.secrets.enableApi=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
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)))
.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)))
.thenReturn(SECRET_DEFAULT_LIST);
Environment mockNativeEnvironment = new Environment("gateway", "default");
mockNativeEnvironment.add(new PropertySource("nativeProperties", Map.of("key1", "value1")));
when(nativeEnvironmentRepository.findOne(anyString(), anyString(), eq(null), anyBoolean()))
.thenReturn(mockNativeEnvironment);
ResponseEntity<Environment> 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()).hasSizeGreaterThanOrEqualTo(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"));
}
}
@Nested
@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.kubernetes.config.enableApi=false",
"spring.cloud.kubernetes.secrets.enableApi=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
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)))
.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)))
.thenReturn(SECRET_DEFAULT_LIST);
Environment mockNativeEnvironment = new Environment("gateway", "default");
mockNativeEnvironment.add(new PropertySource("nativeProperties", Map.of("key1", "value1")));
when(nativeEnvironmentRepository.findOne(anyString(), anyString(), eq(null), anyBoolean()))
.thenReturn(mockNativeEnvironment);
ResponseEntity<Environment> 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()).hasSizeGreaterThanOrEqualTo(3);
assertThat(environment.getPropertySources().get(0).getName()).isEqualTo("secret.gateway.default.default");
assertThat(environment.getPropertySources().get(1).getName()).contains("nativeProperties");
assertThat(environment.getPropertySources()).anyMatch(ps -> ps.getName().contains("native"));
}
}
@Nested
@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" },
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
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)))
.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)))
.thenReturn(SECRET_DEFAULT_LIST);
Environment mockNativeEnvironment = new Environment("gateway", "default");
mockNativeEnvironment.add(new PropertySource("nativeProperties", Map.of("key1", "value1")));
when(nativeEnvironmentRepository.findOne(anyString(), anyString(), eq(null), anyBoolean()))
.thenReturn(mockNativeEnvironment);
ResponseEntity<Environment> 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()).hasSizeGreaterThanOrEqualTo(3);
assertThat(environment.getPropertySources().get(0).getName())
.isEqualTo("configmap.gateway.default.default");
assertThat(environment.getPropertySources().get(1).getName()).contains("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",
"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)
@ActiveProfiles({ "test", "native", "kubernetes" })
class NativeAndKubernetesConfigServerTest {
@LocalServerPort
private int port;
@MockBean
private CoreV1Api coreV1Api;
@SpyBean
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)))
.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)))
.thenReturn(SECRET_DEFAULT_LIST);
Environment mockNativeEnvironment = new Environment("gateway", "default");
mockNativeEnvironment.add(new PropertySource("nativeProperties", Map.of("key1", "value1")));
when(nativeEnvironmentRepository.findOne(anyString(), anyString(), eq(null), anyBoolean()))
.thenReturn(mockNativeEnvironment);
ResponseEntity<Environment> response = new RestTemplate().exchange(
"http://localhost:" + this.port + "/gateway/default", HttpMethod.GET, null, Environment.class);
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")
&& !environment.getPropertySources().get(1).getName().contains("nativeProperties"))
.isTrue();
assertThat(environment.getPropertySources().get(2).getName()).contains("secret.gateway.default.default");
}
}
}