Introduce API for retrieving the remote config
Extend the ReplicationRemotesApi for retrieving the
configuration associated with multiple replication remotes.
NOTE: The configuration would not include passwords
for the sake of not exposing them when not necessarily needed.
Change-Id: I26b6f098dd7b6331adf929315b2cc1cebdf0eb4a
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/MergedConfigResource.java b/src/main/java/com/googlesource/gerrit/plugins/replication/MergedConfigResource.java
index 315c4a6..58a10f0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/MergedConfigResource.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/MergedConfigResource.java
@@ -78,7 +78,7 @@
return baseVersion + overrides.get().getVersion();
}
- private boolean noOverrides() {
+ boolean noOverrides() {
return overrides == null || overrides.get() == null;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationRemotesApiImpl.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationRemotesApiImpl.java
index dd4d5b0..e4ef318 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationRemotesApiImpl.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationRemotesApiImpl.java
@@ -14,34 +14,42 @@
package com.googlesource.gerrit.plugins.replication;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.server.securestore.SecureStore;
import com.google.inject.Inject;
-import com.google.inject.Provider;
import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.replication.api.ConfigResource;
-import com.googlesource.gerrit.plugins.replication.api.ReplicationConfigOverrides;
import com.googlesource.gerrit.plugins.replication.api.ReplicationRemotesApi;
import java.io.IOException;
+import java.util.Arrays;
import java.util.List;
+import java.util.Set;
import org.eclipse.jgit.lib.Config;
@Singleton
class ReplicationRemotesApiImpl implements ReplicationRemotesApi {
private final SecureStore secureStore;
- private final Provider<ConfigResource> baseConfigProvider;
- private final DynamicItem<ReplicationConfigOverrides> configOverridesItem;
+ private final MergedConfigResource mergedConfigResource;
@Inject
- ReplicationRemotesApiImpl(
- SecureStore secureStore,
- Provider<ConfigResource> baseConfigProvider,
- @Nullable DynamicItem<ReplicationConfigOverrides> configOverridesItem) {
+ ReplicationRemotesApiImpl(SecureStore secureStore, MergedConfigResource mergedConfigResource) {
this.secureStore = secureStore;
- this.baseConfigProvider = baseConfigProvider;
- this.configOverridesItem = configOverridesItem;
+ this.mergedConfigResource = mergedConfigResource;
+ }
+
+ @Override
+ public Config get(String... remoteNames) {
+ Config replicationConfig = mergedConfigResource.getConfig();
+ Config remoteConfig = new Config();
+ for (String remoteName : remoteNames) {
+ Set<String> configNames = replicationConfig.getNames("remote", remoteName);
+ for (String configName : configNames) {
+ String[] values = replicationConfig.getStringList("remote", remoteName, configName);
+ if (values.length > 0) {
+ remoteConfig.setStringList("remote", remoteName, configName, Arrays.asList(values));
+ }
+ }
+ }
+ return remoteConfig;
}
@Override
@@ -54,11 +62,7 @@
SeparatedRemoteConfigs configs = onlyRemoteSectionsWithSeparatedPasswords(remoteConfig);
persistRemotesPasswords(configs);
- if (hasConfigOverrides()) {
- configOverridesItem.get().update(configs.remotes);
- } else {
- baseConfigProvider.get().update(configs.remotes);
- }
+ mergedConfigResource.update(configs.remotes);
}
private SeparatedRemoteConfigs onlyRemoteSectionsWithSeparatedPasswords(Config configUpdates) {
@@ -85,10 +89,6 @@
}
}
- private boolean hasConfigOverrides() {
- return configOverridesItem != null && configOverridesItem.get() != null;
- }
-
private static class SeparatedRemoteConfigs {
private final Config remotes = new Config();
private final Config passwords = new Config();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/api/ReplicationRemotesApi.java b/src/main/java/com/googlesource/gerrit/plugins/replication/api/ReplicationRemotesApi.java
index fde2abc..76d6d35 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/api/ReplicationRemotesApi.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/api/ReplicationRemotesApi.java
@@ -28,6 +28,19 @@
public interface ReplicationRemotesApi {
/**
+ * Retrieves the configuration for a remote by name.
+ *
+ * <p>Builds a JGit {@link Config} with the remote's configuration obtained by parsing the
+ * replication configuration sources.
+ *
+ * <p>NOTE: The remotes secrets are excluded for security reasons.
+ *
+ * @param remoteNames the remote names to retrieve.
+ * @return {@link Config} associated with the remoteName(s)
+ */
+ Config get(String... remoteNames);
+
+ /**
* Adds or updates the remote configuration for the replication plugin.
*
* <p>Provided JGit {@link Config} object should contain at least one named <em>remote</em>
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationRemotesApiTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationRemotesApiTest.java
index 3aa97e8..a806875 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationRemotesApiTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationRemotesApiTest.java
@@ -19,20 +19,23 @@
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import com.google.common.io.MoreFiles;
import com.google.common.truth.StringSubject;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.securestore.SecureStore;
-import com.google.inject.util.Providers;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.googlesource.gerrit.plugins.replication.api.ConfigResource;
import com.googlesource.gerrit.plugins.replication.api.ReplicationConfigOverrides;
import com.googlesource.gerrit.plugins.replication.api.ReplicationRemotesApi;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jgit.lib.Config;
import org.junit.After;
import org.junit.Before;
@@ -43,12 +46,36 @@
private Path testSite;
private SecureStore secureStoreMock;
private FileConfigResource baseConfig;
+ private Injector testInjector;
+ private AtomicReference<ReplicationConfigOverrides> testOverrides;
+ private String url1;
+ private String remoteName1;
+ private String url2;
+ private String remoteName2;
@Before
public void setUp() throws Exception {
testSite = Files.createTempDirectory("replicationRemotesUpdateTest");
secureStoreMock = mock(SecureStore.class);
baseConfig = new FileConfigResource(new SitePaths(testSite));
+ testOverrides = new AtomicReference<>(new TestReplicationConfigOverrides());
+ testInjector =
+ Guice.createInjector(
+ new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(ConfigResource.class).toInstance(baseConfig);
+ bind(SecureStore.class).toInstance(secureStoreMock);
+ bind(ReplicationRemotesApi.class).to(ReplicationRemotesApiImpl.class);
+ DynamicItem.itemOf(binder(), ReplicationConfigOverrides.class);
+ DynamicItem.bind(binder(), ReplicationConfigOverrides.class)
+ .toProvider(testOverrides::get);
+ }
+ });
+ url1 = "fake_url1";
+ remoteName1 = "site1";
+ url2 = "fake_url2";
+ remoteName2 = "site2";
}
@After
@@ -59,7 +86,7 @@
@Test
public void shouldThrowWhenNoRemotesInTheUpdate() {
Config update = new Config();
- ReplicationRemotesApi objectUnderTest = newReplicationConfigUpdater();
+ ReplicationRemotesApi objectUnderTest = getReplicationRemotesApi();
assertThrows(IllegalArgumentException.class, () -> objectUnderTest.update(update));
@@ -69,64 +96,83 @@
}
@Test
- public void addRemoteSectionToBaseConfigWhenNoOverrides() throws Exception {
- String url = "fake_url";
- Config update = new Config();
- setRemoteSite(update, "url", url);
- ReplicationRemotesApi objectUnderTest = newReplicationConfigUpdater();
-
- objectUnderTest.update(update);
-
- assertRemoteSite(baseConfig.getConfig(), "url").isEqualTo(url);
+ public void shouldReturnEmptyConfigWhenNoRemotes() {
+ ReplicationRemotesApi objectUnderTest = getReplicationRemotesApi();
+ assertThat(objectUnderTest.get("site").getSections()).isEmpty();
}
@Test
- public void addRemoteSectionToBaseOverridesConfig() throws Exception {
- TestReplicationConfigOverrides testOverrides = new TestReplicationConfigOverrides();
- String url = "fake_url";
+ public void addRemoteSectionsToBaseConfigWhenNoOverrides() throws Exception {
+ testOverrides.set(null);
+
Config update = new Config();
- setRemoteSite(update, "url", url);
- ReplicationRemotesApi objectUnderTest = newReplicationConfigUpdater(testOverrides);
+ setRemoteSite(update, remoteName1, "url", url1);
+ setRemoteSite(update, remoteName2, "url", url2);
+ ReplicationRemotesApi objectUnderTest = getReplicationRemotesApi();
objectUnderTest.update(update);
- assertRemoteSite(testOverrides.getConfig(), "url").isEqualTo(url);
- assertRemoteSite(baseConfig.getConfig(), "url").isNull();
+ assertRemoteSite(baseConfig.getConfig(), remoteName1, "url").isEqualTo(url1);
+ assertRemoteSite(baseConfig.getConfig(), remoteName2, "url").isEqualTo(url2);
}
@Test
- public void encryptPassword() throws Exception {
- TestReplicationConfigOverrides testOverrides = new TestReplicationConfigOverrides();
+ public void shouldReturnRemotesFromBaseConfigWhenNoOverrides() {
+ ReplicationRemotesApi objectUnderTest = getReplicationRemotesApi();
+
+ baseConfig.getConfig().setString("remote", remoteName1, "url", url1);
+ baseConfig.getConfig().setString("remote", remoteName2, "url", url2);
+
+ Config remotesConfig = objectUnderTest.get(remoteName1, remoteName2);
+ assertRemoteSite(remotesConfig, remoteName1, "url").isEqualTo(url1);
+ assertRemoteSite(remotesConfig, remoteName2, "url").isEqualTo(url2);
+ }
+
+ @Test
+ public void addRemotesSectionToBaseOverridesConfig() throws Exception {
+ Config update = new Config();
+ setRemoteSite(update, remoteName1, "url", url1);
+ setRemoteSite(update, remoteName2, "url", url2);
+ ReplicationRemotesApi objectUnderTest = getReplicationRemotesApi();
+
+ objectUnderTest.update(update);
+
+ assertRemoteSite(testOverrides.get().getConfig(), remoteName1, "url").isEqualTo(url1);
+ assertRemoteSite(testOverrides.get().getConfig(), remoteName2, "url").isEqualTo(url2);
+ assertRemoteSite(baseConfig.getConfig(), remoteName1, "url").isNull();
+ assertRemoteSite(baseConfig.getConfig(), remoteName2, "url").isNull();
+
+ Config remotesConfig = objectUnderTest.get(remoteName1, remoteName2);
+ assertRemoteSite(remotesConfig, remoteName1, "url").isEqualTo(url1);
+ assertRemoteSite(remotesConfig, remoteName2, "url").isEqualTo(url2);
+ }
+
+ @Test
+ public void shouldEncryptPasswordButNotStoreInConfig() throws Exception {
Config update = new Config();
String password = "my_secret_password";
- setRemoteSite(update, "password", password);
- ReplicationRemotesApi objectUnderTest = newReplicationConfigUpdater(testOverrides);
+ String remoteName = "site";
+ setRemoteSite(update, remoteName, "password", password);
+ ReplicationRemotesApi objectUnderTest = getReplicationRemotesApi();
objectUnderTest.update(update);
- verify(secureStoreMock).setList("remote", "site", "password", List.of(password));
- assertRemoteSite(baseConfig.getConfig(), "password").isNull();
- assertRemoteSite(testOverrides.getConfig(), "password").isNull();
+ verify(secureStoreMock).setList("remote", remoteName, "password", List.of(password));
+ assertRemoteSite(baseConfig.getConfig(), remoteName, "password").isNull();
+ assertRemoteSite(testOverrides.get().getConfig(), remoteName, "password").isNull();
+ assertRemoteSite(objectUnderTest.get(remoteName), remoteName, "password").isNull();
}
- private ReplicationRemotesApi newReplicationConfigUpdater() {
- return newReplicationConfigUpdater(null);
+ private void setRemoteSite(Config config, String remoteName, String name, String value) {
+ config.setString("remote", remoteName, name, value);
}
- private void setRemoteSite(Config config, String name, String value) {
- config.setString("remote", "site", name, value);
+ private StringSubject assertRemoteSite(Config config, String remoteName, String name) {
+ return assertThat(config.getString("remote", remoteName, name));
}
- private StringSubject assertRemoteSite(Config config, String name) {
- return assertThat(config.getString("remote", "site", name));
- }
-
- private ReplicationRemotesApi newReplicationConfigUpdater(ReplicationConfigOverrides overrides) {
- DynamicItem<ReplicationConfigOverrides> dynamicItemMock = mock(DynamicItem.class);
- when(dynamicItemMock.get()).thenReturn(overrides);
-
- return new ReplicationRemotesApiImpl(
- secureStoreMock, Providers.of(baseConfig), dynamicItemMock);
+ private ReplicationRemotesApi getReplicationRemotesApi() {
+ return testInjector.getInstance(ReplicationRemotesApi.class);
}
static class TestReplicationConfigOverrides implements ReplicationConfigOverrides {