Fix profile specific configuration not loaded (#351)

Fixes: #347
This commit is contained in:
Georgios Andrianakis
2019-03-20 17:07:47 +02:00
committed by Ryan Baxter
parent 8e014f2615
commit 03ed0f2242
10 changed files with 35 additions and 171 deletions

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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<ConfigurableApplicationContext>, Ordered {
private static final int ORDER = 100;
private final Supplier<KubernetesProfileApplicationListener> 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<KubernetesProfileApplicationListener> listenerSupplier) {
this.listenerSupplier = listenerSupplier;
}
@Override
public int getOrder() {
return ORDER;
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
this.listenerSupplier.get()
.addKubernetesProfile(applicationContext.getEnvironment());
}
}

View File

@@ -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<ApplicationEnvironmentPreparedEvent>, 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");

View File

@@ -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

View File

@@ -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");
}
}

View File

@@ -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 {

View File

@@ -0,0 +1,2 @@
greeting:
message: Hello from k8s

View File

@@ -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:

View File

@@ -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