diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/ConfigServerMvcConfiguration.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/ConfigServerMvcConfiguration.java index aaf4b170..fb91c0d2 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/ConfigServerMvcConfiguration.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/ConfigServerMvcConfiguration.java @@ -27,19 +27,21 @@ import org.springframework.cloud.config.server.environment.EnvironmentEncryptorE import org.springframework.cloud.config.server.environment.EnvironmentRepository; import org.springframework.cloud.config.server.resource.ResourceController; import org.springframework.cloud.config.server.resource.ResourceRepository; +import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @author Dave Syer * @author Roy Clarkson + * @author Tim Ysewyn */ @Configuration @ConditionalOnWebApplication -public class ConfigServerMvcConfiguration extends WebMvcConfigurerAdapter { +public class ConfigServerMvcConfiguration implements WebMvcConfigurer { @Autowired(required = false) private EnvironmentEncryptor environmentEncryptor; @@ -55,6 +57,7 @@ public class ConfigServerMvcConfiguration extends WebMvcConfigurerAdapter { } @Bean + @RefreshScope public EnvironmentController environmentController( EnvironmentRepository envRepository, ConfigServerProperties server) { EnvironmentController controller = new EnvironmentController( diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/ResourceRepositoryConfiguration.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/ResourceRepositoryConfiguration.java index 21da4c7c..dcdf966b 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/ResourceRepositoryConfiguration.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/ResourceRepositoryConfiguration.java @@ -18,7 +18,6 @@ package org.springframework.cloud.config.server.config; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.config.server.environment.SearchPathLocator; import org.springframework.cloud.config.server.resource.GenericResourceRepository; import org.springframework.cloud.config.server.resource.ResourceRepository; @@ -27,10 +26,9 @@ import org.springframework.context.annotation.Configuration; /** * @author Dave Syer - * + * @author Tim Ysewyn */ @Configuration -@EnableConfigurationProperties(ConfigServerProperties.class) @ConditionalOnMissingBean(ResourceRepository.class) public class ResourceRepositoryConfiguration { diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/BootstrapConfigServerIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/BootstrapConfigServerIntegrationTests.java index 7c31ace6..0b11fb81 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/BootstrapConfigServerIntegrationTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/BootstrapConfigServerIntegrationTests.java @@ -64,8 +64,10 @@ public class BootstrapConfigServerIntegrationTests { public void contextLoads() { Environment environment = new TestRestTemplate().getForObject( "http://localhost:" + this.port + "/foo/development/", Environment.class); - assertThat(environment.getPropertySources().isEmpty()).isFalse(); - assertThat(environment.getPropertySources().get(0).getSource().get("info.foo")) + assertThat(environment.getPropertySources()).hasSize(2); + assertThat(environment.getPropertySources().get(0).getSource().get("bar")) + .isEqualTo("foo"); + assertThat(environment.getPropertySources().get(1).getSource().get("info.foo")) .isEqualTo("bar"); } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/RefreshableConfigServerIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/RefreshableConfigServerIntegrationTests.java new file mode 100644 index 00000000..ebc59d8d --- /dev/null +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/RefreshableConfigServerIntegrationTests.java @@ -0,0 +1,142 @@ +/* + * 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 + * + * 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.config.server; + +import java.io.IOException; + +import org.eclipse.jgit.junit.MockSystemReader; +import org.eclipse.jgit.util.SystemReader; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.cloud.config.environment.Environment; +import org.springframework.cloud.config.server.RefreshableConfigServerIntegrationTests.TestConfiguration; +import org.springframework.cloud.config.server.environment.EnvironmentRepository; +import org.springframework.cloud.config.server.resource.ResourceRepository; +import org.springframework.cloud.config.server.test.ConfigServerTestUtils; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.BDDMockito.given; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = TestConfiguration.class, properties = { + "spring.cloud.config.enabled=true", + "management.endpoints.web.exposure.include=env, refresh" }, webEnvironment = WebEnvironment.RANDOM_PORT) +@ActiveProfiles("test") +@DirtiesContext +public class RefreshableConfigServerIntegrationTests { + + private static String localRepo = null; + + @LocalServerPort + private int port; + + @BeforeClass + public static void init() throws IOException { + // mock Git configuration to make tests independent of local Git configuration + SystemReader.setInstance(new MockSystemReader()); + + localRepo = ConfigServerTestUtils.prepareLocalRepo(); + } + + @AfterClass + public static void after() throws IOException { + ConfigServerTestUtils.deleteLocalRepo(localRepo); + } + + /* + * We're emulating an application "foo" which is running with the "development" profile + * and is asking for its properties using the REST endpoint. We're also calling the + * /env & /refresh actuator endpoints to change the + * `spring.cloud.config.server.overrides.foo` property. Since we see that we only get + * the overridden "foo" property after the context refresh we are sure that the + * properties have been set and the EnvironmentController bean has successfully been + * recreated with the new overrides. + */ + @Test + public void refreshOverrides() { + Environment environment = new TestRestTemplate().getForObject( + "http://localhost:" + this.port + "/foo/development/", Environment.class); + assertThat(environment.getPropertySources()).isEmpty(); + + String actuatorEndpoint = "http://localhost:" + this.port + "/actuator"; + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", "application/json"); + HttpEntity request = new HttpEntity<>( + "{\"name\": \"spring.cloud.config.server.overrides.foo\", \"value\": \"bar\"}", + headers); + ResponseEntity response = new TestRestTemplate() + .postForEntity(actuatorEndpoint + "/env", request, Void.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + + response = new TestRestTemplate().postForEntity(actuatorEndpoint + "/refresh", + null, Void.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + + environment = new TestRestTemplate().getForObject( + "http://localhost:" + this.port + "/foo/development/", Environment.class); + assertThat(environment.getPropertySources()).isNotEmpty(); + assertThat(environment.getPropertySources().get(0).getSource().get("foo")) + .isEqualTo("bar"); + } + + @Configuration + @EnableAutoConfiguration + @EnableConfigServer + protected static class TestConfiguration { + + @Bean + public EnvironmentRepository environmentRepository() { + EnvironmentRepository repository = Mockito.mock(EnvironmentRepository.class); + Environment environment = new Environment("", ""); + given(repository.findOne(isA(String.class), isA(String.class), + nullable(String.class))).willReturn(environment); + return repository; + } + + @Bean + public ResourceRepository resourceRepository() { + ResourceRepository repository = Mockito.mock(ResourceRepository.class); + given(repository.findOne(isA(String.class), isA(String.class), + nullable(String.class), isA(String.class))) + .willReturn(new ByteArrayResource("".getBytes())); + return repository; + } + + } + +} diff --git a/spring-cloud-config-server/src/test/resources/enable-bootstrap.yml b/spring-cloud-config-server/src/test/resources/enable-bootstrap.yml index fab99da1..6fcb23ff 100644 --- a/spring-cloud-config-server/src/test/resources/enable-bootstrap.yml +++ b/spring-cloud-config-server/src/test/resources/enable-bootstrap.yml @@ -1,4 +1,6 @@ spring: + application: + name: enable-bootstrap cloud: config: server: diff --git a/spring-cloud-config-server/src/test/resources/encrypt-repo/enable-bootstrap.yml b/spring-cloud-config-server/src/test/resources/encrypt-repo/enable-bootstrap.yml new file mode 100644 index 00000000..63e43ddb --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/encrypt-repo/enable-bootstrap.yml @@ -0,0 +1,6 @@ +spring: + cloud: + config: + server: + overrides: + bar: foo diff --git a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/COMMIT_EDITMSG b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/COMMIT_EDITMSG index c8fcd951..8f9fc884 100644 --- a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/COMMIT_EDITMSG +++ b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/COMMIT_EDITMSG @@ -1 +1 @@ -Updated +Added server overrides diff --git a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/index b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/index index 41937d55..f6761ccd 100644 Binary files a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/index and b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/index differ diff --git a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/logs/HEAD b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/logs/HEAD index dc9c2ab0..3e9d8789 100644 --- a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/logs/HEAD +++ b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/logs/HEAD @@ -6,3 +6,4 @@ 7df4a26d5437d9d4090cd5809967f870444cde8f 9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 Dave Syer 1498491043 +0100 checkout: moving from raw to master 9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 ad5e0cb7036ed11ddd4b7be6ed86ad3565c8a3fc Dave Syer 1498491468 +0100 commit: Add encrypted property ad5e0cb7036ed11ddd4b7be6ed86ad3565c8a3fc bd414a6cc8653d7e282df0a257babc6283b83596 Marcin Grzejszczak 1549357702 +0100 commit: Updated +bd414a6cc8653d7e282df0a257babc6283b83596 fd07d827993aaf6ed7ef1b979767ee9277d1d409 Tim Ysewyn 1564492480 +0200 commit: Added server overrides diff --git a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/logs/refs/heads/master b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/logs/refs/heads/master index 5412791a..7ca96c00 100644 --- a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/logs/refs/heads/master +++ b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/logs/refs/heads/master @@ -1,3 +1,4 @@ 0000000000000000000000000000000000000000 9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 Dave Syer 1406860776 -0700 branch: Created from 9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 ad5e0cb7036ed11ddd4b7be6ed86ad3565c8a3fc Dave Syer 1498491468 +0100 commit: Add encrypted property ad5e0cb7036ed11ddd4b7be6ed86ad3565c8a3fc bd414a6cc8653d7e282df0a257babc6283b83596 Marcin Grzejszczak 1549357702 +0100 commit: Updated +bd414a6cc8653d7e282df0a257babc6283b83596 fd07d827993aaf6ed7ef1b979767ee9277d1d409 Tim Ysewyn 1564492480 +0200 commit: Added server overrides diff --git a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/objects/63/e43ddbda928b903e56f601409552bbfb7fdd99 b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/objects/63/e43ddbda928b903e56f601409552bbfb7fdd99 new file mode 100644 index 00000000..245ed5d6 Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/objects/63/e43ddbda928b903e56f601409552bbfb7fdd99 differ diff --git a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/objects/ba/97b023d1d0faa44cc337479d6a8ac1ebcdb00d b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/objects/ba/97b023d1d0faa44cc337479d6a8ac1ebcdb00d new file mode 100644 index 00000000..9d045672 Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/objects/ba/97b023d1d0faa44cc337479d6a8ac1ebcdb00d differ diff --git a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/objects/fd/07d827993aaf6ed7ef1b979767ee9277d1d409 b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/objects/fd/07d827993aaf6ed7ef1b979767ee9277d1d409 new file mode 100644 index 00000000..f89b2f16 Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/objects/fd/07d827993aaf6ed7ef1b979767ee9277d1d409 differ diff --git a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/refs/heads/master b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/refs/heads/master index 51053139..65ee9fbb 100644 --- a/spring-cloud-config-server/src/test/resources/encrypt-repo/git/refs/heads/master +++ b/spring-cloud-config-server/src/test/resources/encrypt-repo/git/refs/heads/master @@ -1 +1 @@ -bd414a6cc8653d7e282df0a257babc6283b83596 +fd07d827993aaf6ed7ef1b979767ee9277d1d409