Merge "Add config option to prevent group updates while migrating groups"
This commit is contained in:
@@ -106,6 +106,7 @@ public class GroupsUpdate {
|
||||
private final MetaDataUpdateFactory metaDataUpdateFactory;
|
||||
private final GitReferenceUpdated gitRefUpdated;
|
||||
private final boolean writeGroupsToNoteDb;
|
||||
private final boolean reviewDbUpdatesAreBlocked;
|
||||
|
||||
@Inject
|
||||
GroupsUpdate(
|
||||
@@ -143,6 +144,7 @@ public class GroupsUpdate {
|
||||
// Don't flip this flag in a production setting! We only added it to spread the implementation
|
||||
// of groups in NoteDb among several changes which are gradually merged.
|
||||
writeGroupsToNoteDb = config.getBoolean("user", null, "writeGroupsToNoteDb", false);
|
||||
reviewDbUpdatesAreBlocked = config.getBoolean("user", null, "blockReviewDbGroupUpdates", false);
|
||||
}
|
||||
|
||||
private static MetaDataUpdateFactory getMetaDataUpdateFactory(
|
||||
@@ -255,6 +257,7 @@ public class GroupsUpdate {
|
||||
private InternalGroup createGroupInReviewDb(
|
||||
ReviewDb db, InternalGroupCreation groupCreation, InternalGroupUpdate groupUpdate)
|
||||
throws OrmException {
|
||||
checkIfReviewDbUpdatesAreBlocked();
|
||||
|
||||
AccountGroupName gn = new AccountGroupName(groupCreation.getNameKey(), groupCreation.getId());
|
||||
// first insert the group name to validate that the group name hasn't
|
||||
@@ -294,6 +297,8 @@ public class GroupsUpdate {
|
||||
|
||||
private UpdateResult updateGroupInReviewDb(
|
||||
ReviewDb db, AccountGroup group, InternalGroupUpdate groupUpdate) throws OrmException {
|
||||
checkIfReviewDbUpdatesAreBlocked();
|
||||
|
||||
AccountGroup.NameKey originalName = group.getNameKey();
|
||||
applyUpdate(group, groupUpdate);
|
||||
AccountGroup.NameKey updatedName = group.getNameKey();
|
||||
@@ -618,6 +623,12 @@ public class GroupsUpdate {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfReviewDbUpdatesAreBlocked() throws OrmException {
|
||||
if (reviewDbUpdatesAreBlocked) {
|
||||
throw new OrmException("Updates to groups in ReviewDb are blocked");
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface MetaDataUpdateFactory {
|
||||
MetaDataUpdate create(
|
||||
|
||||
@@ -87,10 +87,12 @@ public class GroupRebuilderIT extends AbstractDaemonTest {
|
||||
@Test
|
||||
public void basicGroupProperties() throws Exception {
|
||||
GroupInfo createdGroup = gApi.groups().create(name("group")).get();
|
||||
InternalGroup reviewDbGroup = groups.getGroup(db, new AccountGroup.UUID(createdGroup.id)).get();
|
||||
deleteGroupRefs(reviewDbGroup);
|
||||
|
||||
assertThat(removeRefState(rebuild(reviewDbGroup))).isEqualTo(roundToSecond(reviewDbGroup));
|
||||
try (BlockReviewDbUpdatesForGroups ctx = new BlockReviewDbUpdatesForGroups()) {
|
||||
InternalGroup reviewDbGroup =
|
||||
groups.getGroup(db, new AccountGroup.UUID(createdGroup.id)).get();
|
||||
deleteGroupRefs(reviewDbGroup);
|
||||
assertThat(removeRefState(rebuild(reviewDbGroup))).isEqualTo(roundToSecond(reviewDbGroup));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -105,46 +107,48 @@ public class GroupRebuilderIT extends AbstractDaemonTest {
|
||||
|
||||
gApi.groups().id(group1.id).addGroups(group2.id);
|
||||
|
||||
InternalGroup reviewDbGroup = groups.getGroup(db, new AccountGroup.UUID(group1.id)).get();
|
||||
deleteGroupRefs(reviewDbGroup);
|
||||
try (BlockReviewDbUpdatesForGroups ctx = new BlockReviewDbUpdatesForGroups()) {
|
||||
InternalGroup reviewDbGroup = groups.getGroup(db, new AccountGroup.UUID(group1.id)).get();
|
||||
deleteGroupRefs(reviewDbGroup);
|
||||
|
||||
InternalGroup noteDbGroup = rebuild(reviewDbGroup);
|
||||
assertThat(removeRefState(noteDbGroup)).isEqualTo(roundToSecond(reviewDbGroup));
|
||||
InternalGroup noteDbGroup = rebuild(reviewDbGroup);
|
||||
assertThat(removeRefState(noteDbGroup)).isEqualTo(roundToSecond(reviewDbGroup));
|
||||
|
||||
ImmutableList<CommitInfo> log = log(group1);
|
||||
assertThat(log).hasSize(4);
|
||||
ImmutableList<CommitInfo> log = log(group1);
|
||||
assertThat(log).hasSize(4);
|
||||
|
||||
assertThat(log.get(0)).message().isEqualTo("Create group");
|
||||
assertThat(log.get(0)).author().name().isEqualTo(serverIdent.get().getName());
|
||||
assertThat(log.get(0)).author().email().isEqualTo(serverIdent.get().getEmailAddress());
|
||||
assertThat(log.get(0)).author().date().isEqualTo(noteDbGroup.getCreatedOn());
|
||||
assertThat(log.get(0)).author().tz().isEqualTo(serverIdent.get().getTimeZoneOffset());
|
||||
assertThat(log.get(0)).committer().isEqualTo(log.get(0).author);
|
||||
assertThat(log.get(0)).message().isEqualTo("Create group");
|
||||
assertThat(log.get(0)).author().name().isEqualTo(serverIdent.get().getName());
|
||||
assertThat(log.get(0)).author().email().isEqualTo(serverIdent.get().getEmailAddress());
|
||||
assertThat(log.get(0)).author().date().isEqualTo(noteDbGroup.getCreatedOn());
|
||||
assertThat(log.get(0)).author().tz().isEqualTo(serverIdent.get().getTimeZoneOffset());
|
||||
assertThat(log.get(0)).committer().isEqualTo(log.get(0).author);
|
||||
|
||||
assertThat(log.get(1))
|
||||
.message()
|
||||
.isEqualTo("Update group\n\nAdd: Administrator <" + admin.id + "@" + serverId + ">");
|
||||
assertThat(log.get(1)).author().name().isEqualTo(admin.fullName);
|
||||
assertThat(log.get(1)).author().email().isEqualTo(admin.id + "@" + serverId);
|
||||
assertThat(log.get(1)).committer().hasSameDateAs(log.get(1).author);
|
||||
assertThat(log.get(1))
|
||||
.message()
|
||||
.isEqualTo("Update group\n\nAdd: Administrator <" + admin.id + "@" + serverId + ">");
|
||||
assertThat(log.get(1)).author().name().isEqualTo(admin.fullName);
|
||||
assertThat(log.get(1)).author().email().isEqualTo(admin.id + "@" + serverId);
|
||||
assertThat(log.get(1)).committer().hasSameDateAs(log.get(1).author);
|
||||
|
||||
assertThat(log.get(2))
|
||||
.message()
|
||||
.isEqualTo(
|
||||
"Update group\n"
|
||||
+ "\n"
|
||||
+ ("Add: User <" + user.id + "@" + serverId + ">\n")
|
||||
+ ("Add: User2 <" + user2.id + "@" + serverId + ">"));
|
||||
assertThat(log.get(2)).author().name().isEqualTo(admin.fullName);
|
||||
assertThat(log.get(2)).author().email().isEqualTo(admin.id + "@" + serverId);
|
||||
assertThat(log.get(2)).committer().hasSameDateAs(log.get(2).author);
|
||||
assertThat(log.get(2))
|
||||
.message()
|
||||
.isEqualTo(
|
||||
"Update group\n"
|
||||
+ "\n"
|
||||
+ ("Add: User <" + user.id + "@" + serverId + ">\n")
|
||||
+ ("Add: User2 <" + user2.id + "@" + serverId + ">"));
|
||||
assertThat(log.get(2)).author().name().isEqualTo(admin.fullName);
|
||||
assertThat(log.get(2)).author().email().isEqualTo(admin.id + "@" + serverId);
|
||||
assertThat(log.get(2)).committer().hasSameDateAs(log.get(2).author);
|
||||
|
||||
assertThat(log.get(3))
|
||||
.message()
|
||||
.isEqualTo("Update group\n\nAdd-group: " + group2.name + " <" + group2.id + ">");
|
||||
assertThat(log.get(3)).author().name().isEqualTo(admin.fullName);
|
||||
assertThat(log.get(3)).author().email().isEqualTo(admin.id + "@" + serverId);
|
||||
assertThat(log.get(3)).committer().hasSameDateAs(log.get(3).author);
|
||||
assertThat(log.get(3))
|
||||
.message()
|
||||
.isEqualTo("Update group\n\nAdd-group: " + group2.name + " <" + group2.id + ">");
|
||||
assertThat(log.get(3)).author().name().isEqualTo(admin.fullName);
|
||||
assertThat(log.get(3)).author().email().isEqualTo(admin.id + "@" + serverId);
|
||||
assertThat(log.get(3)).committer().hasSameDateAs(log.get(3).author);
|
||||
}
|
||||
}
|
||||
|
||||
private static InternalGroup removeRefState(InternalGroup group) throws Exception {
|
||||
@@ -209,4 +213,19 @@ public class GroupRebuilderIT extends AbstractDaemonTest {
|
||||
assertThat(commitDates).named("commit timestamps for %s", result).isOrdered();
|
||||
return result.build();
|
||||
}
|
||||
|
||||
private class BlockReviewDbUpdatesForGroups implements AutoCloseable {
|
||||
BlockReviewDbUpdatesForGroups() {
|
||||
blockReviewDbUpdates(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
blockReviewDbUpdates(false);
|
||||
}
|
||||
|
||||
private void blockReviewDbUpdates(boolean block) {
|
||||
cfg.setBoolean("user", null, "readGroupsFromNoteDb", block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
|
||||
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
@@ -56,6 +57,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.RestApiException;
|
||||
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
|
||||
import com.google.gerrit.extensions.restapi.Url;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
@@ -73,6 +75,7 @@ import com.google.gerrit.server.index.group.GroupIndexer;
|
||||
import com.google.gerrit.server.index.group.StalenessChecker;
|
||||
import com.google.gerrit.server.util.MagicBranch;
|
||||
import com.google.gerrit.testing.ConfigSuite;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
import java.io.IOException;
|
||||
@@ -998,6 +1001,40 @@ public class GroupsIT extends AbstractDaemonTest {
|
||||
allUsers, RefNames.REFS_GROUPS + "*", Permission.READ, groupRef(REGISTERED_USERS));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Sandboxed
|
||||
public void blockReviewDbUpdatesOnGroupCreation() throws Exception {
|
||||
assume().that(groupsInNoteDb()).isFalse();
|
||||
cfg.setBoolean("user", null, "blockReviewDbGroupUpdates", true);
|
||||
try {
|
||||
gApi.groups().create(name("foo"));
|
||||
fail("Expected RestApiException: Updates to groups in ReviewDb are blocked");
|
||||
} catch (RestApiException e) {
|
||||
assertWriteGroupToReviewDbBlockedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Sandboxed
|
||||
public void blockReviewDbUpdatesOnGroupUpdate() throws Exception {
|
||||
assume().that(groupsInNoteDb()).isFalse();
|
||||
String group1 = gApi.groups().create(name("foo")).get().id;
|
||||
String group2 = gApi.groups().create(name("bar")).get().id;
|
||||
cfg.setBoolean("user", null, "blockReviewDbGroupUpdates", true);
|
||||
try {
|
||||
gApi.groups().id(group1).addGroups(group2);
|
||||
fail("Expected RestApiException: Updates to groups in ReviewDb are blocked");
|
||||
} catch (RestApiException e) {
|
||||
assertWriteGroupToReviewDbBlockedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertWriteGroupToReviewDbBlockedException(Exception e) throws Exception {
|
||||
Throwable t = Throwables.getRootCause(e);
|
||||
assertThat(t).isInstanceOf(OrmException.class);
|
||||
assertThat(t.getMessage()).isEqualTo("Updates to groups in ReviewDb are blocked");
|
||||
}
|
||||
|
||||
private GroupReference groupRef(AccountGroup.UUID groupUuid) {
|
||||
GroupDescription.Basic groupDescription = groupBackend.get(groupUuid);
|
||||
return new GroupReference(groupDescription.getGroupUUID(), groupDescription.getName());
|
||||
|
||||
Reference in New Issue
Block a user