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:
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Bootstrap components
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.config.server.ConfigServerBootstrapConfiguration
|
||||
Reference in New Issue
Block a user