Stream events listener should respect `remote.NAME.projects` param
remote.NAME.projects param specifies which repositories should be
replicated from the remote. Add filtering to the StreamEventListener
to make sure that pull-replication does not trigger fetch operations
for repositories outside of the list.
Bug: Issue 16751
Change-Id: I43de26602ae84a41631f6f8c6052389e959367ff
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/StreamEventListener.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/StreamEventListener.java
index 2961360..0477b1a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/StreamEventListener.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/StreamEventListener.java
@@ -27,12 +27,14 @@
import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.EventListener;
import com.google.gerrit.server.events.ProjectCreatedEvent;
+import com.google.gerrit.server.events.ProjectEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.googlesource.gerrit.plugins.replication.pull.FetchOne;
+import com.googlesource.gerrit.plugins.replication.pull.SourcesCollection;
import com.googlesource.gerrit.plugins.replication.pull.api.DeleteRefCommand;
import com.googlesource.gerrit.plugins.replication.pull.api.FetchAction;
import com.googlesource.gerrit.plugins.replication.pull.api.FetchJob;
@@ -53,6 +55,7 @@
private Factory fetchJobFactory;
private final Provider<PullReplicationApiRequestMetrics> metricsProvider;
+ private final SourcesCollection sources;
@Inject
public StreamEventListener(
@@ -61,13 +64,15 @@
ProjectInitializationAction projectInitializationAction,
WorkQueue workQueue,
FetchJob.Factory fetchJobFactory,
- Provider<PullReplicationApiRequestMetrics> metricsProvider) {
+ Provider<PullReplicationApiRequestMetrics> metricsProvider,
+ SourcesCollection sources) {
this.instanceId = instanceId;
this.deleteCommand = deleteCommand;
this.projectInitializationAction = projectInitializationAction;
this.workQueue = workQueue;
this.fetchJobFactory = fetchJobFactory;
this.metricsProvider = metricsProvider;
+ this.sources = sources;
requireNonNull(
Strings.emptyToNull(this.instanceId), "gerrit.instanceId cannot be null or empty");
@@ -86,7 +91,7 @@
}
public void fetchRefsForEvent(Event event) throws AuthException, PermissionBackendException {
- if (instanceId.equals(event.instanceId)) {
+ if (instanceId.equals(event.instanceId) || !shouldReplicateProject(event)) {
return;
}
@@ -138,6 +143,19 @@
}
}
+ private boolean shouldReplicateProject(Event event) {
+ if (!(event instanceof ProjectEvent)) {
+ return false;
+ }
+
+ ProjectEvent projectEvent = (ProjectEvent) event;
+ return sources.getAll().stream()
+ .filter(s -> s.getRemoteConfigName().equals(projectEvent.instanceId))
+ .findFirst()
+ .map(s -> s.wouldFetchProject(projectEvent.getProjectNameKey()))
+ .orElse(false);
+ }
+
private boolean isRefDelete(RefUpdatedEvent event) {
return ZERO_ID_NAME.equals(event.refUpdate.get().newRev);
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/StreamEventListenerTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/StreamEventListenerTest.java
index b87d42c..9312432 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/StreamEventListenerTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/StreamEventListenerTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import com.google.common.collect.Lists;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.restapi.AuthException;
@@ -32,6 +33,8 @@
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.googlesource.gerrit.plugins.replication.pull.FetchOne;
+import com.googlesource.gerrit.plugins.replication.pull.Source;
+import com.googlesource.gerrit.plugins.replication.pull.SourcesCollection;
import com.googlesource.gerrit.plugins.replication.pull.api.DeleteRefCommand;
import com.googlesource.gerrit.plugins.replication.pull.api.FetchAction.Input;
import com.googlesource.gerrit.plugins.replication.pull.api.FetchJob;
@@ -65,6 +68,8 @@
@Mock private DeleteRefCommand deleteRefCommand;
@Captor ArgumentCaptor<Input> inputCaptor;
@Mock private PullReplicationApiRequestMetrics metrics;
+ @Mock private SourcesCollection sources;
+ @Mock private Source source;
private StreamEventListener objectUnderTest;
@@ -73,6 +78,9 @@
when(workQueue.getDefaultQueue()).thenReturn(executor);
when(fetchJobFactory.create(eq(Project.nameKey(TEST_PROJECT)), any(), any()))
.thenReturn(fetchJob);
+ when(sources.getAll()).thenReturn(Lists.newArrayList(source));
+ when(source.wouldFetchProject(any())).thenReturn(true);
+ when(source.getRemoteConfigName()).thenReturn(REMOTE_INSTANCE_ID);
objectUnderTest =
new StreamEventListener(
INSTANCE_ID,
@@ -80,7 +88,8 @@
projectInitializationAction,
workQueue,
fetchJobFactory,
- () -> metrics);
+ () -> metrics,
+ sources);
}
@Test
@@ -90,6 +99,7 @@
objectUnderTest.onEvent(event);
verify(executor, never()).submit(any(Runnable.class));
+ verify(sources, never()).getAll();
}
@Test
@@ -109,6 +119,25 @@
}
@Test
+ public void shouldSkipEventWhenNotOnAllowedProjectsList() {
+ when(source.wouldFetchProject(any())).thenReturn(false);
+
+ RefUpdatedEvent event = new RefUpdatedEvent();
+ RefUpdateAttribute refUpdate = new RefUpdateAttribute();
+ refUpdate.refName = TEST_REF_NAME;
+ refUpdate.project = TEST_PROJECT;
+ refUpdate.oldRev = ObjectId.zeroId().getName();
+ refUpdate.newRev = NEW_REV;
+
+ event.instanceId = REMOTE_INSTANCE_ID;
+ event.refUpdate = () -> refUpdate;
+
+ objectUnderTest.onEvent(event);
+
+ verify(executor, never()).submit(any(Runnable.class));
+ }
+
+ @Test
public void shouldDeleteRefForRefDeleteEvent() throws IOException, RestApiException {
RefUpdatedEvent event = new RefUpdatedEvent();
RefUpdateAttribute refUpdate = new RefUpdateAttribute();