Protects from NPE when no data returned from Vault. Fixes #445.

This commit is contained in:
Ryan Baxter
2016-07-19 09:35:59 -04:00
parent 8ad7f06c71
commit 1f0bbddc54
3 changed files with 75 additions and 11 deletions

View File

@@ -32,6 +32,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.web.client.RestTemplate;
/**
* @author Dave Syer
@@ -106,7 +107,7 @@ public class EnvironmentRepositoryConfiguration {
protected static class VaultConfiguration {
@Bean
public EnvironmentRepository environmentRepository(HttpServletRequest request, EnvironmentWatch watch) {
return new VaultEnvironmentRepository(request, watch);
return new VaultEnvironmentRepository(request, watch, new RestTemplate());
}
}

View File

@@ -61,16 +61,17 @@ public class VaultEnvironmentRepository implements EnvironmentRepository {
@NotEmpty
private String profileSeparator = ",";
private RestTemplate rest = new RestTemplate();
private RestTemplate rest;
//TODO: move to watchState:String on findOne?
private HttpServletRequest request;
private EnvironmentWatch watch;
public VaultEnvironmentRepository(HttpServletRequest request, EnvironmentWatch watch) {
public VaultEnvironmentRepository(HttpServletRequest request, EnvironmentWatch watch, RestTemplate rest) {
this.request = request;
this.watch = watch;
this.rest = rest;
}
@Override
@@ -89,13 +90,15 @@ public class VaultEnvironmentRepository implements EnvironmentRepository {
for (String key : keys) {
// read raw 'data' key from vault
String data = read(key);
// data is in json format of which, yaml is a superset, so parse
final YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ByteArrayResource(data.getBytes()));
Properties properties = yaml.getObject();
if (data != null) {
// data is in json format of which, yaml is a superset, so parse
final YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ByteArrayResource(data.getBytes()));
Properties properties = yaml.getObject();
if (!properties.isEmpty()) {
environment.add(new PropertySource("vault:"+key, properties));
if (!properties.isEmpty()) {
environment.add(new PropertySource("vault:" + key, properties));
}
}
}

View File

@@ -1,14 +1,74 @@
package org.springframework.cloud.config.server.environment;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.cloud.config.environment.Environment;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.client.RestTemplate;
/**
* @author Spencer Gibb
* @author Ryan Baxter
*/
public class VaultEnvironmentRepositoryTests {
@Before
public void init() {}
@Test
public void testFindOne() {
//TODO: implement testFindOne
public void testFindOne() throws IOException {
MockHttpServletRequest configRequest = new MockHttpServletRequest();
configRequest.addHeader("X-CONFIG-TOKEN", "mytoken");
RestTemplate rest = Mockito.mock(RestTemplate.class);
ResponseEntity<VaultEnvironmentRepository.VaultResponse> myAppResp = Mockito.mock(ResponseEntity.class);
Mockito.when(myAppResp.getStatusCode()).thenReturn(HttpStatus.OK);
VaultEnvironmentRepository.VaultResponse myAppVaultResp = Mockito.mock(VaultEnvironmentRepository.VaultResponse.class);
Mockito.when(myAppVaultResp.getData()).thenReturn("{\"foo\":\"bar\"}");
Mockito.when(myAppResp.getBody()).thenReturn(myAppVaultResp);
Mockito.when(rest.exchange(Mockito.eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
Mockito.eq(HttpMethod.GET), Mockito.any(HttpEntity.class), Mockito.eq(VaultEnvironmentRepository.VaultResponse.class),
Mockito.eq("secret"), Mockito.eq("myapp"))).thenReturn(myAppResp);
ResponseEntity<VaultEnvironmentRepository.VaultResponse> appResp = Mockito.mock(ResponseEntity.class);
Mockito.when(appResp.getStatusCode()).thenReturn(HttpStatus.OK);
VaultEnvironmentRepository.VaultResponse appVaultResp = Mockito.mock(VaultEnvironmentRepository.VaultResponse.class);
Mockito.when(appVaultResp.getData()).thenReturn(null);
Mockito.when(appResp.getBody()).thenReturn(appVaultResp);
Mockito.when(rest.exchange(Mockito.eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
Mockito.eq(HttpMethod.GET), Mockito.any(HttpEntity.class), Mockito.eq(VaultEnvironmentRepository.VaultResponse.class),
Mockito.eq("secret"), Mockito.eq("application"))).thenReturn(appResp);
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(configRequest, new EnvironmentWatch.Default(), rest);
Environment e = repo.findOne("myapp", null, null);
assertEquals("myapp", e.getName());
Map<String,String> result = new HashMap<String,String>();
result.put("foo", "bar");
assertEquals(result, e.getPropertySources().get(0).getSource());
}
@Test(expected = IllegalArgumentException.class)
public void missingConfigToken() throws IOException {
MockHttpServletRequest configRequest = new MockHttpServletRequest();
RestTemplate rest = Mockito.mock(RestTemplate.class);
ResponseEntity<VaultEnvironmentRepository.VaultResponse> myAppResp = Mockito.mock(ResponseEntity.class);
Mockito.when(myAppResp.getStatusCode()).thenReturn(HttpStatus.OK);
VaultEnvironmentRepository.VaultResponse myAppVaultResp = Mockito.mock(VaultEnvironmentRepository.VaultResponse.class);
Mockito.when(myAppVaultResp.getData()).thenReturn("{\"foo\":\"bar\"}");
Mockito.when(myAppResp.getBody()).thenReturn(myAppVaultResp);
Mockito.when(rest.exchange(Mockito.eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
Mockito.eq(HttpMethod.GET), Mockito.any(HttpEntity.class), Mockito.eq(VaultEnvironmentRepository.VaultResponse.class),
Mockito.eq("secret"), Mockito.eq("myapp"))).thenReturn(myAppResp);
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(configRequest, new EnvironmentWatch.Default(), rest);
repo.findOne("myapp", null, null);
}
}