Spring cloud connector for Config server

This commit is contained in:
Chris Schaefer
2015-01-09 14:31:57 -05:00
parent c7bca2009d
commit 38e48bc3f0
7 changed files with 177 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
package org.springframework.cloud.pcf.configserver;
import org.springframework.cloud.Cloud;
import org.springframework.cloud.CloudFactory;
import org.springframework.cloud.service.ServiceInfo;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import java.util.Collections;
/**
* Connector to Config Server service
*
* @author Chris Schaefer
*/
@Configuration
public class ConfigServerServiceConnector implements ApplicationListener<ApplicationEvent>, Ordered {
/**
* TODO:
* Bind ApplicationListener to ApplicationEnvironmentPreparedEvent, remove reflection
* and add test after repo migration in which we will have a direct dependency on boot.
*/
private static final String PROPERTY_SOURCE_NAME = "vcapConfigServerUri";
private static final String EVENT_ENVIRONMENT_METHOD_NAME = "getEnvironment";
private static final String SPRING_CLOUD_CONFIG_URI = "spring.cloud.config.uri";
private static final String EVENT_CLASS_NAME = "org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent";
private Cloud cloud;
@Override
public void onApplicationEvent(ApplicationEvent event) {
if(!supports(event.getClass().getName()) || cloud != null) {
return;
}
cloud = new CloudFactory().getCloud();
for(ServiceInfo serviceInfo : cloud.getServiceInfos()) {
if(serviceInfo instanceof ConfigServerServiceInfo) {
String uri = ((ConfigServerServiceInfo) serviceInfo).getUri();
MapPropertySource mapPropertySource = new MapPropertySource(PROPERTY_SOURCE_NAME,
Collections.<String, Object>singletonMap(SPRING_CLOUD_CONFIG_URI, uri));
getEnvironment(event).getPropertySources().addFirst(mapPropertySource);
}
}
}
private boolean supports(String className) {
return EVENT_CLASS_NAME.equals(className);
}
private ConfigurableEnvironment getEnvironment(ApplicationEvent event) {
Method method = ReflectionUtils.findMethod(event.getClass(), EVENT_ENVIRONMENT_METHOD_NAME);
try {
return (ConfigurableEnvironment) method.invoke(event);
} catch (Exception e) {
throw new RuntimeException("Error obtaining Environment from event", e);
}
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 4;
}
}

View File

@@ -0,0 +1,14 @@
package org.springframework.cloud.pcf.configserver;
import org.springframework.cloud.service.UriBasedServiceInfo;
/**
* Service info to access Config Server services
*
* @author Chris Schaefer
*/
public class ConfigServerServiceInfo extends UriBasedServiceInfo {
public ConfigServerServiceInfo(String id, String uriString) {
super(id, uriString);
}
}

View File

@@ -0,0 +1,28 @@
package org.springframework.cloud.pcf.configserver;
import org.springframework.cloud.cloudfoundry.CloudFoundryServiceInfoCreator;
import org.springframework.cloud.cloudfoundry.Tags;
import java.util.Map;
/**
* Service info creator for Config Server services
*
* @author Chris Schaefer
*/
public class ConfigServerServiceInfoCreator extends CloudFoundryServiceInfoCreator<ConfigServerServiceInfo> {
private static final String CREDENTIALS_ID_KEY = "name";
private static final String CONFIG_SERVER_SERVICE_TAG_NAME = "configuration";
public ConfigServerServiceInfoCreator() {
super(new Tags(CONFIG_SERVER_SERVICE_TAG_NAME));
}
@Override
public ConfigServerServiceInfo createServiceInfo(Map<String, Object> serviceData) {
String id = (String) serviceData.get(CREDENTIALS_ID_KEY);
String uri = getUriFromCredentials(getCredentials(serviceData));
return new ConfigServerServiceInfo(id, uri);
}
}

View File

@@ -1,2 +1,3 @@
org.springframework.cloud.pcf.phd.PhdServiceInfoCreator
org.springframework.cloud.pcf.eureka.EurekaServiceInfoCreator
org.springframework.cloud.pcf.configserver.ConfigServerServiceInfoCreator

View File

@@ -0,0 +1,2 @@
org.springframework.context.ApplicationListener=\
org.springframework.cloud.pcf.configserver.ConfigServerServiceConnector

View File

@@ -0,0 +1,46 @@
package org.springframework.cloud.pcf.configserver;
import org.junit.Test;
import org.springframework.cloud.cloudfoundry.AbstractCloudFoundryConnectorTest;
import org.springframework.cloud.service.ServiceInfo;
import java.util.List;
import static org.mockito.Mockito.when;
/**
* Connector tests for Config Server services
*
* @author Chris Schaefer
*/
public class ConfigServerServiceInfoCreatorTest extends AbstractCloudFoundryConnectorTest {
private static final String CONFIG_SERVER_SERVICE_TAG_NAME = "myConfigServerService";
private static final String VCAP_SERVICES_ENV_KEY = "VCAP_SERVICES";
private static final String PAYLOAD_FILE_NAME = "test-config-server-info.json";
private static final String PAYLOAD_TEMPLATE_SERVICE_NAME = "$serviceName";
private static final String PAYLOAD_TEMPLATE_HOSTNAME = "$hostname";
private static final String PAYLOAD_TEMPLATE_PORT = "$port";
private static final String PAYLOAD_TEMPLATE_USER = "$user";
private static final String PAYLOAD_TEMPLATE_PASS = "$pass";
@Test
public void configServerServiceCreationWithTags() {
when(mockEnvironment.getEnvValue(VCAP_SERVICES_ENV_KEY))
.thenReturn(getServicesPayload(getConfigServerServicePayload(CONFIG_SERVER_SERVICE_TAG_NAME,
hostname, port, username, password)));
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
assertServiceFoundOfType(serviceInfos, CONFIG_SERVER_SERVICE_TAG_NAME, ConfigServerServiceInfo.class);
}
private String getConfigServerServicePayload(String serviceName, String hostname, int port, String user, String password) {
String payload = readTestDataFile(PAYLOAD_FILE_NAME);
payload = payload.replace(PAYLOAD_TEMPLATE_SERVICE_NAME, serviceName);
payload = payload.replace(PAYLOAD_TEMPLATE_HOSTNAME, hostname);
payload = payload.replace(PAYLOAD_TEMPLATE_PORT, Integer.toString(port));
payload = payload.replace(PAYLOAD_TEMPLATE_USER, user);
payload = payload.replace(PAYLOAD_TEMPLATE_PASS, password);
return payload;
}
}

View File

@@ -0,0 +1,11 @@
{
"name":"$serviceName",
"label":"p-config",
"plan":"standard",
"tags":[
"configuration"
],
"credentials":{
"uri":"http://$username:$password@$hostname:$port/"
}
}