123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- /*
- * SonarQube
- * Copyright (C) 2009-2021 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.ce.container;
-
- import com.google.common.annotations.VisibleForTesting;
- import java.time.Clock;
- import java.util.List;
- import javax.annotation.CheckForNull;
- import org.sonar.api.SonarEdition;
- import org.sonar.api.SonarQubeSide;
- import org.sonar.api.SonarQubeVersion;
- import org.sonar.api.config.EmailSettings;
- import org.sonar.api.internal.MetadataLoader;
- import org.sonar.api.internal.SonarRuntimeImpl;
- import org.sonar.api.profiles.XMLProfileParser;
- import org.sonar.api.profiles.XMLProfileSerializer;
- import org.sonar.api.resources.Languages;
- import org.sonar.api.resources.ResourceTypes;
- import org.sonar.api.rules.AnnotationRuleParser;
- import org.sonar.api.server.profile.BuiltInQualityProfileAnnotationLoader;
- import org.sonar.api.server.rule.RulesDefinitionXmlLoader;
- import org.sonar.api.utils.Durations;
- import org.sonar.api.utils.System2;
- import org.sonar.api.utils.UriReader;
- import org.sonar.api.utils.Version;
- import org.sonar.api.utils.log.Loggers;
- import org.sonar.ce.CeConfigurationModule;
- import org.sonar.ce.CeDistributedInformationImpl;
- import org.sonar.ce.CeHttpModule;
- import org.sonar.ce.CeQueueModule;
- import org.sonar.ce.CeTaskCommonsModule;
- import org.sonar.ce.StandaloneCeDistributedInformation;
- import org.sonar.ce.async.SynchronousAsyncExecution;
- import org.sonar.ce.cleaning.CeCleaningModule;
- import org.sonar.ce.cleaning.NoopCeCleaningSchedulerImpl;
- import org.sonar.ce.db.ReadOnlyPropertiesDao;
- import org.sonar.ce.issue.index.NoAsyncIssueIndexing;
- import org.sonar.ce.logging.CeProcessLogging;
- import org.sonar.ce.monitoring.CEQueueStatusImpl;
- import org.sonar.ce.monitoring.DistributedCEQueueStatusImpl;
- import org.sonar.ce.platform.CECoreExtensionsInstaller;
- import org.sonar.ce.platform.ComputeEngineExtensionInstaller;
- import org.sonar.ce.platform.DatabaseCompatibility;
- import org.sonar.ce.queue.PurgeCeActivities;
- import org.sonar.ce.task.projectanalysis.ProjectAnalysisTaskModule;
- import org.sonar.ce.task.projectanalysis.analysis.ProjectConfigurationFactory;
- import org.sonar.ce.task.projectanalysis.issue.AdHocRuleCreator;
- import org.sonar.ce.task.projectanalysis.notification.ReportAnalysisFailureNotificationModule;
- import org.sonar.ce.task.projectanalysis.taskprocessor.IssueSyncTaskModule;
- import org.sonar.ce.taskprocessor.CeProcessingScheduler;
- import org.sonar.ce.taskprocessor.CeTaskProcessorModule;
- import org.sonar.core.component.DefaultResourceTypes;
- import org.sonar.core.config.CorePropertyDefinitions;
- import org.sonar.core.extension.CoreExtensionRepositoryImpl;
- import org.sonar.core.extension.CoreExtensionsLoader;
- import org.sonar.core.platform.ComponentContainer;
- import org.sonar.core.platform.EditionProvider;
- import org.sonar.core.platform.Module;
- import org.sonar.core.platform.PlatformEditionProvider;
- import org.sonar.core.platform.PluginClassLoader;
- import org.sonar.core.platform.PluginClassloaderFactory;
- import org.sonar.core.util.UuidFactoryImpl;
- import org.sonar.db.DBSessionsImpl;
- import org.sonar.db.DaoModule;
- import org.sonar.db.DbClient;
- import org.sonar.db.DefaultDatabase;
- import org.sonar.db.MyBatis;
- 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.config.ConfigurationProvider;
- import org.sonar.server.es.EsModule;
- import org.sonar.server.es.ProjectIndexersImpl;
- import org.sonar.server.extension.CoreExtensionBootstraper;
- import org.sonar.server.extension.CoreExtensionStopper;
- import org.sonar.server.favorite.FavoriteUpdater;
- import org.sonar.server.issue.IssueFieldsSetter;
- import org.sonar.server.issue.IssueStorage;
- import org.sonar.server.issue.index.IssueIndexer;
- import org.sonar.server.issue.index.IssueIteratorFactory;
- import org.sonar.server.issue.notification.IssuesChangesNotificationModule;
- import org.sonar.server.issue.notification.MyNewIssuesEmailTemplate;
- import org.sonar.server.issue.notification.MyNewIssuesNotificationHandler;
- import org.sonar.server.issue.notification.NewIssuesEmailTemplate;
- import org.sonar.server.issue.notification.NewIssuesNotificationHandler;
- import org.sonar.server.issue.workflow.FunctionExecutor;
- import org.sonar.server.issue.workflow.IssueWorkflow;
- import org.sonar.server.l18n.ServerI18n;
- import org.sonar.server.log.ServerLogging;
- import org.sonar.server.measure.index.ProjectMeasuresIndexer;
- import org.sonar.server.metric.CoreCustomMetrics;
- import org.sonar.server.metric.MetricFinder;
- import org.sonar.server.metric.UnanalyzedLanguageMetrics;
- import org.sonar.server.notification.DefaultNotificationManager;
- import org.sonar.server.notification.NotificationService;
- import org.sonar.server.notification.email.EmailNotificationChannel;
- import org.sonar.server.platform.OfficialDistribution;
- import org.sonar.server.platform.ServerFileSystemImpl;
- import org.sonar.server.platform.ServerImpl;
- import org.sonar.server.platform.ServerLifecycleNotifier;
- import org.sonar.server.platform.StartupMetadataProvider;
- import org.sonar.server.platform.TempFolderProvider;
- import org.sonar.server.platform.UrlSettings;
- import org.sonar.server.platform.WebServerImpl;
- import org.sonar.server.platform.db.migration.MigrationConfigurationModule;
- import org.sonar.server.platform.db.migration.version.DatabaseVersion;
- import org.sonar.server.platform.monitoring.DbSection;
- import org.sonar.server.platform.monitoring.cluster.ProcessInfoProvider;
- import org.sonar.server.platform.serverid.JdbcUrlSanitizer;
- import org.sonar.server.platform.serverid.ServerIdChecksum;
- import org.sonar.server.plugins.InstalledPluginReferentialFactory;
- import org.sonar.server.plugins.ServerExtensionInstaller;
- import org.sonar.server.property.InternalPropertiesImpl;
- import org.sonar.server.qualitygate.QualityGateEvaluatorImpl;
- import org.sonar.server.qualitygate.QualityGateFinder;
- import org.sonar.server.qualitygate.notification.QGChangeEmailTemplate;
- import org.sonar.server.qualitygate.notification.QGChangeNotificationHandler;
- import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
- import org.sonar.server.rule.DefaultRuleFinder;
- import org.sonar.server.rule.index.RuleIndex;
- import org.sonar.server.rule.index.RuleIndexer;
- import org.sonar.server.setting.DatabaseSettingLoader;
- import org.sonar.server.setting.DatabaseSettingsEnabler;
- import org.sonar.server.setting.ThreadLocalSettings;
- import org.sonar.server.user.index.UserIndex;
- import org.sonar.server.user.index.UserIndexer;
- import org.sonar.server.util.OkHttpClientProvider;
- import org.sonar.server.util.Paths2Impl;
- import org.sonar.server.view.index.ViewIndex;
- import org.sonar.server.view.index.ViewIndexer;
- import org.sonar.server.webhook.WebhookModule;
- import org.sonarqube.ws.Rules;
-
- import static java.util.Objects.requireNonNull;
- import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
- import static org.sonar.core.extension.PlatformLevelPredicates.hasPlatformLevel;
- import static org.sonar.core.extension.PlatformLevelPredicates.hasPlatformLevel4OrNone;
- import static org.sonar.process.ProcessProperties.Property.CLUSTER_ENABLED;
- import static org.sonar.process.ProcessProperties.Property.SONARCLOUD_ENABLED;
-
- public class ComputeEngineContainerImpl implements ComputeEngineContainer {
-
- private ComputeEngineStatus computeEngineStatus;
- @CheckForNull
- private ComponentContainer level1;
- @CheckForNull
- private ComponentContainer level4;
-
- @Override
- public void setComputeEngineStatus(ComputeEngineStatus computeEngineStatus) {
- this.computeEngineStatus = computeEngineStatus;
- }
-
- @Override
- public ComputeEngineContainer start(Props props) {
- this.level1 = new ComponentContainer();
- populateLevel1(this.level1, props, requireNonNull(computeEngineStatus));
- configureFromModules(this.level1);
- startLevel1(this.level1);
-
- ComponentContainer level2 = this.level1.createChild();
- populateLevel2(level2);
- configureFromModules(level2);
- startLevel2(level2);
-
- ComponentContainer level3 = level2.createChild();
- populateLevel3(level3);
- configureFromModules(level3);
- startLevel3(level3);
-
- this.level4 = level3.createChild();
- populateLevel4(this.level4, props);
- configureFromModules(this.level4);
- startLevel4(this.level4);
-
- startupTasks();
-
- return this;
- }
-
- private static void startLevel1(ComponentContainer level1) {
- level1.getComponentByType(CoreExtensionsLoader.class)
- .load();
- level1.getComponentByType(CECoreExtensionsInstaller.class)
- .install(level1, hasPlatformLevel(1), noAdditionalSideFilter());
-
- level1.startComponents();
- }
-
- private static void startLevel2(ComponentContainer level2) {
- level2.getComponentByType(CECoreExtensionsInstaller.class)
- .install(level2, hasPlatformLevel(2), noAdditionalSideFilter());
-
- level2.startComponents();
- }
-
- private static void startLevel3(ComponentContainer level3) {
- level3.getComponentByType(CECoreExtensionsInstaller.class)
- .install(level3, hasPlatformLevel(3), noAdditionalSideFilter());
-
- level3.startComponents();
- }
-
- private static void startLevel4(ComponentContainer level4) {
- level4.getComponentByType(CECoreExtensionsInstaller.class)
- .install(level4, hasPlatformLevel4OrNone(), noAdditionalSideFilter());
- level4.getComponentByType(ServerExtensionInstaller.class)
- .installExtensions(level4);
-
- level4.startComponents();
-
- PlatformEditionProvider editionProvider = level4.getComponentByType(PlatformEditionProvider.class);
- Loggers.get(ComputeEngineContainerImpl.class)
- .info("Running {} edition", editionProvider.get().map(EditionProvider.Edition::getLabel).orElse(""));
- }
-
- private void startupTasks() {
- ComponentContainer startupLevel = this.level4.createChild();
- startupLevel.add(startupComponents());
- startupLevel.startComponents();
- // done in PlatformLevelStartup
- ServerLifecycleNotifier serverLifecycleNotifier = startupLevel.getComponentByType(ServerLifecycleNotifier.class);
- if (serverLifecycleNotifier != null) {
- serverLifecycleNotifier.notifyStart();
- }
- startupLevel.stopComponents();
- }
-
- @Override
- public ComputeEngineContainer stopWorkers() {
- if (level4 != null) {
- // try to graceful stop in-progress tasks
- CeProcessingScheduler ceProcessingScheduler = level4.getComponentByType(CeProcessingScheduler.class);
- ceProcessingScheduler.gracefulStopScheduling();
- }
- return this;
- }
-
- @Override
- public ComputeEngineContainer stop() {
- if (level4 != null) {
- // try to graceful but quick stop in-progress tasks
- CeProcessingScheduler ceProcessingScheduler = level4.getComponentByType(CeProcessingScheduler.class);
- ceProcessingScheduler.hardStopScheduling();
- }
- this.level1.stopComponents();
- return this;
- }
-
- @VisibleForTesting
- protected ComponentContainer getComponentContainer() {
- return level4;
- }
-
- private static void populateLevel1(ComponentContainer container, Props props, ComputeEngineStatus computeEngineStatus) {
- Version apiVersion = MetadataLoader.loadVersion(System2.INSTANCE);
- SonarEdition edition = MetadataLoader.loadEdition(System2.INSTANCE);
- container.add(
- props.rawProperties(),
- ThreadLocalSettings.class,
- new ConfigurationProvider(),
- new SonarQubeVersion(apiVersion),
- SonarRuntimeImpl.forSonarQube(apiVersion, SonarQubeSide.COMPUTE_ENGINE, edition),
- CeProcessLogging.class,
- UuidFactoryImpl.INSTANCE,
- NetworkUtilsImpl.INSTANCE,
- WebServerImpl.class,
- LogbackHelper.class,
- DefaultDatabase.class,
- MyBatis.class,
- PurgeProfiler.class,
- ServerFileSystemImpl.class,
- new TempFolderProvider(),
- System2.INSTANCE,
- Paths2Impl.getInstance(),
- Clock.systemDefaultZone(),
-
- // DB
- DaoModule.class,
- ReadOnlyPropertiesDao.class,
- DBSessionsImpl.class,
- DbClient.class,
-
- // Elasticsearch
- EsModule.class,
-
- // rules/qprofiles
- RuleIndex.class,
-
- new OkHttpClientProvider(),
- computeEngineStatus,
-
- CoreExtensionRepositoryImpl.class,
- CoreExtensionsLoader.class,
- CECoreExtensionsInstaller.class);
- container.add(toArray(CorePropertyDefinitions.all()));
- }
-
- private static void populateLevel2(ComponentContainer container) {
- container.add(
- MigrationConfigurationModule.class,
- DatabaseVersion.class,
- DatabaseCompatibility.class,
-
- DatabaseSettingLoader.class,
- DatabaseSettingsEnabler.class,
- UrlSettings.class,
-
- // add ReadOnlyPropertiesDao at level2 again so that it shadows PropertiesDao
- ReadOnlyPropertiesDao.class,
-
- // plugins
- PluginClassloaderFactory.class,
- CePluginJarExploder.class,
- PluginClassLoader.class,
- CePluginRepository.class,
- InstalledPluginReferentialFactory.class,
- ComputeEngineExtensionInstaller.class,
-
- // depends on plugins
- ServerI18n.class, // used by RuleI18nManager
- Durations.class // used in Web Services and DebtCalculator
- );
- }
-
- private static void populateLevel3(ComponentContainer container) {
- container.add(
- new StartupMetadataProvider(),
- JdbcUrlSanitizer.class,
- ServerIdChecksum.class,
- UriReader.class,
- ServerImpl.class,
- SynchronousAsyncExecution.class);
- }
-
- private static void populateLevel4(ComponentContainer container, Props props) {
- container.add(
- ResourceTypes.class,
- DefaultResourceTypes.get(),
-
- // quality profile
- ActiveRuleIndexer.class,
- XMLProfileParser.class,
- XMLProfileSerializer.class,
- BuiltInQualityProfileAnnotationLoader.class,
- Rules.QProfiles.class,
-
- // rule
- AnnotationRuleParser.class,
- DefaultRuleFinder.class,
- RulesDefinitionXmlLoader.class,
- AdHocRuleCreator.class,
- RuleIndexer.class,
-
- // languages
- Languages.class, // used by CommonRuleDefinitionsImpl
-
- // measure
- CoreCustomMetrics.class,
- MetricFinder.class,
- UnanalyzedLanguageMetrics.class,
-
- UserIndexer.class,
- UserIndex.class,
-
- // components,
- FavoriteUpdater.class,
- ProjectIndexersImpl.class,
- QGChangeNotificationHandler.class,
- QGChangeNotificationHandler.newMetadata(),
- ProjectMeasuresIndexer.class,
- ComponentIndexer.class,
-
- // views
- ViewIndexer.class,
- ViewIndex.class,
-
- // issues
- IssueStorage.class,
- NoAsyncIssueIndexing.class,
- IssueIndexer.class,
- IssueIteratorFactory.class,
- IssueFieldsSetter.class, // used in Web Services and CE's DebtCalculator
- FunctionExecutor.class, // used by IssueWorkflow
- IssueWorkflow.class, // used in Web Services and CE's DebtCalculator
- NewIssuesEmailTemplate.class,
- MyNewIssuesEmailTemplate.class,
- NewIssuesNotificationHandler.class,
- NewIssuesNotificationHandler.newMetadata(),
- MyNewIssuesNotificationHandler.class,
- MyNewIssuesNotificationHandler.newMetadata(),
- IssuesChangesNotificationModule.class,
-
- // Notifications
- QGChangeEmailTemplate.class,
- EmailSettings.class,
- NotificationService.class,
- DefaultNotificationManager.class,
- EmailNotificationChannel.class,
- ReportAnalysisFailureNotificationModule.class,
-
- // System
- ServerLogging.class,
-
- // SonarSource editions
- PlatformEditionProvider.class,
-
- // privileged plugins
- CoreExtensionBootstraper.class,
- CoreExtensionStopper.class,
-
- // Compute engine (must be after Views and Developer Cockpit)
- CeConfigurationModule.class,
- CeQueueModule.class,
- CeHttpModule.class,
- CeTaskCommonsModule.class,
- ProjectAnalysisTaskModule.class,
- IssueSyncTaskModule.class,
- CeTaskProcessorModule.class,
- OfficialDistribution.class,
-
- InternalPropertiesImpl.class,
- ProjectConfigurationFactory.class,
-
- // webhooks
- WebhookModule.class,
-
- QualityGateFinder.class,
- QualityGateEvaluatorImpl.class
-
- );
-
- if (props.valueAsBoolean(SONARCLOUD_ENABLED.getKey())) {
- // no cleaning job on sonarcloud and no distributed information
- container.add(
- NoopCeCleaningSchedulerImpl.class,
- StandaloneCeDistributedInformation.class,
- CEQueueStatusImpl.class);
- } else if (props.valueAsBoolean(CLUSTER_ENABLED.getKey())) {
- container.add(
- CeCleaningModule.class,
-
- // system health
- CeDistributedInformationImpl.class,
-
- // system info
- DbSection.class,
- ProcessInfoProvider.class,
-
- DistributedCEQueueStatusImpl.class);
- } else {
- container.add(
- CeCleaningModule.class,
- StandaloneCeDistributedInformation.class,
- CEQueueStatusImpl.class);
- }
- }
-
- private static Object[] startupComponents() {
- return new Object[] {
- ServerLifecycleNotifier.class,
- PurgeCeActivities.class
- };
- }
-
- private static Object[] toArray(List<?> list) {
- return list.toArray(new Object[list.size()]);
- }
-
- private static void configureFromModules(ComponentContainer container) {
- List<Module> modules = container.getComponentsByType(Module.class);
- for (Module module : modules) {
- module.configure(container);
- }
- }
- }
|