Use local file:/... repository in place instead of cloning
Since JGit cannot use the "local" protocol (only git, ssh and https) we can't use file:/... repositories in the same way as the other protocols. Formerly we would copy the whole directory and use the copy as a local cache. But then users are confused when they commit changes to the "remote" and they don't show up in the server. It seems less confusing to simply use the local repository as the basedir (although it does mean that ssh: should be used if you are scaling up the config server). Fixes gh-63
This commit is contained in:
@@ -72,11 +72,15 @@ the repository you can set the "spring.cloud.config.server.git.uri"
|
||||
configuration property in the Config Server (e.g. in
|
||||
`application.yml`). If you set it with a `file:` prefix it should work
|
||||
from a local repository so you can get started quickly and easily
|
||||
without a server (it doesn't matter if it's not bare because the
|
||||
Config Server never makes changes to the "remote" repository). To
|
||||
scale the Config Server up and make it highly available, however, you
|
||||
would need to have all instances of the server pointing to the same
|
||||
repository, so only a shared file system would work.
|
||||
without a server, but in that case the server operates directly on the
|
||||
local repository without cloning it (it doesn't matter if it's not
|
||||
bare because the Config Server never makes changes to the "remote"
|
||||
repository). To scale the Config Server up and make it highly
|
||||
available, you would need to have all instances of the server pointing
|
||||
to the same repository, so only a shared file system would work. Even
|
||||
in that case it is better to use the `ssh:` protocol for a shared
|
||||
filesystem repository, so that the server can clone it and use a local
|
||||
working copy as a cache.
|
||||
|
||||
This repository implementation maps the `{label}` parameter of the
|
||||
HTTP resource to a git label (commit id, branch name or tag).
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -27,21 +28,24 @@ import org.eclipse.jgit.util.FileUtils;
|
||||
public class ConfigServerTestUtils {
|
||||
|
||||
public static String prepareLocalRepo() throws IOException {
|
||||
return prepareLocalRepo("target/test-classes", "config-repo", "target/config");
|
||||
return prepareLocalRepo("target/repos", "config-repo", "target/config");
|
||||
}
|
||||
|
||||
public static String prepareLocalRepo(String repoPath) throws IOException {
|
||||
return prepareLocalRepo("target/test-classes", repoPath, "target/config");
|
||||
return prepareLocalRepo("target/repos", repoPath, "target/config");
|
||||
}
|
||||
|
||||
public static String prepareLocalRepo(String buildDir, String repoPath,
|
||||
String checkoutDir) throws IOException {
|
||||
new File(buildDir).mkdirs();
|
||||
if (!repoPath.startsWith("/")) {
|
||||
repoPath = "/" + repoPath;
|
||||
}
|
||||
if (!repoPath.endsWith("/")) {
|
||||
repoPath = repoPath + "/";
|
||||
}
|
||||
File source = new File("src/test/resources" + repoPath);
|
||||
FileSystemUtils.copyRecursively(source, new File(buildDir + repoPath));
|
||||
File dotGit = new File(buildDir + repoPath + ".git");
|
||||
File git = new File(buildDir + repoPath + "git");
|
||||
if (git.exists()) {
|
||||
@@ -60,4 +64,16 @@ public class ConfigServerTestUtils {
|
||||
return "file:" + buildDir + repoPath;
|
||||
}
|
||||
|
||||
public static String copyLocalRepo(String path) throws IOException {
|
||||
File dest = new File("target/repos/" + path);
|
||||
FileSystemUtils.deleteRecursively(dest);
|
||||
FileSystemUtils.copyRecursively(new File("target/repos/config-repo"), dest);
|
||||
return "file:./target/repos/" + path;
|
||||
}
|
||||
|
||||
public static boolean deleteLocalRepo(String path) throws IOException {
|
||||
File dest = new File("target/repos/" + path);
|
||||
return FileSystemUtils.deleteRecursively(dest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ import org.springframework.cloud.config.PropertySource;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.jcraft.jsch.Session;
|
||||
|
||||
@@ -75,10 +75,10 @@ public class JGitEnvironmentRepository implements EnvironmentRepository, Initial
|
||||
private boolean initialized;
|
||||
|
||||
private String[] searchPaths = new String[0];
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(uri!=null, "You need to configure a uri for the git repository");
|
||||
Assert.state(uri != null, "You need to configure a uri for the git repository");
|
||||
}
|
||||
|
||||
public JGitEnvironmentRepository(ConfigurableEnvironment environment) {
|
||||
@@ -220,8 +220,8 @@ public class JGitEnvironmentRepository implements EnvironmentRepository, Initial
|
||||
* Assumes we are on a tracking branch (should be safe)
|
||||
*/
|
||||
private void pull(Git git, String label, Ref ref) {
|
||||
PullCommand pull = git.pull();
|
||||
try {
|
||||
PullCommand pull = git.pull();
|
||||
if (hasText(username)) {
|
||||
setCredentialsProvider(pull);
|
||||
}
|
||||
@@ -229,7 +229,7 @@ public class JGitEnvironmentRepository implements EnvironmentRepository, Initial
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("Could not pull remote for " + label + " (current ref=" + ref
|
||||
+ ")");
|
||||
+ "), remote: " + git.getRepository().getConfig().getString("remote", "origin", "url"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +261,12 @@ public class JGitEnvironmentRepository implements EnvironmentRepository, Initial
|
||||
|
||||
private Git copyFromLocalRepository() throws IOException {
|
||||
Git git;
|
||||
FileSystemUtils.copyRecursively(new UrlResource(uri).getFile(), basedir);
|
||||
File remote = new UrlResource(StringUtils.cleanPath(uri)).getFile();
|
||||
Assert.state(remote.isDirectory(), "No directory at " + uri);
|
||||
File gitDir = new File(remote, ".git");
|
||||
Assert.state(gitDir.exists(), "No .git at " + uri);
|
||||
Assert.state(gitDir.isDirectory(), "No .git directory at " + uri);
|
||||
basedir = remote;
|
||||
git = Git.open(basedir);
|
||||
return git;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = ConfigServerApplication.class)
|
||||
@IntegrationTest({"server.port:0", "spring.config.name:configserver", "spring.cloud.config.server.git.uri:file:./target/test-classes/config-repo"})
|
||||
@IntegrationTest({"server.port:0", "spring.config.name:configserver", "spring.cloud.config.server.git.uri:file:./target/repos/config-repo"})
|
||||
@WebAppConfiguration
|
||||
@ActiveProfiles("test")
|
||||
public class ApplicationTests {
|
||||
|
||||
@@ -19,8 +19,11 @@ package org.springframework.cloud.config.server;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -31,6 +34,8 @@ import org.springframework.cloud.config.Environment;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -47,6 +52,7 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
if (basedir.exists()) {
|
||||
FileUtils.delete(basedir, FileUtils.RECURSIVE);
|
||||
}
|
||||
ConfigServerTestUtils.deleteLocalRepo("config-copy");
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -60,20 +66,42 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
public void vanilla() throws IOException {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo();
|
||||
context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
//TODO: why didn't .properties() work for me?
|
||||
.run("--spring.cloud.config.server.git.uri=" + uri);
|
||||
.properties("spring.cloud.config.server.git.uri:" + uri).run();
|
||||
// TODO: why didn't .properties() work for me?
|
||||
// .run("--spring.cloud.config.server.git.uri=" + uri);
|
||||
EnvironmentRepository repository = context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("bar", "staging", "master");
|
||||
Environment environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pull() throws Exception {
|
||||
ConfigServerTestUtils.prepareLocalRepo();
|
||||
String uri = ConfigServerTestUtils.copyLocalRepo("config-copy");
|
||||
context = new SpringApplicationBuilder(TestConfiguration.class).web(false).run(
|
||||
"--spring.cloud.config.server.git.uri=" + uri);
|
||||
EnvironmentRepository repository = context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("bar", "staging", "master");
|
||||
Environment environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals("bar", environment.getPropertySources().get(0).getSource()
|
||||
.get("foo"));
|
||||
Git git = Git.open(ResourceUtils.getFile(uri).getAbsoluteFile());
|
||||
git.checkout().setName("master").call();
|
||||
StreamUtils.copy("foo: foo", Charset.defaultCharset(), new FileOutputStream(
|
||||
ResourceUtils.getFile(uri + "/bar.properties")));
|
||||
git.add().addFilepattern("bar.properties").call();
|
||||
git.commit().setMessage("Updated for pull").call();
|
||||
environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals("foo", environment.getPropertySources().get(0).getSource()
|
||||
.get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nested() throws IOException {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo("another-config-repo");
|
||||
context = new SpringApplicationBuilder(TestConfiguration.class)
|
||||
.web(false)
|
||||
//TODO: why didn't .properties() work for me?
|
||||
context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
// TODO: why didn't .properties() work for me?
|
||||
.run("--spring.cloud.config.server.git.uri=" + uri,
|
||||
"--spring.cloud.config.server.git.searchPaths=sub");
|
||||
EnvironmentRepository repository = context.getBean(EnvironmentRepository.class);
|
||||
|
||||
Reference in New Issue
Block a user