Merge branch 'master' into 2.0.x

This commit is contained in:
Spencer Gibb
2017-10-20 17:22:15 -04:00
8 changed files with 171 additions and 6 deletions

View File

@@ -1164,12 +1164,14 @@ server {
}
----
NOTE: just like the source files for environment configuration, the
NOTE: Just like the source files for environment configuration, the
"profile" is used to resolve the file name, so if you want a
profile-specific file then `/\*/development/*/logback.xml` will be
resolved by a file called `logback-development.xml` (in preference
to `logback.xml`).
NOTE: If you do not want to supply the `label` and let the server use the default label, you can supply a `useDefaultLabel` request parameter. So, the above example for the `default` profile could look like `/foo/default/nginx.conf?useDefaultLabel`.
== Embedding the Config Server
The Config Server runs best as a standalone application, but if you

View File

@@ -21,6 +21,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.cloud.config.client.ConfigClientProperties;
import org.springframework.cloud.config.server.config.ConfigServerProperties;
import org.springframework.cloud.config.server.config.EnvironmentRepositoryConfiguration;
import org.springframework.cloud.config.server.config.TransportConfiguration;
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
import org.springframework.cloud.config.server.environment.EnvironmentRepositoryPropertySourceLocator;
import org.springframework.context.annotation.Bean;
@@ -44,7 +45,7 @@ import org.springframework.util.StringUtils;
public class ConfigServerBootstrapConfiguration {
@EnableConfigurationProperties(ConfigServerProperties.class)
@Import(EnvironmentRepositoryConfiguration.class)
@Import({ EnvironmentRepositoryConfiguration.class, TransportConfiguration.class })
protected static class LocalPropertySourceLocatorConfiguration {
@Autowired

View File

@@ -117,7 +117,7 @@ class EnvironmentPrefixHelper {
if (value.contains(ESCAPE)) {
return value.substring(value.indexOf(ESCAPE) + ESCAPE.length());
}
return value.substring(value.lastIndexOf("}") + 1);
return value.replaceFirst("^(\\{.*?:.*?\\})+", "");
}
private String removeEnvironmentPrefix(String input) {

View File

@@ -49,6 +49,7 @@ import org.springframework.web.util.UrlPathHelper;
* to replace placeholders in the resource text.
*
* @author Dave Syer
* @author Daniel Lavoie
*
*/
@RestController
@@ -77,9 +78,23 @@ public class ResourceController {
return retrieve(name, profile, label, path, resolvePlaceholders);
}
@RequestMapping(value = "/{name}/{profile}/**", params = "useDefaultLabel")
public String retrieve(@PathVariable String name, @PathVariable String profile,
HttpServletRequest request,
@RequestParam(defaultValue = "true") boolean resolvePlaceholders)
throws IOException {
String path = getFilePath(request, name, profile, null);
return retrieve(name, profile, null, path, resolvePlaceholders);
}
private String getFilePath(HttpServletRequest request, String name, String profile,
String label) {
String stem = String.format("/%s/%s/%s/", name, profile, label);
String stem;
if(label != null ) {
stem = String.format("/%s/%s/%s/", name, profile, label);
}else {
stem = String.format("/%s/%s/", name, profile);
}
String path = this.helper.getPathWithinApplication(request);
path = path.substring(path.indexOf(stem) + stem.length());
return path;
@@ -87,6 +102,11 @@ public class ResourceController {
synchronized String retrieve(String name, String profile, String label, String path,
boolean resolvePlaceholders) throws IOException {
if (name != null && name.contains("(_)")) {
// "(_)" is uncommon in a git repo name, but "/" cannot be matched
// by Spring MVC
name = name.replace("(_)", "/");
}
if (label != null && label.contains("(_)")) {
// "(_)" is uncommon in a git branch name, but "/" cannot be matched
// by Spring MVC
@@ -116,6 +136,11 @@ public class ResourceController {
synchronized byte[] binary(String name, String profile, String label, String path)
throws IOException {
if (name != null && name.contains("(_)")) {
// "(_)" is uncommon in a git repo name, but "/" cannot be matched
// by Spring MVC
name = name.replace("(_)", "/");
}
if (label != null && label.contains("(_)")) {
// "(_)" is uncommon in a git branch name, but "/" cannot be matched
// by Spring MVC

View File

@@ -135,6 +135,20 @@ public class EncryptionControllerTests {
assertThat("Prefix must be stripped prior to encrypt", captor.getValue(), not(containsString("{key:test}")));
}
@Test
public void encryptDecyptTextWithCurlyBrace() {
this.controller = new EncryptionController(
new SingleTextEncryptorLocator(new RsaSecretEncryptor()));
String plain = "textwith}brace";
String cipher = this.controller.encrypt(plain,
MediaType.APPLICATION_FORM_URLENCODED);
String decrypt = this.controller.decrypt(cipher,
MediaType.APPLICATION_FORM_URLENCODED);
assertEquals(plain, decrypt);
}
@Test
public void addEnvironment() {
TextEncryptorLocator locator = new TextEncryptorLocator() {

View File

@@ -81,4 +81,14 @@ public class EnvironmentPrefixHelperTests {
assertEquals("mykey", keys.get("key"));
}
@Test
public void testTextWithCurlyBracesNoPrefix() {
assertEquals("textwith}brac{es", this.helper.stripPrefix("textwith}brac{es"));
}
@Test
public void testTextWithCurlyBracesPrefix() {
assertEquals("textwith}brac{es{and}prefix", this.helper
.stripPrefix("{key:foo}{name:bar}textwith}brac{es{and}prefix"));
}
}

View File

@@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.config.environment.Environment;
import org.springframework.cloud.config.server.environment.EnvironmentController;
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
import org.springframework.cloud.config.server.resource.ResourceControllerIntegrationTests.ControllerConfiguration;
import org.springframework.context.annotation.Bean;
@@ -41,10 +42,11 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
/**
* @author Dave Syer
* @author Daniel Lavoie
*
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ControllerConfiguration.class)
@SpringBootTest(classes = ControllerConfiguration.class, properties = "trace")
@DirtiesContext
public class ResourceControllerIntegrationTests {
@@ -74,6 +76,19 @@ public class ResourceControllerIntegrationTests {
Mockito.verify(this.resources).findOne("foo", "default", "master", "foo.txt");
}
@Test
public void resourceNoLabel() throws Exception {
Mockito.when(this.repository.findOne("foo", "default", null))
.thenReturn(new Environment("foo", "default", "master"));
Mockito.when(this.resources.findOne("foo", "default", null, "foo.txt"))
.thenReturn(new ByteArrayResource("hello".getBytes()));
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default/foo.txt")
.param("useDefaultLabel", ""))
.andExpect(MockMvcResultMatchers.status().isOk());
Mockito.verify(this.repository).findOne("foo", "default", null);
Mockito.verify(this.resources).findOne("foo", "default", null, "foo.txt");
}
@Configuration
@EnableWebMvc
@Import(PropertyPlaceholderAutoConfiguration.class)
@@ -92,7 +107,12 @@ public class ResourceControllerIntegrationTests {
}
@Bean
public ResourceController controller() {
public EnvironmentController environmentController() {
return new EnvironmentController(environmentRepository());
}
@Bean
public ResourceController resourceController() {
return new ResourceController(resourceRepository(), environmentRepository());
}

View File

@@ -28,6 +28,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
@@ -89,6 +90,52 @@ public class ResourceControllerTests {
assertEquals("foo: ${foo}", resource);
}
@Test
public void applicationAndLabelPlaceholdersWithoutSlash() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test/{application}/{label}");
String resource = this.controller.retrieve("dev", "bar", "spam", "foo.txt", true);
assertEquals("foo: dev_bar/spam", resource);
}
@Test
public void applicationPlaceholderWithSlash() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test/{application}");
String resource = this.controller.retrieve("dev(_)spam", "bar", "", "foo.txt", true);
assertEquals("foo: dev_bar/spam", resource);
}
@Test
public void applicationPlaceholderWithSlashNullLabel() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test/{application}");
String resource = this.controller.retrieve("dev(_)spam", "bar", null, "foo.txt", true);
assertEquals("foo: dev_bar/spam", resource);
}
@Test
public void labelPlaceholderWithSlash() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test/{label}");
String resource = this.controller.retrieve("dev", "bar", "dev(_)spam", "foo.txt", true);
assertEquals("foo: dev_bar/spam", resource);
}
@Test
public void profilePlaceholderNullLabel() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test/{profile}");
String resource = this.controller.retrieve("bar", "dev", null, "spam/foo.txt", true);
assertEquals("foo: dev_bar/spam", resource);
}
@Test
public void nullNameAndLabel() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test");
try {
this.controller.retrieve(null, "foo", "bar", "spam/foo.txt", true);
}
catch (Exception e) {
assertNotNull(e);
}
}
@Test
public void labelWithSlash() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test");
@@ -145,6 +192,52 @@ public class ResourceControllerTests {
assertEquals("foo: dev_bar/spam", resource);
}
@Test
public void applicationAndLabelPlaceholdersWithoutSlashForBinary() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test/{application}/{label}");
byte[] resource = this.controller.binary("dev", "bar", "spam", "foo.txt");
assertEquals("foo: dev_bar/spam", new String(resource));
}
@Test
public void applicationPlaceholderWithSlashForBinary() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test/{application}");
byte[] resource = this.controller.binary("dev(_)spam", "bar", "", "foo.txt");
assertEquals("foo: dev_bar/spam", new String(resource));
}
@Test
public void applicationPlaceholderWithSlashForBinaryNullLabel() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test/{application}");
byte[] resource = this.controller.binary("dev(_)spam", "bar", null, "foo.txt");
assertEquals("foo: dev_bar/spam", new String(resource));
}
@Test
public void labelPlaceholderWithSlashForBinary() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test/{label}");
byte[] resource = this.controller.binary("dev", "bar", "dev(_)spam", "foo.txt");
assertEquals("foo: dev_bar/spam", new String(resource));
}
@Test
public void profilePlaceholderForBinaryNullLabel() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test/{profile}");
byte[] resource = this.controller.binary("bar", "dev", null, "spam/foo.txt");
assertEquals("foo: dev_bar/spam", new String(resource));
}
@Test
public void forBinaryNullName() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test");
try {
this.controller.binary(null, "foo", "bar", "spam/foo.txt");
}
catch (Exception e) {
assertNotNull(e);
}
}
@Test
public void labelWithSlashForBinary() throws Exception {
this.environmentRepository.setSearchLocations("classpath:/test");