@@ -34,7 +34,7 @@ import org.sonar.ce.task.step.TestComputationStepContext; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.BranchDao; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.AnalysisIndexer; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
@@ -53,16 +53,11 @@ public class IndexAnalysisStepIT extends BaseStepTest { | |||
public BatchReportReaderRule reportReader = new BatchReportReaderRule(); | |||
private final DbClient dbClient = mock(DbClient.class); | |||
private final FileStatuses fileStatuses = mock(FileStatuses.class); | |||
private final ProjectIndexer projectIndexer = mock(ProjectIndexer.class); | |||
private final AnalysisIndexer analysisIndexer = mock(AnalysisIndexer.class); | |||
private final DbSession dbSession = mock(DbSession.class); | |||
private final BranchDao branchDao = mock(BranchDao.class); | |||
private final IndexAnalysisStep underTest = new IndexAnalysisStep(treeRootHolder, fileStatuses, dbClient, projectIndexer); | |||
private final IndexAnalysisStep underTest = new IndexAnalysisStep(treeRootHolder, fileStatuses, dbClient, analysisIndexer); | |||
private TestComputationStepContext testComputationStepContext; | |||
@@ -81,7 +76,7 @@ public class IndexAnalysisStepIT extends BaseStepTest { | |||
underTest.execute(testComputationStepContext); | |||
verify(projectIndexer).indexOnAnalysis(PROJECT_UUID, Set.of()); | |||
verify(analysisIndexer).indexOnAnalysis(PROJECT_UUID, Set.of()); | |||
} | |||
@Test | |||
@@ -91,7 +86,7 @@ public class IndexAnalysisStepIT extends BaseStepTest { | |||
underTest.execute(testComputationStepContext); | |||
verify(projectIndexer).indexOnAnalysis(PROJECT_UUID, Set.of()); | |||
verify(analysisIndexer).indexOnAnalysis(PROJECT_UUID, Set.of()); | |||
} | |||
@Test | |||
@@ -103,7 +98,7 @@ public class IndexAnalysisStepIT extends BaseStepTest { | |||
underTest.execute(testComputationStepContext); | |||
verify(projectIndexer).indexOnAnalysis(PROJECT_UUID, anyUuids); | |||
verify(analysisIndexer).indexOnAnalysis(PROJECT_UUID, anyUuids); | |||
} | |||
@Test | |||
@@ -114,7 +109,7 @@ public class IndexAnalysisStepIT extends BaseStepTest { | |||
underTest.execute(testComputationStepContext); | |||
verify(projectIndexer).indexOnAnalysis(PROJECT_UUID); | |||
verify(analysisIndexer).indexOnAnalysis(PROJECT_UUID); | |||
} | |||
@Override |
@@ -23,22 +23,22 @@ import java.util.Collection; | |||
import java.util.List; | |||
import org.sonar.api.server.ServerSide; | |||
import org.sonar.db.purge.PurgeListener; | |||
import org.sonar.server.component.index.ComponentIndexer; | |||
import org.sonar.server.component.index.EntityDefinitionIndexer; | |||
import org.sonar.server.issue.index.IssueIndexer; | |||
@ServerSide | |||
public class IndexPurgeListener implements PurgeListener { | |||
private final IssueIndexer issueIndexer; | |||
private final ComponentIndexer componentIndexer; | |||
private final EntityDefinitionIndexer entityDefinitionIndexer; | |||
public IndexPurgeListener(IssueIndexer issueIndexer, ComponentIndexer componentIndexer) { | |||
public IndexPurgeListener(IssueIndexer issueIndexer, EntityDefinitionIndexer entityDefinitionIndexer) { | |||
this.issueIndexer = issueIndexer; | |||
this.componentIndexer = componentIndexer; | |||
this.entityDefinitionIndexer = entityDefinitionIndexer; | |||
} | |||
@Override | |||
public void onComponentsDisabling(String projectUuid, Collection<String> disabledComponentUuids) { | |||
componentIndexer.delete(projectUuid, disabledComponentUuids); | |||
entityDefinitionIndexer.delete(projectUuid, disabledComponentUuids); | |||
} | |||
@Override |
@@ -28,7 +28,7 @@ import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; | |||
import org.sonar.ce.task.step.ComputationStep; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.AnalysisIndexer; | |||
public class IndexAnalysisStep implements ComputationStep { | |||
@@ -36,10 +36,10 @@ public class IndexAnalysisStep implements ComputationStep { | |||
private final TreeRootHolder treeRootHolder; | |||
private final FileStatuses fileStatuses; | |||
private final ProjectIndexer[] indexers; | |||
private final AnalysisIndexer[] indexers; | |||
private final DbClient dbClient; | |||
public IndexAnalysisStep(TreeRootHolder treeRootHolder, FileStatuses fileStatuses, DbClient dbClient, ProjectIndexer... indexers) { | |||
public IndexAnalysisStep(TreeRootHolder treeRootHolder, FileStatuses fileStatuses, DbClient dbClient, AnalysisIndexer... indexers) { | |||
this.treeRootHolder = treeRootHolder; | |||
this.fileStatuses = fileStatuses; | |||
this.indexers = indexers; | |||
@@ -49,14 +49,14 @@ public class IndexAnalysisStep implements ComputationStep { | |||
@Override | |||
public void execute(ComputationStep.Context context) { | |||
String branchUuid = treeRootHolder.getRoot().getUuid(); | |||
Consumer<ProjectIndexer> projectIndexerConsumer = getProjectIndexerConsumer(branchUuid); | |||
for (ProjectIndexer indexer : indexers) { | |||
Consumer<AnalysisIndexer> analysisIndexerConsumer = getAnalysisIndexerConsumer(branchUuid); | |||
for (AnalysisIndexer indexer : indexers) { | |||
LOGGER.debug("Call {}", indexer); | |||
projectIndexerConsumer.accept(indexer); | |||
analysisIndexerConsumer.accept(indexer); | |||
} | |||
} | |||
private Consumer<ProjectIndexer> getProjectIndexerConsumer(String branchUuid) { | |||
private Consumer<AnalysisIndexer> getAnalysisIndexerConsumer(String branchUuid) { | |||
Set<String> fileUuidsMarkedAsUnchanged = fileStatuses.getFileUuidsMarkedAsUnchanged(); | |||
return isBranchNeedIssueSync(branchUuid) | |||
? (indexer -> indexer.indexOnAnalysis(branchUuid)) |
@@ -21,7 +21,7 @@ package org.sonar.ce.task.projectanalysis.purge; | |||
import java.util.List; | |||
import org.junit.Test; | |||
import org.sonar.server.component.index.ComponentIndexer; | |||
import org.sonar.server.component.index.EntityDefinitionIndexer; | |||
import org.sonar.server.issue.index.IssueIndexer; | |||
import static java.util.Arrays.asList; | |||
@@ -32,9 +32,9 @@ import static org.mockito.Mockito.verify; | |||
public class IndexPurgeListenerTest { | |||
private IssueIndexer issueIndexer = mock(IssueIndexer.class); | |||
private ComponentIndexer componentIndexer = mock(ComponentIndexer.class); | |||
private EntityDefinitionIndexer entityDefinitionIndexer = mock(EntityDefinitionIndexer.class); | |||
private IndexPurgeListener underTest = new IndexPurgeListener(issueIndexer, componentIndexer); | |||
private IndexPurgeListener underTest = new IndexPurgeListener(issueIndexer, entityDefinitionIndexer); | |||
@Test | |||
public void test_onComponentDisabling() { | |||
@@ -43,7 +43,7 @@ public class IndexPurgeListenerTest { | |||
List<String> uuids = singletonList(uuid); | |||
underTest.onComponentsDisabling(projectUuid, uuids); | |||
verify(componentIndexer).delete(projectUuid, uuids); | |||
verify(entityDefinitionIndexer).delete(projectUuid, uuids); | |||
} | |||
@Test |
@@ -89,10 +89,10 @@ import org.sonar.db.purge.PurgeProfiler; | |||
import org.sonar.process.NetworkUtilsImpl; | |||
import org.sonar.process.Props; | |||
import org.sonar.process.logging.LogbackHelper; | |||
import org.sonar.server.component.index.ComponentIndexer; | |||
import org.sonar.server.component.index.EntityDefinitionIndexer; | |||
import org.sonar.server.config.ConfigurationProvider; | |||
import org.sonar.server.es.EsModule; | |||
import org.sonar.server.es.ProjectIndexersImpl; | |||
import org.sonar.server.es.IndexersImpl; | |||
import org.sonar.server.extension.CoreExtensionBootstraper; | |||
import org.sonar.server.extension.CoreExtensionStopper; | |||
import org.sonar.server.favorite.FavoriteUpdater; | |||
@@ -381,11 +381,11 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer { | |||
// components, | |||
FavoriteUpdater.class, | |||
ProjectIndexersImpl.class, | |||
IndexersImpl.class, | |||
QGChangeNotificationHandler.class, | |||
QGChangeNotificationHandler.newMetadata(), | |||
ProjectMeasuresIndexer.class, | |||
ComponentIndexer.class, | |||
EntityDefinitionIndexer.class, | |||
// views | |||
ViewIndexer.class, |
@@ -162,36 +162,9 @@ public class EntityDaoIT { | |||
List<EntityDto> result = new LinkedList<>(); | |||
ResultHandler<EntityDto> handler = resultContext -> result.add(resultContext.getResultObject()); | |||
entityDao.scrollForIndexing(db.getSession(), null, handler); | |||
entityDao.scrollForIndexing(db.getSession(), handler); | |||
assertThat(result).extracting(EntityDto::getUuid) | |||
.containsOnly(project.projectUuid(), application.projectUuid(), portfolio.getUuid()); | |||
} | |||
@Test | |||
public void scrollEntitiesForIndexing_whenEntityUuidSpecified_shouldReturnSpecificEntity() { | |||
ProjectData application = db.components().insertPrivateApplication(); | |||
ProjectData project = db.components().insertPrivateProject(); | |||
PortfolioDto portfolio = db.components().insertPrivatePortfolioDto(); | |||
List<EntityDto> result = new LinkedList<>(); | |||
ResultHandler<EntityDto> handler = resultContext -> result.add(resultContext.getResultObject()); | |||
entityDao.scrollForIndexing(db.getSession(), project.projectUuid(), handler); | |||
assertThat(result).extracting(EntityDto::getUuid) | |||
.containsOnly(project.projectUuid()); | |||
} | |||
@Test | |||
public void scrollEntitiesForIndexing_whenNonExistingUuidSpecified_shouldReturnEmpty() { | |||
ProjectData application = db.components().insertPrivateApplication(); | |||
ProjectData project = db.components().insertPrivateProject(); | |||
PortfolioDto portfolio = db.components().insertPrivatePortfolioDto(); | |||
List<EntityDto> result = new LinkedList<>(); | |||
ResultHandler<EntityDto> handler = resultContext -> result.add(resultContext.getResultObject()); | |||
entityDao.scrollForIndexing(db.getSession(), "unknown", handler); | |||
assertThat(result).isEmpty(); | |||
} | |||
} |
@@ -58,8 +58,8 @@ public class EntityDao implements Dao { | |||
return Optional.ofNullable(mapper(dbSession).selectByComponentUuid(componentUuid)); | |||
} | |||
public void scrollForIndexing(DbSession session, @Nullable String entityUuid, ResultHandler<EntityDto> handler) { | |||
mapper(session).scrollForIndexing(entityUuid, handler); | |||
public void scrollForIndexing(DbSession session, ResultHandler<EntityDto> handler) { | |||
mapper(session).scrollForIndexing(handler); | |||
} | |||
private static EntityMapper mapper(DbSession session) { |
@@ -40,5 +40,5 @@ public interface EntityMapper { | |||
List<EntityDto> selectByKeys(@Param("keys") Collection<String> keys); | |||
void scrollForIndexing(@Param("entityUuid") @Nullable String entityUuid, ResultHandler<EntityDto> handler); | |||
void scrollForIndexing(ResultHandler<EntityDto> handler); | |||
} |
@@ -171,10 +171,6 @@ public class UserDao implements Dao { | |||
mapper(dbSession).clearHomepages("PROJECT", entityDto.getUuid(), system2.now()); | |||
} | |||
public void cleanHomepage(DbSession dbSession, ComponentDto component) { | |||
mapper(dbSession).clearHomepages("PROJECT", component.uuid(), system2.now()); | |||
} | |||
public void cleanHomepage(DbSession dbSession, UserDto user) { | |||
mapper(dbSession).clearHomepage(user.getLogin(), system2.now()); | |||
} |
@@ -85,17 +85,11 @@ | |||
</foreach>) | |||
</select> | |||
<select id="scrollForIndexing" parameterType="map" resultType="Entity" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY"> | |||
<select id="scrollForIndexing" resultType="Entity" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY"> | |||
(select <include refid="entityProjectColumns"/> | |||
from projects p | |||
<if test="entityUuid != null"> | |||
where p.uuid = #{entityUuid,jdbcType=VARCHAR} | |||
</if>) | |||
from projects p) | |||
UNION | |||
(select <include refid="entityPortfolioColumns"/> | |||
from portfolios p | |||
<if test="entityUuid != null"> | |||
where p.uuid = #{entityUuid,jdbcType=VARCHAR} | |||
</if>) | |||
from portfolios p) | |||
</select> | |||
</mapper> |
@@ -30,14 +30,15 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ProjectData; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.es.EsQueueDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.IndexingResult; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import static java.util.Collections.emptySet; | |||
import static java.util.Collections.singletonList; | |||
@@ -46,11 +47,13 @@ import static org.elasticsearch.index.query.QueryBuilders.matchQuery; | |||
import static org.sonar.api.resources.Qualifiers.PROJECT; | |||
import static org.sonar.server.component.index.ComponentIndexDefinition.FIELD_NAME; | |||
import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_COMPONENT; | |||
import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_CREATION; | |||
import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_DELETION; | |||
import static org.sonar.server.es.Indexers.EntityEvent.PERMISSION_CHANGE; | |||
import static org.sonar.server.es.Indexers.EntityEvent.CREATION; | |||
import static org.sonar.server.es.Indexers.EntityEvent.DELETION; | |||
import static org.sonar.server.es.Indexers.EntityEvent.PROJECT_TAGS_UPDATE; | |||
import static org.sonar.server.es.newindex.DefaultIndexSettingsElement.SORTABLE_ANALYZER; | |||
public class ComponentIndexerIT { | |||
public class EntityDefinitionIndexerIT { | |||
private System2 system2 = System2.INSTANCE; | |||
@@ -61,7 +64,7 @@ public class ComponentIndexerIT { | |||
private DbClient dbClient = db.getDbClient(); | |||
private DbSession dbSession = db.getSession(); | |||
private ComponentIndexer underTest = new ComponentIndexer(db.getDbClient(), es.client()); | |||
private EntityDefinitionIndexer underTest = new EntityDefinitionIndexer(db.getDbClient(), es.client()); | |||
@Test | |||
public void test_getIndexTypes() { | |||
@@ -152,7 +155,7 @@ public class ComponentIndexerIT { | |||
public void do_not_update_index_on_project_tag_update() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
indexEntity(project, ProjectIndexer.Cause.PROJECT_TAGS_UPDATE); | |||
indexProject(project, PROJECT_TAGS_UPDATE); | |||
assertThatIndexHasSize(0); | |||
} | |||
@@ -161,7 +164,7 @@ public class ComponentIndexerIT { | |||
public void do_not_update_index_on_permission_change() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
indexEntity(project, ProjectIndexer.Cause.PERMISSION_CHANGE); | |||
indexProject(project, PERMISSION_CHANGE); | |||
assertThatIndexHasSize(0); | |||
} | |||
@@ -170,7 +173,7 @@ public class ComponentIndexerIT { | |||
public void update_index_on_project_creation() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
IndexingResult result = indexEntity(project, PROJECT_CREATION); | |||
IndexingResult result = indexProject(project, CREATION); | |||
assertThatIndexContainsOnly(project); | |||
assertThat(result.getTotal()).isOne(); | |||
@@ -180,7 +183,7 @@ public class ComponentIndexerIT { | |||
@Test | |||
public void delete_some_components() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
indexEntity(project, PROJECT_CREATION); | |||
indexProject(project, CREATION); | |||
underTest.delete(project.getUuid(), emptySet()); | |||
@@ -190,43 +193,42 @@ public class ComponentIndexerIT { | |||
@Test | |||
public void delete_project() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
indexEntity(project, PROJECT_CREATION); | |||
indexProject(project, CREATION); | |||
assertThatIndexHasSize(1); | |||
db.getDbClient().purgeDao().deleteProject(db.getSession(), project.getUuid(), PROJECT, project.getName(), project.getKey()); | |||
indexEntity(project, PROJECT_DELETION); | |||
indexProject(project, DELETION); | |||
assertThatIndexHasSize(0); | |||
} | |||
@Test | |||
public void indexOnAnalysis_updates_index_on_changes() { | |||
ProjectData project = db.components().insertPrivateProject(); | |||
underTest.indexOnAnalysis(project.getMainBranchComponent().uuid()); | |||
assertThatEntityHasName(project.projectUuid(), project.getProjectDto().getName()); | |||
// modify | |||
ProjectDto projectDto = project.getProjectDto(); | |||
projectDto.setName("NewName"); | |||
ProjectData project = db.components().insertPrivateProject(); | |||
ProjectDto projectDto = project.getProjectDto(); | |||
db.getDbClient().projectDao().update(dbSession, projectDto); | |||
db.commit(); | |||
underTest.indexOnAnalysis(project.getMainBranchDto().getUuid()); | |||
assertThatEntityHasName(projectDto.getUuid(), projectDto.getName()); | |||
// verify that index is updated | |||
underTest.indexOnAnalysis(project.getMainBranchComponent().uuid()); | |||
// modify | |||
projectDto.setName("NewName"); | |||
assertThatIndexContainsOnly(projectDto.getUuid()); | |||
assertThatEntityHasName(projectDto.getUuid(), "NewName"); | |||
} | |||
db.getDbClient().projectDao().update(dbSession, projectDto); | |||
db.commit(); | |||
// verify that index is updated | |||
underTest.indexOnAnalysis(project.getMainBranchDto().getUuid()); | |||
assertThatIndexContainsOnly(projectDto.getUuid()); | |||
assertThatEntityHasName(projectDto.getUuid(), "NewName"); | |||
} | |||
@Test | |||
public void errors_during_indexing_are_recovered() { | |||
ProjectDto project1 = db.components().insertPrivateProject().getProjectDto(); | |||
es.lockWrites(TYPE_COMPONENT); | |||
IndexingResult result = indexEntity(project1, PROJECT_CREATION); | |||
IndexingResult result = indexProject(project1, CREATION); | |||
assertThat(result.getTotal()).isOne(); | |||
assertThat(result.getFailures()).isOne(); | |||
@@ -244,9 +246,9 @@ public class ComponentIndexerIT { | |||
assertThatIndexContainsOnly(project1); | |||
} | |||
private IndexingResult indexEntity(EntityDto entity, ProjectIndexer.Cause cause) { | |||
private IndexingResult indexProject(ProjectDto project, Indexers.EntityEvent cause) { | |||
DbSession dbSession = db.getSession(); | |||
Collection<EsQueueDto> items = underTest.prepareForRecovery(dbSession, singletonList(entity.getUuid()), cause); | |||
Collection<EsQueueDto> items = underTest.prepareForRecoveryOnEntityEvent(dbSession, singletonList(project.getUuid()), cause); | |||
dbSession.commit(); | |||
return underTest.index(dbSession, items); | |||
} |
@@ -43,11 +43,13 @@ import org.sonar.db.component.ProjectData; | |||
import org.sonar.db.es.EsQueueDto; | |||
import org.sonar.db.issue.IssueDto; | |||
import org.sonar.db.issue.IssueTesting; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.es.IndexType; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.Indexers.EntityEvent; | |||
import org.sonar.server.es.IndexingResult; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.StartupIndexer; | |||
import org.sonar.server.permission.index.AuthorizationScope; | |||
import org.sonar.server.permission.index.IndexPermissions; | |||
@@ -62,6 +64,9 @@ import static java.util.Collections.singletonList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | |||
import static org.sonar.db.component.ComponentTesting.newFileDto; | |||
import static org.sonar.server.es.Indexers.BranchEvent.DELETION; | |||
import static org.sonar.server.es.Indexers.EntityEvent.PROJECT_KEY_UPDATE; | |||
import static org.sonar.server.es.Indexers.EntityEvent.PROJECT_TAGS_UPDATE; | |||
import static org.sonar.server.issue.IssueDocTesting.newDoc; | |||
import static org.sonar.server.issue.index.IssueIndexDefinition.TYPE_ISSUE; | |||
import static org.sonar.server.permission.index.IndexAuthorizationConstants.TYPE_AUTHORIZATION; | |||
@@ -79,17 +84,17 @@ public class IssueIndexerIT { | |||
private final IssueIndexer underTest = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()), null); | |||
@Test | |||
public void test_getIndexTypes() { | |||
public void getIndexTypes_shouldReturnTypeIssue() { | |||
assertThat(underTest.getIndexTypes()).containsExactly(TYPE_ISSUE); | |||
} | |||
@Test | |||
public void test_getAuthorizationScope() { | |||
public void getAuthorizationScope_shouldBeProject() { | |||
AuthorizationScope scope = underTest.getAuthorizationScope(); | |||
assertThat(scope.getIndexType().getIndex()).isEqualTo(IssueIndexDefinition.DESCRIPTOR); | |||
assertThat(scope.getIndexType().getType()).isEqualTo(TYPE_AUTHORIZATION); | |||
Predicate<IndexPermissions> projectPredicate = scope.getProjectPredicate(); | |||
Predicate<IndexPermissions> projectPredicate = scope.getEntityPredicate(); | |||
IndexPermissions project = new IndexPermissions("P1", Qualifiers.PROJECT); | |||
IndexPermissions file = new IndexPermissions("F1", Qualifiers.FILE); | |||
assertThat(projectPredicate.test(project)).isTrue(); | |||
@@ -97,7 +102,7 @@ public class IssueIndexerIT { | |||
} | |||
@Test | |||
public void indexOnStartup_scrolls_db_and_adds_all_issues_to_index() { | |||
public void indexAllIssues_shouldIndexAllIssues() { | |||
IssueDto issue1 = db.issues().insert(); | |||
IssueDto issue2 = db.issues().insert(); | |||
@@ -107,7 +112,7 @@ public class IssueIndexerIT { | |||
} | |||
@Test | |||
public void verify_indexed_fields() { | |||
public void indexAllIssues_shouldIndexAllIssueFields() { | |||
RuleDto rule = db.rules().insert(); | |||
ProjectData projectData = db.components().insertPrivateProject(); | |||
ComponentDto project = projectData.getMainBranchComponent(); | |||
@@ -142,7 +147,7 @@ public class IssueIndexerIT { | |||
} | |||
@Test | |||
public void verify_security_standards_indexation() { | |||
public void indexAllIssues_shouldIndexSecurityStandards() { | |||
RuleDto rule = db.rules().insert(r -> r.setSecurityStandards(new HashSet<>(Arrays.asList("cwe:123", "owaspTop10:a3", "cwe:863", "owaspAsvs-4.0:2.1.1")))); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ComponentDto dir = db.components().insertComponent(ComponentTesting.newDirectory(project, "src/main/java/foo")); | |||
@@ -166,7 +171,7 @@ public class IssueIndexerIT { | |||
Set<IndexType> uninitializedIndexTypes = emptySet(); | |||
assertThatThrownBy(() -> underTest.indexOnStartup(uninitializedIndexTypes)) | |||
.isInstanceOf(IllegalStateException.class) | |||
.hasMessage("SYNCHRONE StartupIndexer must implement indexOnStartup"); | |||
.hasMessage("SYNCHRONOUS StartupIndexer must implement indexOnStartup"); | |||
assertThatIndexHasSize(0); | |||
assertThatEsQueueTableHasSize(0); | |||
es.unlockWrites(TYPE_ISSUE); | |||
@@ -175,13 +180,13 @@ public class IssueIndexerIT { | |||
@Test | |||
public void indexOnAnalysis_indexes_the_issues_of_project() { | |||
RuleDto rule = db.rules().insert(); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ComponentDto file = db.components().insertComponent(newFileDto(project)); | |||
IssueDto issue = db.issues().insert(rule, project, file); | |||
ComponentDto branchComponent = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ComponentDto file = db.components().insertComponent(newFileDto(branchComponent)); | |||
IssueDto issue = db.issues().insert(rule, branchComponent, file); | |||
ComponentDto otherProject = db.components().insertPrivateProject().getMainBranchComponent(); | |||
db.components().insertComponent(newFileDto(otherProject)); | |||
underTest.indexOnAnalysis(project.uuid()); | |||
underTest.indexOnAnalysis(branchComponent.uuid()); | |||
assertThatIndexHasOnly(issue); | |||
} | |||
@@ -189,14 +194,14 @@ public class IssueIndexerIT { | |||
@Test | |||
public void indexOnAnalysis_does_not_delete_orphan_docs() { | |||
RuleDto rule = db.rules().insert(); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ComponentDto file = db.components().insertComponent(newFileDto(project)); | |||
IssueDto issue = db.issues().insert(rule, project, file); | |||
ProjectData projectData = db.components().insertPrivateProject(); | |||
ComponentDto file = db.components().insertComponent(newFileDto(projectData.getMainBranchComponent())); | |||
IssueDto issue = db.issues().insert(rule, projectData.getMainBranchComponent(), file); | |||
// orphan in the project | |||
addIssueToIndex(project.uuid(), "orphan"); | |||
addIssueToIndex(projectData.projectUuid(), projectData.getMainBranchComponent().uuid(), "orphan"); | |||
underTest.indexOnAnalysis(project.uuid()); | |||
underTest.indexOnAnalysis(projectData.getMainBranchComponent().uuid()); | |||
assertThat(es.getDocuments(TYPE_ISSUE)) | |||
.extracting(SearchHit::getId) | |||
@@ -222,43 +227,51 @@ public class IssueIndexerIT { | |||
} | |||
@Test | |||
public void index_is_not_updated_when_creating_project() { | |||
// it's impossible to already have an issue on a project | |||
// that is being created, but it's just to verify that | |||
// indexing is disabled | |||
public void index_is_not_updated_when_updating_project_key() { | |||
// issue is inserted to verify that indexing of project is not triggered | |||
IssueDto issue = db.issues().insert(); | |||
IndexingResult result = indexProject(issue.getProjectUuid(), ProjectIndexer.Cause.PROJECT_CREATION); | |||
IndexingResult result = indexProject(issue.getProjectUuid(), PROJECT_KEY_UPDATE); | |||
assertThat(result.getTotal()).isZero(); | |||
assertThatIndexHasSize(0); | |||
} | |||
@Test | |||
public void index_is_not_updated_when_updating_project_key() { | |||
public void index_is_not_updated_when_updating_tags() { | |||
// issue is inserted to verify that indexing of project is not triggered | |||
IssueDto issue = db.issues().insert(); | |||
IndexingResult result = indexProject(issue.getProjectUuid(), ProjectIndexer.Cause.PROJECT_KEY_UPDATE); | |||
IndexingResult result = indexProject(issue.getProjectUuid(), PROJECT_TAGS_UPDATE); | |||
assertThat(result.getTotal()).isZero(); | |||
assertThatIndexHasSize(0); | |||
} | |||
@Test | |||
public void index_is_not_updated_when_updating_tags() { | |||
// issue is inserted to verify that indexing of project is not triggered | |||
IssueDto issue = db.issues().insert(); | |||
public void index_is_updated_when_deleting_branch() { | |||
ProjectDto project = db.components().insertPublicProject().getProjectDto(); | |||
BranchDto branch1 = db.components().insertProjectBranch(project); | |||
BranchDto branch2 = db.components().insertProjectBranch(project); | |||
IndexingResult result = indexProject(issue.getProjectUuid(), ProjectIndexer.Cause.PROJECT_TAGS_UPDATE); | |||
assertThat(result.getTotal()).isZero(); | |||
assertThatIndexHasSize(0); | |||
addIssueToIndex(project.getUuid(), branch1.getUuid(), "I1"); | |||
addIssueToIndex(project.getUuid(), branch1.getUuid(), "I2"); | |||
addIssueToIndex(project.getUuid(), branch2.getUuid(), "I3"); | |||
assertThatIndexHasSize(3); | |||
IndexingResult result = indexBranch(branch1.getUuid(), DELETION); | |||
assertThat(result.getTotal()).isEqualTo(2); | |||
assertThat(result.getSuccess()).isEqualTo(2); | |||
assertThatIndexHasOnly("I3"); | |||
} | |||
@Test | |||
public void index_is_updated_when_deleting_project() { | |||
addIssueToIndex("P1", "I1"); | |||
BranchDto branch = db.components().insertPrivateProject().getMainBranchDto(); | |||
addIssueToIndex(branch.getProjectUuid(), branch.getUuid(), "I1"); | |||
assertThatIndexHasSize(1); | |||
IndexingResult result = indexProject("P1", ProjectIndexer.Cause.PROJECT_DELETION); | |||
IndexingResult result = indexProject(branch.getProjectUuid(), EntityEvent.DELETION); | |||
assertThat(result.getTotal()).isOne(); | |||
assertThat(result.getSuccess()).isOne(); | |||
@@ -267,24 +280,26 @@ public class IssueIndexerIT { | |||
@Test | |||
public void errors_during_project_deletion_are_recovered() { | |||
addIssueToIndex("P1", "I1"); | |||
assertThatIndexHasSize(1); | |||
addIssueToIndex("P1", "B1", "I1"); | |||
addIssueToIndex("P1", "B2", "I2"); | |||
assertThatIndexHasSize(2); | |||
es.lockWrites(TYPE_ISSUE); | |||
IndexingResult result = indexProject("P1", ProjectIndexer.Cause.PROJECT_DELETION); | |||
assertThat(result.getTotal()).isOne(); | |||
assertThat(result.getFailures()).isOne(); | |||
IndexingResult result = indexProject("P1", EntityEvent.DELETION); | |||
assertThat(result.getTotal()).isEqualTo(2); | |||
assertThat(result.getFailures()).isEqualTo(2); | |||
// index is still read-only, fail to recover | |||
result = recover(); | |||
assertThat(result.getTotal()).isOne(); | |||
assertThat(result.getFailures()).isOne(); | |||
assertThatIndexHasSize(1); | |||
assertThat(result.getTotal()).isEqualTo(2); | |||
assertThat(result.getFailures()).isEqualTo(2); | |||
assertThatIndexHasSize(2); | |||
es.unlockWrites(TYPE_ISSUE); | |||
result = recover(); | |||
assertThat(result.getTotal()).isOne(); | |||
assertThat(result.getTotal()).isEqualTo(2); | |||
assertThat(result.getFailures()).isZero(); | |||
assertThatIndexHasSize(0); | |||
} | |||
@@ -310,8 +325,8 @@ public class IssueIndexerIT { | |||
@Test | |||
public void commitAndIndexIssues_removes_issue_from_index_if_it_does_not_exist_in_db() { | |||
IssueDto issue1 = new IssueDto().setKee("I1").setProjectUuid("P1"); | |||
addIssueToIndex(issue1.getProjectUuid(), issue1.getKey()); | |||
IssueDto issue1 = new IssueDto().setKee("I1").setProjectUuid("B1"); | |||
addIssueToIndex("B1", issue1.getProjectUuid(), issue1.getKey()); | |||
IssueDto issue2 = db.issues().insert(); | |||
underTest.commitAndIndexIssues(db.getSession(), asList(issue1, issue2)); | |||
@@ -400,7 +415,7 @@ public class IssueIndexerIT { | |||
es.lockWrites(TYPE_ISSUE); | |||
IndexingResult result = indexProject(project.uuid(), ProjectIndexer.Cause.PROJECT_DELETION); | |||
IndexingResult result = indexBranch(project.uuid(), DELETION); | |||
assertThat(result.getTotal()).isEqualTo(2L); | |||
assertThat(result.getFailures()).isEqualTo(2L); | |||
@@ -419,18 +434,24 @@ public class IssueIndexerIT { | |||
assertThatEsQueueTableHasSize(0); | |||
} | |||
private IndexingResult indexProject(String projectUuid, ProjectIndexer.Cause cause) { | |||
Collection<EsQueueDto> items = underTest.prepareForRecovery(db.getSession(), singletonList(projectUuid), cause); | |||
private IndexingResult indexBranch(String branchUuid, Indexers.BranchEvent cause) { | |||
Collection<EsQueueDto> items = underTest.prepareForRecoveryOnBranchEvent(db.getSession(), singletonList(branchUuid), cause); | |||
db.commit(); | |||
return underTest.index(db.getSession(), items); | |||
} | |||
private IndexingResult indexProject(String projectUuid, EntityEvent cause) { | |||
Collection<EsQueueDto> items = underTest.prepareForRecoveryOnEntityEvent(db.getSession(), singletonList(projectUuid), cause); | |||
db.commit(); | |||
return underTest.index(db.getSession(), items); | |||
} | |||
@Test | |||
public void deleteByKeys_deletes_docs_by_keys() { | |||
addIssueToIndex("P1", "Issue1"); | |||
addIssueToIndex("P1", "Issue2"); | |||
addIssueToIndex("P1", "Issue3"); | |||
addIssueToIndex("P2", "Issue4"); | |||
public void deleteByKeys_shouldDeleteDocsByKeys() { | |||
addIssueToIndex("P1", "B1", "Issue1"); | |||
addIssueToIndex("P1", "B1", "Issue2"); | |||
addIssueToIndex("P1", "B1", "Issue3"); | |||
addIssueToIndex("P2", "B2", "Issue4"); | |||
assertThatIndexHasOnly("Issue1", "Issue2", "Issue3", "Issue4"); | |||
@@ -440,8 +461,8 @@ public class IssueIndexerIT { | |||
} | |||
@Test | |||
public void deleteByKeys_does_not_recover_from_errors() { | |||
addIssueToIndex("P1", "Issue1"); | |||
public void deleteByKeys_shouldNotRecoverFromErrors() { | |||
addIssueToIndex("P1", "B1","Issue1"); | |||
es.lockWrites(TYPE_ISSUE); | |||
List<String> issues = List.of("Issue1"); | |||
@@ -454,12 +475,12 @@ public class IssueIndexerIT { | |||
} | |||
@Test | |||
public void nothing_to_do_when_delete_issues_on_empty_list() { | |||
addIssueToIndex("P1", "Issue1"); | |||
addIssueToIndex("P1", "Issue2"); | |||
addIssueToIndex("P1", "Issue3"); | |||
public void deleteByKeys_whenEmptyList_shouldDoNothing() { | |||
addIssueToIndex("P1", "B1", "Issue1"); | |||
addIssueToIndex("P1", "B1", "Issue2"); | |||
addIssueToIndex("P1", "B1", "Issue3"); | |||
underTest.deleteByKeys("P1", emptyList()); | |||
underTest.deleteByKeys("B1", emptyList()); | |||
assertThatIndexHasOnly("Issue1", "Issue2", "Issue3"); | |||
} | |||
@@ -533,14 +554,14 @@ public class IssueIndexerIT { | |||
@Test | |||
public void issue_on_project_has_main_code_scope() { | |||
RuleDto rule = db.rules().insert(); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
IssueDto issue = db.issues().insert(rule, project, project); | |||
ComponentDto mainBranchComponent = db.components().insertPrivateProject().getMainBranchComponent(); | |||
IssueDto issue = db.issues().insert(rule, mainBranchComponent, mainBranchComponent); | |||
underTest.indexAllIssues(); | |||
IssueDoc doc = es.getDocuments(TYPE_ISSUE, IssueDoc.class).get(0); | |||
assertThat(doc.getId()).isEqualTo(issue.getKey()); | |||
assertThat(doc.componentUuid()).isEqualTo(project.uuid()); | |||
assertThat(doc.componentUuid()).isEqualTo(mainBranchComponent.uuid()); | |||
assertThat(doc.scope()).isEqualTo(IssueScope.MAIN); | |||
} | |||
@@ -552,17 +573,17 @@ public class IssueIndexerIT { | |||
@Test | |||
public void indexOnAnalysis_whenChangedComponents_shouldReindexOnlyChangedComponents() { | |||
RuleDto rule = db.rules().insert(); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ComponentDto changedComponent1 = db.components().insertComponent(newFileDto(project)); | |||
ComponentDto unchangedComponent = db.components().insertComponent(newFileDto(project)); | |||
ComponentDto ChangedComponent2 = db.components().insertComponent(newFileDto(project)); | |||
IssueDto changedIssue1 = db.issues().insert(rule, project, changedComponent1); | |||
IssueDto changedIssue2 = db.issues().insert(rule, project, changedComponent1); | |||
IssueDto changedIssue3 = db.issues().insert(rule, project, ChangedComponent2); | |||
db.issues().insert(rule, project, unchangedComponent); | |||
db.issues().insert(rule, project, unchangedComponent); | |||
underTest.indexOnAnalysis(project.uuid(), Set.of(unchangedComponent.uuid())); | |||
ComponentDto mainBranchComponent = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ComponentDto changedComponent1 = db.components().insertComponent(newFileDto(mainBranchComponent)); | |||
ComponentDto unchangedComponent = db.components().insertComponent(newFileDto(mainBranchComponent)); | |||
ComponentDto ChangedComponent2 = db.components().insertComponent(newFileDto(mainBranchComponent)); | |||
IssueDto changedIssue1 = db.issues().insert(rule, mainBranchComponent, changedComponent1); | |||
IssueDto changedIssue2 = db.issues().insert(rule, mainBranchComponent, changedComponent1); | |||
IssueDto changedIssue3 = db.issues().insert(rule, mainBranchComponent, ChangedComponent2); | |||
db.issues().insert(rule, mainBranchComponent, unchangedComponent); | |||
db.issues().insert(rule, mainBranchComponent, unchangedComponent); | |||
underTest.indexOnAnalysis(mainBranchComponent.uuid(), Set.of(unchangedComponent.uuid())); | |||
assertThatIndexHasOnly(changedIssue1, changedIssue2, changedIssue3); | |||
} | |||
@@ -570,12 +591,12 @@ public class IssueIndexerIT { | |||
@Test | |||
public void indexOnAnalysis_whenEmptyUnchangedComponents_shouldReindexEverything() { | |||
RuleDto rule = db.rules().insert(); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ComponentDto changedComponent = db.components().insertComponent(newFileDto(project)); | |||
IssueDto changedIssue1 = db.issues().insert(rule, project, changedComponent); | |||
IssueDto changedIssue2 = db.issues().insert(rule, project, changedComponent); | |||
ComponentDto mainBranchComponent = db.components().insertPrivateProject().getMainBranchComponent(); | |||
ComponentDto changedComponent = db.components().insertComponent(newFileDto(mainBranchComponent)); | |||
IssueDto changedIssue1 = db.issues().insert(rule, mainBranchComponent, changedComponent); | |||
IssueDto changedIssue2 = db.issues().insert(rule, mainBranchComponent, changedComponent); | |||
underTest.indexOnAnalysis(project.uuid(), Set.of()); | |||
underTest.indexOnAnalysis(mainBranchComponent.uuid(), Set.of()); | |||
assertThatIndexHasOnly(changedIssue1, changedIssue2); | |||
} | |||
@@ -583,17 +604,17 @@ public class IssueIndexerIT { | |||
@Test | |||
public void indexOnAnalysis_whenChangedComponentWithoutIssue_shouldReindexNothing() { | |||
db.rules().insert(); | |||
ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); | |||
db.components().insertComponent(newFileDto(project)); | |||
ComponentDto mainBranchComponent = db.components().insertPrivateProject().getMainBranchComponent(); | |||
db.components().insertComponent(newFileDto(mainBranchComponent)); | |||
underTest.indexOnAnalysis(project.uuid(), Set.of()); | |||
underTest.indexOnAnalysis(mainBranchComponent.uuid(), Set.of()); | |||
assertThat(es.getDocuments(TYPE_ISSUE)).isEmpty(); | |||
} | |||
private void addIssueToIndex(String projectUuid, String issueKey) { | |||
private void addIssueToIndex(String projectUuid, String branchUuid, String issueKey) { | |||
es.putDocuments(TYPE_ISSUE, | |||
newDoc().setKey(issueKey).setProjectUuid(projectUuid)); | |||
newDoc().setKey(issueKey).setProjectUuid(projectUuid).setBranchUuid(branchUuid)); | |||
} | |||
private void assertThatIndexHasSize(long expectedSize) { |
@@ -37,8 +37,8 @@ import org.sonar.db.component.SnapshotDto; | |||
import org.sonar.db.es.EsQueueDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.IndexingResult; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.permission.index.AuthorizationScope; | |||
import org.sonar.server.permission.index.IndexPermissions; | |||
@@ -52,10 +52,10 @@ import static org.elasticsearch.index.query.QueryBuilders.termsQuery; | |||
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; | |||
import static org.sonar.server.es.EsClient.prepareSearch; | |||
import static org.sonar.server.es.IndexType.FIELD_INDEX_TYPE; | |||
import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_CREATION; | |||
import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_DELETION; | |||
import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_KEY_UPDATE; | |||
import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_TAGS_UPDATE; | |||
import static org.sonar.server.es.Indexers.EntityEvent.CREATION; | |||
import static org.sonar.server.es.Indexers.EntityEvent.DELETION; | |||
import static org.sonar.server.es.Indexers.EntityEvent.PROJECT_KEY_UPDATE; | |||
import static org.sonar.server.es.Indexers.EntityEvent.PROJECT_TAGS_UPDATE; | |||
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_QUALIFIER; | |||
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_TAGS; | |||
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_UUID; | |||
@@ -74,12 +74,12 @@ public class ProjectMeasuresIndexerIT { | |||
private final ProjectMeasuresIndexer underTest = new ProjectMeasuresIndexer(db.getDbClient(), es.client()); | |||
@Test | |||
public void test_getAuthorizationScope() { | |||
public void getAuthorizationScope_shouldReturnTrueForProjectAndApp() { | |||
AuthorizationScope scope = underTest.getAuthorizationScope(); | |||
assertThat(scope.getIndexType().getIndex()).isEqualTo(ProjectMeasuresIndexDefinition.DESCRIPTOR); | |||
assertThat(scope.getIndexType().getType()).isEqualTo(TYPE_AUTHORIZATION); | |||
Predicate<IndexPermissions> projectPredicate = scope.getProjectPredicate(); | |||
Predicate<IndexPermissions> projectPredicate = scope.getEntityPredicate(); | |||
IndexPermissions project = new IndexPermissions("P1", Qualifiers.PROJECT); | |||
IndexPermissions app = new IndexPermissions("P1", Qualifiers.APP); | |||
IndexPermissions file = new IndexPermissions("F1", Qualifiers.FILE); | |||
@@ -89,14 +89,14 @@ public class ProjectMeasuresIndexerIT { | |||
} | |||
@Test | |||
public void index_nothing() { | |||
public void indexOnStartup_whenNoEntities_shouldNotIndexAnything() { | |||
underTest.indexOnStartup(emptySet()); | |||
assertThat(es.countDocuments(TYPE_PROJECT_MEASURES)).isZero(); | |||
} | |||
@Test | |||
public void indexOnStartup_indexes_all_projects() { | |||
public void indexOnStartup_shouldIndexAllProjects() { | |||
SnapshotDto project1 = db.components().insertProjectAndSnapshot(newPrivateProjectDto()); | |||
SnapshotDto project2 = db.components().insertProjectAndSnapshot(newPrivateProjectDto()); | |||
SnapshotDto project3 = db.components().insertProjectAndSnapshot(newPrivateProjectDto()); | |||
@@ -205,7 +205,7 @@ public class ProjectMeasuresIndexerIT { | |||
public void update_index_when_project_is_created() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
IndexingResult result = indexProject(project, PROJECT_CREATION); | |||
IndexingResult result = indexProject(project, CREATION); | |||
assertThatIndexContainsOnly(project); | |||
assertThat(result.getTotal()).isOne(); | |||
@@ -215,12 +215,11 @@ public class ProjectMeasuresIndexerIT { | |||
@Test | |||
public void update_index_when_project_tags_are_updated() { | |||
ProjectDto project = db.components().insertPrivateProject(defaults(), p -> p.setTagsString("foo")).getProjectDto(); | |||
indexProject(project, PROJECT_CREATION); | |||
indexProject(project, CREATION); | |||
assertThatProjectHasTag(project, "foo"); | |||
project.setTagsString("bar"); | |||
db.getDbClient().projectDao().updateTags(db.getSession(), project); | |||
// TODO change indexing? | |||
IndexingResult result = indexProject(project, PROJECT_TAGS_UPDATE); | |||
assertThatProjectHasTag(project, "bar"); | |||
@@ -231,11 +230,11 @@ public class ProjectMeasuresIndexerIT { | |||
@Test | |||
public void delete_doc_from_index_when_project_is_deleted() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
indexProject(project, PROJECT_CREATION); | |||
indexProject(project, CREATION); | |||
assertThatIndexContainsOnly(project); | |||
db.getDbClient().purgeDao().deleteProject(db.getSession(), project.getUuid(), Qualifiers.PROJECT, project.getName(), project.getKey()); | |||
IndexingResult result = indexProject(project, PROJECT_DELETION); | |||
IndexingResult result = indexProject(project, DELETION); | |||
assertThat(es.countDocuments(TYPE_PROJECT_MEASURES)).isZero(); | |||
assertThat(result.getTotal()).isOne(); | |||
@@ -258,7 +257,7 @@ public class ProjectMeasuresIndexerIT { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
es.lockWrites(TYPE_PROJECT_MEASURES); | |||
IndexingResult result = indexProject(project, PROJECT_CREATION); | |||
IndexingResult result = indexProject(project, CREATION); | |||
assertThat(result.getTotal()).isOne(); | |||
assertThat(result.getFailures()).isOne(); | |||
@@ -288,9 +287,9 @@ public class ProjectMeasuresIndexerIT { | |||
assertThat(es.countDocuments(TYPE_PROJECT_MEASURES)).isZero(); | |||
} | |||
private IndexingResult indexProject(ProjectDto project, ProjectIndexer.Cause cause) { | |||
private IndexingResult indexProject(ProjectDto project, Indexers.EntityEvent cause) { | |||
DbSession dbSession = db.getSession(); | |||
Collection<EsQueueDto> items = underTest.prepareForRecovery(dbSession, singletonList(project.getUuid()), cause); | |||
Collection<EsQueueDto> items = underTest.prepareForRecoveryOnEntityEvent(dbSession, singletonList(project.getUuid()), cause); | |||
dbSession.commit(); | |||
return underTest.index(dbSession, items); | |||
} |
@@ -35,14 +35,16 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.es.EsQueueDto; | |||
import org.sonar.server.es.AnalysisIndexer; | |||
import org.sonar.server.es.BaseDoc; | |||
import org.sonar.server.es.BulkIndexer; | |||
import org.sonar.server.es.BulkIndexer.Size; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.EventIndexer; | |||
import org.sonar.server.es.IndexType; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.IndexingResult; | |||
import org.sonar.server.es.OneToManyResilientIndexingListener; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.permission.index.AuthorizationDoc; | |||
import org.sonar.server.permission.index.AuthorizationScope; | |||
import org.sonar.server.permission.index.NeedAuthorizationIndexer; | |||
@@ -50,15 +52,18 @@ import org.sonar.server.permission.index.NeedAuthorizationIndexer; | |||
import static java.util.Collections.emptyList; | |||
import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_COMPONENT; | |||
public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexer { | |||
/** | |||
* Indexes the definition of all entities: projects, applications, portfolios and sub-portfolios. | |||
*/ | |||
public class EntityDefinitionIndexer implements EventIndexer, AnalysisIndexer, NeedAuthorizationIndexer { | |||
private static final AuthorizationScope AUTHORIZATION_SCOPE = new AuthorizationScope(TYPE_COMPONENT, project -> true); | |||
private static final AuthorizationScope AUTHORIZATION_SCOPE = new AuthorizationScope(TYPE_COMPONENT, entity -> true); | |||
private static final Set<IndexType> INDEX_TYPES = Set.of(TYPE_COMPONENT); | |||
private final DbClient dbClient; | |||
private final EsClient esClient; | |||
public ComponentIndexer(DbClient dbClient, EsClient esClient) { | |||
public EntityDefinitionIndexer(DbClient dbClient, EsClient esClient) { | |||
this.dbClient = dbClient; | |||
this.esClient = esClient; | |||
} | |||
@@ -91,7 +96,7 @@ public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexe | |||
return; | |||
} | |||
EntityDto entity = dbClient.entityDao().selectByComponentUuid(dbSession, branchUuid) | |||
.orElseThrow(() -> new IllegalStateException("Can't find entity " + branchUuid)); | |||
.orElseThrow(() -> new IllegalStateException("Can't find entity for branch " + branchUuid)); | |||
doIndexByEntityUuid(entity); | |||
} | |||
} | |||
@@ -102,20 +107,23 @@ public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexe | |||
} | |||
@Override | |||
public Collection<EsQueueDto> prepareForRecovery(DbSession dbSession, Collection<String> projectUuids, Cause cause) { | |||
switch (cause) { | |||
case MEASURE_CHANGE, PROJECT_TAGS_UPDATE, PERMISSION_CHANGE: | |||
// measures, tags and permissions are not part of type components/component | |||
return emptyList(); | |||
case PROJECT_CREATION, PROJECT_DELETION, PROJECT_KEY_UPDATE: | |||
List<EsQueueDto> items = projectUuids.stream() | |||
.map(projectUuid -> EsQueueDto.create(TYPE_COMPONENT.format(), projectUuid, null, projectUuid)) | |||
.collect(MoreCollectors.toArrayList(projectUuids.size())); | |||
return dbClient.esQueueDao().insert(dbSession, items); | |||
default: | |||
// defensive case | |||
throw new IllegalStateException("Unsupported cause: " + cause); | |||
} | |||
public Collection<EsQueueDto> prepareForRecoveryOnEntityEvent(DbSession dbSession, Collection<String> entityUuids, Indexers.EntityEvent cause) { | |||
return switch (cause) { | |||
case PROJECT_TAGS_UPDATE, PERMISSION_CHANGE -> | |||
// measures, tags and permissions does not affect the definition of entities | |||
emptyList(); | |||
case CREATION, DELETION, PROJECT_KEY_UPDATE -> { | |||
List<EsQueueDto> items = entityUuids.stream() | |||
.map(entityUuid -> EsQueueDto.create(TYPE_COMPONENT.format(), entityUuid, null, entityUuid)) | |||
.collect(MoreCollectors.toArrayList(entityUuids.size())); | |||
yield dbClient.esQueueDao().insert(dbSession, items); | |||
} | |||
}; | |||
} | |||
@Override | |||
public Collection<EsQueueDto> prepareForRecoveryOnBranchEvent(DbSession dbSession, Collection<String> branchUuids, Indexers.BranchEvent cause) { | |||
return emptyList(); | |||
} | |||
@Override | |||
@@ -130,13 +138,10 @@ public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexe | |||
Set<String> entityUuids = items.stream().map(EsQueueDto::getDocId).collect(MoreCollectors.toHashSet(items.size())); | |||
Set<String> remaining = new HashSet<>(entityUuids); | |||
for (String entityUuid : entityUuids) { | |||
dbClient.entityDao().scrollForIndexing(dbSession, entityUuid, context -> { | |||
EntityDto dto = context.getResultObject(); | |||
remaining.remove(dto.getUuid()); | |||
bulkIndexer.add(toDocument(dto).toIndexRequest()); | |||
}); | |||
} | |||
dbClient.entityDao().selectByUuids(dbSession, entityUuids).forEach(dto -> { | |||
remaining.remove(dto.getUuid()); | |||
bulkIndexer.add(toDocument(dto).toIndexRequest()); | |||
}); | |||
// the remaining uuids reference projects that don't exist in db. They must | |||
// be deleted from index. | |||
@@ -169,7 +174,7 @@ public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexe | |||
BulkIndexer bulk = new BulkIndexer(esClient, TYPE_COMPONENT, bulkSize); | |||
bulk.start(); | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
dbClient.entityDao().scrollForIndexing(dbSession, null, context -> { | |||
dbClient.entityDao().scrollForIndexing(dbSession, context -> { | |||
EntityDto dto = context.getResultObject(); | |||
bulk.add(toDocument(dto).toIndexRequest()); | |||
}); | |||
@@ -197,7 +202,7 @@ public class ComponentIndexer implements ProjectIndexer, NeedAuthorizationIndexe | |||
BulkIndexer bulk = new BulkIndexer(esClient, TYPE_COMPONENT, Size.REGULAR); | |||
bulk.start(); | |||
Arrays.stream(docs) | |||
.map(ComponentIndexer::toDocument) | |||
.map(EntityDefinitionIndexer::toDocument) | |||
.map(BaseDoc::toIndexRequest) | |||
.forEach(bulk::add); | |||
bulk.stop(); |
@@ -0,0 +1,43 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.es; | |||
import java.util.Set; | |||
/** | |||
* Indexers that should be called when a project branch is analyzed | |||
*/ | |||
public interface AnalysisIndexer { | |||
/** | |||
* This method is called when an analysis must be indexed. | |||
* | |||
* @param branchUuid UUID of a project or application branch | |||
*/ | |||
void indexOnAnalysis(String branchUuid); | |||
/** | |||
* This method is called when an analysis must be indexed. | |||
* | |||
* @param branchUuid UUID of a project or application branch | |||
* @param unchangedComponentUuids UUIDs of components that didn't change in this analysis. | |||
* Indexers can be optimized by not re-indexing data related to these components. | |||
*/ | |||
void indexOnAnalysis(String branchUuid, Set<String> unchangedComponentUuids); | |||
} |
@@ -24,24 +24,11 @@ import java.util.Set; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.es.EsQueueDto; | |||
/** | |||
* A {@link ProjectIndexer} populates an Elasticsearch index | |||
* containing project-related documents, for instance issues | |||
* or tests. This interface allows to quickly integrate new | |||
* indices in the lifecycle of projects. | |||
* | |||
* If the related index handles verification of authorization, | |||
* then the implementation of {@link ProjectIndexer} must | |||
* also implement {@link org.sonar.server.permission.index.NeedAuthorizationIndexer} | |||
*/ | |||
public interface ProjectIndexer extends ResilientIndexer { | |||
public interface BranchIndexer extends ResilientIndexer { | |||
enum Cause { | |||
PROJECT_CREATION, | |||
PROJECT_DELETION, | |||
PROJECT_KEY_UPDATE, | |||
PROJECT_TAGS_UPDATE, | |||
PERMISSION_CHANGE, | |||
CREATION, | |||
DELETION, | |||
MEASURE_CHANGE | |||
} | |||
@@ -50,9 +37,9 @@ public interface ProjectIndexer extends ResilientIndexer { | |||
* | |||
* @param branchUuid UUID of a project or application branch, or the UUID of a portfolio. | |||
*/ | |||
void indexOnAnalysis(String branchUuid); | |||
void indexBranchOnAnalysis(String branchUuid); | |||
void indexOnAnalysis(String branchUuid, Set<String> unchangedComponentUuids); | |||
void indexBranchOnAnalysis(String branchUuid, Set<String> unchangedComponentUuids); | |||
Collection<EsQueueDto> prepareForRecovery(DbSession dbSession, Collection<String> projectUuids, ProjectIndexer.Cause cause); | |||
Collection<EsQueueDto> prepareBranchIndexForRecovery(DbSession dbSession, Collection<String> branchUuids, BranchIndexer.Cause cause); | |||
} |
@@ -19,27 +19,22 @@ | |||
*/ | |||
package org.sonar.server.es; | |||
import com.google.common.collect.ArrayListMultimap; | |||
import com.google.common.collect.ListMultimap; | |||
import java.util.Collection; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.es.EsQueueDto; | |||
public class TestProjectIndexers implements ProjectIndexers { | |||
private final ListMultimap<String, ProjectIndexer.Cause> calls = ArrayListMultimap.create(); | |||
@Override | |||
public void commitAndIndexByProjectUuids(DbSession dbSession, Collection<String> projectUuids, ProjectIndexer.Cause cause) { | |||
dbSession.commit(); | |||
projectUuids.forEach(projectUuid -> calls.put(projectUuid, cause)); | |||
} | |||
/** | |||
* A {@link EventIndexer} populates an Elasticsearch index | |||
* based on events related to entities and branches. This interface allows to quickly integrate new | |||
* indices in the lifecycle of entities and branches. | |||
* | |||
* If the related index handles verification of authorization, | |||
* then the implementation of {@link EventIndexer} must | |||
* also implement {@link org.sonar.server.permission.index.NeedAuthorizationIndexer} | |||
*/ | |||
public interface EventIndexer extends ResilientIndexer { | |||
Collection<EsQueueDto> prepareForRecoveryOnEntityEvent(DbSession dbSession, Collection<String> entityUuids, Indexers.EntityEvent cause); | |||
public boolean hasBeenCalled(String projectUuid, ProjectIndexer.Cause expectedCause) { | |||
return calls.get(projectUuid).contains(expectedCause); | |||
} | |||
Collection<EsQueueDto> prepareForRecoveryOnBranchEvent(DbSession dbSession, Collection<String> branchUuids, Indexers.BranchEvent cause); | |||
public boolean hasBeenCalled(String projectUuid) { | |||
return calls.containsKey(projectUuid); | |||
} | |||
} |
@@ -0,0 +1,81 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.es; | |||
import java.util.Collection; | |||
import java.util.stream.Collectors; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.entity.EntityDto; | |||
public interface Indexers { | |||
enum EntityEvent { | |||
CREATION, | |||
DELETION, | |||
PROJECT_KEY_UPDATE, | |||
PROJECT_TAGS_UPDATE, | |||
PERMISSION_CHANGE | |||
} | |||
enum BranchEvent { | |||
// Note that when a project/app is deleted, no events are sent for each branch removed as part of that process | |||
DELETION, | |||
MEASURE_CHANGE | |||
} | |||
/** | |||
* Re-index data based on the event. It commits the DB session once any indexation request was written in the same session, | |||
* ensuring consistency between the DB and the indexes. Therefore, DB data changes that cause the indexation event should | |||
* be done using the same DB session and the session should be uncommitted. | |||
*/ | |||
void commitAndIndexOnEntityEvent(DbSession dbSession, Collection<String> entityUuids, EntityEvent cause); | |||
/** | |||
* Re-index data based on the event. It commits the DB session once any indexation request was written in the same session, | |||
* ensuring consistency between the DB and the indexes. Therefore, DB data changes that cause the indexation event should | |||
* be done using the same DB session and the session should be uncommitted. | |||
*/ | |||
void commitAndIndexOnBranchEvent(DbSession dbSession, Collection<String> branchUuids, BranchEvent cause); | |||
/** | |||
* Re-index data based on the event. It commits the DB session once any indexation request was written in the same session, | |||
* ensuring consistency between the DB and the indexes. Therefore, DB data changes that cause the indexation event should | |||
* be done using the same DB session and the session should be uncommitted. | |||
*/ | |||
default void commitAndIndexEntities(DbSession dbSession, Collection<? extends EntityDto> entities, EntityEvent cause) { | |||
Collection<String> entityUuids = entities.stream() | |||
.map(EntityDto::getUuid) | |||
.collect(MoreCollectors.toSet(entities.size())); | |||
commitAndIndexOnEntityEvent(dbSession, entityUuids, cause); | |||
} | |||
/** | |||
* Re-index data based on the event. It commits the DB session once any indexation request was written in the same session, | |||
* ensuring consistency between the DB and the indexes. Therefore, DB data changes that cause the indexation event should | |||
* be done using the same DB session and the session should be uncommitted. | |||
*/ | |||
default void commitAndIndexBranches(DbSession dbSession, Collection<BranchDto> branches, BranchEvent cause) { | |||
Collection<String> branchUuids = branches.stream() | |||
.map(BranchDto::getUuid) | |||
.collect(Collectors.toSet()); | |||
commitAndIndexOnBranchEvent(dbSession, branchUuids, cause); | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.es; | |||
import java.util.Collection; | |||
import java.util.IdentityHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.function.Function; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.es.EsQueueDto; | |||
import static java.util.Arrays.asList; | |||
/** | |||
* Delegates events to indexers, that may want to reindex something based on the event. | |||
*/ | |||
public class IndexersImpl implements Indexers { | |||
private final List<EventIndexer> indexers; | |||
public IndexersImpl(EventIndexer... indexers) { | |||
this.indexers = asList(indexers); | |||
} | |||
/** | |||
* Asks all indexers to queue an indexation request in the DB to index the specified entities, if needed (according to | |||
* "cause" parameter), then call all indexers to index the requests. | |||
* The idea is that the indexation requests are committed into the DB at the same time as the data that caused those requests | |||
* to be created, for consistency. | |||
* If the indexation fails, the indexation requests will still be in the DB and can be processed again later. | |||
*/ | |||
@Override | |||
public void commitAndIndexOnEntityEvent(DbSession dbSession, Collection<String> entityUuids, EntityEvent cause) { | |||
indexOnEvent(dbSession, indexer -> indexer.prepareForRecoveryOnEntityEvent(dbSession, entityUuids, cause)); | |||
} | |||
/** | |||
* Asks all indexers to queue an indexation request in the DB to index the specified branches, if needed (according to | |||
* "cause" parameter), then call all indexers to index the requests. | |||
* The idea is that the indexation requests are committed into the DB at the same time as the data that caused those requests | |||
* to be created, for consistency. | |||
* If the indexation fails, the indexation requests will still be in the DB and can be processed again later. | |||
*/ | |||
@Override | |||
public void commitAndIndexOnBranchEvent(DbSession dbSession, Collection<String> branchUuids, BranchEvent cause) { | |||
indexOnEvent(dbSession, indexer -> indexer.prepareForRecoveryOnBranchEvent(dbSession, branchUuids, cause)); | |||
} | |||
private void indexOnEvent(DbSession dbSession, Function<EventIndexer, Collection<EsQueueDto>> esQueueSupplier) { | |||
Map<EventIndexer, Collection<EsQueueDto>> itemsByIndexer = new IdentityHashMap<>(); | |||
indexers.forEach(i -> itemsByIndexer.put(i, esQueueSupplier.apply(i))); | |||
dbSession.commit(); | |||
// ensure that indexer#index() is called only with the item type that it supports | |||
itemsByIndexer.forEach((indexer, items) -> indexer.index(dbSession, items)); | |||
} | |||
} |
@@ -1,64 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.es; | |||
import java.util.Collection; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.project.ProjectDto; | |||
public interface ProjectIndexers { | |||
/** | |||
* Commits the DB transaction and indexes the specified projects, if needed (according to | |||
* "cause" parameter). | |||
* IMPORTANT - UUIDs must relate to applications and projects only. Modules, directories and files are forbidden | |||
* and will lead to lack of indexing. | |||
*/ | |||
void commitAndIndexByProjectUuids(DbSession dbSession, Collection<String> projectUuids, ProjectIndexer.Cause cause); | |||
default void commitAndIndexEntities(DbSession dbSession, Collection<? extends EntityDto> entities, ProjectIndexer.Cause cause) { | |||
Collection<String> entityUuids = entities.stream() | |||
.map(EntityDto::getUuid) | |||
.collect(MoreCollectors.toSet(entities.size())); | |||
commitAndIndexByProjectUuids(dbSession, entityUuids, cause); | |||
} | |||
default void commitAndIndexProjects(DbSession dbSession, Collection<ProjectDto> projects, ProjectIndexer.Cause cause) { | |||
commitAndIndexEntities(dbSession, projects, cause); | |||
} | |||
default void commitAndIndexComponents(DbSession dbSession, Collection<ComponentDto> projects, ProjectIndexer.Cause cause) { | |||
Collection<String> projectUuids = projects.stream() | |||
.map(ComponentDto::branchUuid) | |||
.collect(MoreCollectors.toSet(projects.size())); | |||
commitAndIndexByProjectUuids(dbSession, projectUuids, cause); | |||
} | |||
default void commitAndIndexBranches(DbSession dbSession, Collection<BranchDto> branches, ProjectIndexer.Cause cause) { | |||
Collection<String> branchUuids = branches.stream() | |||
.map(BranchDto::getUuid) | |||
.toList(); | |||
commitAndIndexByProjectUuids(dbSession, branchUuids, cause); | |||
} | |||
} |
@@ -1,48 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.es; | |||
import java.util.Collection; | |||
import java.util.IdentityHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.es.EsQueueDto; | |||
import static java.util.Arrays.asList; | |||
public class ProjectIndexersImpl implements ProjectIndexers { | |||
private final List<ProjectIndexer> indexers; | |||
public ProjectIndexersImpl(ProjectIndexer... indexers) { | |||
this.indexers = asList(indexers); | |||
} | |||
@Override | |||
public void commitAndIndexByProjectUuids(DbSession dbSession, Collection<String> projectUuids, ProjectIndexer.Cause cause) { | |||
Map<ProjectIndexer, Collection<EsQueueDto>> itemsByIndexer = new IdentityHashMap<>(); | |||
indexers.forEach(i -> itemsByIndexer.put(i, i.prepareForRecovery(dbSession, projectUuids, cause))); | |||
dbSession.commit(); | |||
// ensure that indexer#index() is called only with the item type that it supports | |||
itemsByIndexer.forEach((indexer, items) -> indexer.index(dbSession, items)); | |||
} | |||
} |
@@ -24,13 +24,13 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.es.EsQueueDto; | |||
/** | |||
* Indexers that are resilient | |||
* Indexers that are resilient. These indexers handle indexation items that are queued in the DB. | |||
*/ | |||
public interface ResilientIndexer extends StartupIndexer { | |||
/** | |||
* Index the items and delete them from es_queue DB table when the indexation | |||
* is done, keeping them if there is a failure on the item of the collection | |||
* is done. If there is a failure, the items are kept in DB to be re-processed later. | |||
* | |||
* @param dbSession the db session | |||
* @param items the items to be indexed |
@@ -34,7 +34,7 @@ public interface StartupIndexer { | |||
} | |||
default void triggerAsyncIndexOnStartup(Set<IndexType> uninitializedIndexTypes) { | |||
throw new IllegalStateException("ASYNCHRONE StartupIndexer must implement initAsyncIndexOnStartup"); | |||
throw new IllegalStateException("ASYNCHRONOUS StartupIndexer must implement initAsyncIndexOnStartup"); | |||
} | |||
/** | |||
@@ -42,7 +42,7 @@ public interface StartupIndexer { | |||
* if there is at least one uninitialized type. | |||
*/ | |||
default void indexOnStartup(Set<IndexType> uninitializedIndexTypes) { | |||
throw new IllegalStateException("SYNCHRONE StartupIndexer must implement indexOnStartup"); | |||
throw new IllegalStateException("SYNCHRONOUS StartupIndexer must implement indexOnStartup"); | |||
} | |||
Set<IndexType> getIndexTypes(); |
@@ -25,27 +25,31 @@ import com.google.common.collect.ListMultimap; | |||
import java.util.Collection; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import org.elasticsearch.action.index.IndexRequest; | |||
import org.elasticsearch.action.search.SearchRequest; | |||
import org.elasticsearch.search.builder.SearchSourceBuilder; | |||
import org.sonar.api.resources.Qualifiers; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.api.resources.Qualifiers; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.es.EsQueueDto; | |||
import org.sonar.db.issue.IssueDto; | |||
import org.sonar.server.es.AnalysisIndexer; | |||
import org.sonar.server.es.BulkIndexer; | |||
import org.sonar.server.es.BulkIndexer.Size; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.EventIndexer; | |||
import org.sonar.server.es.IndexType; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.IndexingListener; | |||
import org.sonar.server.es.IndexingResult; | |||
import org.sonar.server.es.OneToManyResilientIndexingListener; | |||
import org.sonar.server.es.OneToOneResilientIndexingListener; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.permission.index.AuthorizationDoc; | |||
import org.sonar.server.permission.index.AuthorizationScope; | |||
import org.sonar.server.permission.index.NeedAuthorizationIndexer; | |||
@@ -53,21 +57,31 @@ import org.sonar.server.permission.index.NeedAuthorizationIndexer; | |||
import static java.util.Collections.emptyList; | |||
import static org.elasticsearch.index.query.QueryBuilders.boolQuery; | |||
import static org.elasticsearch.index.query.QueryBuilders.termQuery; | |||
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_BRANCH_UUID; | |||
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID; | |||
import static org.sonar.server.issue.index.IssueIndexDefinition.TYPE_ISSUE; | |||
public class IssueIndexer implements ProjectIndexer, NeedAuthorizationIndexer { | |||
/** | |||
* Indexes issues. All issues belong directly to a project branch, so they only change when a project branch changes. | |||
*/ | |||
public class IssueIndexer implements EventIndexer, AnalysisIndexer, NeedAuthorizationIndexer { | |||
/** | |||
* Indicates that es_queue.doc_id references an issue. Only this issue must be indexed. | |||
*/ | |||
private static final String ID_TYPE_ISSUE_KEY = "issueKey"; | |||
/** | |||
* Indicates that es_queue.doc_id references a project. All the issues of the project must be indexed. | |||
* Indicates that es_queue.doc_id references a branch. All the issues of the branch must be indexed. | |||
* Note that the constant is misleading, but we can't update it since there might some items in the DB during the upgrade. | |||
*/ | |||
private static final String ID_TYPE_BRANCH_UUID = "projectUuid"; | |||
/** | |||
* Indicates that es_queue.doc_id references a project and that all issues in it should be delete. | |||
*/ | |||
private static final String ID_TYPE_PROJECT_UUID = "projectUuid"; | |||
private static final String ID_TYPE_DELETE_PROJECT_UUID = "deleteProjectUuid"; | |||
private static final Logger LOGGER = LoggerFactory.getLogger(IssueIndexer.class); | |||
private static final AuthorizationScope AUTHORIZATION_SCOPE = new AuthorizationScope(TYPE_ISSUE, project -> Qualifiers.PROJECT.equals(project.getQualifier())); | |||
private static final AuthorizationScope AUTHORIZATION_SCOPE = new AuthorizationScope(TYPE_ISSUE, entity -> Qualifiers.PROJECT.equals(entity.getQualifier())); | |||
private static final Set<IndexType> INDEX_TYPES = Set.of(TYPE_ISSUE); | |||
private final EsClient esClient; | |||
@@ -127,23 +141,44 @@ public class IssueIndexer implements ProjectIndexer, NeedAuthorizationIndexer { | |||
} | |||
@Override | |||
public Collection<EsQueueDto> prepareForRecovery(DbSession dbSession, Collection<String> projectUuids, ProjectIndexer.Cause cause) { | |||
switch (cause) { | |||
case PROJECT_CREATION, MEASURE_CHANGE, PROJECT_KEY_UPDATE, PROJECT_TAGS_UPDATE, PERMISSION_CHANGE: | |||
public Collection<EsQueueDto> prepareForRecoveryOnEntityEvent(DbSession dbSession, Collection<String> entityUuids, Indexers.EntityEvent cause) { | |||
return switch (cause) { | |||
case CREATION, PROJECT_KEY_UPDATE, PROJECT_TAGS_UPDATE, PERMISSION_CHANGE -> | |||
// Nothing to do, issues do not exist at project creation | |||
// Measures, permissions, project key and tags are not used in type issues/issue | |||
return emptyList(); | |||
emptyList(); | |||
case PROJECT_DELETION: | |||
List<EsQueueDto> items = projectUuids.stream() | |||
.map(projectUuid -> createQueueDto(projectUuid, ID_TYPE_PROJECT_UUID, projectUuid)) | |||
.collect(MoreCollectors.toArrayList(projectUuids.size())); | |||
return dbClient.esQueueDao().insert(dbSession, items); | |||
case DELETION -> { | |||
List<EsQueueDto> items = createProjectDeleteRecoveryItems(entityUuids); | |||
yield dbClient.esQueueDao().insert(dbSession, items); | |||
} | |||
}; | |||
} | |||
default: | |||
// defensive case | |||
throw new IllegalStateException("Unsupported cause: " + cause); | |||
} | |||
@Override | |||
public Collection<EsQueueDto> prepareForRecoveryOnBranchEvent(DbSession dbSession, Collection<String> branchUuids, Indexers.BranchEvent cause) { | |||
return switch (cause) { | |||
case MEASURE_CHANGE -> | |||
// Measures, permissions, project key and tags are not used in type issues/issue | |||
emptyList(); | |||
case DELETION -> { | |||
List<EsQueueDto> items = createBranchRecoveryItems(branchUuids); | |||
yield dbClient.esQueueDao().insert(dbSession, items); | |||
} | |||
}; | |||
} | |||
private List<EsQueueDto> createProjectDeleteRecoveryItems(Collection<String> entityUuids) { | |||
return entityUuids.stream() | |||
.map(entityUuid -> createQueueDto(entityUuid, ID_TYPE_DELETE_PROJECT_UUID, entityUuid)) | |||
.collect(Collectors.toList()); | |||
} | |||
private List<EsQueueDto> createBranchRecoveryItems(Collection<String> branchUuids) { | |||
return branchUuids.stream() | |||
.map(branchUuid -> createQueueDto(branchUuid, ID_TYPE_BRANCH_UUID, branchUuid)) | |||
.collect(Collectors.toList()); | |||
} | |||
/** | |||
@@ -170,12 +205,16 @@ public class IssueIndexer implements ProjectIndexer, NeedAuthorizationIndexer { | |||
@Override | |||
public IndexingResult index(DbSession dbSession, Collection<EsQueueDto> items) { | |||
ListMultimap<String, EsQueueDto> itemsByIssueKey = ArrayListMultimap.create(); | |||
ListMultimap<String, EsQueueDto> itemsByProjectUuid = ArrayListMultimap.create(); | |||
ListMultimap<String, EsQueueDto> itemsByBranchUuid = ArrayListMultimap.create(); | |||
ListMultimap<String, EsQueueDto> itemsByDeleteProjectUuid = ArrayListMultimap.create(); | |||
items.forEach(i -> { | |||
if (ID_TYPE_ISSUE_KEY.equals(i.getDocIdType())) { | |||
itemsByIssueKey.put(i.getDocId(), i); | |||
} else if (ID_TYPE_PROJECT_UUID.equals(i.getDocIdType())) { | |||
itemsByProjectUuid.put(i.getDocId(), i); | |||
} else if (ID_TYPE_BRANCH_UUID.equals(i.getDocIdType())) { | |||
itemsByBranchUuid.put(i.getDocId(), i); | |||
} else if (ID_TYPE_DELETE_PROJECT_UUID.equals(i.getDocIdType())) { | |||
itemsByDeleteProjectUuid.put(i.getDocId(), i); | |||
} else { | |||
LOGGER.error("Unsupported es_queue.doc_id_type for issues. Manual fix is required: " + i); | |||
} | |||
@@ -183,7 +222,8 @@ public class IssueIndexer implements ProjectIndexer, NeedAuthorizationIndexer { | |||
IndexingResult result = new IndexingResult(); | |||
result.add(doIndexIssueItems(dbSession, itemsByIssueKey)); | |||
result.add(doIndexProjectItems(dbSession, itemsByProjectUuid)); | |||
result.add(doIndexBranchItems(dbSession, itemsByBranchUuid)); | |||
result.add(doDeleteProjectIndexItems(dbSession, itemsByDeleteProjectUuid)); | |||
return result; | |||
} | |||
@@ -211,28 +251,38 @@ public class IssueIndexer implements ProjectIndexer, NeedAuthorizationIndexer { | |||
return bulkIndexer.stop(); | |||
} | |||
private IndexingResult doIndexProjectItems(DbSession dbSession, ListMultimap<String, EsQueueDto> itemsByProjectUuid) { | |||
if (itemsByProjectUuid.isEmpty()) { | |||
private IndexingResult doDeleteProjectIndexItems(DbSession dbSession, ListMultimap<String, EsQueueDto> itemsByDeleteProjectUuid) { | |||
IndexingListener listener = new OneToManyResilientIndexingListener(dbClient, dbSession, itemsByDeleteProjectUuid.values()); | |||
BulkIndexer bulkIndexer = createBulkIndexer(listener); | |||
bulkIndexer.start(); | |||
for (String projectUuid : itemsByDeleteProjectUuid.keySet()) { | |||
addProjectDeletionToBulkIndexer(bulkIndexer, projectUuid); | |||
} | |||
return bulkIndexer.stop(); | |||
} | |||
private IndexingResult doIndexBranchItems(DbSession dbSession, ListMultimap<String, EsQueueDto> itemsByBranchUuid) { | |||
if (itemsByBranchUuid.isEmpty()) { | |||
return new IndexingResult(); | |||
} | |||
// one project, referenced by es_queue.doc_id = many issues | |||
IndexingListener listener = new OneToManyResilientIndexingListener(dbClient, dbSession, itemsByProjectUuid.values()); | |||
// one branch, referenced by es_queue.doc_id = many issues | |||
IndexingListener listener = new OneToManyResilientIndexingListener(dbClient, dbSession, itemsByBranchUuid.values()); | |||
BulkIndexer bulkIndexer = createBulkIndexer(listener); | |||
bulkIndexer.start(); | |||
for (String projectUuid : itemsByProjectUuid.keySet()) { | |||
// TODO support loading of multiple projects in a single SQL request | |||
try (IssueIterator issues = issueIteratorFactory.createForBranch(projectUuid)) { | |||
for (String branchUuid : itemsByBranchUuid.keySet()) { | |||
try (IssueIterator issues = issueIteratorFactory.createForBranch(branchUuid)) { | |||
if (issues.hasNext()) { | |||
do { | |||
IssueDoc doc = issues.next(); | |||
bulkIndexer.add(newIndexRequest(doc)); | |||
} while (issues.hasNext()); | |||
} else { | |||
// project does not exist or has no issues. In both case | |||
// all the documents related to this project are deleted. | |||
addProjectDeletionToBulkIndexer(bulkIndexer, projectUuid); | |||
// branch does not exist or has no issues. In both cases, | |||
// all the documents related to this branch are deleted. | |||
Optional<BranchDto> branch = dbClient.branchDao().selectByUuid(dbSession, branchUuid); | |||
branch.ifPresent(b -> addBranchDeletionToBulkIndexer(bulkIndexer, b.getProjectUuid(), b.getUuid())); | |||
} | |||
} | |||
} | |||
@@ -288,6 +338,17 @@ public class IssueIndexer implements ProjectIndexer, NeedAuthorizationIndexer { | |||
bulkIndexer.addDeletion(search); | |||
} | |||
private static void addBranchDeletionToBulkIndexer(BulkIndexer bulkIndexer, String projectUUid, String branchUuid) { | |||
SearchRequest search = EsClient.prepareSearch(TYPE_ISSUE.getMainType()) | |||
// routing is based on the parent (See BaseDoc#getRouting). | |||
// The parent is set to the projectUUid when an issue is indexed (See IssueDoc#setProjectUuid). We need to set it here | |||
// so that the search finds the indexed docs to be deleted. | |||
.routing(AuthorizationDoc.idOf(projectUUid)) | |||
.source(new SearchSourceBuilder().query(boolQuery().must(termQuery(FIELD_ISSUE_BRANCH_UUID, branchUuid)))); | |||
bulkIndexer.addDeletion(search); | |||
} | |||
private static EsQueueDto createQueueDto(String docId, String docIdType, String projectUuid) { | |||
return EsQueueDto.create(TYPE_ISSUE.format(), docId, docIdType, AuthorizationDoc.idOf(projectUuid)); | |||
} |
@@ -26,32 +26,41 @@ import java.util.Date; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.resources.Qualifiers; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.es.EsQueueDto; | |||
import org.sonar.db.measure.ProjectMeasuresIndexerIterator; | |||
import org.sonar.db.measure.ProjectMeasuresIndexerIterator.ProjectMeasures; | |||
import org.sonar.server.es.AnalysisIndexer; | |||
import org.sonar.server.es.BulkIndexer; | |||
import org.sonar.server.es.BulkIndexer.Size; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.EventIndexer; | |||
import org.sonar.server.es.IndexType; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.IndexingListener; | |||
import org.sonar.server.es.IndexingResult; | |||
import org.sonar.server.es.OneToOneResilientIndexingListener; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.permission.index.AuthorizationDoc; | |||
import org.sonar.server.permission.index.AuthorizationScope; | |||
import org.sonar.server.permission.index.NeedAuthorizationIndexer; | |||
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURES; | |||
public class ProjectMeasuresIndexer implements ProjectIndexer, NeedAuthorizationIndexer { | |||
/** | |||
* Indexes data related to projects and applications. | |||
* The name is a bit misleading - it indexes a lot more data than just measures. | |||
* We index by project/app UUID, but we get a lot of the data from their main branches. | |||
*/ | |||
public class ProjectMeasuresIndexer implements EventIndexer, AnalysisIndexer, NeedAuthorizationIndexer { | |||
private static final AuthorizationScope AUTHORIZATION_SCOPE = new AuthorizationScope(TYPE_PROJECT_MEASURES, | |||
project -> Qualifiers.PROJECT.equals(project.getQualifier()) || Qualifiers.APP.equals(project.getQualifier())); | |||
entity -> Qualifiers.PROJECT.equals(entity.getQualifier()) || Qualifiers.APP.equals(entity.getQualifier())); | |||
private static final Set<IndexType> INDEX_TYPES = Set.of(TYPE_PROJECT_MEASURES); | |||
private final DbClient dbClient; | |||
@@ -82,33 +91,46 @@ public class ProjectMeasuresIndexer implements ProjectIndexer, NeedAuthorization | |||
} | |||
@Override | |||
public void indexOnAnalysis(String projectUuid) { | |||
indexOnAnalysis(projectUuid, Set.of()); | |||
public void indexOnAnalysis(String branchUuid) { | |||
indexOnAnalysis(branchUuid, Set.of()); | |||
} | |||
@Override | |||
public void indexOnAnalysis(String projectUuid, Set<String> unchangedComponentUuids) { | |||
doIndex(Size.REGULAR, projectUuid); | |||
public void indexOnAnalysis(String branchUuid, Set<String> unchangedComponentUuids) { | |||
doIndex(Size.REGULAR, branchUuid); | |||
} | |||
@Override | |||
public Collection<EsQueueDto> prepareForRecovery(DbSession dbSession, Collection<String> projectUuids, ProjectIndexer.Cause cause) { | |||
switch (cause) { | |||
case PERMISSION_CHANGE: | |||
// nothing to do, permissions are not used in type projectmeasures/projectmeasure | |||
return Collections.emptyList(); | |||
case MEASURE_CHANGE, PROJECT_KEY_UPDATE, PROJECT_CREATION, PROJECT_TAGS_UPDATE, PROJECT_DELETION: | |||
public Collection<EsQueueDto> prepareForRecoveryOnEntityEvent(DbSession dbSession, Collection<String> entityUuids, Indexers.EntityEvent cause) { | |||
return switch (cause) { | |||
case PERMISSION_CHANGE -> | |||
// nothing to do, permissions are not used in index type projectmeasures/projectmeasure | |||
Collections.emptyList(); | |||
case PROJECT_KEY_UPDATE, CREATION, PROJECT_TAGS_UPDATE, DELETION -> | |||
// when MEASURE_CHANGE or PROJECT_KEY_UPDATE project must be re-indexed because key is used in this index | |||
// when PROJECT_CREATION provisioned projects are supported by WS api/components/search_projects | |||
List<EsQueueDto> items = projectUuids.stream() | |||
.map(projectUuid -> EsQueueDto.create(TYPE_PROJECT_MEASURES.format(), projectUuid, null, projectUuid)) | |||
.collect(MoreCollectors.toArrayList(projectUuids.size())); | |||
return dbClient.esQueueDao().insert(dbSession, items); | |||
default: | |||
// defensive case | |||
throw new IllegalStateException("Unsupported cause: " + cause); | |||
} | |||
prepareForRecovery(dbSession, entityUuids); | |||
}; | |||
} | |||
@Override | |||
public Collection<EsQueueDto> prepareForRecoveryOnBranchEvent(DbSession dbSession, Collection<String> branchUuids, Indexers.BranchEvent cause) { | |||
return switch (cause) { | |||
case DELETION -> Collections.emptyList(); | |||
case MEASURE_CHANGE -> { | |||
Set<String> entityUuids = dbClient.branchDao().selectByUuids(dbSession, branchUuids) | |||
.stream().map(BranchDto::getProjectUuid) | |||
.collect(Collectors.toSet()); | |||
yield prepareForRecovery(dbSession, entityUuids); | |||
} | |||
}; | |||
} | |||
private Collection<EsQueueDto> prepareForRecovery(DbSession dbSession, Collection<String> entityUuids) { | |||
List<EsQueueDto> items = entityUuids.stream() | |||
.map(entityUuid -> EsQueueDto.create(TYPE_PROJECT_MEASURES.format(), entityUuid, null, entityUuid)) | |||
.collect(MoreCollectors.toArrayList(entityUuids.size())); | |||
return dbClient.esQueueDao().insert(dbSession, items); | |||
} | |||
public IndexingResult commitAndIndex(DbSession dbSession, Collection<String> projectUuids) { |
@@ -51,9 +51,9 @@ public class AuthorizationDoc extends BaseDoc { | |||
return idOf(entityUuid); | |||
} | |||
public static String idOf(String projectUuid) { | |||
requireNonNull(projectUuid, "projectUuid can't be null"); | |||
return ID_PREFIX + projectUuid; | |||
public static String idOf(String entityUuid) { | |||
requireNonNull(entityUuid, "entityUuid can't be null"); | |||
return ID_PREFIX + entityUuid; | |||
} | |||
public static String entityUuidOf(String id) { |
@@ -31,11 +31,11 @@ import static org.sonar.server.permission.index.IndexAuthorizationConstants.TYPE | |||
@Immutable | |||
public final class AuthorizationScope { | |||
private final IndexMainType indexType; | |||
private final Predicate<IndexPermissions> projectPredicate; | |||
private final Predicate<IndexPermissions> entityPredicate; | |||
public AuthorizationScope(IndexRelationType functionalType, Predicate<IndexPermissions> projectPredicate) { | |||
public AuthorizationScope(IndexRelationType functionalType, Predicate<IndexPermissions> entityPredicate) { | |||
this.indexType = getAuthorizationIndexType(functionalType); | |||
this.projectPredicate = requireNonNull(projectPredicate); | |||
this.entityPredicate = requireNonNull(entityPredicate); | |||
} | |||
/** | |||
@@ -59,9 +59,9 @@ public final class AuthorizationScope { | |||
} | |||
/** | |||
* Predicates that filters the projects to be involved in authorization. | |||
* Predicates that filters the entities to be involved in authorization. | |||
*/ | |||
public Predicate<IndexPermissions> getProjectPredicate() { | |||
return projectPredicate; | |||
public Predicate<IndexPermissions> getEntityPredicate() { | |||
return entityPredicate; | |||
} | |||
} |
@@ -19,9 +19,11 @@ | |||
*/ | |||
package org.sonar.server.permission.index; | |||
import org.sonar.server.es.EventIndexer; | |||
/** | |||
* An {@link NeedAuthorizationIndexer} defines how | |||
* a {@link org.sonar.server.es.ProjectIndexer} populates | |||
* a {@link EventIndexer} populates | |||
* the type named {@link WebAuthorizationTypeSupport#TYPE_AUTHORIZATION}, which | |||
* is used to verify that a user can access to projects. | |||
*/ |
@@ -0,0 +1,103 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.es; | |||
import java.util.List; | |||
import java.util.Set; | |||
import org.junit.Test; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.es.EsQueueDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.server.es.Indexers.BranchEvent.DELETION; | |||
import static org.sonar.server.es.Indexers.EntityEvent.CREATION; | |||
public class IndexersImplTest { | |||
@Test | |||
public void commitAndIndexOnEntityEvent_shouldCallIndexerWithSupportedItems() { | |||
List<EsQueueDto> items1 = List.of(EsQueueDto.create("fake/fake1", "P1"), EsQueueDto.create("fake/fake1", "P1")); | |||
List<EsQueueDto> items2 = List.of(EsQueueDto.create("fake/fake2", "P1")); | |||
EventIndexer indexer1 = mock(EventIndexer.class); | |||
EventIndexer indexer2 = mock(EventIndexer.class); | |||
DbSession dbSession = mock(DbSession.class); | |||
IndexersImpl underTest = new IndexersImpl(indexer1, indexer2); | |||
when(indexer1.prepareForRecoveryOnEntityEvent(dbSession, Set.of("P1"), CREATION)).thenReturn(items1); | |||
when(indexer2.prepareForRecoveryOnEntityEvent(dbSession, Set.of("P1"), CREATION)).thenReturn(items2); | |||
underTest.commitAndIndexOnEntityEvent(dbSession, Set.of("P1"), CREATION); | |||
verify(indexer1).index(dbSession, items1); | |||
verify(indexer2).index(dbSession, items2); | |||
} | |||
@Test | |||
public void commitAndIndexOnBranchEvent_shouldCallIndexerWithSupportedItems() { | |||
List<EsQueueDto> items1 = List.of(EsQueueDto.create("fake/fake1", "P1"), EsQueueDto.create("fake/fake1", "P1")); | |||
List<EsQueueDto> items2 = List.of(EsQueueDto.create("fake/fake2", "P1")); | |||
EventIndexer indexer1 = mock(EventIndexer.class); | |||
EventIndexer indexer2 = mock(EventIndexer.class); | |||
DbSession dbSession = mock(DbSession.class); | |||
IndexersImpl underTest = new IndexersImpl(indexer1, indexer2); | |||
when(indexer1.prepareForRecoveryOnBranchEvent(dbSession, Set.of("P1"), DELETION)).thenReturn(items1); | |||
when(indexer2.prepareForRecoveryOnBranchEvent(dbSession, Set.of("P1"), DELETION)).thenReturn(items2); | |||
underTest.commitAndIndexOnBranchEvent(dbSession, Set.of("P1"), DELETION); | |||
verify(indexer1).index(dbSession, items1); | |||
verify(indexer2).index(dbSession, items2); | |||
} | |||
@Test | |||
public void commitAndIndexEntities_shouldIndexAllUuids() { | |||
EventIndexer indexer1 = mock(EventIndexer.class); | |||
DbSession dbSession = mock(DbSession.class); | |||
IndexersImpl underTest = new IndexersImpl(indexer1); | |||
ProjectDto p1 = ComponentTesting.newProjectDto(); | |||
underTest.commitAndIndexEntities(dbSession, Set.of(p1), CREATION); | |||
verify(indexer1).prepareForRecoveryOnEntityEvent(dbSession, Set.of(p1.getUuid()), CREATION); | |||
} | |||
@Test | |||
public void commitAndIndexBranches_shouldIndexAllBranchUuids() { | |||
EventIndexer indexer1 = mock(EventIndexer.class); | |||
DbSession dbSession = mock(DbSession.class); | |||
IndexersImpl underTest = new IndexersImpl(indexer1); | |||
BranchDto b1 = new BranchDto().setUuid("b1"); | |||
underTest.commitAndIndexBranches(dbSession, Set.of(b1), DELETION); | |||
verify(indexer1).prepareForRecoveryOnBranchEvent(dbSession, Set.of(b1.getUuid()), DELETION); | |||
} | |||
} |
@@ -1,55 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.es; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import org.junit.Test; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.server.es.ProjectIndexer.Cause; | |||
import static java.util.Collections.singletonList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
public class ProjectIndexersImplTest { | |||
@Test | |||
public void commitAndIndex_indexes_project() { | |||
ComponentDto project = ComponentTesting.newPublicProjectDto(); | |||
FakeIndexers underTest = new FakeIndexers(); | |||
underTest.commitAndIndexComponents(mock(DbSession.class), singletonList(project), Cause.PROJECT_CREATION); | |||
assertThat(underTest.calls).containsExactly(project.uuid()); | |||
} | |||
private static class FakeIndexers implements ProjectIndexers { | |||
private final List<String> calls = new ArrayList<>(); | |||
@Override | |||
public void commitAndIndexByProjectUuids(DbSession dbSession, Collection<String> projectUuids, Cause cause) { | |||
calls.addAll(projectUuids); | |||
} | |||
} | |||
} |
@@ -1,120 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.es; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Set; | |||
import org.junit.Test; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.es.EsQueueDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.singletonList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
public class ProjectIndexersTest { | |||
@Test | |||
public void commitAndIndexByProjectUuids_calls_indexer_with_only_its_supported_items() { | |||
EsQueueDto item1a = EsQueueDto.create("fake/fake1", "P1"); | |||
EsQueueDto item1b = EsQueueDto.create("fake/fake1", "P1"); | |||
EsQueueDto item2 = EsQueueDto.create("fake/fake2", "P1"); | |||
FakeIndexer indexer1 = new FakeIndexer(asList(item1a, item1b)); | |||
FakeIndexer indexer2 = new FakeIndexer(singletonList(item2)); | |||
DbSession dbSession = mock(DbSession.class); | |||
ProjectIndexersImpl underTest = new ProjectIndexersImpl(indexer1, indexer2); | |||
underTest.commitAndIndexByProjectUuids(dbSession, singletonList("P1"), ProjectIndexer.Cause.PROJECT_CREATION); | |||
assertThat(indexer1.calledItems).containsExactlyInAnyOrder(item1a, item1b); | |||
assertThat(indexer2.calledItems).containsExactlyInAnyOrder(item2); | |||
} | |||
@Test | |||
public void commitAndIndexByEntityUuids_calls_indexer_with_only_its_supported_items() { | |||
ProjectIndexersTestImpl projectIndexers = new ProjectIndexersTestImpl(); | |||
ProjectDto p1 = ComponentTesting.newProjectDto(); | |||
ProjectDto p2 = ComponentTesting.newProjectDto(); | |||
p1.setUuid("p1"); | |||
p2.setUuid("p2"); | |||
projectIndexers.commitAndIndexEntities(null, List.of(p1, p2), ProjectIndexer.Cause.PROJECT_CREATION); | |||
assertThat(projectIndexers.cause).isEqualTo(ProjectIndexer.Cause.PROJECT_CREATION); | |||
assertThat(projectIndexers.calledProjectUuids).containsOnly("p1", "p2"); | |||
} | |||
private static class ProjectIndexersTestImpl implements ProjectIndexers { | |||
Collection<String> calledProjectUuids; | |||
ProjectIndexer.Cause cause; | |||
@Override | |||
public void commitAndIndexByProjectUuids(DbSession dbSession, Collection<String> projectUuids, ProjectIndexer.Cause cause) { | |||
this.calledProjectUuids = projectUuids; | |||
this.cause = cause; | |||
} | |||
} | |||
private static class FakeIndexer implements ProjectIndexer { | |||
private final List<EsQueueDto> items; | |||
private Collection<EsQueueDto> calledItems; | |||
private FakeIndexer(List<EsQueueDto> items) { | |||
this.items = items; | |||
} | |||
@Override | |||
public void indexOnStartup(Set<IndexType> uninitializedIndexTypes) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
@Override | |||
public Set<IndexType> getIndexTypes() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
@Override | |||
public Collection<EsQueueDto> prepareForRecovery(DbSession dbSession, Collection<String> projectUuids, Cause cause) { | |||
return items; | |||
} | |||
@Override | |||
public IndexingResult index(DbSession dbSession, Collection<EsQueueDto> items) { | |||
this.calledItems = items; | |||
return new IndexingResult(); | |||
} | |||
@Override | |||
public void indexOnAnalysis(String branchUuid) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
@Override | |||
public void indexOnAnalysis(String branchUuid, Set<String> unchangedComponentUuids) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
} | |||
} |
@@ -27,9 +27,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; | |||
import static org.sonar.server.es.StartupIndexer.Type.SYNCHRONOUS; | |||
public class StartupIndexerTest { | |||
private StartupIndexer underTest = () -> null; | |||
private final StartupIndexer underTest = () -> null; | |||
@Test | |||
public void getType() { | |||
@@ -40,14 +38,14 @@ public class StartupIndexerTest { | |||
public void triggerAsyncIndexOnStartup() { | |||
assertThatThrownBy(() -> underTest.triggerAsyncIndexOnStartup(Collections.emptySet())) | |||
.isInstanceOf(IllegalStateException.class) | |||
.hasMessage("ASYNCHRONE StartupIndexer must implement initAsyncIndexOnStartup"); | |||
.hasMessage("ASYNCHRONOUS StartupIndexer must implement initAsyncIndexOnStartup"); | |||
} | |||
@Test | |||
public void indexOnStartup() { | |||
assertThatThrownBy(() -> underTest.indexOnStartup(Collections.emptySet())) | |||
.isInstanceOf(IllegalStateException.class) | |||
.hasMessage("SYNCHRONE StartupIndexer must implement indexOnStartup"); | |||
.hasMessage("SYNCHRONOUS StartupIndexer must implement indexOnStartup"); | |||
} | |||
} |
@@ -49,7 +49,7 @@ public class AuthorizationDocTest { | |||
public void idOf_fails_with_NPE_if_argument_is_null() { | |||
assertThatThrownBy(() -> AuthorizationDoc.idOf(null)) | |||
.isInstanceOf(NullPointerException.class) | |||
.hasMessage("projectUuid can't be null"); | |||
.hasMessage("entityUuid can't be null"); | |||
} | |||
@Test | |||
@@ -81,7 +81,7 @@ public class AuthorizationDocTest { | |||
assertThatThrownBy(() -> underTest.getId()) | |||
.isInstanceOf(NullPointerException.class) | |||
.hasMessage("projectUuid can't be null"); | |||
.hasMessage("entityUuid can't be null"); | |||
} | |||
@Test |
@@ -0,0 +1,65 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2023 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.es; | |||
import com.google.common.collect.ArrayListMultimap; | |||
import com.google.common.collect.ListMultimap; | |||
import java.util.Collection; | |||
import org.sonar.db.DbSession; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class TestIndexers implements Indexers { | |||
private final ListMultimap<String, EntityEvent> entityCalls = ArrayListMultimap.create(); | |||
private final ListMultimap<String, BranchEvent> branchCalls = ArrayListMultimap.create(); | |||
@Override | |||
public void commitAndIndexOnEntityEvent(DbSession dbSession, Collection<String> entityUuids, EntityEvent cause) { | |||
dbSession.commit(); | |||
entityUuids.forEach(entityUuid -> entityCalls.put(entityUuid, cause)); | |||
} | |||
@Override | |||
public void commitAndIndexOnBranchEvent(DbSession dbSession, Collection<String> branchUuids, BranchEvent cause) { | |||
dbSession.commit(); | |||
branchUuids.forEach(branchUuid -> branchCalls.put(branchUuid, cause)); | |||
} | |||
public boolean hasBeenCalledForEntity(String entityUuid, EntityEvent expectedCause) { | |||
assertThat(branchCalls.keySet()).isEmpty(); | |||
return entityCalls.get(entityUuid).contains(expectedCause); | |||
} | |||
public boolean hasBeenCalledForEntity(String projectUuid) { | |||
assertThat(branchCalls.keySet()).isEmpty(); | |||
return entityCalls.containsKey(projectUuid); | |||
} | |||
public boolean hasBeenCalledForBranch(String branchUuid, BranchEvent expectedCause) { | |||
assertThat(entityCalls.keySet()).isEmpty(); | |||
return branchCalls.get(branchUuid).contains(expectedCause); | |||
} | |||
public boolean hasBeenCalledForBranch(String branchUuid) { | |||
assertThat(entityCalls.keySet()).isEmpty(); | |||
return branchCalls.containsKey(branchUuid); | |||
} | |||
} |
@@ -47,7 +47,6 @@ import static org.sonar.db.ce.CeTaskCharacteristicDto.BRANCH_TYPE_KEY; | |||
import static org.sonar.db.ce.CeTaskCharacteristicDto.PULL_REQUEST; | |||
import static org.sonar.db.ce.CeTaskTypes.BRANCH_ISSUE_SYNC; | |||
@ServerSide | |||
public class AsyncIssueIndexingImpl implements AsyncIssueIndexing { | |||
private static final Logger LOG = LoggerFactory.getLogger(AsyncIssueIndexingImpl.class); |
@@ -35,21 +35,21 @@ import org.sonar.db.es.EsQueueDto; | |||
import org.sonar.server.es.BulkIndexer; | |||
import org.sonar.server.es.BulkIndexer.Size; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.EventIndexer; | |||
import org.sonar.server.es.IndexType; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.IndexingResult; | |||
import org.sonar.server.es.OneToOneResilientIndexingListener; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import static java.util.Collections.emptyList; | |||
import static org.sonar.core.util.stream.MoreCollectors.toArrayList; | |||
/** | |||
* Populates the types "authorization" of each index requiring project | |||
* Populates the types "authorization" of each index requiring entity | |||
* authorization. | |||
*/ | |||
public class PermissionIndexer implements ProjectIndexer { | |||
public class PermissionIndexer implements EventIndexer { | |||
private final DbClient dbClient; | |||
private final EsClient esClient; | |||
private final Collection<AuthorizationScope> authorizationScopes; | |||
@@ -99,28 +99,20 @@ public class PermissionIndexer implements ProjectIndexer { | |||
} | |||
@Override | |||
public void indexOnAnalysis(String branchUuid) { | |||
// nothing to do, permissions don't change during an analysis | |||
} | |||
@Override | |||
public void indexOnAnalysis(String branchUuid, Set<String> unchangedComponentUuids) { | |||
// nothing to do, permissions don't change during an analysis | |||
} | |||
@Override | |||
public Collection<EsQueueDto> prepareForRecovery(DbSession dbSession, Collection<String> projectUuids, ProjectIndexer.Cause cause) { | |||
public Collection<EsQueueDto> prepareForRecoveryOnEntityEvent(DbSession dbSession, Collection<String> entityUuids, Indexers.EntityEvent cause) { | |||
return switch (cause) { | |||
case MEASURE_CHANGE, PROJECT_KEY_UPDATE, PROJECT_TAGS_UPDATE -> | |||
case PROJECT_KEY_UPDATE, PROJECT_TAGS_UPDATE -> | |||
// nothing to change. Measures, project key and tags are not part of this index | |||
emptyList(); | |||
case PROJECT_CREATION, PROJECT_DELETION, PERMISSION_CHANGE -> insertIntoEsQueue(dbSession, projectUuids); | |||
default -> | |||
// defensive case | |||
throw new IllegalStateException("Unsupported cause: " + cause); | |||
case CREATION, DELETION, PERMISSION_CHANGE -> insertIntoEsQueue(dbSession, entityUuids); | |||
}; | |||
} | |||
@Override | |||
public Collection<EsQueueDto> prepareForRecoveryOnBranchEvent(DbSession dbSession, Collection<String> branchUuids, Indexers.BranchEvent cause) { | |||
return emptyList(); | |||
} | |||
private Collection<EsQueueDto> insertIntoEsQueue(DbSession dbSession, Collection<String> projectUuids) { | |||
List<EsQueueDto> items = indexTypeByFormat.values().stream() | |||
.flatMap(indexType -> projectUuids.stream().map(projectUuid -> EsQueueDto.create(indexType.format(), AuthorizationDoc.idOf(projectUuid), null, projectUuid))) | |||
@@ -143,7 +135,7 @@ public class PermissionIndexer implements ProjectIndexer { | |||
bulkIndexer.start(); | |||
authorizations.stream() | |||
.filter(scope.getProjectPredicate()) | |||
.filter(scope.getEntityPredicate()) | |||
.map(dto -> AuthorizationDoc.fromDto(indexType, dto).toIndexRequest()) | |||
.forEach(bulkIndexer::add); | |||
@@ -179,7 +171,7 @@ public class PermissionIndexer implements ProjectIndexer { | |||
}); | |||
// the remaining references on entities that don't exist in db. They must | |||
// be deleted from index. | |||
// be deleted from the index. | |||
remainingEntityUuids.forEach(entityUuid -> bulkIndexers.forEach(bi -> { | |||
String authorizationDocId = AuthorizationDoc.idOf(entityUuid); | |||
bi.addDeletion(bi.getIndexType(), authorizationDocId, authorizationDocId); |
@@ -52,7 +52,7 @@ public class ComponentIndexSearchTest { | |||
@Rule | |||
public ComponentTextSearchFeatureRule features = new ComponentTextSearchFeatureRule(); | |||
private final ComponentIndexer indexer = new ComponentIndexer(db.getDbClient(), es.client()); | |||
private final EntityDefinitionIndexer indexer = new EntityDefinitionIndexer(db.getDbClient(), es.client()); | |||
private final PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, indexer); | |||
private final ComponentIndex underTest = new ComponentIndex(es.client(), new WebAuthorizationTypeSupport(userSession), System2.INSTANCE); | |||
@@ -52,7 +52,7 @@ public abstract class ComponentIndexTest { | |||
@Rule | |||
public ComponentTextSearchFeatureRule features = new ComponentTextSearchFeatureRule(); | |||
protected ComponentIndexer indexer = new ComponentIndexer(db.getDbClient(), es.client()); | |||
protected EntityDefinitionIndexer indexer = new EntityDefinitionIndexer(db.getDbClient(), es.client()); | |||
protected ComponentIndex index = new ComponentIndex(es.client(), new WebAuthorizationTypeSupport(userSession), System2.INSTANCE); | |||
protected PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, indexer); | |||
@@ -19,21 +19,15 @@ | |||
*/ | |||
package org.sonar.server.permission.index; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.Collection; | |||
import java.util.Set; | |||
import org.elasticsearch.action.index.IndexRequest; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.es.EsQueueDto; | |||
import org.sonar.server.es.AnalysisIndexer; | |||
import org.sonar.server.es.BaseDoc; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.IndexType; | |||
import org.sonar.server.es.IndexingResult; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import static org.sonar.server.permission.index.FooIndexDefinition.TYPE_FOO; | |||
public class FooIndexer implements ProjectIndexer, NeedAuthorizationIndexer { | |||
public class FooIndexer implements AnalysisIndexer, NeedAuthorizationIndexer { | |||
private static final AuthorizationScope AUTHORIZATION_SCOPE = new AuthorizationScope(TYPE_FOO, p -> true); | |||
@@ -59,11 +53,6 @@ public class FooIndexer implements ProjectIndexer, NeedAuthorizationIndexer { | |||
addToIndex(branchUuid, "baz"); | |||
} | |||
@Override | |||
public Collection<EsQueueDto> prepareForRecovery(DbSession dbSession, Collection<String> projectUuids, Cause cause) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
private void addToIndex(String projectUuid, String name) { | |||
FooDoc fooDoc = new FooDoc(projectUuid, name); | |||
esClient.index(new IndexRequest(TYPE_FOO.getMainType().getIndex().getName()) | |||
@@ -92,19 +81,4 @@ public class FooIndexer implements ProjectIndexer, NeedAuthorizationIndexer { | |||
} | |||
} | |||
@Override | |||
public void indexOnStartup(Set<IndexType> uninitializedIndexTypes) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
@Override | |||
public Set<IndexType> getIndexTypes() { | |||
return ImmutableSet.of(TYPE_FOO); | |||
} | |||
@Override | |||
public IndexingResult index(DbSession dbSession, Collection<EsQueueDto> items) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
} |
@@ -34,8 +34,8 @@ import org.sonar.db.user.UserDto; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.es.IndexType; | |||
import org.sonar.server.es.IndexType.IndexMainType; | |||
import org.sonar.server.es.Indexers.EntityEvent; | |||
import org.sonar.server.es.IndexingResult; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import static java.util.Arrays.asList; | |||
@@ -44,7 +44,7 @@ import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.api.resources.Qualifiers.PROJECT; | |||
import static org.sonar.api.web.UserRole.ADMIN; | |||
import static org.sonar.api.web.UserRole.USER; | |||
import static org.sonar.server.es.ProjectIndexer.Cause.PERMISSION_CHANGE; | |||
import static org.sonar.server.es.Indexers.EntityEvent.PERMISSION_CHANGE; | |||
import static org.sonar.server.permission.index.IndexAuthorizationConstants.TYPE_AUTHORIZATION; | |||
public class PermissionIndexerTest { | |||
@@ -98,7 +98,7 @@ public class PermissionIndexerTest { | |||
// Simulate a indexation issue | |||
db.getDbClient().purgeDao().deleteProject(db.getSession(), project1.getUuid(), PROJECT, project1.getName(), project1.getKey()); | |||
underTest.prepareForRecovery(db.getSession(), asList(project1.getUuid()), ProjectIndexer.Cause.PROJECT_DELETION); | |||
underTest.prepareForRecoveryOnEntityEvent(db.getSession(), asList(project1.getUuid()), EntityEvent.DELETION); | |||
assertThat(db.countRowsOfTable(db.getSession(), "es_queue")).isOne(); | |||
Collection<EsQueueDto> esQueueDtos = db.getDbClient().esQueueDao().selectForRecovery(db.getSession(), Long.MAX_VALUE, 2); | |||
@@ -246,21 +246,11 @@ public class PermissionIndexerTest { | |||
verifyAuthorized(projectOnOrg1, user); | |||
} | |||
@Test | |||
public void indexOnAnalysis_does_nothing_because_CE_does_not_touch_permissions() { | |||
ProjectDto project = createAndIndexPublicProject(); | |||
underTest.indexOnAnalysis(project.getUuid()); | |||
assertThatAuthIndexHasSize(0); | |||
verifyAnyoneNotAuthorized(project); | |||
} | |||
@Test | |||
public void permissions_are_not_updated_on_project_tags_update() { | |||
ProjectDto project = createAndIndexPublicProject(); | |||
indexPermissions(project, ProjectIndexer.Cause.PROJECT_TAGS_UPDATE); | |||
indexPermissions(project, EntityEvent.PROJECT_TAGS_UPDATE); | |||
assertThatAuthIndexHasSize(0); | |||
verifyAnyoneNotAuthorized(project); | |||
@@ -270,7 +260,7 @@ public class PermissionIndexerTest { | |||
public void permissions_are_not_updated_on_project_key_update() { | |||
ProjectDto project = createAndIndexPublicProject(); | |||
indexPermissions(project, ProjectIndexer.Cause.PROJECT_TAGS_UPDATE); | |||
indexPermissions(project, EntityEvent.PROJECT_TAGS_UPDATE); | |||
assertThatAuthIndexHasSize(0); | |||
verifyAnyoneNotAuthorized(project); | |||
@@ -282,7 +272,7 @@ public class PermissionIndexerTest { | |||
UserDto user = db.users().insertUser(); | |||
db.users().insertProjectPermissionOnUser(user, USER, project); | |||
indexPermissions(project, ProjectIndexer.Cause.PROJECT_CREATION); | |||
indexPermissions(project, EntityEvent.CREATION); | |||
assertThatAuthIndexHasSize(1); | |||
verifyAuthorized(project, user); | |||
@@ -294,7 +284,7 @@ public class PermissionIndexerTest { | |||
UserDto user1 = db.users().insertUser(); | |||
UserDto user2 = db.users().insertUser(); | |||
db.users().insertProjectPermissionOnUser(user1, USER, project); | |||
indexPermissions(project, ProjectIndexer.Cause.PROJECT_CREATION); | |||
indexPermissions(project, EntityEvent.CREATION); | |||
verifyAuthorized(project, user1); | |||
verifyNotAuthorized(project, user2); | |||
@@ -310,11 +300,11 @@ public class PermissionIndexerTest { | |||
ProjectDto project = createAndIndexPrivateProject(); | |||
UserDto user = db.users().insertUser(); | |||
db.users().insertProjectPermissionOnUser(user, USER, project); | |||
indexPermissions(project, ProjectIndexer.Cause.PROJECT_CREATION); | |||
indexPermissions(project, EntityEvent.CREATION); | |||
verifyAuthorized(project, user); | |||
db.getDbClient().purgeDao().deleteProject(db.getSession(), project.getUuid(), PROJECT, project.getUuid(), project.getKey()); | |||
indexPermissions(project, ProjectIndexer.Cause.PROJECT_DELETION); | |||
indexPermissions(project, EntityEvent.DELETION); | |||
verifyNotAuthorized(project, user); | |||
assertThatAuthIndexHasSize(0); | |||
@@ -392,9 +382,9 @@ public class PermissionIndexerTest { | |||
return userSession; | |||
} | |||
private IndexingResult indexPermissions(EntityDto entity, ProjectIndexer.Cause cause) { | |||
private IndexingResult indexPermissions(EntityDto entity, EntityEvent cause) { | |||
DbSession dbSession = db.getSession(); | |||
Collection<EsQueueDto> items = underTest.prepareForRecovery(dbSession, singletonList(entity.getUuid()), cause); | |||
Collection<EsQueueDto> items = underTest.prepareForRecoveryOnEntityEvent(dbSession, singletonList(entity.getUuid()), cause); | |||
dbSession.commit(); | |||
return underTest.index(dbSession, items); | |||
} |
@@ -43,7 +43,7 @@ import org.sonar.db.user.UserDto; | |||
import org.sonar.server.almintegration.ws.ImportHelper; | |||
import org.sonar.server.almintegration.ws.ProjectKeyGenerator; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
@@ -92,7 +92,7 @@ public class ImportAzureProjectActionIT { | |||
private final DefaultBranchNameResolver defaultBranchNameResolver = mock(DefaultBranchNameResolver.class); | |||
private final ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), i18n, System2.INSTANCE, | |||
mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()), new TestProjectIndexers(), new SequenceUuidFactory(), | |||
mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()), new TestIndexers(), new SequenceUuidFactory(), | |||
defaultBranchNameResolver, true); | |||
private final Encryption encryption = mock(Encryption.class); |
@@ -43,7 +43,7 @@ import org.sonar.db.user.UserDto; | |||
import org.sonar.server.almintegration.ws.ImportHelper; | |||
import org.sonar.server.almintegration.ws.ProjectKeyGenerator; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
@@ -92,7 +92,7 @@ public class ImportBitbucketCloudRepoActionIT { | |||
DefaultBranchNameResolver defaultBranchNameResolver = mock(DefaultBranchNameResolver.class); | |||
private final ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), i18n, System2.INSTANCE, | |||
mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()), new TestProjectIndexers(), new SequenceUuidFactory(), | |||
mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()), new TestIndexers(), new SequenceUuidFactory(), | |||
defaultBranchNameResolver, true); | |||
private final ImportHelper importHelper = new ImportHelper(db.getDbClient(), userSession); |
@@ -19,7 +19,6 @@ | |||
*/ | |||
package org.sonar.server.almintegration.ws.bitbucketserver; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.List; | |||
@@ -48,7 +47,7 @@ import org.sonar.db.user.UserDto; | |||
import org.sonar.server.almintegration.ws.ImportHelper; | |||
import org.sonar.server.almintegration.ws.ProjectKeyGenerator; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
@@ -100,7 +99,7 @@ public class ImportBitbucketServerProjectActionIT { | |||
private NewCodeDefinitionResolver newCodeDefinitionResolver = new NewCodeDefinitionResolver(db.getDbClient(), editionProvider); | |||
private final ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), i18n, System2.INSTANCE, | |||
mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()), new TestProjectIndexers(), new SequenceUuidFactory(), | |||
mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()), new TestIndexers(), new SequenceUuidFactory(), | |||
defaultBranchNameResolver, true); | |||
private final ImportHelper importHelper = new ImportHelper(db.getDbClient(), userSession); |
@@ -41,7 +41,7 @@ import org.sonar.db.user.UserDto; | |||
import org.sonar.server.almintegration.ws.ImportHelper; | |||
import org.sonar.server.almintegration.ws.ProjectKeyGenerator; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
import org.sonar.server.exceptions.UnauthorizedException; | |||
import org.sonar.server.favorite.FavoriteUpdater; | |||
@@ -87,7 +87,7 @@ public class ImportGithubProjectActionIT { | |||
private final ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), mock(I18n.class), System2.INSTANCE, | |||
mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()), new TestProjectIndexers(), new SequenceUuidFactory(), | |||
mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()), new TestIndexers(), new SequenceUuidFactory(), | |||
defaultBranchNameResolver, true); | |||
private final ImportHelper importHelper = new ImportHelper(db.getDbClient(), userSession); |
@@ -41,7 +41,7 @@ import org.sonar.db.user.UserDto; | |||
import org.sonar.server.almintegration.ws.ImportHelper; | |||
import org.sonar.server.almintegration.ws.ProjectKeyGenerator; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.favorite.FavoriteUpdater; | |||
import org.sonar.server.newcodeperiod.NewCodeDefinitionResolver; | |||
import org.sonar.server.permission.PermissionTemplateService; | |||
@@ -83,7 +83,7 @@ public class ImportGitLabProjectActionIT { | |||
DefaultBranchNameResolver defaultBranchNameResolver = mock(DefaultBranchNameResolver.class); | |||
private final ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), mock(I18n.class), System2.INSTANCE, | |||
mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()), new TestProjectIndexers(), new SequenceUuidFactory(), | |||
mock(PermissionTemplateService.class), new FavoriteUpdater(db.getDbClient()), new TestIndexers(), new SequenceUuidFactory(), | |||
defaultBranchNameResolver, true); | |||
private final GitlabHttpClient gitlabHttpClient = mock(GitlabHttpClient.class); | |||
@@ -137,7 +137,7 @@ public class ImportGitLabProjectActionIT { | |||
assertThat(projectDto).isPresent(); | |||
assertThat(db.getDbClient().projectAlmSettingDao().selectByProject(db.getSession(), projectDto.get())).isPresent(); | |||
assertThat(db.getDbClient().newCodePeriodDao().selectByProject(db.getSession(), projectDto.get().getUuid())) | |||
assertThat(db.getDbClient().newCodePeriodDao().selectByProject(db.getSession(), projectDto.get().getUuid())) | |||
.isPresent() | |||
.get() | |||
.extracting(NewCodePeriodDto::getType, NewCodePeriodDto::getValue, NewCodePeriodDto::getBranchUuid) | |||
@@ -252,7 +252,6 @@ public class ImportGitLabProjectActionIT { | |||
.containsExactlyInAnyOrder(tuple(DEFAULT_MAIN_BRANCH_NAME, true)); | |||
} | |||
@Test | |||
public void import_project_without_NCD() { | |||
UserDto user = db.users().insertUser(); | |||
@@ -284,7 +283,6 @@ public class ImportGitLabProjectActionIT { | |||
assertThat(db.getDbClient().projectAlmSettingDao().selectByProject(db.getSession(), projectDto.get())).isPresent(); | |||
} | |||
private Project getGitlabProject() { | |||
return new Project(randomAlphanumeric(5), randomAlphanumeric(5)); | |||
} |
@@ -51,9 +51,9 @@ public class DeleteActionIT { | |||
@Rule | |||
public DbTester db = DbTester.create(System2.INSTANCE, true); | |||
private ComponentCleanerService componentCleanerService = mock(ComponentCleanerService.class); | |||
private ComponentFinder componentFinder = TestComponentFinder.from(db); | |||
private ProjectLifeCycleListeners projectLifeCycleListeners = mock(ProjectLifeCycleListeners.class); | |||
private final ComponentCleanerService componentCleanerService = mock(ComponentCleanerService.class); | |||
private final ComponentFinder componentFinder = TestComponentFinder.from(db); | |||
private final ProjectLifeCycleListeners projectLifeCycleListeners = mock(ProjectLifeCycleListeners.class); | |||
@Rule | |||
public UserSessionRule userSession = UserSessionRule.standalone(); |
@@ -182,7 +182,7 @@ public class BranchReportSubmitterIT { | |||
ComponentCreationData componentCreationData = mock(ComponentCreationData.class); | |||
when(componentCreationData.mainBranchComponent()) | |||
.thenAnswer((Answer<ComponentDto>) invocation -> db.components().insertPrivateProject(nonExistingProject).getMainBranchComponent()); | |||
when(componentUpdater.createWithoutCommit(any(), any(), eq(user.getUuid()), eq(user.getLogin()), any())) | |||
when(componentUpdater.createWithoutCommit(any(), any(), eq(user.getUuid()), eq(user.getLogin()))) | |||
.thenReturn(componentCreationData); | |||
when(branchSupportDelegate.createBranchComponent(any(DbSession.class), same(componentKey), eq(nonExistingProject), any())).thenReturn(createdBranch); | |||
when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), any(), eq(nonExistingProject.getKey()))).thenReturn(true); | |||
@@ -197,7 +197,7 @@ public class BranchReportSubmitterIT { | |||
verify(branchSupportDelegate).createBranchComponent(any(DbSession.class), same(componentKey), eq(nonExistingProject), eq(exitingProjectMainBranch)); | |||
verifyNoMoreInteractions(branchSupportDelegate); | |||
verifyQueueSubmit(nonExistingProject, createdBranch, user, randomCharacteristics, taskUuid); | |||
verify(componentUpdater).commitAndIndex(any(DbSession.class), eq(nonExistingProject)); | |||
verify(componentUpdater).commitAndIndex(any(DbSession.class), eq(componentCreationData)); | |||
} | |||
@Test |
@@ -41,7 +41,7 @@ import org.sonar.db.permission.GlobalPermission; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.favorite.FavoriteUpdater; | |||
@@ -87,7 +87,7 @@ public class ReportSubmitterIT { | |||
private final DefaultBranchNameResolver defaultBranchNameResolver = mock(DefaultBranchNameResolver.class); | |||
private final CeQueue queue = mock(CeQueueImpl.class); | |||
private final TestProjectIndexers projectIndexers = new TestProjectIndexers(); | |||
private final TestIndexers projectIndexers = new TestIndexers(); | |||
private final PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class); | |||
private final ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), mock(I18n.class), mock(System2.class), permissionTemplateService, |
@@ -19,10 +19,9 @@ | |||
*/ | |||
package org.sonar.server.component; | |||
import java.util.List; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.resources.ResourceType; | |||
import org.sonar.api.resources.ResourceTypes; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
@@ -36,15 +35,18 @@ import org.sonar.db.portfolio.PortfolioDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.webhook.WebhookDto; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.Indexers.BranchEvent; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | |||
import static org.mockito.ArgumentMatchers.anyString; | |||
import static org.mockito.ArgumentMatchers.any; | |||
import static org.mockito.ArgumentMatchers.eq; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_DELETION; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.verifyNoMoreInteractions; | |||
import static org.sonar.server.es.Indexers.EntityEvent.DELETION; | |||
public class ComponentCleanerServiceIT { | |||
@@ -55,19 +57,20 @@ public class ComponentCleanerServiceIT { | |||
private final DbClient dbClient = db.getDbClient(); | |||
private final DbSession dbSession = db.getSession(); | |||
private final TestProjectIndexers projectIndexers = new TestProjectIndexers(); | |||
private final ResourceTypes mockResourceTypes = mock(ResourceTypes.class); | |||
private final ComponentCleanerService underTest = new ComponentCleanerService(dbClient, mockResourceTypes, projectIndexers); | |||
private final Indexers indexers = mock(Indexers.class); | |||
private final ComponentCleanerService underTest = new ComponentCleanerService(dbClient, indexers); | |||
@Test | |||
public void delete_project_from_db_and_index() { | |||
DbData data1 = insertProjectData(); | |||
DbData data2 = insertProjectData(); | |||
underTest.delete(dbSession, data1.project); | |||
underTest.deleteEntity(dbSession, data1.project); | |||
assertNotExists(data1); | |||
assertExists(data2); | |||
verify(indexers).commitAndIndexEntities(any(), eq(List.of(data1.project)), eq(DELETION)); | |||
verifyNoMoreInteractions(indexers); | |||
} | |||
@Test | |||
@@ -82,6 +85,10 @@ public class ComponentCleanerServiceIT { | |||
assertNotExists(data1); | |||
assertNotExists(data2); | |||
assertExists(data3); | |||
verify(indexers).commitAndIndexEntities(any(), eq(List.of(data1.project)), eq(DELETION)); | |||
verify(indexers).commitAndIndexEntities(any(), eq(List.of(data2.project)), eq(DELETION)); | |||
verifyNoMoreInteractions(indexers); | |||
} | |||
@Test | |||
@@ -91,9 +98,7 @@ public class ComponentCleanerServiceIT { | |||
ProjectData projectData2 = db.components().insertPublicProject(); | |||
ComponentDto componentDto2 = projectData2.getMainBranchComponent(); | |||
mockResourceTypeAsValidProject(); | |||
underTest.delete(dbSession, projectData1.getProjectDto()); | |||
underTest.deleteEntity(dbSession, projectData1.getProjectDto()); | |||
dbSession.commit(); | |||
assertNotExists(componentDto1); | |||
@@ -101,12 +106,9 @@ public class ComponentCleanerServiceIT { | |||
} | |||
@Test | |||
public void fail_with_IAE_if_project_non_deletable() { | |||
ProjectData projectData = db.components().insertPublicProject(); | |||
mockResourceTypeAsNonDeletable(); | |||
dbSession.commit(); | |||
ProjectDto project = projectData.getProjectDto(); | |||
assertThatThrownBy(() -> underTest.delete(dbSession, project)) | |||
public void fail_with_IAE_if_deleting_subview() { | |||
PortfolioDto portfolio = new PortfolioDto().setParentUuid("parent").setRootUuid("root").setUuid("uuid"); | |||
assertThatThrownBy(() -> underTest.deleteEntity(dbSession, portfolio)) | |||
.withFailMessage("Only projects can be deleted") | |||
.isInstanceOf(IllegalArgumentException.class); | |||
} | |||
@@ -119,7 +121,7 @@ public class ComponentCleanerServiceIT { | |||
ProjectData app1 = insertApplication(data2.project); | |||
ProjectData app2 = insertApplication(data3.project); | |||
underTest.delete(dbSession, app1.getProjectDto()); | |||
underTest.deleteEntity(dbSession, app1.getProjectDto()); | |||
dbSession.commit(); | |||
assertProjectOrAppExists(app1.getProjectDto(), app1.getMainBranchDto(), false); | |||
@@ -127,20 +129,21 @@ public class ComponentCleanerServiceIT { | |||
assertExists(data1); | |||
assertExists(data2); | |||
assertExists(data3); | |||
verify(indexers).commitAndIndexEntities(any(), eq(List.of(app1.getProjectDto())), eq(DELETION)); | |||
verifyNoMoreInteractions(indexers); | |||
} | |||
@Test | |||
public void delete_WhenDeletingPortfolio_ShouldDeleteComponents() { | |||
PortfolioDto portfolioDto1 = db.components().insertPrivatePortfolioDto(); | |||
PortfolioDto portfolioDto2 = db.components().insertPrivatePortfolioDto(); | |||
mockResourceTypeAsValidProject(); | |||
underTest.delete(dbSession, portfolioDto1); | |||
underTest.deleteEntity(dbSession, portfolioDto1); | |||
assertThat(dbClient.componentDao().selectByUuid(dbSession, portfolioDto1.getUuid())).isEmpty(); | |||
assertThat(dbClient.componentDao().selectByUuid(dbSession, portfolioDto2.getUuid())).isPresent(); | |||
assertThat(projectIndexers.hasBeenCalled(portfolioDto1.getUuid(), PROJECT_DELETION)).isTrue(); | |||
verify(indexers).commitAndIndexEntities(any(), eq(List.of(portfolioDto1)), eq(DELETION)); | |||
verifyNoMoreInteractions(indexers); | |||
} | |||
private ProjectData insertApplication(ProjectDto project) { | |||
@@ -165,6 +168,8 @@ public class ComponentCleanerServiceIT { | |||
assertThat(dbClient.componentDao().selectByUuid(dbSession, otherBranch.getUuid())).isEmpty(); | |||
assertThat(dbClient.branchDao().selectByUuid(dbSession, otherBranch.getUuid())).isEmpty(); | |||
verify(indexers).commitAndIndexBranches(any(), eq(List.of(otherBranch)), eq(BranchEvent.DELETION)); | |||
verifyNoMoreInteractions(indexers); | |||
} | |||
@Test | |||
@@ -179,6 +184,7 @@ public class ComponentCleanerServiceIT { | |||
assertExists(data1); | |||
assertExists(data2); | |||
assertExists(data3); | |||
verifyNoMoreInteractions(indexers); | |||
} | |||
@Test | |||
@@ -196,8 +202,6 @@ public class ComponentCleanerServiceIT { | |||
ProjectDto projectDto1 = dbClient.projectDao().selectByUuid(dbSession, project1.getUuid()).get(); | |||
ProjectDto projectDto2 = dbClient.projectDao().selectByUuid(dbSession, project2.getUuid()).get(); | |||
mockResourceTypeAsValidProject(); | |||
underTest.delete(dbSession, asList(projectDto1, projectDto2)); | |||
assertThat(db.countRowsOfTable(db.getSession(), "webhooks")).isOne(); | |||
@@ -211,30 +215,15 @@ public class ComponentCleanerServiceIT { | |||
RuleDto rule = db.rules().insert(); | |||
IssueDto issue = db.issues().insert(rule, mainBranch, mainBranch); | |||
SnapshotDto analysis = db.components().insertSnapshot(mainBranch); | |||
mockResourceTypeAsValidProject(); | |||
return new DbData(projectData.getProjectDto(), projectData.getMainBranchDto(), analysis, issue); | |||
} | |||
private void mockResourceTypeAsValidProject() { | |||
ResourceType resourceType = mock(ResourceType.class); | |||
when(resourceType.getBooleanProperty(anyString())).thenReturn(true); | |||
when(mockResourceTypes.get(anyString())).thenReturn(resourceType); | |||
} | |||
private void mockResourceTypeAsNonDeletable() { | |||
ResourceType resourceType = mock(ResourceType.class); | |||
when(resourceType.getBooleanProperty("deletable")).thenReturn(false); | |||
when(mockResourceTypes.get(anyString())).thenReturn(resourceType); | |||
} | |||
private void assertNotExists(DbData data) { | |||
assertDataInDb(data, false); | |||
assertThat(projectIndexers.hasBeenCalled(data.project.getUuid(), PROJECT_DELETION)).isTrue(); | |||
} | |||
private void assertExists(DbData data) { | |||
assertDataInDb(data, true); | |||
assertThat(projectIndexers.hasBeenCalled(data.project.getUuid(), PROJECT_DELETION)).isFalse(); | |||
} | |||
private void assertDataInDb(DbData data, boolean exists) { |
@@ -30,13 +30,12 @@ import org.sonar.api.web.UserRole; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentTesting; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.pushevent.PushEventDto; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.project.ProjectLifeCycleListeners; | |||
import org.sonar.server.tester.UserSessionRule; | |||
@@ -56,7 +55,7 @@ public class ComponentServiceUpdateKeyIT { | |||
private DbClient dbClient = db.getDbClient(); | |||
private DbSession dbSession = db.getSession(); | |||
private TestProjectIndexers projectIndexers = new TestProjectIndexers(); | |||
private TestIndexers projectIndexers = new TestIndexers(); | |||
private ProjectLifeCycleListeners projectLifeCycleListeners = mock(ProjectLifeCycleListeners.class); | |||
private ComponentService underTest = new ComponentService(dbClient, userSession, projectIndexers, projectLifeCycleListeners); | |||
@@ -84,7 +83,7 @@ public class ComponentServiceUpdateKeyIT { | |||
assertThat(dbClient.componentDao().selectByKey(dbSession, inactiveFile.getKey())).isEmpty(); | |||
assertThat(projectIndexers.hasBeenCalled(project.getUuid(), ProjectIndexer.Cause.PROJECT_KEY_UPDATE)).isTrue(); | |||
assertThat(projectIndexers.hasBeenCalledForEntity(project.getUuid(), Indexers.EntityEvent.PROJECT_KEY_UPDATE)).isTrue(); | |||
Deque<PushEventDto> pushEvents = db.getDbClient().pushEventDao().selectChunkByProjectUuids(dbSession, Set.of(project.getUuid()), 0L, "id", 20); | |||
@@ -109,7 +108,7 @@ public class ComponentServiceUpdateKeyIT { | |||
dbSession.commit(); | |||
assertComponentKeyHasBeenUpdated(provisionedProject.getKey(), "provisionedProject2"); | |||
assertThat(projectIndexers.hasBeenCalled(provisionedProject.getUuid(), ProjectIndexer.Cause.PROJECT_KEY_UPDATE)).isTrue(); | |||
assertThat(projectIndexers.hasBeenCalledForEntity(provisionedProject.getUuid(), Indexers.EntityEvent.PROJECT_KEY_UPDATE)).isTrue(); | |||
} | |||
@Test |
@@ -36,14 +36,13 @@ import org.sonar.db.component.BranchType; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.favorite.FavoriteUpdater; | |||
import org.sonar.server.l18n.I18nRule; | |||
import org.sonar.server.permission.PermissionTemplateService; | |||
import org.sonar.server.project.DefaultBranchNameResolver; | |||
import org.sonar.server.project.Project; | |||
import static java.util.stream.IntStream.rangeClosed; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; | |||
@@ -71,7 +70,7 @@ public class ComponentUpdaterIT { | |||
@Rule | |||
public final I18nRule i18n = new I18nRule().put("qualifier.TRK", "Project"); | |||
private final TestProjectIndexers projectIndexers = new TestProjectIndexers(); | |||
private final TestIndexers projectIndexers = new TestIndexers(); | |||
private final PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class); | |||
private final DefaultBranchNameResolver defaultBranchNameResolver = mock(DefaultBranchNameResolver.class); | |||
@@ -108,7 +107,7 @@ public class ComponentUpdaterIT { | |||
assertThat(loaded.getCreatedAt()).isNotNull(); | |||
assertThat(db.getDbClient().componentDao().selectByKey(db.getSession(), DEFAULT_PROJECT_KEY)).isPresent(); | |||
assertThat(projectIndexers.hasBeenCalled(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION)).isTrue(); | |||
assertThat(projectIndexers.hasBeenCalledForEntity(returned.projectDto().getUuid(), Indexers.EntityEvent.CREATION)).isTrue(); | |||
Optional<BranchDto> branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), returned.mainBranchComponent().uuid()); | |||
assertThat(branch).isPresent(); | |||
@@ -134,21 +133,6 @@ public class ComponentUpdaterIT { | |||
assertThat(branch).get().extracting(BranchDto::getBranchKey).isEqualTo("main-branch-global"); | |||
} | |||
@Test | |||
public void create_project_with_main_branch_param() { | |||
String customBranchName = "main-branch-custom"; | |||
NewComponent project = NewComponent.newComponentBuilder() | |||
.setKey(DEFAULT_PROJECT_KEY) | |||
.setName(DEFAULT_PROJECT_NAME) | |||
.setPrivate(true) | |||
.build(); | |||
ComponentDto returned = underTest.create(db.getSession(), project, null, null, customBranchName).mainBranchComponent(); | |||
Optional<BranchDto> branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), returned.branchUuid()); | |||
assertThat(branch).get().extracting(BranchDto::getBranchKey).isEqualTo(customBranchName); | |||
} | |||
@Test | |||
public void persist_private_flag_true_when_creating_project() { | |||
NewComponent project = NewComponent.newComponentBuilder() | |||
@@ -187,7 +171,7 @@ public class ComponentUpdaterIT { | |||
assertThat(loaded.getKey()).isEqualTo("view-key"); | |||
assertThat(loaded.name()).isEqualTo("view-name"); | |||
assertThat(loaded.qualifier()).isEqualTo("VW"); | |||
assertThat(projectIndexers.hasBeenCalled(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION)).isTrue(); | |||
assertThat(projectIndexers.hasBeenCalledForEntity(loaded.uuid(), Indexers.EntityEvent.CREATION)).isTrue(); | |||
Optional<BranchDto> branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), returned.uuid()); | |||
assertThat(branch).isNotPresent(); | |||
} | |||
@@ -202,11 +186,11 @@ public class ComponentUpdaterIT { | |||
ComponentCreationData returned = underTest.create(db.getSession(), application, null, null); | |||
ComponentDto loaded = db.getDbClient().componentDao().selectOrFailByUuid(db.getSession(), returned.mainBranchComponent().uuid()); | |||
ProjectDto loaded = db.getDbClient().projectDao().selectByUuid(db.getSession(), returned.projectDto().getUuid()).get(); | |||
assertThat(loaded.getKey()).isEqualTo("app-key"); | |||
assertThat(loaded.name()).isEqualTo("app-name"); | |||
assertThat(loaded.qualifier()).isEqualTo("APP"); | |||
assertThat(projectIndexers.hasBeenCalled(loaded.uuid(), ProjectIndexer.Cause.PROJECT_CREATION)).isTrue(); | |||
assertThat(loaded.getName()).isEqualTo("app-name"); | |||
assertThat(loaded.getQualifier()).isEqualTo("APP"); | |||
assertThat(projectIndexers.hasBeenCalledForEntity(loaded.getUuid(), Indexers.EntityEvent.CREATION)).isTrue(); | |||
Optional<BranchDto> branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), returned.mainBranchComponent().uuid()); | |||
assertThat(branch).isPresent(); | |||
assertThat(branch.get().getKey()).isEqualTo(DEFAULT_MAIN_BRANCH_NAME); | |||
@@ -398,7 +382,7 @@ public class ComponentUpdaterIT { | |||
public void create_createsComponentWithMasterBranchName() { | |||
String componentNameAndKey = "createApplicationOrPortfolio"; | |||
ComponentDto app = underTest.create(db.getSession(), NewComponent.newComponentBuilder().setName(componentNameAndKey) | |||
.setKey(componentNameAndKey).setQualifier("APP").build(), null, null, null).mainBranchComponent(); | |||
.setKey(componentNameAndKey).setQualifier("APP").build(), null, null).mainBranchComponent(); | |||
Optional<BranchDto> branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), app.branchUuid()); | |||
assertThat(branch).isPresent(); |
@@ -22,7 +22,6 @@ package org.sonar.server.component.ws; | |||
import com.google.common.base.Joiner; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.eclipse.jface.text.projection.ProjectionDocument; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
@@ -36,7 +35,7 @@ import org.sonar.db.component.ResourceTypesRule; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.component.index.ComponentIndex; | |||
import org.sonar.server.component.index.ComponentIndexer; | |||
import org.sonar.server.component.index.EntityDefinitionIndexer; | |||
import org.sonar.server.component.ws.SearchAction.SearchRequest; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.l18n.I18nRule; | |||
@@ -77,7 +76,7 @@ public class SearchActionIT { | |||
private final I18nRule i18n = new I18nRule(); | |||
private final ResourceTypesRule resourceTypes = new ResourceTypesRule(); | |||
private final ComponentIndexer indexer = new ComponentIndexer(db.getDbClient(), es.client()); | |||
private final EntityDefinitionIndexer indexer = new EntityDefinitionIndexer(db.getDbClient(), es.client()); | |||
private final PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, indexer); | |||
private final ComponentIndex index = new ComponentIndex(es.client(), new WebAuthorizationTypeSupport(userSession), System2.INSTANCE); | |||
@@ -1397,7 +1397,7 @@ public class SearchProjectsActionIT { | |||
authorizationIndexerTester.allowOnlyAnyone(r.getResultObject()); | |||
} | |||
}; | |||
db.getDbClient().entityDao().scrollForIndexing(dbSession, null, rh); | |||
db.getDbClient().entityDao().scrollForIndexing(dbSession, rh); | |||
} | |||
private ComponentDto insertPortfolio() { |
@@ -38,7 +38,7 @@ import org.sonar.db.component.ProjectData; | |||
import org.sonar.db.component.ResourceTypesRule; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.component.index.ComponentIndex; | |||
import org.sonar.server.component.index.ComponentIndexer; | |||
import org.sonar.server.component.index.EntityDefinitionIndexer; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.favorite.FavoriteFinder; | |||
import org.sonar.server.permission.index.PermissionIndexerTester; | |||
@@ -89,11 +89,11 @@ public class SuggestionsActionIT { | |||
public final UserSessionRule userSessionRule = UserSessionRule.standalone(); | |||
public final ResourceTypesRule resourceTypes = new ResourceTypesRule(); | |||
private final ComponentIndexer componentIndexer = new ComponentIndexer(db.getDbClient(), es.client()); | |||
private final EntityDefinitionIndexer entityDefinitionIndexer = new EntityDefinitionIndexer(db.getDbClient(), es.client()); | |||
private final FavoriteFinder favoriteFinder = mock(FavoriteFinder.class); | |||
private final ComponentIndex index = new ComponentIndex(es.client(), new WebAuthorizationTypeSupport(userSessionRule), System2.INSTANCE); | |||
private final SuggestionsAction underTest = new SuggestionsAction(db.getDbClient(), index, favoriteFinder, userSessionRule, resourceTypes); | |||
private final PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, componentIndexer); | |||
private final PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, entityDefinitionIndexer); | |||
private final WsActionTester ws = new WsActionTester(underTest); | |||
@Before | |||
@@ -134,7 +134,7 @@ public class SuggestionsActionIT { | |||
public void test_example_json_response() { | |||
ProjectDto project1 = db.components().insertPublicProject(p -> p.setKey("org.sonarsource:sonarqube").setName("SonarSource :: SonarQube")).getProjectDto(); | |||
ProjectDto project2 = db.components().insertPublicProject(p -> p.setKey("org.sonarsource:sonarlint").setName("SonarSource :: SonarLint")).getProjectDto(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(project1); | |||
authorizationIndexerTester.allowOnlyAnyone(project2); | |||
@@ -152,7 +152,7 @@ public class SuggestionsActionIT { | |||
public void suggestions_without_query_should_contain_recently_browsed() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
userSessionRule.addProjectPermission(USER, project); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -177,7 +177,7 @@ public class SuggestionsActionIT { | |||
public void suggestions_without_query_should_contain_recently_browsed_public_project() { | |||
ProjectDto project = db.components().insertPublicProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
.setMethod("POST") | |||
@@ -201,7 +201,7 @@ public class SuggestionsActionIT { | |||
public void suggestions_without_query_should_not_contain_recently_browsed_without_permission() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
.setMethod("POST") | |||
@@ -218,7 +218,7 @@ public class SuggestionsActionIT { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
doReturn(singletonList(project)).when(favoriteFinder).list(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
userSessionRule.addProjectPermission(USER, project); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -243,7 +243,7 @@ public class SuggestionsActionIT { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
doReturn(singletonList(project)).when(favoriteFinder).list(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
.setMethod("POST") | |||
@@ -259,7 +259,7 @@ public class SuggestionsActionIT { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
doReturn(singletonList(project)).when(favoriteFinder).list(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
userSessionRule.addProjectPermission(USER, project); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -284,7 +284,7 @@ public class SuggestionsActionIT { | |||
public void suggestions_without_query_should_not_contain_matches_that_are_neither_favorites_nor_recently_browsed() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
userSessionRule.addProjectPermission(USER, project); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -306,7 +306,7 @@ public class SuggestionsActionIT { | |||
ProjectDto project4 = db.components().insertPrivateProject(p -> p.setName("Delta")).getProjectDto(); | |||
doReturn(asList(project4, project2)).when(favoriteFinder).list(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
userSessionRule.addProjectPermission(USER, project1); | |||
userSessionRule.addProjectPermission(USER, project2); | |||
userSessionRule.addProjectPermission(USER, project3); | |||
@@ -331,7 +331,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void suggestions_without_query_should_return_empty_qualifiers() { | |||
ProjectData project = db.components().insertPrivateProject(); | |||
componentIndexer.indexOnAnalysis(project.getMainBranchDto().getUuid()); | |||
entityDefinitionIndexer.indexOnAnalysis(project.getMainBranchDto().getUuid()); | |||
userSessionRule.addProjectPermission(USER, project.getProjectDto()); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -349,7 +349,7 @@ public class SuggestionsActionIT { | |||
public void suggestions_should_filter_allowed_qualifiers() { | |||
resourceTypes.setAllQualifiers(PROJECT, FILE, UNIT_TEST_FILE); | |||
ProjectData project = db.components().insertPrivateProject(); | |||
componentIndexer.indexOnAnalysis(project.getMainBranchDto().getUuid()); | |||
entityDefinitionIndexer.indexOnAnalysis(project.getMainBranchDto().getUuid()); | |||
userSessionRule.addProjectPermission(USER, project.getProjectDto()); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -366,7 +366,7 @@ public class SuggestionsActionIT { | |||
public void exact_match_in_one_qualifier() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(project); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -391,7 +391,7 @@ public class SuggestionsActionIT { | |||
public void should_not_return_suggestion_on_non_existing_project() { | |||
ProjectDto project = db.components().insertPrivateProject().getProjectDto(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(project); | |||
db.getDbClient().purgeDao().deleteProject(db.getSession(), project.getUuid(), PROJECT, project.getName(), project.getKey()); | |||
@@ -412,7 +412,7 @@ public class SuggestionsActionIT { | |||
public void must_not_search_if_no_valid_tokens_are_provided() { | |||
ProjectDto project = db.components().insertPrivateProject(p -> p.setName("SonarQube")).getProjectDto(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(project); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -438,7 +438,7 @@ public class SuggestionsActionIT { | |||
public void should_warn_about_short_inputs_but_return_results_based_on_other_terms() { | |||
ProjectDto project = db.components().insertPrivateProject(p -> p.setName("SonarQube")).getProjectDto(); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(project); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -456,7 +456,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void should_contain_component_names() { | |||
ProjectData project1 = db.components().insertPrivateProject(p -> p.setName("Project1")); | |||
componentIndexer.indexOnAnalysis(project1.getMainBranchDto().getUuid()); | |||
entityDefinitionIndexer.indexOnAnalysis(project1.getMainBranchDto().getUuid()); | |||
authorizationIndexerTester.allowOnlyAnyone(project1.getProjectDto()); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -476,7 +476,7 @@ public class SuggestionsActionIT { | |||
ComponentDto project = projectData.getMainBranchComponent(); | |||
ComponentDto file1 = newFileDto(project).setName("File1"); | |||
ComponentDto file2 = newFileDto(project).setName("File2"); | |||
componentIndexer.indexOnAnalysis(project.branchUuid()); | |||
entityDefinitionIndexer.indexOnAnalysis(project.branchUuid()); | |||
authorizationIndexerTester.allowOnlyAnyone(projectData.getProjectDto()); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -497,8 +497,8 @@ public class SuggestionsActionIT { | |||
ProjectData nonFavouriteProject = db.components().insertPublicProject(p -> p.setName("Project2")); | |||
doReturn(singletonList(favouriteProject.getProjectDto())).when(favoriteFinder).list(); | |||
componentIndexer.indexOnAnalysis(favouriteProject.getMainBranchDto().getUuid()); | |||
componentIndexer.indexOnAnalysis(nonFavouriteProject.getMainBranchDto().getUuid()); | |||
entityDefinitionIndexer.indexOnAnalysis(favouriteProject.getMainBranchDto().getUuid()); | |||
entityDefinitionIndexer.indexOnAnalysis(nonFavouriteProject.getMainBranchDto().getUuid()); | |||
authorizationIndexerTester.allowOnlyAnyone(favouriteProject.getProjectDto(), nonFavouriteProject.getProjectDto()); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -515,7 +515,7 @@ public class SuggestionsActionIT { | |||
@Test | |||
public void should_return_empty_qualifiers() { | |||
ProjectData project = db.components().insertPrivateProject(); | |||
componentIndexer.indexOnAnalysis(project.getMainBranchComponent().uuid()); | |||
entityDefinitionIndexer.indexOnAnalysis(project.getMainBranchComponent().uuid()); | |||
authorizationIndexerTester.allowOnlyAnyone(project.getProjectDto()); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -541,7 +541,7 @@ public class SuggestionsActionIT { | |||
ComponentDto dir = db.components().insertComponent(ComponentTesting.newDirectory(project, "path").setName(query)); | |||
ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project, dir).setName(query)); | |||
ComponentDto test = db.components().insertComponent(ComponentTesting.newFileDto(project, dir).setName(query).setQualifier(UNIT_TEST_FILE)); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(projectData.getProjectDto()); | |||
authorizationIndexerTester.allowOnlyAnyone(view); | |||
authorizationIndexerTester.allowOnlyAnyone(appData.getProjectDto()); | |||
@@ -565,7 +565,7 @@ public class SuggestionsActionIT { | |||
ComponentDto project = db.components().insertPublicProject().getMainBranchComponent(); | |||
authorizationIndexerTester.allowOnlyAnyone(project); | |||
ComponentDto branch = db.components().insertProjectBranch(project); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
authorizationIndexerTester.allowOnlyAnyone(project); | |||
SuggestionsWsResponse response = ws.newRequest() | |||
@@ -684,7 +684,7 @@ public class SuggestionsActionIT { | |||
.mapToObj(i -> db.components().insertPublicProject(p -> p.setName(namePrefix + i)).getProjectDto()) | |||
.collect(Collectors.toList()); | |||
componentIndexer.indexAll(); | |||
entityDefinitionIndexer.indexAll(); | |||
projects.forEach(authorizationIndexerTester::allowOnlyAnyone); | |||
TestRequest request = ws.newRequest() |
@@ -40,7 +40,7 @@ import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.SnapshotDto; | |||
import org.sonar.db.metric.MetricDto; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.qualitygate.EvaluatedQualityGate; | |||
import org.sonar.server.qualitygate.QualityGate; | |||
import org.sonar.server.qualitygate.changeevent.QGChangeEvent; | |||
@@ -61,7 +61,7 @@ public class LiveMeasureComputerImplIT { | |||
@Rule | |||
public DbTester db = DbTester.create(true); | |||
private final TestProjectIndexers projectIndexer = new TestProjectIndexers(); | |||
private final TestIndexers projectIndexer = new TestIndexers(); | |||
private MetricDto metric1; | |||
private MetricDto metric2; | |||
private ComponentDto project; |
@@ -37,8 +37,8 @@ import org.sonar.db.portfolio.PortfolioDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.GroupDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.es.ProjectIndexers; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.TemplateMatchingKeyException; | |||
import org.sonar.server.tester.UserSessionRule; | |||
@@ -60,8 +60,8 @@ public class PermissionTemplateServiceIT { | |||
private final UserSessionRule userSession = UserSessionRule.standalone(); | |||
private final PermissionTemplateDbTester templateDb = dbTester.permissionTemplates(); | |||
private final DbSession session = dbTester.getSession(); | |||
private final ProjectIndexers projectIndexers = new TestProjectIndexers(); | |||
private final PermissionTemplateService underTest = new PermissionTemplateService(dbTester.getDbClient(), projectIndexers, userSession, defaultTemplatesResolver, | |||
private final Indexers indexers = new TestIndexers(); | |||
private final PermissionTemplateService underTest = new PermissionTemplateService(dbTester.getDbClient(), indexers, userSession, defaultTemplatesResolver, | |||
new SequenceUuidFactory()); | |||
@Test |
@@ -31,7 +31,7 @@ import org.sonar.db.component.ResourceTypesRule; | |||
import org.sonar.db.permission.template.PermissionTemplateDto; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.es.ProjectIndexersImpl; | |||
import org.sonar.server.es.IndexersImpl; | |||
import org.sonar.server.permission.GroupPermissionChanger; | |||
import org.sonar.server.permission.PermissionUpdater; | |||
import org.sonar.server.permission.UserPermissionChanger; | |||
@@ -82,7 +82,7 @@ public abstract class BasePermissionWsIT<A extends PermissionsWsAction> { | |||
protected PermissionUpdater newPermissionUpdater() { | |||
return new PermissionUpdater( | |||
new ProjectIndexersImpl(new PermissionIndexer(db.getDbClient(), es.client())), | |||
new IndexersImpl(new PermissionIndexer(db.getDbClient(), es.client())), | |||
new UserPermissionChanger(db.getDbClient(), new SequenceUuidFactory()), | |||
new GroupPermissionChanger(db.getDbClient(), new SequenceUuidFactory())); | |||
} |
@@ -34,7 +34,7 @@ import org.sonar.db.permission.template.PermissionTemplateDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.GroupDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
@@ -70,7 +70,7 @@ public class ApplyTemplateActionIT extends BasePermissionWsIT<ApplyTemplateActio | |||
private final ResourceTypesRule resourceTypesRule = new ResourceTypesRule().setRootQualifiers(PROJECT, VIEW, APP); | |||
private final DefaultTemplatesResolver defaultTemplatesResolver = new DefaultTemplatesResolverImpl(dbTester.getDbClient(), resourceTypesRule); | |||
private final PermissionTemplateService permissionTemplateService = new PermissionTemplateService(db.getDbClient(), | |||
new TestProjectIndexers(), userSession, defaultTemplatesResolver, new SequenceUuidFactory()); | |||
new TestIndexers(), userSession, defaultTemplatesResolver, new SequenceUuidFactory()); | |||
@Override | |||
protected ApplyTemplateAction buildWsAction() { |
@@ -39,8 +39,8 @@ import org.sonar.db.portfolio.PortfolioDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.GroupDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.es.ProjectIndexers; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
import org.sonar.server.l18n.I18nRule; | |||
@@ -71,14 +71,14 @@ public class BulkApplyTemplateActionIT extends BasePermissionWsIT<BulkApplyTempl | |||
private GroupDto group1; | |||
private GroupDto group2; | |||
private PermissionTemplateDto template1; | |||
private final ProjectIndexers projectIndexers = new TestProjectIndexers(); | |||
private final Indexers indexers = new TestIndexers(); | |||
private final ResourceTypesRule resourceTypesRule = new ResourceTypesRule().setRootQualifiers(PROJECT, VIEW, APP); | |||
private final DefaultTemplatesResolver defaultTemplatesResolver = new DefaultTemplatesResolverImpl(db.getDbClient(), resourceTypesRule); | |||
@Override | |||
protected BulkApplyTemplateAction buildWsAction() { | |||
PermissionTemplateService permissionTemplateService = new PermissionTemplateService(db.getDbClient(), | |||
projectIndexers, userSession, defaultTemplatesResolver, new SequenceUuidFactory()); | |||
indexers, userSession, defaultTemplatesResolver, new SequenceUuidFactory()); | |||
return new BulkApplyTemplateAction(db.getDbClient(), userSession, permissionTemplateService, newPermissionWsSupport(), new I18nRule(), newRootResourceTypes()); | |||
} | |||
@@ -238,7 +238,7 @@ public class BulkDeleteActionIT { | |||
.setParam("projects", StringUtils.join(keys, ",")) | |||
.execute(); | |||
verify(componentCleanerService, times(1_000)).delete(any(DbSession.class), any(EntityDto.class)); | |||
verify(componentCleanerService, times(1_000)).deleteEntity(any(DbSession.class), any(EntityDto.class)); | |||
ArgumentCaptor<Set<Project>> projectsCaptor = ArgumentCaptor.forClass(Set.class); | |||
verify(projectLifeCycleListeners).onProjectsDeleted(projectsCaptor.capture()); | |||
assertThat(projectsCaptor.getValue()).hasSize(1_000); | |||
@@ -255,7 +255,7 @@ public class BulkDeleteActionIT { | |||
doNothing() | |||
.doThrow(expectedException) | |||
.when(componentCleanerService) | |||
.delete(any(), any(ProjectDto.class)); | |||
.deleteEntity(any(), any(ProjectDto.class)); | |||
try { | |||
ws.newRequest() | |||
@@ -314,7 +314,7 @@ public class BulkDeleteActionIT { | |||
private void verifyEntityDeleted(EntityDto... entities) { | |||
ArgumentCaptor<EntityDto> argument = ArgumentCaptor.forClass(EntityDto.class); | |||
verify(componentCleanerService, times(entities.length)).delete(any(DbSession.class), argument.capture()); | |||
verify(componentCleanerService, times(entities.length)).deleteEntity(any(DbSession.class), argument.capture()); | |||
for (EntityDto entity : entities) { | |||
assertThat(argument.getAllValues()).extracting(EntityDto::getUuid).contains(entity.getUuid()); |
@@ -38,7 +38,8 @@ import org.sonar.db.newcodeperiod.NewCodePeriodDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.favorite.FavoriteUpdater; | |||
@@ -96,12 +97,12 @@ public class CreateActionIT { | |||
private final DefaultBranchNameResolver defaultBranchNameResolver = mock(DefaultBranchNameResolver.class); | |||
private final ProjectDefaultVisibility projectDefaultVisibility = mock(ProjectDefaultVisibility.class); | |||
private final TestProjectIndexers projectIndexers = new TestProjectIndexers(); | |||
private final TestIndexers projectIndexers = new TestIndexers(); | |||
private final PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class); | |||
private PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class); | |||
private final PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class); | |||
private NewCodeDefinitionResolver newCodeDefinitionResolver = new NewCodeDefinitionResolver(db.getDbClient(), editionProvider); | |||
private final NewCodeDefinitionResolver newCodeDefinitionResolver = new NewCodeDefinitionResolver(db.getDbClient(), editionProvider); | |||
private final WsActionTester ws = new WsActionTester( | |||
new CreateAction( | |||
db.getDbClient(), userSession, | |||
@@ -133,9 +134,11 @@ public class CreateActionIT { | |||
.extracting(ComponentDto::getKey, ComponentDto::name, ComponentDto::qualifier, ComponentDto::scope, ComponentDto::isPrivate) | |||
.containsOnly(DEFAULT_PROJECT_KEY, DEFAULT_PROJECT_NAME, "TRK", "PRJ", false); | |||
assertThat(db.getDbClient().branchDao().selectByUuid(db.getSession(), component.branchUuid()).get()) | |||
BranchDto branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), component.branchUuid()).get(); | |||
assertThat(branch) | |||
.extracting(BranchDto::getKey) | |||
.isEqualTo(MAIN_BRANCH); | |||
projectIndexers.hasBeenCalledForEntity(branch.getProjectUuid(), Indexers.EntityEvent.CREATION); | |||
} | |||
@Test |
@@ -20,18 +20,14 @@ | |||
package org.sonar.server.project.ws; | |||
import java.util.List; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.mockito.ArgumentCaptor; | |||
import org.sonar.api.resources.ResourceType; | |||
import org.sonar.api.resources.ResourceTypes; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.web.UserRole; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.component.ComponentDbTester; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ProjectData; | |||
import org.sonar.db.permission.GlobalPermission; | |||
@@ -40,7 +36,7 @@ import org.sonar.db.user.UserDto; | |||
import org.sonar.db.webhook.WebhookDbTester; | |||
import org.sonar.db.webhook.WebhookDto; | |||
import org.sonar.server.component.ComponentCleanerService; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.UnauthorizedException; | |||
import org.sonar.server.project.Project; | |||
@@ -54,10 +50,8 @@ import static java.util.Collections.singleton; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | |||
import static org.mockito.ArgumentMatchers.any; | |||
import static org.mockito.ArgumentMatchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.db.user.UserTesting.newUserDto; | |||
import static org.sonar.server.component.TestComponentFinder.from; | |||
import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECT; | |||
@@ -75,7 +69,6 @@ public class DeleteActionIT { | |||
private final WebhookDbTester webhookDbTester = db.webhooks(); | |||
private final ComponentCleanerService componentCleanerService = mock(ComponentCleanerService.class); | |||
private final ProjectLifeCycleListeners projectLifeCycleListeners = mock(ProjectLifeCycleListeners.class); | |||
private final ResourceTypes mockResourceTypes = mock(ResourceTypes.class); | |||
private final DeleteAction underTest = new DeleteAction( | |||
componentCleanerService, | |||
@@ -84,17 +77,6 @@ public class DeleteActionIT { | |||
userSessionRule, projectLifeCycleListeners); | |||
private final WsActionTester tester = new WsActionTester(underTest); | |||
@Before | |||
public void before() { | |||
mockResourceTypeAsValidProject(); | |||
} | |||
private void mockResourceTypeAsValidProject() { | |||
ResourceType resourceType = mock(ResourceType.class); | |||
when(resourceType.getBooleanProperty(anyString())).thenReturn(true); | |||
when(mockResourceTypes.get(anyString())).thenReturn(resourceType); | |||
} | |||
@Test | |||
public void global_administrator_deletes_project_by_key() { | |||
ProjectData projectData = db.components().insertPrivateProject(); | |||
@@ -128,7 +110,7 @@ public class DeleteActionIT { | |||
dbSession.commit(); | |||
userSessionRule.logIn().addProjectPermission(UserRole.ADMIN, projectData.getProjectDto()); | |||
DeleteAction underTest = new DeleteAction( | |||
new ComponentCleanerService(dbClient, mockResourceTypes, new TestProjectIndexers()), | |||
new ComponentCleanerService(dbClient, new TestIndexers()), | |||
from(db), dbClient, userSessionRule, projectLifeCycleListeners); | |||
new WsActionTester(underTest) | |||
@@ -151,7 +133,7 @@ public class DeleteActionIT { | |||
userSessionRule.logIn().addProjectPermission(UserRole.ADMIN, project); | |||
DeleteAction underTest = new DeleteAction( | |||
new ComponentCleanerService(dbClient, mockResourceTypes, new TestProjectIndexers()), | |||
new ComponentCleanerService(dbClient, new TestIndexers()), | |||
from(db), dbClient, userSessionRule, projectLifeCycleListeners); | |||
new WsActionTester(underTest) | |||
@@ -190,7 +172,7 @@ public class DeleteActionIT { | |||
private String verifyDeletedKey() { | |||
ArgumentCaptor<ProjectDto> argument = ArgumentCaptor.forClass(ProjectDto.class); | |||
verify(componentCleanerService).delete(any(DbSession.class), argument.capture()); | |||
verify(componentCleanerService).deleteEntity(any(DbSession.class), argument.capture()); | |||
return argument.getValue().getKey(); | |||
} | |||
@@ -34,8 +34,8 @@ import org.sonar.db.component.ProjectData; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.component.ComponentService; | |||
import org.sonar.server.es.ProjectIndexers; | |||
import org.sonar.server.es.ProjectIndexersImpl; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.IndexersImpl; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
import org.sonar.server.project.ProjectLifeCycleListenersImpl; | |||
@@ -56,8 +56,8 @@ public class UpdateKeyActionIT { | |||
@Rule | |||
public final UserSessionRule userSessionRule = UserSessionRule.standalone(); | |||
private final DbClient dbClient = db.getDbClient(); | |||
private final ProjectIndexers projectIndexers = new ProjectIndexersImpl(); | |||
private final ComponentService componentService = new ComponentService(dbClient, userSessionRule, projectIndexers, new ProjectLifeCycleListenersImpl()); | |||
private final Indexers indexers = new IndexersImpl(); | |||
private final ComponentService componentService = new ComponentService(dbClient, userSessionRule, indexers, new ProjectLifeCycleListenersImpl()); | |||
private final ComponentFinder componentFinder = new ComponentFinder(dbClient, null); | |||
private final WsActionTester ws = new WsActionTester(new UpdateKeyAction(dbClient, componentService, componentFinder)); | |||
@@ -54,8 +54,8 @@ import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.GroupDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.server.es.EsTester; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.UnauthorizedException; | |||
@@ -101,7 +101,7 @@ public class UpdateVisibilityActionIT { | |||
private final DbClient dbClient = dbTester.getDbClient(); | |||
private final DbSession dbSession = dbTester.getSession(); | |||
private final TestProjectIndexers projectIndexers = new TestProjectIndexers(); | |||
private final TestIndexers projectIndexers = new TestIndexers(); | |||
private final Configuration configuration = mock(Configuration.class); | |||
private final UpdateVisibilityAction underTest = new UpdateVisibilityAction(dbClient, userSessionRule, projectIndexers, new SequenceUuidFactory(), configuration); | |||
@@ -423,7 +423,7 @@ public class UpdateVisibilityActionIT { | |||
.setParam(PARAM_VISIBILITY, initiallyPrivate ? PUBLIC : PRIVATE) | |||
.execute(); | |||
assertThat(projectIndexers.hasBeenCalled(project.projectUuid(), ProjectIndexer.Cause.PERMISSION_CHANGE)).isTrue(); | |||
assertThat(projectIndexers.hasBeenCalledForEntity(project.projectUuid(), Indexers.EntityEvent.PERMISSION_CHANGE)).isTrue(); | |||
} | |||
@Test | |||
@@ -436,7 +436,7 @@ public class UpdateVisibilityActionIT { | |||
.setParam(PARAM_VISIBILITY, initiallyPrivate ? PRIVATE : PUBLIC) | |||
.execute(); | |||
assertThat(projectIndexers.hasBeenCalled(project.projectUuid())).isFalse(); | |||
assertThat(projectIndexers.hasBeenCalledForEntity(project.projectUuid())).isFalse(); | |||
} | |||
@Test |
@@ -32,7 +32,7 @@ import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ProjectData; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.component.TestComponentFinder; | |||
import org.sonar.server.es.TestProjectIndexers; | |||
import org.sonar.server.es.TestIndexers; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.exceptions.NotFoundException; | |||
@@ -48,7 +48,9 @@ import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | |||
import static org.sonar.api.web.UserRole.ADMIN; | |||
import static org.sonar.api.web.UserRole.USER; | |||
import static org.sonar.db.component.ComponentDbTester.defaults; | |||
import static org.sonar.db.component.ComponentTesting.newFileDto; | |||
import static org.sonar.server.es.Indexers.EntityEvent.PROJECT_TAGS_UPDATE; | |||
public class SetActionIT { | |||
@Rule | |||
@@ -58,8 +60,8 @@ public class SetActionIT { | |||
private final DbClient dbClient = db.getDbClient(); | |||
private final DbSession dbSession = db.getSession(); | |||
private final TestProjectIndexers projectIndexers = new TestProjectIndexers(); | |||
private final TagsWsSupport tagsWsSupport = new TagsWsSupport(dbClient, TestComponentFinder.from(db), userSession, projectIndexers, System2.INSTANCE); | |||
private final TestIndexers indexers = new TestIndexers(); | |||
private final TagsWsSupport tagsWsSupport = new TagsWsSupport(dbClient, TestComponentFinder.from(db), userSession, indexers, System2.INSTANCE); | |||
private final WsActionTester ws = new WsActionTester(new SetAction(dbClient, tagsWsSupport)); | |||
private ProjectDto project; | |||
private ComponentDto projectComponent; | |||
@@ -77,15 +79,13 @@ public class SetActionIT { | |||
TestResponse response = call(project.getKey(), "finance , offshore, platform, ,"); | |||
assertTags(project.getKey(), "finance", "offshore", "platform"); | |||
// FIXME verify(indexer).indexProject(project.uuid(), PROJECT_TAGS_UPDATE); | |||
indexers.hasBeenCalledForEntity(project.getUuid(), PROJECT_TAGS_UPDATE); | |||
assertThat(response.getStatus()).isEqualTo(HTTP_NO_CONTENT); | |||
} | |||
@Test | |||
public void reset_tags() { | |||
project = db.components().insertPrivateProject(c -> { | |||
}, p -> p.setTagsString("platform,scanner")).getProjectDto(); | |||
project = db.components().insertPrivateProject(defaults(), p -> p.setTagsString("platform,scanner")).getProjectDto(); | |||
userSession.addProjectPermission(ADMIN, project); | |||
call(project.getKey(), ""); | |||
@@ -95,8 +95,7 @@ public class SetActionIT { | |||
@Test | |||
public void override_existing_tags() { | |||
project = db.components().insertPrivateProject(c -> { | |||
}, p -> p.setTagsString("marketing,languages")).getProjectDto(); | |||
project = db.components().insertPrivateProject(defaults(), p -> p.setTagsString("marketing,languages")).getProjectDto(); | |||
userSession.addProjectPermission(ADMIN, project); | |||
call(project.getKey(), "finance,offshore,platform"); | |||
@@ -111,6 +110,7 @@ public class SetActionIT { | |||
call(project.getKey(), "platform, lambda"); | |||
assertTags(project.getKey(), "platform", "lambda"); | |||
indexers.hasBeenCalledForEntity(project.getUuid(), PROJECT_TAGS_UPDATE); | |||
} | |||
@Test |
@@ -156,7 +156,7 @@ public class ImportAzureProjectAction implements AlmIntegrationsWsAction { | |||
newCodeDefinitionType, newCodeDefinitionValue); | |||
} | |||
componentUpdater.commitAndIndex(dbSession, componentCreationData.mainBranchComponent()); | |||
componentUpdater.commitAndIndex(dbSession, componentCreationData); | |||
return toCreateResponse(projectDto); | |||
} | |||
@@ -180,9 +180,7 @@ public class ImportAzureProjectAction implements AlmIntegrationsWsAction { | |||
.build(), | |||
userSession.isLoggedIn() ? userSession.getUuid() : null, | |||
userSession.isLoggedIn() ? userSession.getLogin() : null, | |||
repo.getDefaultBranchName(), | |||
s -> { | |||
}); | |||
repo.getDefaultBranchName()); | |||
} | |||
private void populatePRSetting(DbSession dbSession, GsonAzureRepo repo, ProjectDto projectDto, AlmSettingDto almSettingDto) { |
@@ -153,7 +153,7 @@ public class ImportBitbucketCloudRepoAction implements AlmIntegrationsWsAction { | |||
newCodeDefinitionType, newCodeDefinitionValue); | |||
} | |||
componentUpdater.commitAndIndex(dbSession, componentCreationData.mainBranchComponent()); | |||
componentUpdater.commitAndIndex(dbSession, componentCreationData); | |||
return toCreateResponse(projectDto); | |||
} | |||
@@ -180,8 +180,7 @@ public class ImportBitbucketCloudRepoAction implements AlmIntegrationsWsAction { | |||
String userUuid = userSession.isLoggedIn() ? userSession.getUuid() : null; | |||
String userLogin = userSession.isLoggedIn() ? userSession.getLogin() : null; | |||
return componentUpdater.createWithoutCommit(dbSession, mainBranch, userUuid, userLogin, defaultBranchName, p -> { | |||
}); | |||
return componentUpdater.createWithoutCommit(dbSession, mainBranch, userUuid, userLogin, defaultBranchName); | |||
} | |||
private void populatePRSetting(DbSession dbSession, Repository repo, ProjectDto projectDto, AlmSettingDto almSettingDto) { |
@@ -165,7 +165,7 @@ public class ImportBitbucketServerProjectAction implements AlmIntegrationsWsActi | |||
newCodeDefinitionType, newCodeDefinitionValue); | |||
} | |||
componentUpdater.commitAndIndex(dbSession, componentCreationData.mainBranchComponent()); | |||
componentUpdater.commitAndIndex(dbSession, componentCreationData); | |||
return toCreateResponse(projectDto); | |||
} | |||
@@ -198,8 +198,7 @@ public class ImportBitbucketServerProjectAction implements AlmIntegrationsWsActi | |||
String userUuid = userSession.isLoggedIn() ? userSession.getUuid() : null; | |||
String userLogin = userSession.isLoggedIn() ? userSession.getLogin() : null; | |||
return componentUpdater.createWithoutCommit(dbSession, newProject, userUuid, userLogin, defaultBranchName, p -> { | |||
}); | |||
return componentUpdater.createWithoutCommit(dbSession, newProject, userUuid, userLogin, defaultBranchName); | |||
} | |||
private void populatePRSetting(DbSession dbSession, Repository repo, ProjectDto componentDto, AlmSettingDto almSettingDto) { |
@@ -164,7 +164,7 @@ public class ImportGithubProjectAction implements AlmIntegrationsWsAction { | |||
newCodeDefinitionType, newCodeDefinitionValue); | |||
} | |||
componentUpdater.commitAndIndex(dbSession, componentCreationData.mainBranchComponent()); | |||
componentUpdater.commitAndIndex(dbSession, componentCreationData); | |||
return toCreateResponse(projectDto); | |||
} | |||
@@ -187,8 +187,7 @@ public class ImportGithubProjectAction implements AlmIntegrationsWsAction { | |||
.setPrivate(visibility) | |||
.setQualifier(PROJECT) | |||
.build(), | |||
userSession.getUuid(), userSession.getLogin(), mainBranchName, s -> { | |||
}); | |||
userSession.getUuid(), userSession.getLogin(), mainBranchName); | |||
} | |||
private void populatePRSetting(DbSession dbSession, Repository repo, ProjectDto projectDto, AlmSettingDto almSettingDto) { |
@@ -144,7 +144,7 @@ public class ImportGitLabProjectAction implements AlmIntegrationsWsAction { | |||
newCodeDefinitionType, newCodeDefinitionValue); | |||
} | |||
componentUpdater.commitAndIndex(dbSession, componentCreationData.mainBranchComponent()); | |||
componentUpdater.commitAndIndex(dbSession, componentCreationData); | |||
return ImportHelper.toCreateResponse(projectDto); | |||
} | |||
@@ -183,8 +183,7 @@ public class ImportGitLabProjectAction implements AlmIntegrationsWsAction { | |||
.setPrivate(visibility) | |||
.setQualifier(PROJECT) | |||
.build(), | |||
userSession.getUuid(), userSession.getLogin(), mainBranchName, s -> { | |||
}); | |||
userSession.getUuid(), userSession.getLogin(), mainBranchName); | |||
} | |||
} |
@@ -38,6 +38,7 @@ import org.sonar.db.ce.CeTaskTypes; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.permission.GlobalPermission; | |||
import org.sonar.server.component.ComponentCreationData; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.component.NewComponent; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
@@ -75,7 +76,7 @@ public class ReportSubmitter { | |||
public CeTask submit(String projectKey, @Nullable String projectName, Map<String, String> characteristics, InputStream reportInput) { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
boolean projectCreated = false; | |||
ComponentCreationData componentCreationData = null; | |||
// Note: when the main branch is analyzed, the characteristics may or may not have the branch name, so componentKey#isMainBranch is not | |||
// reliable! | |||
BranchSupport.ComponentKey componentKey = branchSupport.createComponentKey(projectKey, characteristics); | |||
@@ -86,8 +87,8 @@ public class ReportSubmitter { | |||
mainBranchComponent = mainBranchComponentOpt.get(); | |||
validateProject(dbSession, mainBranchComponent, projectKey); | |||
} else { | |||
mainBranchComponent = createProject(dbSession, componentKey.getKey(), projectName); | |||
projectCreated = true; | |||
componentCreationData = createProject(dbSession, componentKey.getKey(), projectName); | |||
mainBranchComponent = componentCreationData.mainBranchComponent(); | |||
} | |||
BranchDto mainBranch = dbClient.branchDao().selectByUuid(dbSession, mainBranchComponent.branchUuid()) | |||
@@ -103,8 +104,8 @@ public class ReportSubmitter { | |||
.orElseGet(() -> branchSupport.createBranchComponent(dbSession, componentKey, mainBranchComponent, mainBranch)); | |||
} | |||
if (projectCreated) { | |||
componentUpdater.commitAndIndex(dbSession, mainBranchComponent); | |||
if (componentCreationData != null) { | |||
componentUpdater.commitAndIndex(dbSession, componentCreationData); | |||
} else { | |||
dbSession.commit(); | |||
} | |||
@@ -151,7 +152,7 @@ public class ReportSubmitter { | |||
} | |||
} | |||
private ComponentDto createProject(DbSession dbSession, String projectKey, @Nullable String projectName) { | |||
private ComponentCreationData createProject(DbSession dbSession, String projectKey, @Nullable String projectName) { | |||
userSession.checkPermission(GlobalPermission.PROVISION_PROJECTS); | |||
String userUuid = userSession.getUuid(); | |||
String userName = userSession.getLogin(); | |||
@@ -167,8 +168,7 @@ public class ReportSubmitter { | |||
.setQualifier(Qualifiers.PROJECT) | |||
.setPrivate(getDefaultVisibility(dbSession).isPrivate()) | |||
.build(); | |||
return componentUpdater.createWithoutCommit(dbSession, newProject, userUuid, userName, c -> { | |||
}).mainBranchComponent(); | |||
return componentUpdater.createWithoutCommit(dbSession, newProject, userUuid, userName); | |||
} | |||
private Visibility getDefaultVisibility(DbSession dbSession) { |
@@ -21,36 +21,33 @@ package org.sonar.server.component; | |||
import java.util.List; | |||
import org.sonar.api.resources.Qualifiers; | |||
import org.sonar.api.resources.ResourceType; | |||
import org.sonar.api.resources.ResourceTypes; | |||
import org.sonar.api.server.ServerSide; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.es.ProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.es.Indexers.BranchEvent; | |||
import org.sonar.server.es.Indexers.EntityEvent; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static java.util.Collections.singletonList; | |||
import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_DELETION; | |||
@ServerSide | |||
public class ComponentCleanerService { | |||
private final DbClient dbClient; | |||
private final ResourceTypes resourceTypes; | |||
private final ProjectIndexers projectIndexers; | |||
private final Indexers indexers; | |||
public ComponentCleanerService(DbClient dbClient, ResourceTypes resourceTypes, ProjectIndexers projectIndexers) { | |||
public ComponentCleanerService(DbClient dbClient, Indexers indexers) { | |||
this.dbClient = dbClient; | |||
this.resourceTypes = resourceTypes; | |||
this.projectIndexers = projectIndexers; | |||
this.indexers = indexers; | |||
} | |||
public void delete(DbSession dbSession, List<ProjectDto> projects) { | |||
for (ProjectDto project : projects) { | |||
delete(dbSession, project); | |||
deleteEntity(dbSession, project); | |||
} | |||
} | |||
@@ -59,23 +56,17 @@ public class ComponentCleanerService { | |||
throw new IllegalArgumentException("Only non-main branches can be deleted"); | |||
} | |||
dbClient.purgeDao().deleteBranch(dbSession, branch.getUuid()); | |||
projectIndexers.commitAndIndexBranches(dbSession, singletonList(branch), PROJECT_DELETION); | |||
indexers.commitAndIndexBranches(dbSession, singletonList(branch), BranchEvent.DELETION); | |||
} | |||
public void delete(DbSession dbSession, EntityDto entity) { | |||
checkArgument(isDeletable(entity), "Only projects can be deleted"); | |||
public void deleteEntity(DbSession dbSession, EntityDto entity) { | |||
checkArgument(!entity.getQualifier().equals(Qualifiers.SUBVIEW), "Qualifier can't be subview"); | |||
dbClient.purgeDao().deleteProject(dbSession, entity.getUuid(), entity.getQualifier(), entity.getName(), entity.getKey()); | |||
dbClient.userDao().cleanHomepage(dbSession, entity); | |||
if (Qualifiers.PROJECT.equals(entity.getQualifier())) { | |||
dbClient.userTokenDao().deleteByProjectUuid(dbSession, entity.getKey(), entity.getUuid()); | |||
} | |||
projectIndexers.commitAndIndexEntities(dbSession, singletonList(entity), PROJECT_DELETION); | |||
} | |||
private boolean isDeletable(EntityDto entityDto) { | |||
ResourceType resourceType = resourceTypes.get(entityDto.getQualifier()); | |||
// this essentially means PROJECTS, VIEWS and APPS (not SUBVIEWS) | |||
return resourceType != null && resourceType.getBooleanProperty("deletable"); | |||
// Note that we do not send an event for each individual branch being deleted with the project | |||
indexers.commitAndIndexEntities(dbSession, singletonList(entity), EntityEvent.DELETION); | |||
} | |||
} |
@@ -22,8 +22,9 @@ package org.sonar.server.component; | |||
import javax.annotation.Nullable; | |||
import org.sonar.db.component.BranchDto; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.portfolio.PortfolioDto; | |||
import org.sonar.db.project.ProjectDto; | |||
public record ComponentCreationData(ComponentDto mainBranchComponent, @Nullable BranchDto mainBranchDto, | |||
public record ComponentCreationData(ComponentDto mainBranchComponent, @Nullable PortfolioDto portfolioDto, @Nullable BranchDto mainBranchDto, | |||
@Nullable ProjectDto projectDto) { | |||
} |
@@ -27,8 +27,8 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.pushevent.PushEventDto; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.ProjectIndexers; | |||
import org.sonar.server.es.EventIndexer; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.project.Project; | |||
import org.sonar.server.project.ProjectLifeCycleListeners; | |||
import org.sonar.server.project.RekeyedProject; | |||
@@ -45,13 +45,13 @@ public class ComponentService { | |||
private final DbClient dbClient; | |||
private final UserSession userSession; | |||
private final ProjectIndexers projectIndexers; | |||
private final Indexers indexers; | |||
private final ProjectLifeCycleListeners projectLifeCycleListeners; | |||
public ComponentService(DbClient dbClient, UserSession userSession, ProjectIndexers projectIndexers, ProjectLifeCycleListeners projectLifeCycleListeners) { | |||
public ComponentService(DbClient dbClient, UserSession userSession, Indexers indexers, ProjectLifeCycleListeners projectLifeCycleListeners) { | |||
this.dbClient = dbClient; | |||
this.userSession = userSession; | |||
this.projectIndexers = projectIndexers; | |||
this.indexers = indexers; | |||
this.projectLifeCycleListeners = projectLifeCycleListeners; | |||
} | |||
@@ -59,7 +59,7 @@ public class ComponentService { | |||
userSession.checkEntityPermission(UserRole.ADMIN, project); | |||
checkProjectKey(newKey); | |||
dbClient.componentKeyUpdaterDao().updateKey(dbSession, project.getUuid(), project.getKey(), newKey); | |||
projectIndexers.commitAndIndexProjects(dbSession, singletonList(project), ProjectIndexer.Cause.PROJECT_KEY_UPDATE); | |||
indexers.commitAndIndexEntities(dbSession, singletonList(project), Indexers.EntityEvent.PROJECT_KEY_UPDATE); | |||
Project newProject = new Project(project.getUuid(), newKey, project.getName(), project.getDescription(), project.getTags()); | |||
projectLifeCycleListeners.onProjectsRekeyed(singleton(new RekeyedProject(newProject, project.getKey()))); | |||
persistEvent(project, newKey); |
@@ -25,7 +25,6 @@ import java.util.List; | |||
import java.util.Locale; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
import java.util.function.Consumer; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.resources.Qualifiers; | |||
@@ -41,8 +40,7 @@ import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.portfolio.PortfolioDto; | |||
import org.sonar.db.portfolio.PortfolioDto.SelectionMode; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.es.ProjectIndexer.Cause; | |||
import org.sonar.server.es.ProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.favorite.FavoriteUpdater; | |||
import org.sonar.server.permission.PermissionTemplateService; | |||
import org.sonar.server.project.DefaultBranchNameResolver; | |||
@@ -56,7 +54,7 @@ import static org.sonar.server.exceptions.BadRequestException.throwBadRequestExc | |||
public class ComponentUpdater { | |||
private static final Set<String> MAIN_BRANCH_QUALIFIERS = Set.of(Qualifiers.PROJECT, Qualifiers.APP); | |||
private static final Set<String> PROJ_APP_QUALIFIERS = Set.of(Qualifiers.PROJECT, Qualifiers.APP); | |||
private static final String KEY_ALREADY_EXISTS_ERROR = "Could not create %s with key: \"%s\". A similar key already exists: \"%s\""; | |||
private static final String MALFORMED_KEY_ERROR = "Malformed key for %s: '%s'. %s."; | |||
private final DbClient dbClient; | |||
@@ -64,7 +62,7 @@ public class ComponentUpdater { | |||
private final System2 system2; | |||
private final PermissionTemplateService permissionTemplateService; | |||
private final FavoriteUpdater favoriteUpdater; | |||
private final ProjectIndexers projectIndexers; | |||
private final Indexers indexers; | |||
private final UuidFactory uuidFactory; | |||
private final DefaultBranchNameResolver defaultBranchNameResolver; | |||
private final boolean useDifferentUuids; | |||
@@ -72,21 +70,21 @@ public class ComponentUpdater { | |||
@Autowired | |||
public ComponentUpdater(DbClient dbClient, I18n i18n, System2 system2, | |||
PermissionTemplateService permissionTemplateService, FavoriteUpdater favoriteUpdater, | |||
ProjectIndexers projectIndexers, UuidFactory uuidFactory, DefaultBranchNameResolver defaultBranchNameResolver) { | |||
this(dbClient, i18n, system2, permissionTemplateService, favoriteUpdater, projectIndexers, uuidFactory, defaultBranchNameResolver, false); | |||
Indexers indexers, UuidFactory uuidFactory, DefaultBranchNameResolver defaultBranchNameResolver) { | |||
this(dbClient, i18n, system2, permissionTemplateService, favoriteUpdater, indexers, uuidFactory, defaultBranchNameResolver, false); | |||
} | |||
@VisibleForTesting | |||
public ComponentUpdater(DbClient dbClient, I18n i18n, System2 system2, | |||
PermissionTemplateService permissionTemplateService, FavoriteUpdater favoriteUpdater, | |||
ProjectIndexers projectIndexers, UuidFactory uuidFactory, DefaultBranchNameResolver defaultBranchNameResolver, | |||
Indexers indexers, UuidFactory uuidFactory, DefaultBranchNameResolver defaultBranchNameResolver, | |||
boolean useDifferentUuids) { | |||
this.dbClient = dbClient; | |||
this.i18n = i18n; | |||
this.system2 = system2; | |||
this.permissionTemplateService = permissionTemplateService; | |||
this.favoriteUpdater = favoriteUpdater; | |||
this.projectIndexers = projectIndexers; | |||
this.indexers = indexers; | |||
this.uuidFactory = uuidFactory; | |||
this.defaultBranchNameResolver = defaultBranchNameResolver; | |||
this.useDifferentUuids = useDifferentUuids; | |||
@@ -99,19 +97,17 @@ public class ComponentUpdater { | |||
* - Index component in es indexes | |||
*/ | |||
public ComponentCreationData create(DbSession dbSession, NewComponent newComponent, @Nullable String userUuid, @Nullable String userLogin) { | |||
return create(dbSession, newComponent, userUuid, userLogin, null); | |||
} | |||
public ComponentCreationData create(DbSession dbSession, NewComponent newComponent, @Nullable String userUuid, @Nullable String userLogin, | |||
@Nullable String mainBranchName) { | |||
ComponentCreationData componentCreationData = createWithoutCommit(dbSession, newComponent, userUuid, userLogin, mainBranchName, c -> { | |||
}); | |||
commitAndIndex(dbSession, componentCreationData.mainBranchComponent()); | |||
ComponentCreationData componentCreationData = createWithoutCommit(dbSession, newComponent, userUuid, userLogin, null); | |||
commitAndIndex(dbSession, componentCreationData); | |||
return componentCreationData; | |||
} | |||
public void commitAndIndex(DbSession dbSession, ComponentDto componentDto) { | |||
projectIndexers.commitAndIndexComponents(dbSession, singletonList(componentDto), Cause.PROJECT_CREATION); | |||
public void commitAndIndex(DbSession dbSession, ComponentCreationData componentCreationData) { | |||
if (componentCreationData.portfolioDto() != null) { | |||
indexers.commitAndIndexEntities(dbSession, singletonList(componentCreationData.portfolioDto()), Indexers.EntityEvent.CREATION); | |||
} else if (componentCreationData.projectDto() != null) { | |||
indexers.commitAndIndexEntities(dbSession, singletonList(componentCreationData.projectDto()), Indexers.EntityEvent.CREATION); | |||
} | |||
} | |||
/** | |||
@@ -119,8 +115,8 @@ public class ComponentUpdater { | |||
* Don't forget to call commitAndIndex(...) when ready to commit. | |||
*/ | |||
public ComponentCreationData createWithoutCommit(DbSession dbSession, NewComponent newComponent, | |||
@Nullable String userUuid, @Nullable String userLogin, Consumer<ComponentDto> componentModifier) { | |||
return createWithoutCommit(dbSession, newComponent, userUuid, userLogin, null, componentModifier); | |||
@Nullable String userUuid, @Nullable String userLogin) { | |||
return createWithoutCommit(dbSession, newComponent, userUuid, userLogin, null); | |||
} | |||
/** | |||
@@ -128,33 +124,33 @@ public class ComponentUpdater { | |||
* Don't forget to call commitAndIndex(...) when ready to commit. | |||
*/ | |||
public ComponentCreationData createWithoutCommit(DbSession dbSession, NewComponent newComponent, | |||
@Nullable String userUuid, @Nullable String userLogin, @Nullable String mainBranchName, | |||
Consumer<ComponentDto> componentModifier) { | |||
@Nullable String userUuid, @Nullable String userLogin, @Nullable String mainBranchName) { | |||
checkKeyFormat(newComponent.qualifier(), newComponent.key()); | |||
checkKeyAlreadyExists(dbSession, newComponent); | |||
long now = system2.now(); | |||
ComponentDto componentDto = createRootComponent(dbSession, newComponent, componentModifier, now); | |||
ComponentDto componentDto = createRootComponent(dbSession, newComponent, now); | |||
BranchDto mainBranch = null; | |||
ProjectDto projectDto = null; | |||
PortfolioDto portfolioDto = null; | |||
if (isRootProject(componentDto)) { | |||
if (isProjectOrApp(componentDto)) { | |||
projectDto = toProjectDto(componentDto, now); | |||
dbClient.projectDao().insert(dbSession, projectDto); | |||
addToFavourites(dbSession, projectDto, userUuid, userLogin); | |||
mainBranch = createMainBranch(dbSession, componentDto.uuid(), projectDto.getUuid(), mainBranchName); | |||
permissionTemplateService.applyDefaultToNewComponent(dbSession, projectDto, userUuid); | |||
} else if (isRootView(componentDto)) { | |||
PortfolioDto portfolioDto = toPortfolioDto(componentDto, now); | |||
} else if (isPortfolio(componentDto)) { | |||
portfolioDto = toPortfolioDto(componentDto, now); | |||
dbClient.portfolioDao().insert(dbSession, portfolioDto); | |||
permissionTemplateService.applyDefaultToNewComponent(dbSession, portfolioDto, userUuid); | |||
} else { | |||
throw new IllegalArgumentException("Component " + componentDto + " is not a top level entity"); | |||
} | |||
return new ComponentCreationData(componentDto, mainBranch, projectDto); | |||
return new ComponentCreationData(componentDto, portfolioDto, mainBranch, projectDto); | |||
} | |||
private void addToFavourites(DbSession dbSession, ProjectDto projectDto, @Nullable String userUuid, @Nullable String userLogin) { | |||
@@ -179,7 +175,7 @@ public class ComponentUpdater { | |||
} | |||
} | |||
private ComponentDto createRootComponent(DbSession session, NewComponent newComponent, Consumer<ComponentDto> componentModifier, long now) { | |||
private ComponentDto createRootComponent(DbSession session, NewComponent newComponent, long now) { | |||
String uuid = uuidFactory.create(); | |||
ComponentDto component = new ComponentDto() | |||
@@ -195,7 +191,6 @@ public class ComponentUpdater { | |||
.setPrivate(newComponent.isPrivate()) | |||
.setCreatedAt(new Date(now)); | |||
componentModifier.accept(component); | |||
dbClient.componentDao().insert(session, component, true); | |||
return component; | |||
} | |||
@@ -225,14 +220,12 @@ public class ComponentUpdater { | |||
.setCreatedAt(now); | |||
} | |||
private static boolean isRootProject(ComponentDto componentDto) { | |||
return Scopes.PROJECT.equals(componentDto.scope()) | |||
&& MAIN_BRANCH_QUALIFIERS.contains(componentDto.qualifier()); | |||
private static boolean isProjectOrApp(ComponentDto componentDto) { | |||
return PROJ_APP_QUALIFIERS.contains(componentDto.qualifier()); | |||
} | |||
private static boolean isRootView(ComponentDto componentDto) { | |||
return Scopes.PROJECT.equals(componentDto.scope()) | |||
&& Qualifiers.VIEW.contains(componentDto.qualifier()); | |||
private static boolean isPortfolio(ComponentDto componentDto) { | |||
return Qualifiers.VIEW.contains(componentDto.qualifier()); | |||
} | |||
private BranchDto createMainBranch(DbSession session, String componentUuid, String projectUuid, @Nullable String mainBranch) { |
@@ -119,16 +119,17 @@ public class AuthorsAction implements IssuesWsAction { | |||
private List<String> getAuthors(DbSession session, @Nullable EntityDto entity, Request request) { | |||
IssueQuery.Builder issueQueryBuilder = IssueQuery.builder(); | |||
ofNullable(entity).ifPresent(p -> { | |||
switch (p.getQualifier()) { | |||
case Qualifiers.PROJECT -> issueQueryBuilder.projectUuids(Set.of(p.getUuid())); | |||
case Qualifiers.VIEW -> issueQueryBuilder.viewUuids(Set.of(p.getUuid())); | |||
ofNullable(entity).ifPresent(e -> { | |||
switch (e.getQualifier()) { | |||
case Qualifiers.PROJECT -> issueQueryBuilder.projectUuids(Set.of(e.getUuid())); | |||
case Qualifiers.VIEW -> issueQueryBuilder.viewUuids(Set.of(e.getUuid())); | |||
case Qualifiers.APP -> { | |||
BranchDto appMainBranch = dbClient.branchDao().selectMainBranchByProjectUuid(session, entity.getUuid()) | |||
.orElseThrow(() -> new IllegalStateException("Couldn't find main branch for APP " + entity.getUuid())); | |||
issueQueryBuilder.viewUuids(Set.of(appMainBranch.getUuid())); | |||
BranchDto appMainBranch = dbClient.branchDao().selectMainBranchByProjectUuid(session, e.getUuid()) | |||
.orElseThrow(() -> new IllegalStateException("Couldn't find main branch for APP " + e.getUuid())); | |||
issueQueryBuilder.viewUuids(Set.of(entity.getUuid())); | |||
issueQueryBuilder.branchUuid(appMainBranch.getUuid()); | |||
} | |||
default -> throw new IllegalArgumentException(String.format("Component of type '%s' is not supported", p.getQualifier())); | |||
default -> throw new IllegalArgumentException(String.format("Component of type '%s' is not supported", e.getQualifier())); | |||
} | |||
}); | |||
return issueIndex.searchAuthors( |
@@ -39,8 +39,8 @@ import org.sonar.db.measure.LiveMeasureComparator; | |||
import org.sonar.db.measure.LiveMeasureDto; | |||
import org.sonar.db.metric.MetricDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.ProjectIndexers; | |||
import org.sonar.server.es.EventIndexer; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.qualitygate.EvaluatedQualityGate; | |||
import org.sonar.server.qualitygate.QualityGate; | |||
import org.sonar.server.qualitygate.changeevent.QGChangeEvent; | |||
@@ -59,11 +59,11 @@ public class LiveMeasureComputerImpl implements LiveMeasureComputer { | |||
private final ComponentIndexFactory componentIndexFactory; | |||
private final LiveQualityGateComputer qGateComputer; | |||
private final ProjectConfigurationLoader projectConfigurationLoader; | |||
private final ProjectIndexers projectIndexer; | |||
private final Indexers projectIndexer; | |||
private final LiveMeasureTreeUpdater treeUpdater; | |||
public LiveMeasureComputerImpl(DbClient dbClient, MeasureUpdateFormulaFactory formulaFactory, ComponentIndexFactory componentIndexFactory, | |||
LiveQualityGateComputer qGateComputer, ProjectConfigurationLoader projectConfigurationLoader, ProjectIndexers projectIndexer, LiveMeasureTreeUpdater treeUpdater) { | |||
LiveQualityGateComputer qGateComputer, ProjectConfigurationLoader projectConfigurationLoader, Indexers projectIndexer, LiveMeasureTreeUpdater treeUpdater) { | |||
this.dbClient = dbClient; | |||
this.formulaFactory = formulaFactory; | |||
this.componentIndexFactory = componentIndexFactory; | |||
@@ -106,7 +106,7 @@ public class LiveMeasureComputerImpl implements LiveMeasureComputer { | |||
Metric.Level previousStatus = loadPreviousStatus(dbSession, branchComponent); | |||
EvaluatedQualityGate evaluatedQualityGate = qGateComputer.refreshGateStatus(branchComponent, qualityGate, matrix, config); | |||
persistAndIndex(dbSession, matrix, branchComponent); | |||
persistAndIndex(dbSession, matrix, branch); | |||
return Optional.of(new QGChangeEvent(project, branch, lastAnalysis.get(), config, previousStatus, () -> Optional.of(evaluatedQualityGate))); | |||
} | |||
@@ -118,10 +118,10 @@ public class LiveMeasureComputerImpl implements LiveMeasureComputer { | |||
return new MeasureMatrix(componentUuids, metricsPerUuid.values(), measures); | |||
} | |||
private void persistAndIndex(DbSession dbSession, MeasureMatrix matrix, ComponentDto branchComponent) { | |||
private void persistAndIndex(DbSession dbSession, MeasureMatrix matrix, BranchDto branch) { | |||
// persist the measures that have been created or updated | |||
matrix.getChanged().sorted(LiveMeasureComparator.INSTANCE).forEach(m -> dbClient.liveMeasureDao().insertOrUpdate(dbSession, m)); | |||
projectIndexer.commitAndIndexComponents(dbSession, singleton(branchComponent), ProjectIndexer.Cause.MEASURE_CHANGE); | |||
projectIndexer.commitAndIndexBranches(dbSession, singleton(branch), Indexers.BranchEvent.MEASURE_CHANGE); | |||
} | |||
@CheckForNull |
@@ -45,8 +45,7 @@ import org.sonar.db.permission.template.PermissionTemplateUserDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.db.user.UserId; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.ProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.exceptions.TemplateMatchingKeyException; | |||
import org.sonar.server.permission.DefaultTemplatesResolver.ResolvedDefaultTemplates; | |||
import org.sonar.server.user.UserSession; | |||
@@ -62,15 +61,15 @@ import static org.sonar.db.permission.GlobalPermission.SCAN; | |||
public class PermissionTemplateService { | |||
private final DbClient dbClient; | |||
private final ProjectIndexers projectIndexers; | |||
private final Indexers indexers; | |||
private final UserSession userSession; | |||
private final DefaultTemplatesResolver defaultTemplatesResolver; | |||
private final UuidFactory uuidFactory; | |||
public PermissionTemplateService(DbClient dbClient, ProjectIndexers projectIndexers, UserSession userSession, | |||
public PermissionTemplateService(DbClient dbClient, Indexers indexers, UserSession userSession, | |||
DefaultTemplatesResolver defaultTemplatesResolver, UuidFactory uuidFactory) { | |||
this.dbClient = dbClient; | |||
this.projectIndexers = projectIndexers; | |||
this.indexers = indexers; | |||
this.userSession = userSession; | |||
this.defaultTemplatesResolver = defaultTemplatesResolver; | |||
this.uuidFactory = uuidFactory; | |||
@@ -106,11 +105,12 @@ public class PermissionTemplateService { | |||
dbClient.userPermissionDao().deleteEntityPermissions(dbSession, entity); | |||
copyPermissions(dbSession, template, entity, null); | |||
} | |||
projectIndexers.commitAndIndexEntities(dbSession, entities, ProjectIndexer.Cause.PERMISSION_CHANGE); | |||
indexers.commitAndIndexEntities(dbSession, entities, Indexers.EntityEvent.PERMISSION_CHANGE); | |||
} | |||
/** | |||
* Apply the default permission template to a new project (has no permissions yet). | |||
* | |||
* @param projectCreatorUserId id of the user creating the project. | |||
*/ | |||
public void applyDefaultToNewComponent(DbSession dbSession, EntityDto entityDto, @Nullable String projectCreatorUserId) { |
@@ -23,21 +23,20 @@ import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.ProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
/** | |||
* Add or remove global/project permissions to a group. This class does not verify that caller has administration right on the related project. | |||
*/ | |||
public class PermissionUpdater { | |||
private final ProjectIndexers projectIndexers; | |||
private final Indexers indexers; | |||
private final UserPermissionChanger userPermissionChanger; | |||
private final GroupPermissionChanger groupPermissionChanger; | |||
public PermissionUpdater(ProjectIndexers projectIndexers, | |||
public PermissionUpdater(Indexers indexers, | |||
UserPermissionChanger userPermissionChanger, GroupPermissionChanger groupPermissionChanger) { | |||
this.projectIndexers = projectIndexers; | |||
this.indexers = indexers; | |||
this.userPermissionChanger = userPermissionChanger; | |||
this.groupPermissionChanger = groupPermissionChanger; | |||
} | |||
@@ -51,7 +50,7 @@ public class PermissionUpdater { | |||
projectOrViewUuids.add(projectUuid); | |||
} | |||
} | |||
projectIndexers.commitAndIndexByProjectUuids(dbSession, projectOrViewUuids, ProjectIndexer.Cause.PERMISSION_CHANGE); | |||
indexers.commitAndIndexOnEntityEvent(dbSession, projectOrViewUuids, Indexers.EntityEvent.PERMISSION_CHANGE); | |||
} | |||
private boolean doApply(DbSession dbSession, PermissionChange change) { |
@@ -25,6 +25,7 @@ import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.StringUtils; | |||
@@ -151,9 +152,9 @@ public class BulkDeleteAction implements ProjectsWsAction { | |||
List<EntityDto> entities = dbClient.entityDao().selectByKeys(dbSession, componentDtos.stream().map(ComponentDto::getKey).collect(toSet())); | |||
try { | |||
entities.forEach(e -> componentCleanerService.delete(dbSession, e)); | |||
entities.forEach(p -> componentCleanerService.deleteEntity(dbSession, p)); | |||
} finally { | |||
projectLifeCycleListeners.onProjectsDeleted(entities.stream().map(Project::from).collect(MoreCollectors.toSet(componentDtos.size()))); | |||
projectLifeCycleListeners.onProjectsDeleted(entities.stream().map(Project::from).collect(Collectors.toSet())); | |||
} | |||
} | |||
response.noContent(); |
@@ -28,7 +28,9 @@ import org.sonar.api.server.ws.Response; | |||
import org.sonar.api.server.ws.WebService; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.entity.EntityDto; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.component.ComponentCreationData; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.newcodeperiod.NewCodeDefinitionResolver; | |||
import org.sonar.server.project.DefaultBranchNameResolver; | |||
@@ -132,18 +134,18 @@ public class CreateAction implements ProjectsWsAction { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
userSession.checkPermission(PROVISION_PROJECTS); | |||
checkNewCodeDefinitionParam(request.getNewCodeDefinitionType(), request.getNewCodeDefinitionValue()); | |||
ComponentDto componentDto = createProject(request, dbSession); | |||
ComponentCreationData componentData = createProject(request, dbSession); | |||
if (request.getNewCodeDefinitionType() != null) { | |||
String defaultBranchName = Optional.ofNullable(request.getMainBranchKey()).orElse(defaultBranchNameResolver.getEffectiveMainBranchName()); | |||
newCodeDefinitionResolver.createNewCodeDefinition(dbSession, componentDto.uuid(), defaultBranchName, request.getNewCodeDefinitionType(), | |||
newCodeDefinitionResolver.createNewCodeDefinition(dbSession, componentData.mainBranchDto().getUuid(), defaultBranchName, request.getNewCodeDefinitionType(), | |||
request.getNewCodeDefinitionValue()); | |||
} | |||
componentUpdater.commitAndIndex(dbSession, componentDto); | |||
return toCreateResponse(componentDto); | |||
componentUpdater.commitAndIndex(dbSession, componentData); | |||
return toCreateResponse(componentData.projectDto()); | |||
} | |||
} | |||
private ComponentDto createProject(CreateRequest request, DbSession dbSession) { | |||
private ComponentCreationData createProject(CreateRequest request, DbSession dbSession) { | |||
String visibility = request.getVisibility(); | |||
boolean changeToPrivate = visibility == null ? projectDefaultVisibility.get(dbSession).isPrivate() : "private".equals(visibility); | |||
@@ -155,8 +157,7 @@ public class CreateAction implements ProjectsWsAction { | |||
.build(), | |||
userSession.isLoggedIn() ? userSession.getUuid() : null, | |||
userSession.isLoggedIn() ? userSession.getLogin() : null, | |||
request.getMainBranchKey(), s -> { | |||
}).mainBranchComponent(); | |||
request.getMainBranchKey()); | |||
} | |||
@@ -171,13 +172,13 @@ public class CreateAction implements ProjectsWsAction { | |||
.build(); | |||
} | |||
private static CreateWsResponse toCreateResponse(ComponentDto componentDto) { | |||
private static CreateWsResponse toCreateResponse(EntityDto project) { | |||
return CreateWsResponse.newBuilder() | |||
.setProject(CreateWsResponse.Project.newBuilder() | |||
.setKey(componentDto.getKey()) | |||
.setName(componentDto.name()) | |||
.setQualifier(componentDto.qualifier()) | |||
.setVisibility(Visibility.getLabel(componentDto.isPrivate()))) | |||
.setKey(project.getKey()) | |||
.setName(project.getName()) | |||
.setQualifier(project.getQualifier()) | |||
.setVisibility(Visibility.getLabel(project.isPrivate()))) | |||
.build(); | |||
} | |||
@@ -81,7 +81,7 @@ public class DeleteAction implements ProjectsWsAction { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
ProjectDto project = componentFinder.getProjectByKey(dbSession, key); | |||
checkPermission(project); | |||
componentCleanerService.delete(dbSession, project); | |||
componentCleanerService.deleteEntity(dbSession, project); | |||
projectLifeCycleListeners.onProjectsDeleted(singleton(Project.fromProjectDtoWithTags(project))); | |||
} | |||
@@ -34,8 +34,8 @@ import org.sonar.db.permission.GroupPermissionDto; | |||
import org.sonar.db.permission.UserPermissionDto; | |||
import org.sonar.db.user.GroupDto; | |||
import org.sonar.db.user.UserId; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.es.ProjectIndexers; | |||
import org.sonar.server.es.EventIndexer; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.project.Visibility; | |||
import org.sonar.server.user.UserSession; | |||
@@ -57,14 +57,14 @@ public class UpdateVisibilityAction implements ProjectsWsAction { | |||
private final DbClient dbClient; | |||
private final UserSession userSession; | |||
private final ProjectIndexers projectIndexers; | |||
private final Indexers indexers; | |||
private final UuidFactory uuidFactory; | |||
private final Configuration configuration; | |||
public UpdateVisibilityAction(DbClient dbClient, UserSession userSession, ProjectIndexers projectIndexers, UuidFactory uuidFactory, Configuration configuration) { | |||
public UpdateVisibilityAction(DbClient dbClient, UserSession userSession, Indexers indexers, UuidFactory uuidFactory, Configuration configuration) { | |||
this.dbClient = dbClient; | |||
this.userSession = userSession; | |||
this.projectIndexers = projectIndexers; | |||
this.indexers = indexers; | |||
this.uuidFactory = uuidFactory; | |||
this.configuration = configuration; | |||
} | |||
@@ -119,7 +119,7 @@ public class UpdateVisibilityAction implements ProjectsWsAction { | |||
} else { | |||
updatePermissionsToPublic(dbSession, entityDto); | |||
} | |||
projectIndexers.commitAndIndexEntities(dbSession, singletonList(entityDto), ProjectIndexer.Cause.PERMISSION_CHANGE); | |||
indexers.commitAndIndexEntities(dbSession, singletonList(entityDto), Indexers.EntityEvent.PERMISSION_CHANGE); | |||
} | |||
response.noContent(); |
@@ -30,11 +30,11 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.project.ProjectDto; | |||
import org.sonar.server.component.ComponentFinder; | |||
import org.sonar.server.es.ProjectIndexers; | |||
import org.sonar.server.es.Indexers; | |||
import org.sonar.server.user.UserSession; | |||
import static java.util.Collections.singletonList; | |||
import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_TAGS_UPDATE; | |||
import static org.sonar.server.es.Indexers.EntityEvent.PROJECT_TAGS_UPDATE; | |||
import static org.sonar.server.exceptions.BadRequestException.checkRequest; | |||
public class TagsWsSupport { | |||
@@ -47,14 +47,14 @@ public class TagsWsSupport { | |||
private final DbClient dbClient; | |||
private final ComponentFinder componentFinder; | |||
private final UserSession userSession; | |||
private final ProjectIndexers projectIndexers; | |||
private final Indexers indexers; | |||
private final System2 system2; | |||
public TagsWsSupport(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, ProjectIndexers projectIndexers, System2 system2) { | |||
public TagsWsSupport(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, Indexers indexers, System2 system2) { | |||
this.dbClient = dbClient; | |||
this.componentFinder = componentFinder; | |||
this.userSession = userSession; | |||
this.projectIndexers = projectIndexers; | |||
this.indexers = indexers; | |||
this.system2 = system2; | |||
} | |||
@@ -76,7 +76,7 @@ public class TagsWsSupport { | |||
projectOrApplication.setUpdatedAt(system2.now()); | |||
dbClient.projectDao().updateTags(dbSession, projectOrApplication); | |||
projectIndexers.commitAndIndexProjects(dbSession, singletonList(projectOrApplication), PROJECT_TAGS_UPDATE); | |||
indexers.commitAndIndexEntities(dbSession, singletonList(projectOrApplication), PROJECT_TAGS_UPDATE); | |||
} | |||
public static List<String> checkAndUnifyTags(List<String> tags) { |
@@ -82,7 +82,7 @@ import org.sonar.server.component.ComponentService; | |||
import org.sonar.server.component.ComponentUpdater; | |||
import org.sonar.server.component.index.ComponentIndex; | |||
import org.sonar.server.component.index.ComponentIndexDefinition; | |||
import org.sonar.server.component.index.ComponentIndexer; | |||
import org.sonar.server.component.index.EntityDefinitionIndexer; | |||
import org.sonar.server.component.ws.ComponentViewerJsonWriter; | |||
import org.sonar.server.component.ws.ComponentsWsModule; | |||
import org.sonar.server.developers.ws.DevelopersWsModule; | |||
@@ -92,7 +92,7 @@ import org.sonar.server.duplication.ws.ShowResponseBuilder; | |||
import org.sonar.server.email.ws.EmailsWsModule; | |||
import org.sonar.server.es.IndexCreator; | |||
import org.sonar.server.es.IndexDefinitions; | |||
import org.sonar.server.es.ProjectIndexersImpl; | |||
import org.sonar.server.es.IndexersImpl; | |||
import org.sonar.server.es.RecoveryIndexer; | |||
import org.sonar.server.es.metadata.EsDbCompatibilityImpl; | |||
import org.sonar.server.es.metadata.MetadataIndexDefinition; | |||
@@ -434,7 +434,7 @@ public class PlatformLevel4 extends PlatformLevel { | |||
ComponentCleanerService.class, | |||
ComponentIndexDefinition.class, | |||
ComponentIndex.class, | |||
ComponentIndexer.class, | |||
EntityDefinitionIndexer.class, | |||
new LiveMeasureModule(), | |||
ComponentViewerJsonWriter.class, | |||
@@ -615,7 +615,7 @@ public class PlatformLevel4 extends PlatformLevel { | |||
new HttpRequestIdModule(), | |||
RecoveryIndexer.class, | |||
ProjectIndexersImpl.class, | |||
IndexersImpl.class, | |||
// telemetry | |||
TelemetryDataLoaderImpl.class, |