Add self-bootstrap feature for embedded config server

Also switch to use SpringApplicationEnvironmentRepository
in "native" profile (it's more useful as a "getting started"
tool).

Fixes gh-21, fixes gh-33
This commit is contained in:
Dave Syer
2014-10-30 07:17:22 +00:00
parent b6f22b83c7
commit 4c7cc73671
8 changed files with 191 additions and 19 deletions

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2013-2014 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.config.server;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.config.client.ConfigClientProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Bootstrap configuration to fetch external configuration from a (possibly remote)
* {@link EnvironmentRepository}. Off by default because it can delay startup, but can be
* enabled with <code>spring.cloud.config.server.bootstrap=true</code>. This would be
* useful, for example, if the config server were embedded in another app that wanted to
* be configured from the same repository as all the other clients.
*
* @author Dave Syer
*
*/
@ConditionalOnProperty("spring.cloud.config.server.bootstrap")
@Configuration
@Import(ConfigServerConfiguration.class)
public class ConfigServerBootstrapConfiguration {
@Autowired
private EnvironmentRepository repository;
@Autowired
private ConfigClientProperties client;
@Bean
public EnvironmentRepositoryPropertySourceLocator environmentRepositoryPropertySourceLocator() {
return new EnvironmentRepositoryPropertySourceLocator(repository,
client.getName(), client.getEnv(), client.getLabel());
}
}

View File

@@ -16,9 +16,9 @@
package org.springframework.cloud.config.server;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.ConfigurableEnvironment;
@@ -28,18 +28,16 @@ import org.springframework.core.env.ConfigurableEnvironment;
*
*/
@Configuration
@ComponentScan
@ConditionalOnMissingBean(EnvironmentRepository.class)
public class ConfigServerConfiguration {
@Configuration
@Profile("native")
protected static class NativeRepositoryConfiguration {
@Autowired
private ConfigurableEnvironment environment;
@Bean
public NativeEnvironmentRepository repository() {
return new NativeEnvironmentRepository(environment);
@ConfigurationProperties("spring.cloud.config.server")
public SpringApplicationEnvironmentRepository repository() {
return new SpringApplicationEnvironmentRepository();
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2013-2014 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.config.server;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.encrypt.TextEncryptor;
/**
* @author Dave Syer
*
*/
@Configuration
@ConditionalOnWebApplication
public class ConfigServerMvcConfiguration {
@Autowired(required = false)
private TextEncryptor encryptor;
@Autowired
private EnvironmentRepository repository;
@Bean
public EnvironmentController environmentController() {
return new EnvironmentController(repository, encryptionController());
}
@Bean
public EncryptionController encryptionController() {
EncryptionController controller = new EncryptionController();
if (encryptor!=null) {
controller.setEncryptor(encryptor);
}
return controller;
}
}

View File

@@ -18,13 +18,8 @@ package org.springframework.cloud.config.server;
import java.io.File;
import java.io.IOException;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig.Host;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.util.FileUtils;
import com.jcraft.jsch.Session;
/**
* @author Dave Syer
*
@@ -43,12 +38,6 @@ public class ConfigServerTestUtils {
if (!repoPath.endsWith("/")) {
repoPath = repoPath + "/";
}
SshSessionFactory.setInstance(new JschConfigSessionFactory() {
@Override
protected void configure(Host hc, Session session) {
session.setConfig("StrictHostKeyChecking", "no");
}
});
File dotGit = new File(buildDir + repoPath + ".git");
File git = new File(buildDir + repoPath + "git");
if (git.exists()) {

View File

@@ -30,7 +30,7 @@ import org.springframework.context.annotation.Import;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ConfigServerConfiguration.class)
@Import({ConfigServerConfiguration.class, ConfigServerMvcConfiguration.class})
public @interface EnableConfigServer {
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2013-2014 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.config.server;
import java.util.Map;
import org.springframework.cloud.config.PropertySource;
import org.springframework.cloud.config.client.PropertySourceLocator;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
/**
* A PropertySourceLocator that reads from an EnvironmentRepository.
*
* @author Dave Syer
*
*/
public class EnvironmentRepositoryPropertySourceLocator implements PropertySourceLocator {
private EnvironmentRepository repository;
private String name;
private String profiles;
private String label;
public EnvironmentRepositoryPropertySourceLocator(EnvironmentRepository repository,
String name, String profiles, String label) {
this.repository = repository;
this.name = name;
this.profiles = profiles;
this.label = label;
}
@Override
public org.springframework.core.env.PropertySource<?> locate(Environment environment) {
CompositePropertySource composite = new CompositePropertySource("configService");
for (PropertySource source : repository.findOne(name, profiles, label)
.getPropertySources()) {
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) source.getSource();
composite.addPropertySource(new MapPropertySource(source.getName(), map));
}
return composite;
}
}

View File

@@ -37,7 +37,10 @@ import org.eclipse.jgit.api.PullCommand;
import org.eclipse.jgit.api.TransportCommand;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.transport.OpenSshConfig.Host;
import org.springframework.cloud.config.Environment;
import org.springframework.cloud.config.PropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
@@ -45,6 +48,8 @@ import org.springframework.core.io.UrlResource;
import org.springframework.util.Assert;
import org.springframework.util.FileSystemUtils;
import com.jcraft.jsch.Session;
/**
* @author Dave Syer
*
@@ -65,6 +70,8 @@ public class JGitEnvironmentRepository implements EnvironmentRepository {
private String password;
private boolean initialized;
public JGitEnvironmentRepository(ConfigurableEnvironment environment) {
this.environment = environment;
try {
@@ -124,6 +131,7 @@ public class JGitEnvironmentRepository implements EnvironmentRepository {
@Override
public Environment findOne(String application, String profile, String label) {
initialize();
try {
Git git;
if (new File(basedir, ".git").exists()) {
@@ -203,6 +211,18 @@ public class JGitEnvironmentRepository implements EnvironmentRepository {
}
}
private void initialize() {
if (uri.startsWith("file:") && !initialized) {
SshSessionFactory.setInstance(new JschConfigSessionFactory() {
@Override
protected void configure(Host hc, Session session) {
session.setConfig("StrictHostKeyChecking", "no");
}
});
initialized = true;
}
}
private void setCredentialsProvider(TransportCommand<?, ?> cmd) {
cmd.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username,
password));

View File

@@ -0,0 +1,3 @@
# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.config.server.ConfigServerBootstrapConfiguration