Merge branch 'stable-3.4' * stable-3.4: Introduce Bearer Token Authentication Remove authorisation from ProjectInitializationAction Allow internal user to delete project in Pull Replication API in a primary node Fix flaky test in Pull Replication plugin FetchJob creation fails in replica when FetchAction is invoked with async=true Remove authorisation from PullReplicationFilter Use preemptive basic authentication in Pull Replication Plugin Do not rely on magic numbers for parsing the URL Do not use timer.getStartTime() when propating timers metrics Add missing @Assisted when creating the metrics Do not rely on System.nanoTime for E2E metrics Reduce default exclude refs filter Introduce the apply-objects REST-API for the whole '/meta' chain Fix the processing of an empty HTML response body from REST-API Fix issue with ref deletion and global-refdb Fix issue with fetching all refs after project creation Always fallback to fetch when ApplyObject REST-API fails Log the reason why a ref object wasn't loaded by RevisionReader Consider any HTTP 2xx response code from REST-API as success Return NO_CONTENT when removing a ref through ApplyObject Introduce E2E fetch REST-API metrics Fix ApplyObjectIT.shouldApplyRefMetaObject test for apply object Introduce E2E apply object REST-API metrics Add missing @Override to parseRemotes Add more logging for the apply object REST-API Support ApplyObject of non-commit refs Refactor FetchJob to an assisted injection factory Release-Notes: skip Change-Id: I5766e7cd973744c4244c07e9918094d73340f076
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/DeleteProjectTask.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/DeleteProjectTask.java index 527b746..2882482 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/DeleteProjectTask.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/DeleteProjectTask.java
@@ -67,7 +67,7 @@ } catch (URISyntaxException | IOException e) { String errorMessage = String.format("Cannot delete project %s on remote site %s.", project, uri); - logger.atWarning().withCause(e).log(errorMessage); + logger.atWarning().withCause(e).log("%s", errorMessage); repLog.warn(errorMessage); } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchOne.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchOne.java index 4fad8f9..d8da65e 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchOne.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchOne.java
@@ -36,7 +36,6 @@ import com.googlesource.gerrit.plugins.replication.pull.fetch.Fetch; import com.googlesource.gerrit.plugins.replication.pull.fetch.FetchFactory; import com.googlesource.gerrit.plugins.replication.pull.fetch.RefUpdateState; -import com.jcraft.jsch.JSchException; import java.io.IOException; import java.util.Collection; import java.util.HashSet; @@ -330,9 +329,7 @@ stateLog.error("Cannot replicate from " + uri, e, getStatesAsArray()); } catch (TransportException e) { Throwable cause = e.getCause(); - if (cause instanceof JSchException && cause.getMessage().startsWith("UnknownHostKey:")) { - repLog.error("Cannot replicate from {}: {}", uri, cause.getMessage()); - } else if (e instanceof LockFailureException) { + if (e instanceof LockFailureException) { lockRetryCount++; // The LockFailureException message contains both URI and reason // for this failure.
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchRefReplicatedEvent.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchRefReplicatedEvent.java index 8bf257e..0eabf42 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchRefReplicatedEvent.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchRefReplicatedEvent.java
@@ -15,30 +15,23 @@ package com.googlesource.gerrit.plugins.replication.pull; import com.google.gerrit.entities.Project; -import com.google.gerrit.server.events.RefEvent; +import com.googlesource.gerrit.plugins.replication.events.RemoteRefReplicationEvent; import java.util.Objects; import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.transport.URIish; -public class FetchRefReplicatedEvent extends RefEvent { +public class FetchRefReplicatedEvent extends RemoteRefReplicationEvent { static final String TYPE = "fetch-ref-replicated"; - final String project; - final String ref; - final String sourceNode; - final String status; final RefUpdate.Result refUpdateResult; public FetchRefReplicatedEvent( String project, String ref, - String sourceNode, + URIish sourceUri, ReplicationState.RefFetchResult status, RefUpdate.Result refUpdateResult) { - super(TYPE); - this.project = project; - this.ref = ref; - this.sourceNode = sourceNode; - this.status = status.toString(); + super(TYPE, project, ref, sourceUri, status.toString()); this.refUpdateResult = refUpdateResult; } @@ -63,7 +56,7 @@ if (!Objects.equals(event.ref, this.ref)) { return false; } - if (!Objects.equals(event.sourceNode, this.sourceNode)) { + if (!Objects.equals(event.targetUri, this.targetUri)) { return false; } if (!Objects.equals(event.status, this.status)) { @@ -81,8 +74,4 @@ public String getRefName() { return ref; } - - public String getSourceNode() { - return sourceNode; - } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchReplicationScheduledEvent.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchReplicationScheduledEvent.java index 9a29c86..4f96a8f 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchReplicationScheduledEvent.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchReplicationScheduledEvent.java
@@ -15,20 +15,14 @@ package com.googlesource.gerrit.plugins.replication.pull; import com.google.gerrit.entities.Project; -import com.google.gerrit.server.events.RefEvent; +import com.googlesource.gerrit.plugins.replication.events.RemoteRefReplicationEvent; +import org.eclipse.jgit.transport.URIish; -public class FetchReplicationScheduledEvent extends RefEvent { +public class FetchReplicationScheduledEvent extends RemoteRefReplicationEvent { static final String TYPE = "fetch-ref-replication-scheduled"; - final String project; - final String ref; - final String sourceNode; - - public FetchReplicationScheduledEvent(String project, String ref, String sourceNode) { - super(TYPE); - this.project = project; - this.ref = ref; - this.sourceNode = sourceNode; + public FetchReplicationScheduledEvent(String project, String ref, URIish sourceUri) { + super(TYPE, project, ref, sourceUri, null); } @Override @@ -40,8 +34,4 @@ public Project.NameKey getProjectNameKey() { return Project.nameKey(project); } - - public String getSourceNode() { - return sourceNode; - } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchResultProcessing.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchResultProcessing.java index ab16318..eb94ecc 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchResultProcessing.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/FetchResultProcessing.java
@@ -55,7 +55,7 @@ // Default doing nothing } - public static String resolveNodeName(URIish uri) { + private static String resolveNodeName(URIish uri) { StringBuilder sb = new StringBuilder(); if (uri.isRemote()) { sb.append(uri.getHost()); @@ -120,8 +120,7 @@ try { Context.setLocalEvent(true); dispatcher.postEvent( - new FetchRefReplicatedEvent( - project, ref, resolveNodeName(uri), status, refUpdateResult)); + new FetchRefReplicatedEvent(project, ref, uri, status, refUpdateResult)); } catch (PermissionBackendException e) { logger.atSevere().withCause(e).log( "Cannot post event for ref '%s', project %s", ref, project); @@ -189,8 +188,7 @@ URIish uri, ReplicationState.RefFetchResult result, RefUpdate.Result refUpdateResult) { - postEvent( - new FetchRefReplicatedEvent(project, ref, resolveNodeName(uri), result, refUpdateResult)); + postEvent(new FetchRefReplicatedEvent(project, ref, uri, result, refUpdateResult)); } @Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/GerritConfigOps.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/GerritConfigOps.java index 2437d80..bca2219 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/GerritConfigOps.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/GerritConfigOps.java
@@ -46,7 +46,7 @@ uri = new URIish("file://" + basePath + "/" + projectName); return Optional.of(uri); } catch (URISyntaxException e) { - logger.atSevere().withCause(e).log("Unsupported URI for project " + projectName); + logger.atSevere().withCause(e).log("Unsupported URI for project %s", projectName); } return Optional.empty();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/Source.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/Source.java index 6bf4c21..3170eb5 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/Source.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/Source.java
@@ -15,7 +15,6 @@ package com.googlesource.gerrit.plugins.replication.pull; import static com.googlesource.gerrit.plugins.replication.ReplicationFileBasedConfig.replaceName; -import static com.googlesource.gerrit.plugins.replication.pull.FetchResultProcessing.resolveNodeName; import static com.googlesource.gerrit.plugins.replication.pull.ReplicationType.SYNC; import com.google.common.base.Throwables; @@ -796,10 +795,9 @@ private void postReplicationScheduledEvent(FetchOne fetchOp, String inputRef) { Set<String> refs = inputRef == null ? fetchOp.getRefs() : ImmutableSet.of(inputRef); Project.NameKey project = fetchOp.getProjectNameKey(); - String targetNode = resolveNodeName(fetchOp.getURI()); for (String ref : refs) { FetchReplicationScheduledEvent event = - new FetchReplicationScheduledEvent(project.get(), ref, targetNode); + new FetchReplicationScheduledEvent(project.get(), ref, fetchOp.getURI()); try { eventDispatcher.get().postEvent(BranchNameKey.create(project, ref), event); } catch (PermissionBackendException e) { @@ -810,13 +808,16 @@ private void postReplicationFailedEvent(FetchOne fetchOp, RefUpdate.Result result) { Project.NameKey project = fetchOp.getProjectNameKey(); - String sourceNode = resolveNodeName(fetchOp.getURI()); try { Context.setLocalEvent(true); for (String ref : fetchOp.getRefs()) { FetchRefReplicatedEvent event = new FetchRefReplicatedEvent( - project.get(), ref, sourceNode, ReplicationState.RefFetchResult.FAILED, result); + project.get(), + ref, + fetchOp.getURI(), + ReplicationState.RefFetchResult.FAILED, + result); try { eventDispatcher.get().postEvent(BranchNameKey.create(project, ref), event); } catch (PermissionBackendException e) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourceConfiguration.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourceConfiguration.java index ab9c634..aff1266 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourceConfiguration.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourceConfiguration.java
@@ -211,4 +211,9 @@ public int getSlowLatencyThreshold() { return slowLatencyThreshold; } + + @Override + public int getPushBatchSize() { + return 0; + } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourcesCollection.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourcesCollection.java index 7be4971..53adaaa 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourcesCollection.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourcesCollection.java
@@ -27,7 +27,11 @@ import com.googlesource.gerrit.plugins.replication.RemoteConfiguration; import com.googlesource.gerrit.plugins.replication.ReplicationConfig; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; import org.eclipse.jgit.errors.ConfigInvalidException; @Singleton @@ -35,7 +39,7 @@ private static final FluentLogger logger = FluentLogger.forEnclosingClass(); private final Source.Factory sourceFactory; - private volatile List<Source> sources; + private volatile Map<String, Source> sources; private boolean shuttingDown; private final Provider<ReplicationQueue> replicationQueue; @@ -56,22 +60,26 @@ @Override public List<Source> getAll() { - return sources.stream().filter(Objects::nonNull).collect(toList()); + return sources.values().stream().filter(Objects::nonNull).collect(toList()); } - private List<Source> allSources( + public Optional<Source> getByRemoteName(String remoteName) { + return Optional.ofNullable(sources.get(remoteName)); + } + + private Map<String, Source> allSources( Source.Factory sourceFactory, List<RemoteConfiguration> sourceConfigurations) { return sourceConfigurations.stream() .filter((c) -> c instanceof SourceConfiguration) .map((c) -> (SourceConfiguration) c) .map(sourceFactory::create) - .collect(toList()); + .collect(Collectors.toMap(Source::getRemoteConfigName, Function.identity())); } @Override public void startup(WorkQueue workQueue) { shuttingDown = false; - for (Source cfg : sources) { + for (Source cfg : sources.values()) { cfg.start(workQueue); } } @@ -96,7 +104,7 @@ } int discarded = 0; - for (Source cfg : sources) { + for (Source cfg : sources.values()) { discarded += cfg.shutdown(); } return discarded;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/UpdateHeadTask.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/UpdateHeadTask.java index e169eb3..fabe3cd 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/UpdateHeadTask.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/UpdateHeadTask.java
@@ -72,7 +72,7 @@ String.format( "Cannot update HEAD of project %s remote site %s", project.get(), apiURI.toASCIIString()); - logger.atWarning().withCause(e).log(errorMessage); + logger.atWarning().withCause(e).log("%s", errorMessage); repLog.warn(errorMessage); } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectCommand.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectCommand.java index b27d8b7..c268ba1 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectCommand.java
@@ -31,6 +31,8 @@ import com.googlesource.gerrit.plugins.replication.pull.PullReplicationStateLogger; import com.googlesource.gerrit.plugins.replication.pull.ReplicationState; import com.googlesource.gerrit.plugins.replication.pull.ReplicationState.RefFetchResult; +import com.googlesource.gerrit.plugins.replication.pull.Source; +import com.googlesource.gerrit.plugins.replication.pull.SourcesCollection; import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionData; import com.googlesource.gerrit.plugins.replication.pull.api.exception.MissingParentObjectException; import com.googlesource.gerrit.plugins.replication.pull.api.exception.RefUpdateException; @@ -57,17 +59,20 @@ private final ApplyObject applyObject; private final ApplyObjectMetrics metrics; private final DynamicItem<EventDispatcher> eventDispatcher; + private final SourcesCollection sourcesCollection; @Inject public ApplyObjectCommand( PullReplicationStateLogger fetchStateLog, ApplyObject applyObject, ApplyObjectMetrics metrics, - DynamicItem<EventDispatcher> eventDispatcher) { + DynamicItem<EventDispatcher> eventDispatcher, + SourcesCollection sourcesCollection) { this.fetchStateLog = fetchStateLog; this.applyObject = applyObject; this.metrics = metrics; this.eventDispatcher = eventDispatcher; + this.sourcesCollection = sourcesCollection; } public void applyObject( @@ -94,16 +99,23 @@ try { Context.setLocalEvent(true); + Source source = + sourcesCollection + .getByRemoteName(sourceLabel) + .orElseThrow( + () -> + new IllegalStateException( + String.format("Could not find URI for %s remote", sourceLabel))); eventDispatcher .get() .postEvent( new FetchRefReplicatedEvent( name.get(), refName, - sourceLabel, + source.getURI(name), getStatus(refUpdateState), refUpdateState.getResult())); - } catch (PermissionBackendException e) { + } catch (PermissionBackendException | IllegalStateException e) { logger.atSevere().withCause(e).log( "Cannot post event for ref '%s', project %s", refName, name); } finally {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/DeleteRefCommand.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/DeleteRefCommand.java index 2a3a79d..14f2545 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/DeleteRefCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/DeleteRefCommand.java
@@ -33,6 +33,8 @@ import com.googlesource.gerrit.plugins.replication.pull.FetchRefReplicatedEvent; import com.googlesource.gerrit.plugins.replication.pull.PullReplicationStateLogger; import com.googlesource.gerrit.plugins.replication.pull.ReplicationState; +import com.googlesource.gerrit.plugins.replication.pull.Source; +import com.googlesource.gerrit.plugins.replication.pull.SourcesCollection; import com.googlesource.gerrit.plugins.replication.pull.fetch.ApplyObject; import com.googlesource.gerrit.plugins.replication.pull.fetch.RefUpdateState; import java.io.IOException; @@ -40,6 +42,7 @@ import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.transport.URIish; public class DeleteRefCommand { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); @@ -48,6 +51,7 @@ private final ApplyObject applyObject; private final DynamicItem<EventDispatcher> eventDispatcher; private final ProjectCache projectCache; + private final SourcesCollection sourcesCollection; private final PermissionBackend permissionBackend; private final LocalDiskRepositoryManager gitManager; @@ -55,14 +59,16 @@ public DeleteRefCommand( PullReplicationStateLogger fetchStateLog, ProjectCache projectCache, + DynamicItem<EventDispatcher> eventDispatcher, + SourcesCollection sourcesCollection, ApplyObject applyObject, PermissionBackend permissionBackend, - DynamicItem<EventDispatcher> eventDispatcher, LocalDiskRepositoryManager gitManager) { this.fetchStateLog = fetchStateLog; this.projectCache = projectCache; this.applyObject = applyObject; this.eventDispatcher = eventDispatcher; + this.sourcesCollection = sourcesCollection; this.permissionBackend = permissionBackend; this.gitManager = gitManager; } @@ -76,6 +82,15 @@ throw new ResourceNotFoundException(String.format("Project %s was not found", name)); } + Source source = + sourcesCollection + .getByRemoteName(sourceLabel) + .orElseThrow( + () -> + new IllegalStateException( + String.format("Could not find URI for %s remote", sourceLabel))); + URIish sourceUri = source.getURI(name); + try { projectState.get().checkStatePermitsWrite(); permissionBackend @@ -93,7 +108,7 @@ new FetchRefReplicatedEvent( name.get(), refName, - sourceLabel, + sourceUri, ReplicationState.RefFetchResult.SUCCEEDED, RefUpdate.Result.FORCED)); } catch (PermissionBackendException e) { @@ -108,14 +123,14 @@ new FetchRefReplicatedEvent( name.get(), refName, - sourceLabel, + sourceUri, ReplicationState.RefFetchResult.FAILED, RefUpdate.Result.LOCK_FAILURE)); String message = String.format( "RefUpdate lock failure for: sourceLabel=%s, project=%s, refName=%s", sourceLabel, name, refName); - logger.atSevere().withCause(e).log(message); + logger.atSevere().withCause(e).log("%s", message); fetchStateLog.error(message); throw e; } finally {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommand.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommand.java index 3a502ef..dd06875 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommand.java
@@ -81,8 +81,7 @@ ReplicationState state = fetchReplicationStateFactory.create( new FetchResultProcessing.CommandProcessing(this, eventDispatcher.get())); - Optional<Source> source = - sources.getAll().stream().filter(s -> s.getRemoteConfigName().equals(label)).findFirst(); + Optional<Source> source = sources.getByRemoteName(label); if (!source.isPresent()) { String msg = String.format("Remote configuration section %s not found", label); fetchStateLog.error(msg, state);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java index 0afbecf..cbc2cf7 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java
@@ -272,7 +272,7 @@ try { req.addHeader(new BasicScheme().authenticate(creds, req, null)); } catch (AuthenticationException e) { - logger.atFine().log(String.format("Anonymous Basic Authentication for uri: %s", targetUri)); + logger.atFine().log("Anonymous Basic Authentication for uri: %s", targetUri); } } return req;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/FetchGitUpdateProcessingTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/FetchGitUpdateProcessingTest.java index 77dc947..68044b4 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/FetchGitUpdateProcessingTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/FetchGitUpdateProcessingTest.java
@@ -35,6 +35,7 @@ private GitUpdateProcessing gitUpdateProcessing; private CommandProcessing commandProcessing; private Command sshCommandMock; + private static URIish sourceUri; @Before public void setUp() throws Exception { @@ -42,6 +43,7 @@ gitUpdateProcessing = new GitUpdateProcessing(dispatcherMock); sshCommandMock = mock(Command.class); commandProcessing = new CommandProcessing(sshCommandMock, dispatcherMock); + sourceUri = new URIish("git://someHost/someProject.git"); } @Test @@ -51,14 +53,14 @@ new FetchRefReplicatedEvent( "someProject", "refs/heads/master", - "someHost", + sourceUri, RefFetchResult.SUCCEEDED, RefUpdate.Result.NEW); gitUpdateProcessing.onOneProjectReplicationDone( "someProject", "refs/heads/master", - new URIish("git://someHost/someProject.git"), + sourceUri, RefFetchResult.SUCCEEDED, RefUpdate.Result.NEW); verify(dispatcherMock, times(1)).postEvent(eq(expectedEvent)); @@ -71,7 +73,7 @@ new FetchRefReplicatedEvent( "someProject", "refs/heads/master", - "someHost", + sourceUri, RefFetchResult.SUCCEEDED, RefUpdate.Result.NEW); @@ -90,7 +92,7 @@ new FetchRefReplicatedEvent( "someProject", "refs/changes/01/1/1", - "someHost", + sourceUri, RefFetchResult.FAILED, RefUpdate.Result.REJECTED_OTHER_REASON);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectCommandTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectCommandTest.java index d73a6e7..9b5ef46 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectCommandTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectCommandTest.java
@@ -31,6 +31,8 @@ import com.googlesource.gerrit.plugins.replication.pull.ApplyObjectMetrics; import com.googlesource.gerrit.plugins.replication.pull.FetchRefReplicatedEvent; import com.googlesource.gerrit.plugins.replication.pull.PullReplicationStateLogger; +import com.googlesource.gerrit.plugins.replication.pull.Source; +import com.googlesource.gerrit.plugins.replication.pull.SourcesCollection; import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionData; import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionObjectData; import com.googlesource.gerrit.plugins.replication.pull.api.exception.MissingParentObjectException; @@ -38,9 +40,12 @@ import com.googlesource.gerrit.plugins.replication.pull.fetch.ApplyObject; import com.googlesource.gerrit.plugins.replication.pull.fetch.RefUpdateState; import java.io.IOException; +import java.net.URISyntaxException; import java.util.Collections; +import java.util.Optional; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.transport.URIish; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -55,6 +60,7 @@ private static final String TEST_REF_NAME = "refs/changes/01/1/1"; private static final NameKey TEST_PROJECT_NAME = Project.nameKey("test-project"); private static final String TEST_REMOTE_NAME = "test-remote-name"; + private static URIish TEST_REMOTE_URI; private String sampleCommitObjectId = "9f8d52853089a3cf00c02ff7bd0817bd4353a95a"; private String sampleTreeObjectId = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"; @@ -66,20 +72,26 @@ @Mock private DynamicItem<EventDispatcher> eventDispatcherDataItem; @Mock private EventDispatcher eventDispatcher; @Mock private Timer1.Context<String> timetContext; + @Mock private SourcesCollection sourceCollection; + @Mock private Source source; @Captor ArgumentCaptor<Event> eventCaptor; private ApplyObjectCommand objectUnderTest; @Before - public void setup() throws MissingParentObjectException, IOException { + public void setup() throws MissingParentObjectException, IOException, URISyntaxException { RefUpdateState state = new RefUpdateState(TEST_REMOTE_NAME, RefUpdate.Result.NEW); + TEST_REMOTE_URI = new URIish("git://some.remote.uri"); when(eventDispatcherDataItem.get()).thenReturn(eventDispatcher); when(metrics.start(anyString())).thenReturn(timetContext); when(timetContext.stop()).thenReturn(100L); when(applyObject.apply(any(), any(), any())).thenReturn(state); + when(sourceCollection.getByRemoteName(TEST_SOURCE_LABEL)).thenReturn(Optional.of(source)); + when(source.getURI(TEST_PROJECT_NAME)).thenReturn(TEST_REMOTE_URI); objectUnderTest = - new ApplyObjectCommand(fetchStateLog, applyObject, metrics, eventDispatcherDataItem); + new ApplyObjectCommand( + fetchStateLog, applyObject, metrics, eventDispatcherDataItem, sourceCollection); } @Test @@ -95,6 +107,7 @@ FetchRefReplicatedEvent fetchEvent = (FetchRefReplicatedEvent) sentEvent; assertThat(fetchEvent.getProjectNameKey()).isEqualTo(TEST_PROJECT_NAME); assertThat(fetchEvent.getRefName()).isEqualTo(TEST_REF_NAME); + assertThat(fetchEvent.targetUri).isEqualTo(TEST_REMOTE_URI.toASCIIString()); } private RevisionData createSampleRevisionData() {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/DeleteRefCommandTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/DeleteRefCommandTest.java index 4415a4b..1574e0c 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/DeleteRefCommandTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/DeleteRefCommandTest.java
@@ -34,6 +34,8 @@ import com.google.gerrit.server.project.ProjectState; import com.googlesource.gerrit.plugins.replication.pull.FetchRefReplicatedEvent; import com.googlesource.gerrit.plugins.replication.pull.PullReplicationStateLogger; +import com.googlesource.gerrit.plugins.replication.pull.Source; +import com.googlesource.gerrit.plugins.replication.pull.SourcesCollection; import com.googlesource.gerrit.plugins.replication.pull.fetch.ApplyObject; import java.util.Optional; import org.eclipse.jgit.lib.Ref; @@ -41,6 +43,7 @@ import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefUpdate.Result; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.transport.URIish; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -54,6 +57,7 @@ private static final String TEST_SOURCE_LABEL = "test-source-label"; private static final String TEST_REF_NAME = "refs/changes/01/1/1"; private static final NameKey TEST_PROJECT_NAME = Project.nameKey("test-project"); + private static URIish TEST_REMOTE_URI; @Mock private PullReplicationStateLogger fetchStateLog; @Mock private DynamicItem<EventDispatcher> eventDispatcherDataItem; @@ -61,6 +65,8 @@ @Mock private ProjectCache projectCache; @Mock private ApplyObject applyObject; @Mock private ProjectState projectState; + @Mock private SourcesCollection sourceCollection; + @Mock private Source source; @Mock private PermissionBackend permissionBackend; @Mock private WithUser currentUser; @Mock private ForProject forProject; @@ -78,6 +84,9 @@ public void setup() throws Exception { when(eventDispatcherDataItem.get()).thenReturn(eventDispatcher); when(projectCache.get(any())).thenReturn(Optional.of(projectState)); + when(sourceCollection.getByRemoteName(TEST_SOURCE_LABEL)).thenReturn(Optional.of(source)); + TEST_REMOTE_URI = new URIish("git://some.remote.uri"); + when(source.getURI(TEST_PROJECT_NAME)).thenReturn(TEST_REMOTE_URI); when(permissionBackend.currentUser()).thenReturn(currentUser); when(currentUser.project(any())).thenReturn(forProject); when(forProject.ref(any())).thenReturn(forRef); @@ -91,9 +100,10 @@ new DeleteRefCommand( fetchStateLog, projectCache, + eventDispatcherDataItem, + sourceCollection, applyObject, permissionBackend, - eventDispatcherDataItem, gitManager); }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommandTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommandTest.java index 9af2d10..c093719 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommandTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommandTest.java
@@ -25,7 +25,6 @@ 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.extensions.registration.DynamicItem; import com.google.gerrit.server.events.EventDispatcher; @@ -76,8 +75,7 @@ label = "instance-1-label"; when(fetchReplicationStateFactory.create(any())).thenReturn(state); - when(source.getRemoteConfigName()).thenReturn(label); - when(sources.getAll()).thenReturn(Lists.newArrayList(source)); + when(sources.getByRemoteName(label)).thenReturn(Optional.of(source)); when(source.schedule(eq(projectName), eq(REF_NAME_TO_FETCH), eq(state), any(), any())) .thenReturn(CompletableFuture.completedFuture(null)); objectUnderTest =
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/EventsSerializationTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/EventsSerializationTest.java new file mode 100644 index 0000000..efa521c --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/EventsSerializationTest.java
@@ -0,0 +1,83 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// 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 com.googlesource.gerrit.plugins.replication.pull.event; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertTrue; + +import com.google.common.base.Objects; +import com.google.gerrit.server.events.EventGsonProvider; +import com.google.gson.Gson; +import com.googlesource.gerrit.plugins.replication.pull.FetchRefReplicatedEvent; +import com.googlesource.gerrit.plugins.replication.pull.FetchReplicationScheduledEvent; +import com.googlesource.gerrit.plugins.replication.pull.ReplicationState; +import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.transport.URIish; +import org.junit.Before; +import org.junit.Test; + +public class EventsSerializationTest { + private static URIish sourceUri; + private static final Gson eventGson = new EventGsonProvider().get(); + private static final String TEST_PROJECT = "test_project"; + private static final String TEST_REF = "refs/heads/master"; + + @Before + public void setUp() throws Exception { + sourceUri = new URIish(String.format("git://aSourceNode/%s.git", TEST_PROJECT)); + } + + @Test + public void shouldSerializeFetchRefReplicatedEvent() { + FetchRefReplicatedEvent origEvent = + new FetchRefReplicatedEvent( + TEST_PROJECT, + TEST_REF, + sourceUri, + ReplicationState.RefFetchResult.SUCCEEDED, + RefUpdate.Result.FAST_FORWARD); + + assertThat(origEvent) + .isEqualTo(eventGson.fromJson(eventGson.toJson(origEvent), FetchRefReplicatedEvent.class)); + } + + @Test + public void shouldSerializeFetchReplicationScheduledEvent() { + FetchReplicationScheduledEvent origEvent = + new FetchReplicationScheduledEvent(TEST_PROJECT, TEST_REF, sourceUri); + + assertTrue( + equals( + origEvent, + eventGson.fromJson(eventGson.toJson(origEvent), FetchReplicationScheduledEvent.class))); + } + + private boolean equals(FetchReplicationScheduledEvent scheduledEvent, Object other) { + if (!(other instanceof FetchReplicationScheduledEvent)) { + return false; + } + FetchReplicationScheduledEvent event = (FetchReplicationScheduledEvent) other; + if (!Objects.equal(event.project, scheduledEvent.project)) { + return false; + } + if (!Objects.equal(event.ref, scheduledEvent.ref)) { + return false; + } + if (!Objects.equal(event.targetUri, scheduledEvent.targetUri)) { + return false; + } + return Objects.equal(event.status, scheduledEvent.status); + } +}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandlerTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandlerTest.java index e528eca..81a4fc0 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandlerTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandlerTest.java
@@ -28,17 +28,20 @@ import com.googlesource.gerrit.plugins.replication.pull.FetchRefReplicatedEvent; import com.googlesource.gerrit.plugins.replication.pull.ReplicationState; import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.transport.URIish; import org.junit.Before; import org.junit.Test; public class FetchRefReplicatedEventHandlerTest { private ChangeIndexer changeIndexerMock; private FetchRefReplicatedEventHandler fetchRefReplicatedEventHandler; + private static URIish sourceUri; @Before public void setUp() throws Exception { changeIndexerMock = mock(ChangeIndexer.class); fetchRefReplicatedEventHandler = new FetchRefReplicatedEventHandler(changeIndexerMock); + sourceUri = new URIish("git://aSourceNode/testProject.git"); } @Test @@ -52,7 +55,7 @@ new FetchRefReplicatedEvent( projectNameKey.get(), ref, - "aSourceNode", + sourceUri, ReplicationState.RefFetchResult.SUCCEEDED, RefUpdate.Result.FAST_FORWARD)); verify(changeIndexerMock, times(1)).index(eq(projectNameKey), eq(changeId)); @@ -70,7 +73,7 @@ new FetchRefReplicatedEvent( projectNameKey.get(), ref, - "aSourceNode", + sourceUri, ReplicationState.RefFetchResult.SUCCEEDED, RefUpdate.Result.FAST_FORWARD)); verify(changeIndexerMock, never()).index(eq(projectNameKey), eq(changeId)); @@ -85,7 +88,7 @@ new FetchRefReplicatedEvent( projectNameKey.get(), ref, - "aSourceNode", + sourceUri, ReplicationState.RefFetchResult.SUCCEEDED, RefUpdate.Result.FAST_FORWARD)); verify(changeIndexerMock, never()).index(eq(projectNameKey), eq(changeId)); @@ -97,7 +100,7 @@ new FetchRefReplicatedEvent( Project.nameKey("testProject").get(), "invalidRef", - "aSourceNode", + sourceUri, ReplicationState.RefFetchResult.SUCCEEDED, RefUpdate.Result.FAST_FORWARD)); verify(changeIndexerMock, never()).index(any(), any()); @@ -111,7 +114,7 @@ new FetchRefReplicatedEvent( projectNameKey.get(), ref, - "aSourceNode", + sourceUri, ReplicationState.RefFetchResult.FAILED, RefUpdate.Result.FAST_FORWARD)); verify(changeIndexerMock, never()).index(any(), any()); @@ -125,7 +128,7 @@ new FetchRefReplicatedEvent( projectNameKey.get(), ref, - "aSourceNode", + sourceUri, ReplicationState.RefFetchResult.NOT_ATTEMPTED, RefUpdate.Result.FAST_FORWARD)); verify(changeIndexerMock, never()).index(any(), any());