GroupList: Log null UUIDs

These shouldn't happen, but we've observed some in production
(possibly involving a custom group backend). Logging might help us
track it down.

Change-Id: Ib7a956774647d1bea4fb49ad55376de0408dcf71
This commit is contained in:
Dave Borowitz
2016-10-14 18:51:53 -04:00
parent 2e2cd58a5c
commit 11eb31d952
5 changed files with 39 additions and 13 deletions

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.pgm.init.api; package com.google.gerrit.pgm.init.api;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames; import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GroupList; import com.google.gerrit.server.git.GroupList;
@@ -66,7 +67,9 @@ public class AllProjectsConfig extends VersionedMetaDataOnInit {
} }
private GroupList readGroupList() throws IOException { private GroupList readGroupList() throws IOException {
return GroupList.parse(readUTF8(GroupList.FILE_NAME), return GroupList.parse(
new Project.NameKey(project),
readUTF8(GroupList.FILE_NAME),
GroupList.createLoggerSink(GroupList.FILE_NAME, log)); GroupList.createLoggerSink(GroupList.FILE_NAME, log));
} }

View File

@@ -37,9 +37,9 @@ import java.nio.file.Path;
public abstract class VersionedMetaDataOnInit extends VersionedMetaData { public abstract class VersionedMetaDataOnInit extends VersionedMetaData {
protected final String project;
private final InitFlags flags; private final InitFlags flags;
private final SitePaths site; private final SitePaths site;
private final String project;
private final String ref; private final String ref;
protected VersionedMetaDataOnInit(InitFlags flags, SitePaths site, protected VersionedMetaDataOnInit(InitFlags flags, SitePaths site,

View File

@@ -16,7 +16,10 @@ package com.google.gerrit.server.git;
import com.google.gerrit.common.data.GroupReference; import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroup.UUID; import com.google.gerrit.reviewdb.client.Project;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@@ -27,19 +30,29 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
public class GroupList extends TabFile { public class GroupList extends TabFile {
private static final Logger log = LoggerFactory.getLogger(GroupList.class);
public static final String FILE_NAME = "groups"; public static final String FILE_NAME = "groups";
private final Project.NameKey project;
private final Map<AccountGroup.UUID, GroupReference> byUUID; private final Map<AccountGroup.UUID, GroupReference> byUUID;
private GroupList(Map<AccountGroup.UUID, GroupReference> byUUID) { private GroupList(Project.NameKey project,
Map<AccountGroup.UUID, GroupReference> byUUID) {
this.project = project;
this.byUUID = byUUID; this.byUUID = byUUID;
} }
public static GroupList parse(String text, ValidationError.Sink errors) public static GroupList parse(Project.NameKey project, String text,
throws IOException { ValidationError.Sink errors) throws IOException {
List<Row> rows = parse(text, FILE_NAME, TRIM, TRIM, errors); List<Row> rows = parse(text, FILE_NAME, TRIM, TRIM, errors);
Map<AccountGroup.UUID, GroupReference> groupsByUUID = Map<AccountGroup.UUID, GroupReference> groupsByUUID =
new HashMap<>(rows.size()); new HashMap<>(rows.size());
for (Row row : rows) { for (Row row : rows) {
if (row.left == null) {
log.warn("null field in group list for {}:\n{}", project, text);
continue;
}
AccountGroup.UUID uuid = new AccountGroup.UUID(row.left); AccountGroup.UUID uuid = new AccountGroup.UUID(row.left);
String name = row.right; String name = row.right;
GroupReference ref = new GroupReference(uuid, name); GroupReference ref = new GroupReference(uuid, name);
@@ -47,7 +60,7 @@ public class GroupList extends TabFile {
groupsByUUID.put(uuid, ref); groupsByUUID.put(uuid, ref);
} }
return new GroupList(groupsByUUID); return new GroupList(project, groupsByUUID);
} }
public GroupReference byUUID(AccountGroup.UUID uuid) { public GroupReference byUUID(AccountGroup.UUID uuid) {
@@ -56,6 +69,10 @@ public class GroupList extends TabFile {
public GroupReference resolve(GroupReference group) { public GroupReference resolve(GroupReference group) {
if (group != null) { if (group != null) {
if (group.getUUID() == null || group.getUUID().get() == null) {
log.warn("attempting to resolve null group in {}: {}", project, group);
return group;
}
GroupReference ref = byUUID.get(group.getUUID()); GroupReference ref = byUUID.get(group.getUUID());
if (ref != null) { if (ref != null) {
return ref; return ref;
@@ -73,7 +90,11 @@ public class GroupList extends TabFile {
return byUUID.keySet(); return byUUID.keySet();
} }
public void put(UUID uuid, GroupReference reference) { public void put(AccountGroup.UUID uuid, GroupReference reference) {
if (uuid == null || uuid.get() == null) {
log.warn("attempting to put null group in {}: {}", project, reference);
return;
}
byUUID.put(uuid, reference); byUUID.put(uuid, reference);
} }

View File

@@ -910,7 +910,8 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
} }
private void readGroupList() throws IOException { private void readGroupList() throws IOException {
groupList = GroupList.parse(readUTF8(GroupList.FILE_NAME), this); groupList = GroupList.parse(
projectName, readUTF8(GroupList.FILE_NAME), this);
} }
private Map<String, GroupReference> mapGroupReferences() { private Map<String, GroupReference> mapGroupReferences() {

View File

@@ -27,6 +27,7 @@ import static org.junit.Assert.assertTrue;
import com.google.gerrit.common.data.GroupReference; import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -37,7 +38,7 @@ import java.util.Collections;
import java.util.Set; import java.util.Set;
public class GroupListTest { public class GroupListTest {
private static final Project.NameKey PROJECT = new Project.NameKey("project");
private static final String TEXT = private static final String TEXT =
"# UUID \tGroup Name\n" + "#\n" "# UUID \tGroup Name\n" + "#\n"
+ "d96b998f8a66ff433af50befb975d0e2bb6e0999\tNon-Interactive Users\n" + "d96b998f8a66ff433af50befb975d0e2bb6e0999\tNon-Interactive Users\n"
@@ -49,7 +50,7 @@ public class GroupListTest {
public void setup() throws IOException { public void setup() throws IOException {
ValidationError.Sink sink = createNiceMock(ValidationError.Sink.class); ValidationError.Sink sink = createNiceMock(ValidationError.Sink.class);
replay(sink); replay(sink);
groupList = GroupList.parse(TEXT, sink); groupList = GroupList.parse(PROJECT, TEXT, sink);
} }
@Test @Test
@@ -103,7 +104,7 @@ public class GroupListTest {
sink.error(anyObject(ValidationError.class)); sink.error(anyObject(ValidationError.class));
expectLastCall().times(2); expectLastCall().times(2);
replay(sink); replay(sink);
groupList = GroupList.parse(TEXT.replace("\t", " "), sink); groupList = GroupList.parse(PROJECT, TEXT.replace("\t", " "), sink);
verify(sink); verify(sink);
} }