From 03ed0f22426eb645fd396cd739e273d4178990d9 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Wed, 20 Mar 2019 17:07:47 +0200 Subject: [PATCH] Fix profile specific configuration not loaded (#351) Fixes: #347 --- .../config/ConfigMapPropertySource.java | 3 +- .../ConfigMapPropertySourceLocator.java | 6 +- ...bernetesApplicationContextInitializer.java | 65 ----------------- ...netesProfileEnvironmentPostProcessor.java} | 44 +++++------- .../main/resources/META-INF/spring.factories | 5 +- ...ernetesProfileApplicationListenerTest.java | 70 ------------------- .../kubernetes/it/SimpleCoreApplication.java | 6 +- .../main/resources/application-kubernetes.yml | 2 + .../src/main/resources/application.yml | 3 + .../kubernetes/it/GreetingAndHealthIT.java | 2 +- 10 files changed, 35 insertions(+), 171 deletions(-) delete mode 100644 spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesApplicationContextInitializer.java rename spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/{KubernetesProfileApplicationListener.java => KubernetesProfileEnvironmentPostProcessor.java} (65%) delete mode 100644 spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileApplicationListenerTest.java create mode 100644 spring-cloud-kubernetes-integration-tests/simple-core/src/main/resources/application-kubernetes.yml diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySource.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySource.java index 3dd546ea..639ed80d 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySource.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySource.java @@ -62,7 +62,8 @@ public class ConfigMapPropertySource extends MapPropertySource { this(client, name, null, createEnvironmentWithActiveProfiles(profiles)); } - private static Environment createEnvironmentWithActiveProfiles(String[] activeProfiles) { + private static Environment createEnvironmentWithActiveProfiles( + String[] activeProfiles) { StandardEnvironment environment = new StandardEnvironment(); environment.setActiveProfiles(activeProfiles); return environment; diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySourceLocator.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySourceLocator.java index dd241c66..d31c3fa1 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySourceLocator.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySourceLocator.java @@ -120,9 +120,9 @@ public class ConfigMapPropertySourceLocator implements PropertySourceLocator { content, filename, composite); } else if (filename.endsWith(".yml") || filename.endsWith(".yaml")) { - addPropertySourceIfNeeded(c -> PROPERTIES_TO_MAP - .apply(yamlParserGenerator(environment) - .apply(c)), + addPropertySourceIfNeeded( + c -> PROPERTIES_TO_MAP + .apply(yamlParserGenerator(environment).apply(c)), content, filename, composite); } } diff --git a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesApplicationContextInitializer.java b/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesApplicationContextInitializer.java deleted file mode 100644 index ca448c4b..00000000 --- a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesApplicationContextInitializer.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2013-2019 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 - * - * http://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.profile; - -import java.util.function.Supplier; - -import io.fabric8.kubernetes.client.DefaultKubernetesClient; - -import org.springframework.cloud.kubernetes.LazilyInstantiate; -import org.springframework.cloud.kubernetes.StandardPodUtils; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.Ordered; - -/** - * Kubernetes specific application context initializer. - * - * @author Ioannis Canellos - */ -public class KubernetesApplicationContextInitializer implements - ApplicationContextInitializer, Ordered { - - private static final int ORDER = 100; - - private final Supplier listenerSupplier; - - public KubernetesApplicationContextInitializer() { - this(LazilyInstantiate.using(() -> - // If we are inside Kubernetes this should be perfectly valid. - // If not then we won't add the Kubernetes profile anyway. - new KubernetesProfileApplicationListener( - new StandardPodUtils(new DefaultKubernetesClient())))); - } - - public KubernetesApplicationContextInitializer( - Supplier listenerSupplier) { - this.listenerSupplier = listenerSupplier; - } - - @Override - public int getOrder() { - return ORDER; - } - - @Override - public void initialize(ConfigurableApplicationContext applicationContext) { - this.listenerSupplier.get() - .addKubernetesProfile(applicationContext.getEnvironment()); - } - -} diff --git a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileApplicationListener.java b/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileEnvironmentPostProcessor.java similarity index 65% rename from spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileApplicationListener.java rename to spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileEnvironmentPostProcessor.java index d0336867..d5635036 100644 --- a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileApplicationListener.java +++ b/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileEnvironmentPostProcessor.java @@ -16,47 +16,35 @@ package org.springframework.cloud.kubernetes.profile; +import io.fabric8.kubernetes.client.DefaultKubernetesClient; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; -import org.springframework.cloud.kubernetes.PodUtils; -import org.springframework.context.ApplicationListener; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.context.config.ConfigFileApplicationListener; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.cloud.kubernetes.StandardPodUtils; import org.springframework.core.Ordered; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; -/** - * Adds Kubernetes profiles. - * - * @author Ioannis Canellos - */ -public class KubernetesProfileApplicationListener - implements ApplicationListener, Ordered { +public class KubernetesProfileEnvironmentPostProcessor + implements EnvironmentPostProcessor, Ordered { private static final Log LOG = LogFactory - .getLog(KubernetesProfileApplicationListener.class); + .getLog(KubernetesProfileEnvironmentPostProcessor.class); + + // Before ConfigFileApplicationListener so values there can use these ones + private static final int ORDER = ConfigFileApplicationListener.DEFAULT_ORDER - 1; private static final String KUBERNETES_PROFILE = "kubernetes"; - private static final int OFFSET = 1; - - private static final int ORDER = Ordered.HIGHEST_PRECEDENCE + OFFSET; - - private final PodUtils utils; - - public KubernetesProfileApplicationListener(PodUtils utils) { - this.utils = utils; - } - @Override - public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { - ConfigurableEnvironment environment = event.getEnvironment(); - addKubernetesProfile(environment); - } - - void addKubernetesProfile(ConfigurableEnvironment environment) { - if (this.utils.isInsideKubernetes()) { + public void postProcessEnvironment(ConfigurableEnvironment environment, + SpringApplication application) { + final StandardPodUtils podUtils = new StandardPodUtils( + new DefaultKubernetesClient()); + if (podUtils.isInsideKubernetes()) { if (hasKubernetesProfile(environment)) { if (LOG.isDebugEnabled()) { LOG.debug("'kubernetes' already in list of active profiles"); diff --git a/spring-cloud-kubernetes-core/src/main/resources/META-INF/spring.factories b/spring-cloud-kubernetes-core/src/main/resources/META-INF/spring.factories index 226fa4b0..9d0f344c 100644 --- a/spring-cloud-kubernetes-core/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-kubernetes-core/src/main/resources/META-INF/spring.factories @@ -1,5 +1,6 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.kubernetes.KubernetesAutoConfiguration\ -org.springframework.context.ApplicationContextInitializer=\ -org.springframework.cloud.kubernetes.profile.KubernetesApplicationContextInitializer + +org.springframework.boot.env.EnvironmentPostProcessor=\ +org.springframework.cloud.kubernetes.profile.KubernetesProfileEnvironmentPostProcessor diff --git a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileApplicationListenerTest.java b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileApplicationListenerTest.java deleted file mode 100644 index 1ae77b07..00000000 --- a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileApplicationListenerTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2013-2019 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 - * - * http://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.profile; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; -import org.springframework.cloud.kubernetes.PodUtils; -import org.springframework.core.env.ConfigurableEnvironment; - -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class KubernetesProfileApplicationListenerTest { - - private static final String[] ACTIVE_PROFILES = new String[0]; - - @Mock - private ConfigurableEnvironment mockEnvironment; - - @Mock - private PodUtils mockPodUtils; - - @Mock - private ApplicationEnvironmentPreparedEvent mockEvent; - - private KubernetesProfileApplicationListener listener; - - @Before - public void before() { - when(this.mockEnvironment.getActiveProfiles()).thenReturn(ACTIVE_PROFILES); - when(this.mockEvent.getEnvironment()).thenReturn(this.mockEnvironment); - this.listener = new KubernetesProfileApplicationListener(this.mockPodUtils); - } - - @Test - public void shouldEnableKubernetesProfile() { - when(this.mockPodUtils.isInsideKubernetes()).thenReturn(true); - this.listener.onApplicationEvent(this.mockEvent); - verify(this.mockEnvironment).addActiveProfile("kubernetes"); - } - - @Test - public void shouldNotEnableKubernetesProfile() { - when(this.mockPodUtils.isInsideKubernetes()).thenReturn(false); - this.listener.onApplicationEvent(this.mockEvent); - verify(this.mockEnvironment, times(0)).addActiveProfile("kubernetes"); - } - -} diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/main/java/org/springframework/cloud/kubernetes/it/SimpleCoreApplication.java b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/java/org/springframework/cloud/kubernetes/it/SimpleCoreApplication.java index 442cc453..d002fb6f 100644 --- a/spring-cloud-kubernetes-integration-tests/simple-core/src/main/java/org/springframework/cloud/kubernetes/it/SimpleCoreApplication.java +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/java/org/springframework/cloud/kubernetes/it/SimpleCoreApplication.java @@ -16,6 +16,7 @@ package org.springframework.cloud.kubernetes.it; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; @@ -29,9 +30,12 @@ public class SimpleCoreApplication { SpringApplication.run(SimpleCoreApplication.class, args); } + @Value("${greeting.message}") + private String message; + @GetMapping("/greeting") public Greeting home() { - return new Greeting("Hello Spring Boot"); + return new Greeting(message); } public static class Greeting { diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/main/resources/application-kubernetes.yml b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/resources/application-kubernetes.yml new file mode 100644 index 00000000..341afeb5 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/resources/application-kubernetes.yml @@ -0,0 +1,2 @@ +greeting: + message: Hello from k8s diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/main/resources/application.yml b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/resources/application.yml index 86f053fc..f2c43382 100644 --- a/spring-cloud-kubernetes-integration-tests/simple-core/src/main/resources/application.yml +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/main/resources/application.yml @@ -1,6 +1,9 @@ server: port: 8080 +greeting: + message: Hello sb + # we enable some of the management endpoints to make it possible to restart the application management: endpoint: diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/test/java/org/springframework/cloud/kubernetes/it/GreetingAndHealthIT.java b/spring-cloud-kubernetes-integration-tests/simple-core/src/test/java/org/springframework/cloud/kubernetes/it/GreetingAndHealthIT.java index 0fcf97d1..6028de62 100644 --- a/spring-cloud-kubernetes-integration-tests/simple-core/src/test/java/org/springframework/cloud/kubernetes/it/GreetingAndHealthIT.java +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/test/java/org/springframework/cloud/kubernetes/it/GreetingAndHealthIT.java @@ -36,7 +36,7 @@ public class GreetingAndHealthIT { @Test public void testGreetingEndpoint() { given().baseUri(String.format("http://%s:%d", HOST, PORT)).get("greeting").then() - .statusCode(200).body("message", is("Hello Spring Boot")); + .statusCode(200).body("message", is("Hello from k8s")); } @Test