Merge branch 'stable-3.8'
* stable-3.8:
Allow update head with Fetch replication global capability
Revert "Reuse Gerrit code for head update"
Fix pull-replication update head with Gerrit replica
Ignore all broken tests on Gerrit replica
Add indirect commons-lang3 dependency
Do not provide response body when apply-object is successful
Do not record fetch replication metrics when all refs are excluded from fetch task
Change-Id: Iedabde7fd87b686d79f98690fcf4860df5ddf4c0
diff --git a/BUILD b/BUILD
index 0983983..dc1d340 100644
--- a/BUILD
+++ b/BUILD
@@ -16,6 +16,7 @@
resources = glob(["src/main/resources/**/*"]),
deps = [
"//lib/commons:io",
+ "//plugins/delete-project",
"//plugins/replication",
"@commons-lang3//jar",
"@events-broker//jar:neverlink",
@@ -32,6 +33,7 @@
deps = PLUGIN_TEST_DEPS + PLUGIN_DEPS + [
":pull-replication__plugin",
":pull_replication_util",
+ "//plugins/delete-project",
"//plugins/replication",
"@events-broker//jar",
],
@@ -61,6 +63,7 @@
),
deps = PLUGIN_TEST_DEPS + PLUGIN_DEPS + [
":pull-replication__plugin",
+ "//plugins/delete-project",
"//plugins/replication",
],
)
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java
index d1c5ca1..7916994 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java
@@ -50,7 +50,6 @@
import com.googlesource.gerrit.plugins.replication.pull.client.HttpClient;
import com.googlesource.gerrit.plugins.replication.pull.client.SourceHttpClient;
import com.googlesource.gerrit.plugins.replication.pull.event.EventsBrokerConsumerModule;
-import com.googlesource.gerrit.plugins.replication.pull.event.FetchRefReplicatedEventModule;
import com.googlesource.gerrit.plugins.replication.pull.event.StreamEventModule;
import com.googlesource.gerrit.plugins.replication.pull.fetch.ApplyObject;
import java.io.File;
@@ -83,8 +82,6 @@
install(new ApplyObjectCacheModule());
install(new PullReplicationApiModule());
- install(new FetchRefReplicatedEventModule());
-
install(
new FactoryModuleBuilder()
.implement(HttpClient.class, SourceHttpClient.class)
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java
index b88db69..13484b1 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java
@@ -54,7 +54,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
-import org.apache.http.client.ClientProtocolException;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.InvalidObjectIdException;
@@ -504,7 +503,7 @@
private HttpResult initProject(
Project.NameKey project, URIish uri, FetchApiClient fetchClient, HttpResult result)
- throws IOException, ClientProtocolException {
+ throws IOException {
HttpResult initProjectResult = fetchClient.initProject(project, uri);
if (initProjectResult.isSuccessful()) {
result = fetchClient.callFetch(project, FetchOne.ALL_REFS, uri);
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 968a03c..a0fae22 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
@@ -23,6 +23,7 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.server.events.EventDispatcher;
import com.google.gerrit.server.permissions.PermissionBackendException;
@@ -84,7 +85,8 @@
RevisionData revisionsData,
String sourceLabel,
long eventCreatedOn)
- throws IOException, RefUpdateException, MissingParentObjectException {
+ throws IOException, RefUpdateException, MissingParentObjectException,
+ ResourceNotFoundException {
applyObjects(name, refName, new RevisionData[] {revisionsData}, sourceLabel, eventCreatedOn);
}
@@ -94,7 +96,8 @@
RevisionData[] revisionsData,
String sourceLabel,
long eventCreatedOn)
- throws IOException, RefUpdateException, MissingParentObjectException {
+ throws IOException, RefUpdateException, MissingParentObjectException,
+ ResourceNotFoundException {
repLog.info(
"Apply object from {} for {}:{} - {}",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionAction.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionAction.java
index 2e1c5d4..f9165ad 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionAction.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionAction.java
@@ -14,6 +14,8 @@
package com.googlesource.gerrit.plugins.replication.pull.api;
+import static com.googlesource.gerrit.plugins.replication.pull.PullReplicationLogger.repLog;
+
import com.google.gerrit.extensions.api.access.PluginPermission;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
@@ -27,9 +29,12 @@
import com.google.gerrit.server.project.ProjectResource;
import com.google.inject.Inject;
import com.google.inject.Provider;
-import com.googlesource.gerrit.plugins.replication.LocalFS;
+import com.googlesource.gerrit.plugins.deleteproject.cache.CacheDeleteHandler;
+import com.googlesource.gerrit.plugins.deleteproject.fs.RepositoryDelete;
import com.googlesource.gerrit.plugins.replication.pull.GerritConfigOps;
+import java.io.IOException;
import java.util.Optional;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.transport.URIish;
class ProjectDeletionAction
@@ -42,15 +47,21 @@
private final Provider<CurrentUser> userProvider;
private final GerritConfigOps gerritConfigOps;
private final PermissionBackend permissionBackend;
+ private final RepositoryDelete repositoryDelete;
+ private final CacheDeleteHandler cacheDeleteHandler;
@Inject
ProjectDeletionAction(
GerritConfigOps gerritConfigOps,
PermissionBackend permissionBackend,
- Provider<CurrentUser> userProvider) {
+ Provider<CurrentUser> userProvider,
+ RepositoryDelete repositoryDelete,
+ CacheDeleteHandler cacheDeleteHandler) {
this.gerritConfigOps = gerritConfigOps;
this.permissionBackend = permissionBackend;
this.userProvider = userProvider;
+ this.repositoryDelete = repositoryDelete;
+ this.cacheDeleteHandler = cacheDeleteHandler;
}
@Override
@@ -67,11 +78,24 @@
gerritConfigOps.getGitRepositoryURI(String.format("%s.git", projectResource.getName()));
if (maybeRepoURI.isPresent()) {
- if (new LocalFS(maybeRepoURI.get()).deleteProject(projectResource.getNameKey())) {
+ try {
+ // reuse repo deletion logic from delete-project plugin, as it can successfully delete
+ // the git directories hosted on nfs.
+ repositoryDelete.execute(projectResource.getNameKey());
+ // delete the project from the local project cache, otherwise future ops
+ // will fail as the replica will think that the project still exists locally.
+ cacheDeleteHandler.delete(projectResource.getProjectState().getProject());
+ repLog.info(
+ "Deleted local repository {} and removed it from the local project cache",
+ projectResource.getName());
return Response.ok();
+ } catch (RepositoryNotFoundException e) {
+ throw new ResourceNotFoundException(
+ String.format("Repository %s not found", projectResource.getName()), e);
+ } catch (IOException e) {
+ throw new UnprocessableEntityException(
+ String.format("Could not delete project %s", projectResource.getName()));
}
- throw new UnprocessableEntityException(
- String.format("Could not delete project %s", projectResource.getName()));
}
throw new ResourceNotFoundException(
String.format("Could not compute URI for repo: %s", projectResource.getName()));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
index 2df6b0c..04703d5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
@@ -22,6 +22,7 @@
import static javax.servlet.http.HttpServletResponse.SC_CREATED;
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
@@ -156,9 +157,12 @@
} catch (ResourceConflictException e) {
RestApiServlet.replyError(
httpRequest, httpResponse, SC_CONFLICT, e.getMessage(), e.caching(), e);
- } catch (InitProjectException | ResourceNotFoundException e) {
+ } catch (InitProjectException e) {
RestApiServlet.replyError(
httpRequest, httpResponse, SC_INTERNAL_SERVER_ERROR, e.getMessage(), e.caching(), e);
+ } catch (ResourceNotFoundException e) {
+ RestApiServlet.replyError(
+ httpRequest, httpResponse, SC_NOT_FOUND, e.getMessage(), e.caching(), e);
} catch (NoSuchElementException e) {
RestApiServlet.replyError(
httpRequest, httpResponse, SC_BAD_REQUEST, "Project name not present in the url", e);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchApiClient.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchApiClient.java
index 1991260..1b3dc43 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchApiClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchApiClient.java
@@ -22,7 +22,6 @@
import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionData;
import java.io.IOException;
import java.util.List;
-import org.apache.http.client.ClientProtocolException;
import org.eclipse.jgit.transport.URIish;
public interface FetchApiClient {
@@ -33,10 +32,10 @@
HttpResult callFetch(
Project.NameKey project, String refName, URIish targetUri, long startTimeNanos)
- throws ClientProtocolException, IOException;
+ throws IOException;
default HttpResult callFetch(Project.NameKey project, String refName, URIish targetUri)
- throws ClientProtocolException, IOException {
+ throws IOException {
return callFetch(project, refName, targetUri, MILLISECONDS.toNanos(System.currentTimeMillis()));
}
@@ -53,7 +52,7 @@
boolean isDelete,
RevisionData revisionData,
URIish targetUri)
- throws ClientProtocolException, IOException;
+ throws IOException;
HttpResult callSendObjects(
NameKey project,
@@ -61,5 +60,5 @@
long eventCreatedOn,
List<RevisionData> revisionData,
URIish targetUri)
- throws ClientProtocolException, IOException;
+ throws IOException;
}
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 b606ba8..09148fe 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
@@ -14,6 +14,7 @@
package com.googlesource.gerrit.plugins.replication.pull.client;
+import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
import static com.google.gson.FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES;
import static java.util.Objects.requireNonNull;
@@ -48,7 +49,6 @@
import org.apache.http.ParseException;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
@@ -122,7 +122,7 @@
"{\"label\":\"%s\", \"ref_name\": \"%s\", \"async\":%s}",
instanceId, refName, callAsync),
StandardCharsets.UTF_8));
- post.addHeader(new BasicHeader("Content-Type", "application/json"));
+ post.addHeader(new BasicHeader(CONTENT_TYPE, "application/json"));
post.addHeader(
PullReplicationApiRequestMetrics.HTTP_HEADER_X_START_TIME_NANOS,
Long.toString(startTimeNanos));
@@ -137,7 +137,7 @@
String url = formatInitProjectUrl(uri.toString(), project);
HttpPut put = new HttpPut(url);
put.addHeader(new BasicHeader("Accept", MediaType.ANY_TEXT_TYPE.toString()));
- put.addHeader(new BasicHeader("Content-Type", MediaType.PLAIN_TEXT_UTF_8.toString()));
+ put.addHeader(new BasicHeader(CONTENT_TYPE, MediaType.PLAIN_TEXT_UTF_8.toString()));
return executeRequest(put, bearerTokenProvider.get(), uri);
}
@@ -162,7 +162,7 @@
HttpPut req = new HttpPut(url);
req.setEntity(
new StringEntity(String.format("{\"ref\": \"%s\"}", newHead), StandardCharsets.UTF_8));
- req.addHeader(new BasicHeader("Content-Type", MediaType.JSON_UTF_8.toString()));
+ req.addHeader(new BasicHeader(CONTENT_TYPE, MediaType.JSON_UTF_8.toString()));
return executeRequest(req, bearerTokenProvider.get(), apiUri);
}
@@ -177,7 +177,7 @@
boolean isDelete,
@Nullable RevisionData revisionData,
URIish targetUri)
- throws ClientProtocolException, IOException {
+ throws IOException {
if (!isDelete) {
requireNonNull(
@@ -191,7 +191,7 @@
HttpPost post = new HttpPost(url);
post.setEntity(new StringEntity(GSON.toJson(input)));
- post.addHeader(new BasicHeader("Content-Type", MediaType.JSON_UTF_8.toString()));
+ post.addHeader(new BasicHeader(CONTENT_TYPE, MediaType.JSON_UTF_8.toString()));
return executeRequest(post, bearerTokenProvider.get(), targetUri);
}
@@ -202,7 +202,7 @@
long eventCreatedOn,
List<RevisionData> revisionData,
URIish targetUri)
- throws ClientProtocolException, IOException {
+ throws IOException {
if (revisionData.size() == 1) {
return callSendObject(
project, refName, eventCreatedOn, false, revisionData.get(0), targetUri);
@@ -215,7 +215,7 @@
String url = formatUrl(targetUri.toString(), project, "apply-objects");
HttpPost post = new HttpPost(url);
post.setEntity(new StringEntity(GSON.toJson(input)));
- post.addHeader(new BasicHeader("Content-Type", MediaType.JSON_UTF_8.toString()));
+ post.addHeader(new BasicHeader(CONTENT_TYPE, MediaType.JSON_UTF_8.toString()));
return executeRequest(post, bearerTokenProvider.get(), targetUri);
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandler.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandler.java
deleted file mode 100644
index a618e16..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandler.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// 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 com.google.common.flogger.FluentLogger;
-import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.Project;
-import com.google.gerrit.entities.RefNames;
-import com.google.gerrit.server.events.Event;
-import com.google.gerrit.server.events.EventListener;
-import com.google.gerrit.server.index.change.ChangeIndexer;
-import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.replication.pull.Context;
-import com.googlesource.gerrit.plugins.replication.pull.FetchRefReplicatedEvent;
-import com.googlesource.gerrit.plugins.replication.pull.ReplicationState;
-
-public class FetchRefReplicatedEventHandler implements EventListener {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
- private ChangeIndexer changeIndexer;
-
- @Inject
- FetchRefReplicatedEventHandler(ChangeIndexer changeIndexer) {
- this.changeIndexer = changeIndexer;
- }
-
- @Override
- public void onEvent(Event event) {
- if (event instanceof FetchRefReplicatedEvent && isLocalEvent()) {
- FetchRefReplicatedEvent fetchRefReplicatedEvent = (FetchRefReplicatedEvent) event;
- if (!RefNames.isNoteDbMetaRef(fetchRefReplicatedEvent.getRefName())
- || !fetchRefReplicatedEvent
- .getStatus()
- .equals(ReplicationState.RefFetchResult.SUCCEEDED.toString())) {
- return;
- }
-
- Project.NameKey projectNameKey = fetchRefReplicatedEvent.getProjectNameKey();
- logger.atFine().log(
- "Indexing ref '%s' for project %s",
- fetchRefReplicatedEvent.getRefName(), projectNameKey.get());
- Change.Id changeId = Change.Id.fromRef(fetchRefReplicatedEvent.getRefName());
- if (changeId != null) {
- changeIndexer.index(projectNameKey, changeId);
- } else {
- logger.atWarning().log(
- "Couldn't get changeId from refName. Skipping indexing of change %s for project %s",
- fetchRefReplicatedEvent.getRefName(), projectNameKey.get());
- }
- }
- }
-
- private boolean isLocalEvent() {
- return Context.isLocalEvent();
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventModule.java
deleted file mode 100644
index 675563a..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventModule.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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 com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.gerrit.server.events.EventListener;
-
-public class FetchRefReplicatedEventModule extends LifecycleModule {
-
- @Override
- protected void configure() {
- DynamicSet.bind(binder(), EventListener.class).to(FetchRefReplicatedEventHandler.class);
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/ApplyObject.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/ApplyObject.java
index 36356e9..3b6b0be 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/ApplyObject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/ApplyObject.java
@@ -15,6 +15,8 @@
package com.googlesource.gerrit.plugins.replication.pull.fetch;
import com.google.gerrit.entities.Project;
+import com.google.gerrit.extensions.restapi.IdString;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.replication.pull.LocalGitRepositoryManagerProvider;
@@ -22,6 +24,7 @@
import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionObjectData;
import com.googlesource.gerrit.plugins.replication.pull.api.exception.MissingParentObjectException;
import java.io.IOException;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.RefUpdate;
@@ -43,7 +46,7 @@
}
public RefUpdateState apply(Project.NameKey name, RefSpec refSpec, RevisionData[] revisionsData)
- throws MissingParentObjectException, IOException {
+ throws MissingParentObjectException, IOException, ResourceNotFoundException {
try (Repository git = gitManager.openRepository(name)) {
ObjectId refHead = null;
@@ -87,6 +90,8 @@
RefUpdate.Result result = ru.update();
return new RefUpdateState(refSpec.getSource(), result);
}
+ } catch (RepositoryNotFoundException e) {
+ throw new ResourceNotFoundException(IdString.fromDecoded(name.get()));
}
}
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java
index 9b7e8c1..15e2c1b 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java
@@ -59,7 +59,6 @@
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
-import org.apache.http.client.ClientProtocolException;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.storage.file.FileBasedConfig;
@@ -174,7 +173,7 @@
}
@Test
- public void shouldCallSendObjectWhenMetaRef() throws ClientProtocolException, IOException {
+ public void shouldCallSendObjectWhenMetaRef() throws IOException {
Event event = new TestEvent("refs/changes/01/1/meta");
objectUnderTest.start();
objectUnderTest.onEvent(event);
@@ -183,8 +182,7 @@
}
@Test
- public void shouldIgnoreEventWhenIsNotLocalInstanceId()
- throws ClientProtocolException, IOException {
+ public void shouldIgnoreEventWhenIsNotLocalInstanceId() throws IOException {
Event event = new TestEvent();
event.instanceId = FOREIGN_INSTANCE_ID;
objectUnderTest.start();
@@ -221,7 +219,7 @@
}
@Test
- public void shouldCallSendObjectWhenPatchSetRef() throws ClientProtocolException, IOException {
+ public void shouldCallSendObjectWhenPatchSetRef() throws IOException {
Event event = new TestEvent("refs/changes/01/1/1");
objectUnderTest.start();
objectUnderTest.onEvent(event);
@@ -231,7 +229,7 @@
@Test
public void shouldFallbackToCallFetchWhenIOException()
- throws ClientProtocolException, IOException, LargeObjectException, RefUpdateException {
+ throws IOException, LargeObjectException, RefUpdateException {
Event event = new TestEvent("refs/changes/01/1/meta");
objectUnderTest.start();
@@ -244,7 +242,7 @@
@Test
public void shouldFallbackToCallFetchWhenLargeRef()
- throws ClientProtocolException, IOException, LargeObjectException, RefUpdateException {
+ throws IOException, LargeObjectException, RefUpdateException {
Event event = new TestEvent("refs/changes/01/1/1");
objectUnderTest.start();
@@ -256,8 +254,7 @@
}
@Test
- public void shouldFallbackToCallFetchWhenParentObjectIsMissing()
- throws ClientProtocolException, IOException {
+ public void shouldFallbackToCallFetchWhenParentObjectIsMissing() throws IOException {
Event event = new TestEvent("refs/changes/01/1/1");
objectUnderTest.start();
@@ -273,7 +270,7 @@
@Test
public void shouldFallbackToApplyAllParentObjectsWhenParentObjectIsMissingOnMetaRef()
- throws ClientProtocolException, IOException {
+ throws IOException {
Event event = new TestEvent("refs/changes/01/1/meta");
objectUnderTest.start();
@@ -299,7 +296,7 @@
@Test
public void shouldFallbackToApplyAllParentObjectsWhenParentObjectIsMissingOnAllowedRefs()
- throws ClientProtocolException, IOException {
+ throws IOException {
String refName = "refs/tags/test-tag";
Event event = new TestEvent(refName);
objectUnderTest.start();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionTest.java
index d0cd1b4..029db9e 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionTest.java
@@ -27,6 +27,7 @@
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.project.ProjectResource;
@@ -216,6 +217,19 @@
applyObjectAction.apply(projectResource, inputParams);
}
+ @Test(expected = ResourceNotFoundException.class)
+ public void shouldRethrowResourceNotFoundException()
+ throws RestApiException, IOException, RefUpdateException, MissingParentObjectException {
+ RevisionInput inputParams =
+ new RevisionInput(label, refName, DUMMY_EVENT_TIMESTAMP, createSampleRevisionData());
+
+ doThrow(new ResourceNotFoundException("test_projects"))
+ .when(applyObjectCommand)
+ .applyObject(any(), anyString(), any(), anyString(), anyLong());
+
+ applyObjectAction.apply(projectResource, inputParams);
+ }
+
private RevisionData createSampleRevisionData() {
RevisionObjectData commitData =
new RevisionObjectData(
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 7f5a67c..681b695 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
@@ -26,6 +26,7 @@
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.EventDispatcher;
@@ -86,7 +87,9 @@
private ApplyObjectCommand objectUnderTest;
@Before
- public void setup() throws MissingParentObjectException, IOException, URISyntaxException {
+ public void setup()
+ throws MissingParentObjectException, IOException, URISyntaxException,
+ ResourceNotFoundException {
cache = CacheBuilder.newBuilder().build();
RefUpdateState state = new RefUpdateState(TEST_REMOTE_NAME, RefUpdate.Result.NEW);
TEST_REMOTE_URI = new URIish("git://some.remote.uri");
@@ -105,7 +108,7 @@
@Test
public void shouldSendEventWhenApplyObject()
throws PermissionBackendException, IOException, RefUpdateException,
- MissingParentObjectException {
+ MissingParentObjectException, ResourceNotFoundException {
RevisionData sampleRevisionData =
createSampleRevisionData(sampleCommitObjectId, sampleTreeObjectId);
objectUnderTest.applyObject(
@@ -126,7 +129,8 @@
@Test
public void shouldInsertIntoApplyObjectsCacheWhenApplyObjectIsSuccessful()
- throws IOException, RefUpdateException, MissingParentObjectException {
+ throws IOException, RefUpdateException, MissingParentObjectException,
+ ResourceNotFoundException {
RevisionData sampleRevisionData =
createSampleRevisionData(sampleCommitObjectId, sampleTreeObjectId);
RevisionData sampleRevisionData2 =
@@ -156,7 +160,8 @@
@Test(expected = RefUpdateException.class)
public void shouldNotInsertIntoApplyObjectsCacheWhenApplyObjectIsFailure()
- throws IOException, RefUpdateException, MissingParentObjectException {
+ throws IOException, RefUpdateException, MissingParentObjectException,
+ ResourceNotFoundException {
RevisionData sampleRevisionData =
createSampleRevisionData(sampleCommitObjectId, sampleTreeObjectId);
RefUpdateState failureState = new RefUpdateState(TEST_REMOTE_NAME, RefUpdate.Result.IO_FAILURE);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java
index 87a8048..4b81260 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java
@@ -14,6 +14,7 @@
package com.googlesource.gerrit.plugins.replication.pull.api;
+import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowCapability;
import com.google.gerrit.acceptance.config.GerritConfig;
@@ -180,6 +181,49 @@
assertHttpResponseCode(HttpServletResponse.SC_OK));
}
+ @Test
+ @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId")
+ public void shouldRemoveFromTheProjectCacheWhenProjectIsSuccessfullyDeleted() throws Exception {
+ String testProjectName = project.get();
+ url = getURLWithAuthenticationPrefix(testProjectName);
+ assertThat(projectCache.get(project).isPresent()).isTrue();
+
+ httpClientFactory
+ .create(source)
+ .execute(
+ withBasicAuthenticationAsAdmin(createDeleteRequest()),
+ assertHttpResponseCode(HttpServletResponse.SC_OK));
+ assertThat(projectCache.get(project).isPresent()).isFalse();
+ }
+
+ @Test
+ @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId")
+ @GerritConfig(name = "container.replica", value = "true")
+ public void shouldRemoveFromtheReplicaProjectCacheWhenProjectIsSuccessfullyDeletedFromTheReplica()
+ throws Exception {
+ String testProjectName = project.get();
+ url = getURLWithAuthenticationPrefix(testProjectName);
+ assertThat(projectCache.get(project).isPresent()).isTrue();
+
+ httpClientFactory
+ .create(source)
+ .execute(
+ withBasicAuthenticationAsAdmin(createDeleteRequest()),
+ assertHttpResponseCode(HttpServletResponse.SC_OK));
+ assertThat(projectCache.get(project).isPresent()).isFalse();
+ }
+
+ @Test
+ @GerritConfig(name = "container.replica", value = "true")
+ @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId")
+ public void shouldNotRemoveFromTheReplicaCacheIfAProjectCannotBeDeleted() throws Exception {
+ assertThat(projectCache.get(project).isPresent()).isTrue();
+ httpClientFactory
+ .create(source)
+ .execute(createDeleteRequest(), assertHttpResponseCode(HttpServletResponse.SC_FORBIDDEN));
+ assertThat(projectCache.get(project).isPresent()).isTrue();
+ }
+
@Override
protected String getURLWithAuthenticationPrefix(String projectName) {
return String.format(
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java
index 9e5ca8d..6f37785 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java
@@ -243,7 +243,7 @@
}
@Test
- public void shouldBe500WhenResourceNotFound() throws Exception {
+ public void shouldBe404WhenResourceNotFound() throws Exception {
when(request.getRequestURI()).thenReturn(DELETE_PROJECT_URI);
when(request.getMethod()).thenReturn("DELETE");
when(projectsCollection.parse(TopLevelResource.INSTANCE, IdString.fromDecoded(PROJECT_NAME)))
@@ -255,7 +255,7 @@
final PullReplicationFilter pullReplicationFilter = createPullReplicationFilter();
pullReplicationFilter.doFilter(request, response, filterChain);
- verify(response).setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ verify(response).setStatus(HttpServletResponse.SC_NOT_FOUND);
}
@Test
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientBase.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientBase.java
index cdb238e..5de7e7d 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientBase.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientBase.java
@@ -39,7 +39,6 @@
import java.nio.ByteBuffer;
import java.util.Collections;
import org.apache.http.Header;
-import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
@@ -150,8 +149,7 @@
protected abstract void assertAuthentication(HttpRequestBase httpRequest);
@Test
- public void shouldCallFetchEndpoint()
- throws ClientProtocolException, IOException, URISyntaxException {
+ public void shouldCallFetchEndpoint() throws IOException, URISyntaxException {
objectUnderTest.callFetch(Project.nameKey("test_repo"), refName, new URIish(api));
@@ -167,8 +165,7 @@
}
@Test
- public void shouldByDefaultCallSyncFetchForAllRefs()
- throws ClientProtocolException, IOException, URISyntaxException {
+ public void shouldByDefaultCallSyncFetchForAllRefs() throws IOException, URISyntaxException {
objectUnderTest.callFetch(Project.nameKey("test_repo"), refName, new URIish(api));
@@ -179,8 +176,7 @@
}
@Test
- public void shouldCallAsyncFetchForAllRefs()
- throws ClientProtocolException, IOException, URISyntaxException {
+ public void shouldCallAsyncFetchForAllRefs() throws IOException, URISyntaxException {
when(config.getStringList("replication", null, "syncRefs"))
.thenReturn(new String[] {"NO_SYNC_REFS"});
@@ -205,8 +201,7 @@
}
@Test
- public void shouldCallSyncFetchOnlyForMetaRef()
- throws ClientProtocolException, IOException, URISyntaxException {
+ public void shouldCallSyncFetchOnlyForMetaRef() throws IOException, URISyntaxException {
String metaRefName = "refs/changes/01/101/meta";
String expectedMetaRefPayload =
"{\"label\":\"Replication\", \"ref_name\": \"" + metaRefName + "\", \"async\":false}";
@@ -237,8 +232,7 @@
}
@Test
- public void shouldCallFetchEndpointWithPayload()
- throws ClientProtocolException, IOException, URISyntaxException {
+ public void shouldCallFetchEndpointWithPayload() throws IOException, URISyntaxException {
objectUnderTest.callFetch(Project.nameKey("test_repo"), refName, new URIish(api));
@@ -249,8 +243,7 @@
}
@Test
- public void shouldSetContentTypeHeader()
- throws ClientProtocolException, IOException, URISyntaxException {
+ public void shouldSetContentTypeHeader() throws IOException, URISyntaxException {
objectUnderTest.callFetch(Project.nameKey("test_repo"), refName, new URIish(api));
@@ -262,8 +255,7 @@
}
@Test
- public void shouldCallSendObjectEndpoint()
- throws ClientProtocolException, IOException, URISyntaxException {
+ public void shouldCallSendObjectEndpoint() throws IOException, URISyntaxException {
objectUnderTest.callSendObject(
Project.nameKey("test_repo"),
@@ -285,8 +277,7 @@
}
@Test
- public void shouldCallSendObjectEndpointWithPayload()
- throws ClientProtocolException, IOException, URISyntaxException {
+ public void shouldCallSendObjectEndpointWithPayload() throws IOException, URISyntaxException {
objectUnderTest.callSendObject(
Project.nameKey("test_repo"),
@@ -303,8 +294,7 @@
}
@Test
- public void shouldSetContentTypeHeaderForSendObjectCall()
- throws ClientProtocolException, IOException, URISyntaxException {
+ public void shouldSetContentTypeHeaderForSendObjectCall() throws IOException, URISyntaxException {
objectUnderTest.callFetch(Project.nameKey("test_repo"), refName, new URIish(api));
@@ -364,8 +354,7 @@
}
@Test
- public void shouldUseReplicationLabelWhenProvided()
- throws ClientProtocolException, IOException, URISyntaxException {
+ public void shouldUseReplicationLabelWhenProvided() throws IOException, URISyntaxException {
when(config.getString("replication", null, "instanceLabel")).thenReturn(instanceId);
FetchRestApiClient objectUnderTest =
new FetchRestApiClient(
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientWithBasicAuthenticationTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientWithBasicAuthenticationTest.java
index 644afce..2b03d3f 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientWithBasicAuthenticationTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientWithBasicAuthenticationTest.java
@@ -23,7 +23,6 @@
import java.util.Optional;
import org.apache.http.Header;
import org.apache.http.HttpHeaders;
-import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpRequestBase;
import org.eclipse.jgit.transport.CredentialItem;
import org.junit.Before;
@@ -36,7 +35,7 @@
public class FetchRestApiClientWithBasicAuthenticationTest extends FetchRestApiClientBase {
@Before
- public void setup() throws ClientProtocolException, IOException {
+ public void setup() throws IOException {
when(bearerTokenProvider.get()).thenReturn(Optional.empty());
when(credentialProvider.supports(any()))
.thenAnswer(
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientWithBearerTokenTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientWithBearerTokenTest.java
index 90d71ad..a79f4b8 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientWithBearerTokenTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientWithBearerTokenTest.java
@@ -23,7 +23,6 @@
import java.util.Optional;
import org.apache.http.Header;
import org.apache.http.HttpHeaders;
-import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpRequestBase;
import org.junit.Before;
import org.junit.runner.RunWith;
@@ -33,7 +32,7 @@
public class FetchRestApiClientWithBearerTokenTest extends FetchRestApiClientBase {
@Before
- public void setup() throws ClientProtocolException, IOException {
+ public void setup() throws IOException {
when(bearerTokenProvider.get()).thenReturn(Optional.of("some-bearer-token"));
when(replicationConfig.getConfig()).thenReturn(config);
when(config.getStringList("replication", null, "syncRefs")).thenReturn(new String[0]);
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
deleted file mode 100644
index 81a4fc0..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/event/FetchRefReplicatedEventHandlerTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-// 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 org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.Project;
-import com.google.gerrit.server.index.change.ChangeIndexer;
-import com.googlesource.gerrit.plugins.replication.pull.Context;
-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
- public void onEventShouldIndexExistingChange() {
- Project.NameKey projectNameKey = Project.nameKey("testProject");
- String ref = "refs/changes/41/41/meta";
- Change.Id changeId = Change.Id.fromRef(ref);
- try {
- Context.setLocalEvent(true);
- fetchRefReplicatedEventHandler.onEvent(
- new FetchRefReplicatedEvent(
- projectNameKey.get(),
- ref,
- sourceUri,
- ReplicationState.RefFetchResult.SUCCEEDED,
- RefUpdate.Result.FAST_FORWARD));
- verify(changeIndexerMock, times(1)).index(eq(projectNameKey), eq(changeId));
- } finally {
- Context.unsetLocalEvent();
- }
- }
-
- @Test
- public void onEventShouldNotIndexIfNotLocalEvent() {
- Project.NameKey projectNameKey = Project.nameKey("testProject");
- String ref = "refs/changes/41/41/meta";
- Change.Id changeId = Change.Id.fromRef(ref);
- fetchRefReplicatedEventHandler.onEvent(
- new FetchRefReplicatedEvent(
- projectNameKey.get(),
- ref,
- sourceUri,
- ReplicationState.RefFetchResult.SUCCEEDED,
- RefUpdate.Result.FAST_FORWARD));
- verify(changeIndexerMock, never()).index(eq(projectNameKey), eq(changeId));
- }
-
- @Test
- public void onEventShouldIndexOnlyMetaRef() {
- Project.NameKey projectNameKey = Project.nameKey("testProject");
- String ref = "refs/changes/41/41/1";
- Change.Id changeId = Change.Id.fromRef(ref);
- fetchRefReplicatedEventHandler.onEvent(
- new FetchRefReplicatedEvent(
- projectNameKey.get(),
- ref,
- sourceUri,
- ReplicationState.RefFetchResult.SUCCEEDED,
- RefUpdate.Result.FAST_FORWARD));
- verify(changeIndexerMock, never()).index(eq(projectNameKey), eq(changeId));
- }
-
- @Test
- public void onEventShouldNotIndexMissingChange() {
- fetchRefReplicatedEventHandler.onEvent(
- new FetchRefReplicatedEvent(
- Project.nameKey("testProject").get(),
- "invalidRef",
- sourceUri,
- ReplicationState.RefFetchResult.SUCCEEDED,
- RefUpdate.Result.FAST_FORWARD));
- verify(changeIndexerMock, never()).index(any(), any());
- }
-
- @Test
- public void onEventShouldNotIndexFailingChange() {
- Project.NameKey projectNameKey = Project.nameKey("testProject");
- String ref = "refs/changes/41/41/meta";
- fetchRefReplicatedEventHandler.onEvent(
- new FetchRefReplicatedEvent(
- projectNameKey.get(),
- ref,
- sourceUri,
- ReplicationState.RefFetchResult.FAILED,
- RefUpdate.Result.FAST_FORWARD));
- verify(changeIndexerMock, never()).index(any(), any());
- }
-
- @Test
- public void onEventShouldNotIndexNotAttemptedChange() {
- Project.NameKey projectNameKey = Project.nameKey("testProject");
- String ref = "refs/changes/41/41/meta";
- fetchRefReplicatedEventHandler.onEvent(
- new FetchRefReplicatedEvent(
- projectNameKey.get(),
- ref,
- sourceUri,
- ReplicationState.RefFetchResult.NOT_ATTEMPTED,
- RefUpdate.Result.FAST_FORWARD));
- verify(changeIndexerMock, never()).index(any(), any());
- }
-}