Skip to content

Commit

Permalink
fix JENKINS-62358: NonProductionGradeDatabaseWarningAdministrativeMon…
Browse files Browse the repository at this point in the history
…itor slowing down startup (#513)
  • Loading branch information
bguerin authored Sep 10, 2022
1 parent fe97e72 commit 1fce0b9
Show file tree
Hide file tree
Showing 4 changed files with 321 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti
return true;
}

boolean isDaoInitialized() {
return dao != null;
}

@Nonnull
public synchronized PipelineMavenPluginDao getDao() {
Jenkins j = Jenkins.getInstanceOrNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import hudson.Extension;
import hudson.model.AdministrativeMonitor;

import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;

import static org.apache.commons.lang3.StringUtils.isBlank;

import java.io.IOException;

/**
Expand All @@ -16,8 +19,16 @@ public class NonProductionGradeDatabaseWarningAdministrativeMonitor extends Admi

@Override
public boolean isActivated() {
boolean isEnoughProductionGradeForTheWorkload = GlobalPipelineMavenConfig.get().getDao().isEnoughProductionGradeForTheWorkload();
return !isEnoughProductionGradeForTheWorkload;
String jdbcUrl = GlobalPipelineMavenConfig.get().getJdbcUrl();
if (!isBlank(jdbcUrl)) {
return jdbcUrl.startsWith("jdbc:h2:");
}

if (GlobalPipelineMavenConfig.get().isDaoInitialized()) {
return !GlobalPipelineMavenConfig.get().getDao().isEnoughProductionGradeForTheWorkload();
}

return false;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package org.jenkinsci.plugins.pipeline.maven;

import static com.cloudbees.plugins.credentials.CredentialsScope.GLOBAL;
import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;

import java.util.List;

import org.acegisecurity.Authentication;
import org.junit.ClassRule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.containers.PostgreSQLContainer;

import com.cloudbees.plugins.credentials.Credentials;
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.domains.DomainRequirement;
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;

import hudson.ExtensionList;
import hudson.model.AdministrativeMonitor;
import hudson.model.ItemGroup;
import jenkins.model.Jenkins;

public class NonProductionGradeDatabaseWarningAdministrativeMonitorIntegrationTest {

@ClassRule
public static MySQLContainer<?> MYSQL_DB = new MySQLContainer<>(MySQLContainer.NAME).withUsername("aUser")
.withPassword("aPass");

@ClassRule
public static PostgreSQLContainer<?> POSTGRE_DB = new PostgreSQLContainer<>(PostgreSQLContainer.IMAGE)
.withUsername("aUser").withPassword("aPass");

@ClassRule
public static JenkinsRule j = new JenkinsRule();

private static class FakeCredentialsProvider extends CredentialsProvider {
public FakeCredentialsProvider() {
}

@Override
public boolean isEnabled(Object context) {
return true;
}

@Override
public <C extends Credentials> List<C> getCredentials(Class<C> type, ItemGroup itemGroup,
Authentication authentication, List<DomainRequirement> domainRequirements) {
return (List<C>) asList(new UsernamePasswordCredentialsImpl(GLOBAL, "credsId", "", "aUser", "aPass"));
}

@Override
public <C extends Credentials> List<C> getCredentials(Class<C> type, ItemGroup itemGroup,
Authentication authentication) {
return getCredentials(type, itemGroup, authentication, null);
}
}

@Test
public void shouldMitigateComputationWithH2Database() throws Exception {
NonProductionGradeDatabaseWarningAdministrativeMonitor monitor = j.jenkins
.getExtensionList(AdministrativeMonitor.class)
.get(NonProductionGradeDatabaseWarningAdministrativeMonitor.class);
assertThat(monitor, notNullValue());

assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized(), is(false));
assertThat(monitor.isActivated(), is(false));

GlobalPipelineMavenConfig.get().setJdbcUrl("jdbc:h2:file:/tmp/some.file");

assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized(), is(false));
assertThat(monitor.isActivated(), is(true));

GlobalPipelineMavenConfig.get().setJdbcUrl(null);

assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized(), is(false));
assertThat(monitor.isActivated(), is(false));

GlobalPipelineMavenConfig.get().getDao();

assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized(), is(true));
assertThat(monitor.isActivated(), is(false));

for (int i = 1; i <= 101; i++) {
GlobalPipelineMavenConfig.get().getDao().recordGeneratedArtifact("a job", i, "a.group.id", "anArtifactId",
"1.0.0-SNAPSHOT", "jar", "1.0.0-SNAPSHOT", null, false, "jar", null);
}

assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized(), is(true));
assertThat(monitor.isActivated(), is(true));
}

@Test
public void shouldNotDisplayWarningWithMysqlDatabase() throws Exception {
ExtensionList<CredentialsProvider> extensionList = Jenkins.getInstance()
.getExtensionList(CredentialsProvider.class);
extensionList.add(extensionList.size(), new FakeCredentialsProvider());
GlobalPipelineMavenConfig.get().setJdbcUrl(MYSQL_DB.getJdbcUrl());
GlobalPipelineMavenConfig.get().setJdbcCredentialsId("credsId");

NonProductionGradeDatabaseWarningAdministrativeMonitor monitor = j.jenkins
.getExtensionList(AdministrativeMonitor.class)
.get(NonProductionGradeDatabaseWarningAdministrativeMonitor.class);

assertThat(monitor, notNullValue());
assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized(), is(false));
assertThat(monitor.isActivated(), is(false));
}

@Test
public void shouldNotDisplayWarningWithPostgresDatabase() throws Exception {
ExtensionList<CredentialsProvider> extensionList = Jenkins.getInstance()
.getExtensionList(CredentialsProvider.class);
extensionList.add(extensionList.size(), new FakeCredentialsProvider());
GlobalPipelineMavenConfig.get().setJdbcUrl(POSTGRE_DB.getJdbcUrl());
GlobalPipelineMavenConfig.get().setJdbcCredentialsId("credsId");

NonProductionGradeDatabaseWarningAdministrativeMonitor monitor = j.jenkins
.getExtensionList(AdministrativeMonitor.class)
.get(NonProductionGradeDatabaseWarningAdministrativeMonitor.class);

assertThat(monitor, notNullValue());
assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized(), is(false));
assertThat(monitor.isActivated(), is(false));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package org.jenkinsci.plugins.pipeline.maven;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginDao;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class NonProductionGradeDatabaseWarningAdministrativeMonitorTest {

@InjectMocks
private NonProductionGradeDatabaseWarningAdministrativeMonitor monitor;

@Mock
private GlobalPipelineMavenConfig config;

@Mock
private PipelineMavenPluginDao dao;

@Test
public void test_is_activated_no_config_and_uninitialized() {
try (MockedStatic<GlobalPipelineMavenConfig> c = mockStatic(GlobalPipelineMavenConfig.class)) {
c.when(GlobalPipelineMavenConfig::get).thenReturn(config);
when(config.getJdbcUrl()).thenReturn(null);
when(config.isDaoInitialized()).thenReturn(false);

assertThat(monitor.isActivated(), is(false));

verify(config).getJdbcUrl();
verify(config).isDaoInitialized();
verifyNoMoreInteractions(config, dao);
}
}

@Test
public void test_is_activated_empty_config_and_uninitialized() {
try (MockedStatic<GlobalPipelineMavenConfig> c = mockStatic(GlobalPipelineMavenConfig.class)) {
c.when(GlobalPipelineMavenConfig::get).thenReturn(config);
when(config.getJdbcUrl()).thenReturn("");
when(config.isDaoInitialized()).thenReturn(false);

assertThat(monitor.isActivated(), is(false));

verify(config).getJdbcUrl();
verify(config).isDaoInitialized();
verifyNoMoreInteractions(config, dao);
}
}

@Test
public void test_is_activated_no_config_and_initialized_non_production() {
try (MockedStatic<GlobalPipelineMavenConfig> c = mockStatic(GlobalPipelineMavenConfig.class)) {
c.when(GlobalPipelineMavenConfig::get).thenReturn(config);
when(config.getJdbcUrl()).thenReturn(null);
when(config.isDaoInitialized()).thenReturn(true);
when(config.getDao()).thenReturn(dao);
when(dao.isEnoughProductionGradeForTheWorkload()).thenReturn(false);

assertThat(monitor.isActivated(), is(true));

verify(config).getJdbcUrl();
verify(config).getDao();
verify(config).isDaoInitialized();
verify(dao).isEnoughProductionGradeForTheWorkload();
verifyNoMoreInteractions(config, dao);
}
}

@Test
public void test_is_activated_empty_config_and_initialized_non_production() {
try (MockedStatic<GlobalPipelineMavenConfig> c = mockStatic(GlobalPipelineMavenConfig.class)) {
c.when(GlobalPipelineMavenConfig::get).thenReturn(config);
when(config.getJdbcUrl()).thenReturn("");
when(config.isDaoInitialized()).thenReturn(true);
when(config.getDao()).thenReturn(dao);
when(dao.isEnoughProductionGradeForTheWorkload()).thenReturn(false);

assertThat(monitor.isActivated(), is(true));

verify(config).getJdbcUrl();
verify(config).getDao();
verify(config).isDaoInitialized();
verify(dao).isEnoughProductionGradeForTheWorkload();
verifyNoMoreInteractions(config, dao);
}
}

@Test
public void test_is_activated_no_config_and_initialized_production() {
try (MockedStatic<GlobalPipelineMavenConfig> c = mockStatic(GlobalPipelineMavenConfig.class)) {
c.when(GlobalPipelineMavenConfig::get).thenReturn(config);
when(config.getJdbcUrl()).thenReturn(null);
when(config.isDaoInitialized()).thenReturn(true);
when(config.getDao()).thenReturn(dao);
when(dao.isEnoughProductionGradeForTheWorkload()).thenReturn(true);

assertThat(monitor.isActivated(), is(false));

verify(config).getJdbcUrl();
verify(config).getDao();
verify(config).isDaoInitialized();
verify(dao).isEnoughProductionGradeForTheWorkload();
verifyNoMoreInteractions(config, dao);
}
}

@Test
public void test_is_activated_empty_config_and_initialized_production() {
try (MockedStatic<GlobalPipelineMavenConfig> c = mockStatic(GlobalPipelineMavenConfig.class)) {
c.when(GlobalPipelineMavenConfig::get).thenReturn(config);
when(config.getJdbcUrl()).thenReturn("");
when(config.isDaoInitialized()).thenReturn(true);
when(config.getDao()).thenReturn(dao);
when(dao.isEnoughProductionGradeForTheWorkload()).thenReturn(true);

assertThat(monitor.isActivated(), is(false));

verify(config).getJdbcUrl();
verify(config).getDao();
verify(config).isDaoInitialized();
verify(dao).isEnoughProductionGradeForTheWorkload();
verifyNoMoreInteractions(config, dao);
}
}

@Test
public void test_is_activated_with_h2_config() {
try (MockedStatic<GlobalPipelineMavenConfig> c = mockStatic(GlobalPipelineMavenConfig.class)) {
c.when(GlobalPipelineMavenConfig::get).thenReturn(config);
when(config.getJdbcUrl()).thenReturn("jdbc:h2:some url");

assertThat(monitor.isActivated(), is(true));

verify(config).getJdbcUrl();
verifyNoMoreInteractions(config, dao);
}
}

@Test
public void test_is_activated_with_mysql_config() {
try (MockedStatic<GlobalPipelineMavenConfig> c = mockStatic(GlobalPipelineMavenConfig.class)) {
c.when(GlobalPipelineMavenConfig::get).thenReturn(config);
when(config.getJdbcUrl()).thenReturn("jdbc:mysql:some url");

assertThat(monitor.isActivated(), is(false));

verify(config).getJdbcUrl();
verifyNoMoreInteractions(config, dao);
}
}

@Test
public void test_is_activated_with_postgresql_config() {
try (MockedStatic<GlobalPipelineMavenConfig> c = mockStatic(GlobalPipelineMavenConfig.class)) {
c.when(GlobalPipelineMavenConfig::get).thenReturn(config);
when(config.getJdbcUrl()).thenReturn("jdbc:postgresql:some url");

assertThat(monitor.isActivated(), is(false));

verify(config).getJdbcUrl();
verifyNoMoreInteractions(config, dao);
}
}
}

0 comments on commit 1fce0b9

Please sign in to comment.