Merge "Index admin user account that is created during init"

This commit is contained in:
David Pursehouse
2017-01-12 23:16:43 +00:00
committed by Gerrit Code Review
8 changed files with 109 additions and 45 deletions

View File

@@ -42,6 +42,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet; import com.google.gwtorm.server.ResultSet;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject; import com.google.inject.assistedinject.AssistedInject;
@@ -64,8 +65,8 @@ import io.searchbox.core.Search;
import io.searchbox.core.search.sort.Sort; import io.searchbox.core.search.sort.Sort;
import io.searchbox.core.search.sort.Sort.Sorting; import io.searchbox.core.search.sort.Sort.Sorting;
class ElasticAccountIndex extends AbstractElasticIndex<Account.Id, AccountState> public class ElasticAccountIndex extends
implements AccountIndex { AbstractElasticIndex<Account.Id, AccountState> implements AccountIndex {
static class AccountMapping { static class AccountMapping {
MappingProperties accounts; MappingProperties accounts;
@@ -82,7 +83,7 @@ class ElasticAccountIndex extends AbstractElasticIndex<Account.Id, AccountState>
private final Gson gson; private final Gson gson;
private final AccountMapping mapping; private final AccountMapping mapping;
private final AccountCache accountCache; private final Provider<AccountCache> accountCache;
private final ElasticQueryBuilder queryBuilder; private final ElasticQueryBuilder queryBuilder;
@AssistedInject @AssistedInject
@@ -90,7 +91,7 @@ class ElasticAccountIndex extends AbstractElasticIndex<Account.Id, AccountState>
@GerritServerConfig Config cfg, @GerritServerConfig Config cfg,
FillArgs fillArgs, FillArgs fillArgs,
SitePaths sitePaths, SitePaths sitePaths,
AccountCache accountCache, Provider<AccountCache> accountCache,
@Assisted Schema<AccountState> schema) { @Assisted Schema<AccountState> schema) {
super(cfg, fillArgs, sitePaths, schema, ACCOUNTS_PREFIX); super(cfg, fillArgs, sitePaths, schema, ACCOUNTS_PREFIX);
this.accountCache = accountCache; this.accountCache = accountCache;
@@ -224,7 +225,7 @@ class ElasticAccountIndex extends AbstractElasticIndex<Account.Id, AccountState>
// document (of which there shouldn't be any). The most expensive part to // document (of which there shouldn't be any). The most expensive part to
// compute anyway is the effective group IDs, and we don't have a good way // compute anyway is the effective group IDs, and we don't have a good way
// to reindex when those change. // to reindex when those change.
return accountCache.get(id); return accountCache.get().get(id);
} }
} }
} }

View File

@@ -31,6 +31,7 @@ import com.google.gerrit.server.query.QueryParseException;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet; import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import org.apache.lucene.document.Document; import org.apache.lucene.document.Document;
@@ -77,7 +78,7 @@ public class LuceneAccountIndex
private final GerritIndexWriterConfig indexWriterConfig; private final GerritIndexWriterConfig indexWriterConfig;
private final QueryBuilder<AccountState> queryBuilder; private final QueryBuilder<AccountState> queryBuilder;
private final AccountCache accountCache; private final Provider<AccountCache> accountCache;
private static Directory dir(Schema<AccountState> schema, Config cfg, private static Directory dir(Schema<AccountState> schema, Config cfg,
SitePaths sitePaths) throws IOException { SitePaths sitePaths) throws IOException {
@@ -93,7 +94,7 @@ public class LuceneAccountIndex
LuceneAccountIndex( LuceneAccountIndex(
@GerritServerConfig Config cfg, @GerritServerConfig Config cfg,
SitePaths sitePaths, SitePaths sitePaths,
AccountCache accountCache, Provider<AccountCache> accountCache,
@Assisted Schema<AccountState> schema) throws IOException { @Assisted Schema<AccountState> schema) throws IOException {
super(schema, sitePaths, dir(schema, cfg, sitePaths), ACCOUNTS, null, super(schema, sitePaths, dir(schema, cfg, sitePaths), ACCOUNTS, null,
new GerritIndexWriterConfig(cfg, ACCOUNTS), new SearcherFactory()); new GerritIndexWriterConfig(cfg, ACCOUNTS), new SearcherFactory());
@@ -203,6 +204,6 @@ public class LuceneAccountIndex
// document (of which there shouldn't be any). The most expensive part to // document (of which there shouldn't be any). The most expensive part to
// compute anyway is the effective group IDs, and we don't have a good way // compute anyway is the effective group IDs, and we don't have a good way
// to reindex when those change. // to reindex when those change.
return accountCache.get(id); return accountCache.get().get(id);
} }
} }

