Merge "Remove REST endpoint to rebuild individual groups in NoteDb"
diff --git a/java/com/google/gerrit/server/restapi/group/Module.java b/java/com/google/gerrit/server/restapi/group/Module.java
index 7410ee2..fa1e5c7 100644
--- a/java/com/google/gerrit/server/restapi/group/Module.java
+++ b/java/com/google/gerrit/server/restapi/group/Module.java
@@ -60,7 +60,6 @@
get(GROUP_KIND, "options").to(GetOptions.class);
put(GROUP_KIND, "options").to(PutOptions.class);
get(GROUP_KIND, "log.audit").to(GetAuditLog.class);
- post(GROUP_KIND, "rebuild").to(Rebuild.class);
child(GROUP_KIND, "members").to(MembersCollection.class);
get(MEMBER_KIND).to(GetMember.class);
diff --git a/java/com/google/gerrit/server/restapi/group/Rebuild.java b/java/com/google/gerrit/server/restapi/group/Rebuild.java
deleted file mode 100644
index 9e8cb3f..0000000
--- a/java/com/google/gerrit/server/restapi/group/Rebuild.java
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (C) 2017 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.google.gerrit.server.restapi.group;
-
-import static com.google.common.base.MoreObjects.firstNonNull;
-import static java.util.stream.Collectors.joining;
-
-import com.google.gerrit.common.data.GlobalCapability;
-import com.google.gerrit.extensions.annotations.RequiresCapability;
-import com.google.gerrit.extensions.restapi.BinaryResult;
-import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.group.GroupResource;
-import com.google.gerrit.server.group.db.GroupBundle;
-import com.google.gerrit.server.group.db.GroupRebuilder;
-import com.google.gerrit.server.notedb.GroupsMigration;
-import com.google.gerrit.server.restapi.group.Rebuild.Input;
-import com.google.gerrit.server.update.RefUpdateUtil;
-import com.google.gwtorm.server.OrmDuplicateKeyException;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import java.io.IOException;
-import java.util.List;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Repository;
-
-@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
-@Singleton
-public class Rebuild implements RestModifyView<GroupResource, Input> {
- public static class Input {
- public Boolean force;
- }
-
- private final AllUsersName allUsers;
- private final GitRepositoryManager repoManager;
- private final GroupBundle.Factory bundleFactory;
- private final GroupRebuilder rebuilder;
- private final GroupsMigration migration;
- private final Provider<ReviewDb> db;
-
- @Inject
- Rebuild(
- AllUsersName allUsers,
- GitRepositoryManager repoManager,
- GroupBundle.Factory bundleFactory,
- GroupRebuilder rebuilder,
- GroupsMigration migration,
- Provider<ReviewDb> db) {
- this.allUsers = allUsers;
- this.repoManager = repoManager;
- this.bundleFactory = bundleFactory;
- this.rebuilder = rebuilder;
- this.migration = migration;
- this.db = db;
- }
-
- @Override
- public BinaryResult apply(GroupResource rsrc, Input input)
- throws RestApiException, ConfigInvalidException, OrmException, IOException {
- boolean force = firstNonNull(input.force, false);
- if (!migration.writeToNoteDb()) {
- throw new MethodNotAllowedException("NoteDb writes must be enabled");
- }
- if (migration.readFromNoteDb() && force) {
- throw new MethodNotAllowedException("NoteDb reads must not be enabled when force=true");
- }
- if (!rsrc.isInternalGroup()) {
- throw new MethodNotAllowedException("Not an internal group");
- }
-
- AccountGroup.UUID uuid = rsrc.getGroup().getGroupUUID();
- try (Repository repo = repoManager.openRepository(allUsers)) {
- if (force) {
- RefUpdateUtil.deleteChecked(repo, RefNames.refsGroups(uuid));
- }
- GroupBundle reviewDbBundle =
- bundleFactory.fromReviewDb(db.get(), rsrc.asInternalGroup().get().getId());
- try {
- rebuilder.rebuild(repo, reviewDbBundle, null);
- } catch (OrmDuplicateKeyException e) {
- throw new ResourceConflictException("Group already exists in NoteDb");
- }
-
- GroupBundle noteDbBundle = bundleFactory.fromNoteDb(repo, uuid);
-
- List<String> diffs = GroupBundle.compareWithAudits(reviewDbBundle, noteDbBundle);
- if (diffs.isEmpty()) {
- return BinaryResult.create("No differences between ReviewDb and NoteDb");
- }
- return BinaryResult.create(
- diffs
- .stream()
- .collect(joining("\n", "Differences between ReviewDb and NoteDb:\n", "\n")));
- }
- }
-}
diff --git a/javatests/com/google/gerrit/acceptance/rest/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/rest/group/GroupsIT.java
index a52dd6d..e153e561 100644
--- a/javatests/com/google/gerrit/acceptance/rest/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/group/GroupsIT.java
@@ -15,27 +15,12 @@
package com.google.gerrit.acceptance.rest.group;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.RestResponse;
-import com.google.gerrit.extensions.common.GroupInfo;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.server.group.db.GroupBundle;
-import com.google.gerrit.server.notedb.GroupsMigration;
-import com.google.gerrit.server.restapi.group.Rebuild;
-import com.google.inject.Inject;
-import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.Repository;
import org.junit.Test;
public class GroupsIT extends AbstractDaemonTest {
- @Inject private GroupsMigration groupsMigration;
- @Inject private GroupBundle.Factory bundleFactory;
-
@Test
public void invalidQueryOptions() throws Exception {
RestResponse r = adminRestSession.put("/groups/?query=foo&query2=bar");
@@ -43,138 +28,4 @@
assertThat(r.getEntityContent())
.isEqualTo("\"query\" and \"query2\" options are mutually exclusive");
}
-
- @Test
- public void rebuild() throws Exception {
- assume().that(groupsMigration.writeToNoteDb()).isTrue();
- assume().that(groupsMigration.readFromNoteDb()).isFalse();
-
- GroupInfo g = gApi.groups().create(name("group")).get();
- AccountGroup.UUID uuid = new AccountGroup.UUID(g.id);
- String refName = RefNames.refsGroups(uuid);
- ObjectId oldId;
- GroupBundle oldBundle;
- try (Repository repo = repoManager.openRepository(allUsers)) {
- oldId = repo.exactRef(refName).getObjectId();
- oldBundle = bundleFactory.fromNoteDb(repo, uuid);
- new TestRepository<>(repo).delete(refName);
- }
-
- assertThat(
- adminRestSession.postOK("/groups/" + uuid + "/rebuild", input(null)).getEntityContent())
- .isEqualTo("No differences between ReviewDb and NoteDb");
-
- try (Repository repo = repoManager.openRepository(allUsers)) {
- Ref ref = repo.exactRef(refName);
- assertThat(ref).isNotNull();
-
- // An artifact of the migration process makes the SHA-1 different, but it's actually ok
- // because the bundles are equal.
- assertThat(ref.getObjectId()).isNotEqualTo(oldId);
-
- assertNoDifferences(oldBundle, bundleFactory.fromNoteDb(repo, uuid));
- }
- }
-
- @Test
- public void rebuildFailsWithWritesDisabled() throws Exception {
- assume().that(groupsMigration.writeToNoteDb()).isFalse();
-
- GroupInfo g = gApi.groups().create(name("group")).get();
- AccountGroup.UUID uuid = new AccountGroup.UUID(g.id);
-
- RestResponse res = adminRestSession.post("/groups/" + uuid + "/rebuild", input(null));
- assertThat(res.getStatusCode()).isEqualTo(405);
- assertThat(res.getEntityContent()).isEqualTo("NoteDb writes must be enabled");
- }
-
- @Test
- public void rebuildForceRequiresReadsDisabled() throws Exception {
- assume().that(groupsMigration.writeToNoteDb()).isTrue();
- assume().that(groupsMigration.readFromNoteDb()).isTrue();
-
- GroupInfo g = gApi.groups().create(name("group")).get();
- AccountGroup.UUID uuid = new AccountGroup.UUID(g.id);
-
- RestResponse res = adminRestSession.post("/groups/" + uuid + "/rebuild", input(true));
- assertThat(res.getStatusCode()).isEqualTo(405);
- assertThat(res.getEntityContent())
- .isEqualTo("NoteDb reads must not be enabled when force=true");
- }
-
- @Test
- public void rebuildWithoutForceFailsIfRefExists() throws Exception {
- assume().that(groupsMigration.writeToNoteDb()).isTrue();
- assume().that(groupsMigration.readFromNoteDb()).isFalse();
-
- GroupInfo g = gApi.groups().create(name("group")).get();
- AccountGroup.UUID uuid = new AccountGroup.UUID(g.id);
- String refName = RefNames.refsGroups(uuid);
-
- try (Repository repo = repoManager.openRepository(allUsers)) {
- new TestRepository<>(repo)
- .branch(refName)
- .commit()
- .add("somefile", "contents")
- .create()
- .copy();
- }
-
- RestResponse res = adminRestSession.post("/groups/" + uuid + "/rebuild", input(null));
- assertThat(res.getStatusCode()).isEqualTo(409);
- assertThat(res.getEntityContent()).isEqualTo("Group already exists in NoteDb");
- }
-
- @Test
- public void rebuildForce() throws Exception {
- assume().that(groupsMigration.writeToNoteDb()).isTrue();
- assume().that(groupsMigration.readFromNoteDb()).isFalse();
-
- GroupInfo g = gApi.groups().create(name("group")).get();
- AccountGroup.UUID uuid = new AccountGroup.UUID(g.id);
- String refName = RefNames.refsGroups(uuid);
-
- ObjectId oldId;
- GroupBundle oldBundle;
- try (Repository repo = repoManager.openRepository(allUsers)) {
- oldBundle = bundleFactory.fromNoteDb(repo, uuid);
-
- oldId =
- new TestRepository<>(repo)
- .branch(refName)
- .commit()
- .add("somefile", "contents")
- .create()
- .copy();
- }
-
- assertThat(
- adminRestSession.postOK("/groups/" + uuid + "/rebuild", input(true)).getEntityContent())
- .isEqualTo("No differences between ReviewDb and NoteDb");
-
- try (Repository repo = repoManager.openRepository(allUsers)) {
- Ref ref = repo.exactRef(refName);
- assertThat(ref).isNotNull();
-
- // oldId contains some garbage, so rebuilt value should definitely be different.
- assertThat(ref.getObjectId()).isNotEqualTo(oldId);
-
- assertNoDifferences(oldBundle, bundleFactory.fromNoteDb(repo, uuid));
- }
- }
-
- private static void assertNoDifferences(GroupBundle expected, GroupBundle actual) {
- // Comparing NoteDb to NoteDb, so compare fields instead of using static compare method.
- assertThat(actual.group()).isEqualTo(expected.group());
- assertThat(actual.members()).isEqualTo(expected.members());
- assertThat(actual.memberAudit()).isEqualTo(expected.memberAudit());
- assertThat(actual.byId()).isEqualTo(expected.byId());
- assertThat(actual.byIdAudit()).isEqualTo(expected.byIdAudit());
- }
-
- private static Rebuild.Input input(Boolean force) {
- Rebuild.Input input = new Rebuild.Input();
- input.force = force;
- return input;
- }
}