Merge remote-tracking branch 'origin/1.4.x' into 2.0.x
This commit is contained in:
@@ -971,8 +971,11 @@ The asymmetric choice is superior in terms of security, but it is often more con
|
||||
|
||||
To configure a symmetric key, you need to set `encrypt.key` to a secret String (or use the `ENCRYPT_KEY` environment variable to keep it out of plain-text configuration files).
|
||||
|
||||
To configure an asymmetric key, you can either set the key as a PEM-encoded text value (in `encrypt.key`) or use a keystore (such as the keystore created by the `keytool` utility that comes with the JDK).
|
||||
The following table describes the keystore properties:
|
||||
NOTE: You cannot configure an asymmetric key using `encrypt.key`.
|
||||
|
||||
To configure an asymmetric key use a keystore (e.g. as
|
||||
created by the `keytool` utility that comes with the JDK). The
|
||||
keystore properties are `encrypt.keyStore.\*` with `*` equal to
|
||||
|
||||
[options="header"]
|
||||
|===
|
||||
|
||||
@@ -243,7 +243,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
public synchronized void afterPropertiesSet() throws Exception {
|
||||
Assert.state(getUri() != null,
|
||||
MESSAGE);
|
||||
initialize();
|
||||
|
||||
@@ -17,12 +17,24 @@
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.jgit.api.CheckoutCommand;
|
||||
import org.eclipse.jgit.api.CloneCommand;
|
||||
import org.eclipse.jgit.api.FetchCommand;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.*;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.transport.FetchResult;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -96,6 +108,63 @@ public class JGitEnvironmentRepositoryConcurrencyTests {
|
||||
assertEquals("master", environment.getLabel());
|
||||
}
|
||||
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* Simulates following actions in parallel:
|
||||
* - Client tries to obtain configuration with specified label
|
||||
* - Spring Refresh Context Event occurs
|
||||
*/
|
||||
@Test
|
||||
public void concurrentRefreshContextAndGetLabels() throws Exception {
|
||||
// Prepare the repo
|
||||
final JGitConfigServerTestData testData = JGitConfigServerTestData.prepareClonedGitRepository(TestConfiguration.class);
|
||||
JGitEnvironmentRepository repository = testData.getRepository();
|
||||
repository.setCloneOnStart(true);
|
||||
repository.setGitFactory(new DelayedGitFactoryMock());
|
||||
repository.setBasedir(testData.getClonedGit().getGitWorkingDirectory());
|
||||
repository.setUri(testData.getServerGit().getGitWorkingDirectory().getAbsolutePath().replace("file://", ""));
|
||||
|
||||
final AtomicInteger errorCount = new AtomicInteger();
|
||||
|
||||
// Prepare two threads to do the parallel work
|
||||
Thread client = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
logger.info("client start.");
|
||||
try {
|
||||
Environment environment = testData.getRepository().findOne("bar", "staging", "master");
|
||||
} catch (Exception e) {
|
||||
errorCount.incrementAndGet();
|
||||
e.printStackTrace();
|
||||
}
|
||||
logger.info("client end.");
|
||||
}
|
||||
});
|
||||
|
||||
Thread refresh = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
logger.info("refresh start.");
|
||||
testData.getRepository().afterPropertiesSet();
|
||||
logger.info("refresh end.");
|
||||
} catch (Exception e) {
|
||||
errorCount.incrementAndGet();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Start the parallel actions and wait till the end.
|
||||
refresh.start();
|
||||
client.start();
|
||||
refresh.join();
|
||||
client.join();
|
||||
|
||||
assertEquals(0, errorCount.get());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
@Import({ PropertyPlaceholderAutoConfiguration.class,
|
||||
@@ -103,4 +172,80 @@ public class JGitEnvironmentRepositoryConcurrencyTests {
|
||||
protected static class TestConfiguration {
|
||||
}
|
||||
|
||||
private static class DelayedGitFactoryMock extends JGitEnvironmentRepository.JGitFactory {
|
||||
|
||||
@Override
|
||||
public Git getGitByOpen(File file) throws IOException {
|
||||
Git originalGit = DelayedGitMock.open(file);
|
||||
return new DelayedGitMock(originalGit.getRepository());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloneCommand getCloneCommandByCloneRepository() {
|
||||
return new DelayedCloneCommand();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DelayedGitMock extends Git {
|
||||
|
||||
public DelayedGitMock(Repository repo) {
|
||||
super(repo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchCommand fetch() {
|
||||
return new DelayedFetchCommand(getRepository());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CheckoutCommand checkout() {
|
||||
return new DelayedCheckoutCommand(getRepository());
|
||||
}
|
||||
}
|
||||
|
||||
private static class DelayedCloneCommand extends CloneCommand {
|
||||
@Override
|
||||
public Git call() throws GitAPIException, InvalidRemoteException, TransportException {
|
||||
try {
|
||||
Thread.sleep(250);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return super.call();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DelayedFetchCommand extends FetchCommand {
|
||||
|
||||
public DelayedFetchCommand(Repository repo) {
|
||||
super(repo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchResult call() throws GitAPIException, InvalidRemoteException, TransportException {
|
||||
try {
|
||||
Thread.sleep(250);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return super.call();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DelayedCheckoutCommand extends CheckoutCommand {
|
||||
public DelayedCheckoutCommand(Repository repo) {
|
||||
super(repo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ref call() throws GitAPIException, RefAlreadyExistsException, RefNotFoundException, InvalidRefNameException, CheckoutConflictException {
|
||||
try {
|
||||
Thread.sleep(250);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return super.call();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user