View File

@@ -131,10 +131,18 @@ public class BaseInit extends SiteProgram {
init.initializer.run(); init.initializer.run();
init.flags.deleteOnFailure = false; init.flags.deleteOnFailure = false;
run = createSiteRun(init); Injector sysInjector = createSysInjector(init);
run.upgradeSchema(); IndexManagerOnInit indexManager =
sysInjector.getInstance(IndexManagerOnInit.class);
try {
indexManager.start();
run = createSiteRun(init);
run.upgradeSchema();
init.initializer.postRun(createSysInjector(init)); init.initializer.postRun(sysInjector);
} finally {
indexManager.stop();
}
} catch (Exception | Error failure) { } catch (Exception | Error failure) {
if (init.flags.deleteOnFailure) { if (init.flags.deleteOnFailure) {
recursiveDelete(getSitePath()); recursiveDelete(getSitePath());
@@ -347,7 +355,6 @@ public class BaseInit extends SiteProgram {
final SchemaUpdater schemaUpdater; final SchemaUpdater schemaUpdater;
final SchemaFactory<ReviewDb> schema; final SchemaFactory<ReviewDb> schema;
final GitRepositoryManager repositoryManager; final GitRepositoryManager repositoryManager;
final IndexManagerOnInit indexManager;
@Inject @Inject
SiteRun(ConsoleUI ui, SiteRun(ConsoleUI ui,
@@ -355,50 +362,43 @@ public class BaseInit extends SiteProgram {
InitFlags flags, InitFlags flags,
SchemaUpdater schemaUpdater, SchemaUpdater schemaUpdater,
SchemaFactory<ReviewDb> schema, SchemaFactory<ReviewDb> schema,
GitRepositoryManager repositoryManager, GitRepositoryManager repositoryManager) {
IndexManagerOnInit indexManager) {
this.ui = ui; this.ui = ui;
this.site = site; this.site = site;
this.flags = flags; this.flags = flags;
this.schemaUpdater = schemaUpdater; this.schemaUpdater = schemaUpdater;
this.schema = schema; this.schema = schema;
this.repositoryManager = repositoryManager; this.repositoryManager = repositoryManager;
this.indexManager = indexManager;
} }
void upgradeSchema() throws OrmException { void upgradeSchema() throws OrmException {
final List<String> pruneList = new ArrayList<>(); final List<String> pruneList = new ArrayList<>();
try { schemaUpdater.update(new UpdateUI() {
indexManager.start(); @Override
schemaUpdater.update(new UpdateUI() { public void message(String msg) {
@Override System.err.println(msg);
public void message(String msg) { System.err.flush();
System.err.println(msg); }
System.err.flush();
}
@Override @Override
public boolean yesno(boolean def, String msg) { public boolean yesno(boolean def, String msg) {
return ui.yesno(def, msg); return ui.yesno(def, msg);
} }
@Override @Override
public boolean isBatch() { public boolean isBatch() {
return ui.isBatch(); return ui.isBatch();
} }
@Override @Override
public void pruneSchema(StatementExecutor e, List<String> prune) { public void pruneSchema(StatementExecutor e, List<String> prune) {
for (String p : prune) { for (String p : prune) {
if (!pruneList.contains(p)) { if (!pruneList.contains(p)) {
pruneList.add(p); pruneList.add(p);
}
} }
} }
}); }
} finally { });
indexManager.stop();
}
if (!pruneList.isEmpty()) { if (!pruneList.isEmpty()) {
StringBuilder msg = new StringBuilder(); StringBuilder msg = new StringBuilder();

View File

@@ -29,6 +29,8 @@ import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupName; import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gerrit.reviewdb.client.AccountSshKey; import com.google.gerrit.reviewdb.client.AccountSshKey;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.account.AccountIndexCollection;
import com.google.gwtorm.server.SchemaFactory; import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -38,13 +40,17 @@ import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List;
public class InitAdminUser implements InitStep { public class InitAdminUser implements InitStep {
private final ConsoleUI ui; private final ConsoleUI ui;
private final InitFlags flags; private final InitFlags flags;
private final VersionedAuthorizedKeysOnInit.Factory authorizedKeysFactory; private final VersionedAuthorizedKeysOnInit.Factory authorizedKeysFactory;
private SchemaFactory<ReviewDb> dbFactory; private SchemaFactory<ReviewDb> dbFactory;
private AccountIndexCollection indexCollection;
@Inject @Inject
InitAdminUser( InitAdminUser(
@@ -65,6 +71,11 @@ public class InitAdminUser implements InitStep {
this.dbFactory = dbFactory; this.dbFactory = dbFactory;
} }
@Inject(optional = true)
void set(AccountIndexCollection indexCollection) {
this.indexCollection = indexCollection;
}
@Override @Override
public void postRun() throws Exception { public void postRun() throws Exception {
AuthType authType = AuthType authType =
@@ -84,12 +95,14 @@ public class InitAdminUser implements InitStep {
AccountSshKey sshKey = readSshKey(id); AccountSshKey sshKey = readSshKey(id);
String email = readEmail(sshKey); String email = readEmail(sshKey);
List<AccountExternalId> extIds = new ArrayList<>(2);
AccountExternalId extUser = AccountExternalId extUser =
new AccountExternalId(id, new AccountExternalId.Key( new AccountExternalId(id, new AccountExternalId.Key(
AccountExternalId.SCHEME_USERNAME, username)); AccountExternalId.SCHEME_USERNAME, username));
if (!Strings.isNullOrEmpty(httpPassword)) { if (!Strings.isNullOrEmpty(httpPassword)) {
extUser.setPassword(httpPassword); extUser.setPassword(httpPassword);
} }
extIds.add(extUser);
db.accountExternalIds().insert(Collections.singleton(extUser)); db.accountExternalIds().insert(Collections.singleton(extUser));
if (email != null) { if (email != null) {
@@ -97,6 +110,7 @@ public class InitAdminUser implements InitStep {
new AccountExternalId(id, new AccountExternalId.Key( new AccountExternalId(id, new AccountExternalId.Key(
AccountExternalId.SCHEME_MAILTO, email)); AccountExternalId.SCHEME_MAILTO, email));
extMailto.setEmailAddress(email); extMailto.setEmailAddress(email);
extIds.add(extMailto);
db.accountExternalIds().insert(Collections.singleton(extMailto)); db.accountExternalIds().insert(Collections.singleton(extMailto));
} }
@@ -105,11 +119,11 @@ public class InitAdminUser implements InitStep {
a.setPreferredEmail(email); a.setPreferredEmail(email);
db.accounts().insert(Collections.singleton(a)); db.accounts().insert(Collections.singleton(a));
AccountGroupName adminGroup = db.accountGroupNames().get( AccountGroupName adminGroupName = db.accountGroupNames().get(
new AccountGroup.NameKey("Administrators")); new AccountGroup.NameKey("Administrators"));
AccountGroupMember m = AccountGroupMember m =
new AccountGroupMember(new AccountGroupMember.Key(id, new AccountGroupMember(new AccountGroupMember.Key(id,
adminGroup.getId())); adminGroupName.getId()));
db.accountGroupMembers().insert(Collections.singleton(m)); db.accountGroupMembers().insert(Collections.singleton(m));
if (sshKey != null) { if (sshKey != null) {
@@ -118,6 +132,13 @@ public class InitAdminUser implements InitStep {
authorizedKeys.addKey(sshKey.getSshPublicKey()); authorizedKeys.addKey(sshKey.getSshPublicKey());
authorizedKeys.save("Added SSH key for initial admin user\n"); authorizedKeys.save("Added SSH key for initial admin user\n");
} }
AccountGroup adminGroup =
db.accountGroups().get(adminGroupName.getId());
AccountState as = new AccountState(a,
Collections.singleton(adminGroup.getGroupUUID()), extIds,
new HashMap<>());
indexCollection.getSearchIndex().replace(as);
} }
} }
} }

View File

@@ -15,14 +15,20 @@
package com.google.gerrit.pgm.init.index; package com.google.gerrit.pgm.init.index;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.GroupCache; import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.index.IndexDefinition; import com.google.gerrit.server.index.IndexDefinition;
import com.google.gerrit.server.index.SchemaDefinitions; import com.google.gerrit.server.index.SchemaDefinitions;
import com.google.gerrit.server.index.SingleVersionModule; import com.google.gerrit.server.index.SingleVersionModule;
import com.google.gerrit.server.index.SingleVersionModule.SingleVersionListener; import com.google.gerrit.server.index.SingleVersionModule.SingleVersionListener;
import com.google.gerrit.server.index.account.AccountIndexCollection;
import com.google.gerrit.server.index.account.AccountIndexDefinition;
import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
import com.google.gerrit.server.index.account.AllAccountsIndexer;
import com.google.gerrit.server.index.group.AllGroupsIndexer; import com.google.gerrit.server.index.group.AllGroupsIndexer;
import com.google.gerrit.server.index.group.GroupIndexCollection; import com.google.gerrit.server.index.group.GroupIndexCollection;
import com.google.gerrit.server.index.group.GroupIndexDefinition; import com.google.gerrit.server.index.group.GroupIndexDefinition;
@@ -41,8 +47,26 @@ import java.util.Set;
public class IndexModuleOnInit extends AbstractModule { public class IndexModuleOnInit extends AbstractModule {
static final String INDEX_MANAGER = "IndexModuleOnInit/IndexManager"; static final String INDEX_MANAGER = "IndexModuleOnInit/IndexManager";
private static final ImmutableCollection<SchemaDefinitions<?>> ALL_SCHEMA_DEFS =
ImmutableList.<SchemaDefinitions<?>> of(
AccountSchemaDefinitions.INSTANCE,
GroupSchemaDefinitions.INSTANCE);
@Override @Override
protected void configure() { protected void configure() {
// The AccountIndex implementations (LuceneAccountIndex and
// ElasticAccountIndex) need AccountCache only for reading from the index.
// On init we only want to write to the index, hence we don't need the
// account cache.
bind(AccountCache.class).toProvider(Providers.of(null));
// AccountIndexDefinition wants to have AllAccountsIndexer but it is only
// used by the Reindex program and the OnlineReindexer which are both not
// used during init, hence we don't need AllAccountsIndexer.
bind(AllAccountsIndexer.class).toProvider(Providers.of(null));
bind(AccountIndexCollection.class);
// The GroupIndex implementations (LuceneGroupIndex and ElasticGroupIndex) // The GroupIndex implementations (LuceneGroupIndex and ElasticGroupIndex)
// need GroupCache only for reading from the index. On init we only want to // need GroupCache only for reading from the index. On init we only want to
// write to the index, hence we don't need the group cache. // write to the index, hence we don't need the group cache.
@@ -64,12 +88,14 @@ public class IndexModuleOnInit extends AbstractModule {
@Provides @Provides
Collection<IndexDefinition<?, ?, ?>> getIndexDefinitions( Collection<IndexDefinition<?, ?, ?>> getIndexDefinitions(
AccountIndexDefinition accounts,
GroupIndexDefinition groups) { GroupIndexDefinition groups) {
Collection<IndexDefinition<?, ?, ?>> result = Collection<IndexDefinition<?, ?, ?>> result =
ImmutableList.<IndexDefinition<?, ?, ?>> of( ImmutableList.<IndexDefinition<?, ?, ?>> of(
accounts,
groups); groups);
Set<String> expected = Set<String> expected =
FluentIterable.of(GroupSchemaDefinitions.INSTANCE) FluentIterable.from(ALL_SCHEMA_DEFS)
.transform(SchemaDefinitions::getName) .transform(SchemaDefinitions::getName)
.toSet(); .toSet();
Set<String> actual = FluentIterable.from(result) Set<String> actual = FluentIterable.from(result)

View File

@@ -14,8 +14,10 @@
package com.google.gerrit.pgm.init.index.elasticsearch; package com.google.gerrit.pgm.init.index.elasticsearch;
import com.google.gerrit.elasticsearch.ElasticAccountIndex;
import com.google.gerrit.elasticsearch.ElasticGroupIndex; import com.google.gerrit.elasticsearch.ElasticGroupIndex;
import com.google.gerrit.pgm.init.index.IndexModuleOnInit; import com.google.gerrit.pgm.init.index.IndexModuleOnInit;
import com.google.gerrit.server.index.account.AccountIndex;
import com.google.gerrit.server.index.group.GroupIndex; import com.google.gerrit.server.index.group.GroupIndex;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.assistedinject.FactoryModuleBuilder;
@@ -24,6 +26,11 @@ public class ElasticIndexModuleOnInit extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
install(
new FactoryModuleBuilder()
.implement(AccountIndex.class, ElasticAccountIndex.class)
.build(AccountIndex.Factory.class));
install( install(
new FactoryModuleBuilder() new FactoryModuleBuilder()
.implement(GroupIndex.class, ElasticGroupIndex.class) .implement(GroupIndex.class, ElasticGroupIndex.class)

View File

@@ -14,8 +14,10 @@
package com.google.gerrit.pgm.init.index.lucene; package com.google.gerrit.pgm.init.index.lucene;
import com.google.gerrit.lucene.LuceneAccountIndex;
import com.google.gerrit.lucene.LuceneGroupIndex; import com.google.gerrit.lucene.LuceneGroupIndex;
import com.google.gerrit.pgm.init.index.IndexModuleOnInit; import com.google.gerrit.pgm.init.index.IndexModuleOnInit;
import com.google.gerrit.server.index.account.AccountIndex;
import com.google.gerrit.server.index.group.GroupIndex; import com.google.gerrit.server.index.group.GroupIndex;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.assistedinject.FactoryModuleBuilder;
@@ -23,6 +25,11 @@ import com.google.inject.assistedinject.FactoryModuleBuilder;
public class LuceneIndexModuleOnInit extends AbstractModule { public class LuceneIndexModuleOnInit extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
install(
new FactoryModuleBuilder()
.implement(AccountIndex.class, LuceneAccountIndex.class)
.build(AccountIndex.Factory.class));
install( install(
new FactoryModuleBuilder() new FactoryModuleBuilder()
.implement(GroupIndex.class, LuceneGroupIndex.class) .implement(GroupIndex.class, LuceneGroupIndex.class)

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.server.index.account; package com.google.gerrit.server.index.account;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountState; import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.IndexDefinition; import com.google.gerrit.server.index.IndexDefinition;
@@ -27,7 +28,7 @@ public class AccountIndexDefinition
AccountIndexDefinition( AccountIndexDefinition(
AccountIndexCollection indexCollection, AccountIndexCollection indexCollection,
AccountIndex.Factory indexFactory, AccountIndex.Factory indexFactory,
AllAccountsIndexer allAccountsIndexer) { @Nullable AllAccountsIndexer allAccountsIndexer) {
super(AccountSchemaDefinitions.INSTANCE, indexCollection, indexFactory, super(AccountSchemaDefinitions.INSTANCE, indexCollection, indexFactory,
Providers.of(allAccountsIndexer)); Providers.of(allAccountsIndexer));
} }