Skip to content

Commit

Permalink
LICENSE-96 implement support for staging and new server id format
Browse files Browse the repository at this point in the history
  • Loading branch information
sns-seb authored and SonarTech committed Jul 5, 2018
1 parent 69afc80 commit 45f6d41
Show file tree
Hide file tree
Showing 17 changed files with 1,307 additions and 348 deletions.
Expand Up @@ -132,7 +132,6 @@
import org.sonar.server.platform.DatabaseServerCompatibility; import org.sonar.server.platform.DatabaseServerCompatibility;
import org.sonar.server.platform.DefaultServerUpgradeStatus; import org.sonar.server.platform.DefaultServerUpgradeStatus;
import org.sonar.server.platform.ServerFileSystemImpl; import org.sonar.server.platform.ServerFileSystemImpl;
import org.sonar.server.platform.ServerIdManager;
import org.sonar.server.platform.ServerImpl; import org.sonar.server.platform.ServerImpl;
import org.sonar.server.platform.ServerLifecycleNotifier; import org.sonar.server.platform.ServerLifecycleNotifier;
import org.sonar.server.log.ServerLogging; import org.sonar.server.log.ServerLogging;
Expand All @@ -145,6 +144,7 @@
import org.sonar.server.platform.monitoring.DbSection; import org.sonar.server.platform.monitoring.DbSection;
import org.sonar.server.platform.monitoring.OfficialDistribution; import org.sonar.server.platform.monitoring.OfficialDistribution;
import org.sonar.server.platform.monitoring.cluster.ProcessInfoProvider; import org.sonar.server.platform.monitoring.cluster.ProcessInfoProvider;
import org.sonar.server.platform.serverid.ServerIdModule;
import org.sonar.server.plugins.InstalledPluginReferentialFactory; import org.sonar.server.plugins.InstalledPluginReferentialFactory;
import org.sonar.server.plugins.ServerExtensionInstaller; import org.sonar.server.plugins.ServerExtensionInstaller;
import org.sonar.server.property.InternalPropertiesImpl; import org.sonar.server.property.InternalPropertiesImpl;
Expand Down Expand Up @@ -360,7 +360,7 @@ private static void populateLevel2(ComponentContainer container) {
private static void populateLevel3(ComponentContainer container) { private static void populateLevel3(ComponentContainer container) {
container.add( container.add(
new StartupMetadataProvider(), new StartupMetadataProvider(),
ServerIdManager.class, ServerIdModule.class,
UriReader.class, UriReader.class,
ServerImpl.class, ServerImpl.class,
DefaultOrganizationProviderImpl.class, DefaultOrganizationProviderImpl.class,
Expand Down
Expand Up @@ -22,8 +22,11 @@
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import java.util.Properties; import java.util.Properties;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
Expand All @@ -40,7 +43,6 @@
import org.sonar.process.ProcessId; import org.sonar.process.ProcessId;
import org.sonar.process.ProcessProperties; import org.sonar.process.ProcessProperties;
import org.sonar.process.Props; import org.sonar.process.Props;
import org.sonar.server.platform.ServerIdChecksum;
import org.sonar.server.property.InternalProperties; import org.sonar.server.property.InternalProperties;


import static java.lang.String.valueOf; import static java.lang.String.valueOf;
Expand Down Expand Up @@ -84,7 +86,7 @@ public void test_real_start() throws IOException {
// required persisted properties // required persisted properties
insertProperty(CoreProperties.SERVER_ID, "a_server_id"); insertProperty(CoreProperties.SERVER_ID, "a_server_id");
insertProperty(CoreProperties.SERVER_STARTTIME, DateUtils.formatDateTime(new Date())); insertProperty(CoreProperties.SERVER_STARTTIME, DateUtils.formatDateTime(new Date()));
insertInternalProperty(InternalProperties.SERVER_ID_CHECKSUM, ServerIdChecksum.of("a_server_id", db.getUrl())); insertInternalProperty(InternalProperties.SERVER_ID_CHECKSUM, DigestUtils.sha256Hex("a_server_id|" + cleanJdbcUrl()));


underTest underTest
.start(new Props(properties)); .start(new Props(properties));
Expand All @@ -110,6 +112,7 @@ public void test_real_start() throws IOException {
assertThat(picoContainer.getParent().getComponentAdapters()).hasSize( assertThat(picoContainer.getParent().getComponentAdapters()).hasSize(
CONTAINER_ITSELF CONTAINER_ITSELF
+ 7 // level 3 + 7 // level 3
+ 4 // content of ServerIdModule
); );
assertThat(picoContainer.getParent().getParent().getComponentAdapters()).hasSize( assertThat(picoContainer.getParent().getParent().getComponentAdapters()).hasSize(
CONTAINER_ITSELF CONTAINER_ITSELF
Expand Down Expand Up @@ -140,6 +143,10 @@ public void test_real_start() throws IOException {
assertThat(picoContainer.getLifecycleState().isDisposed()).isTrue(); assertThat(picoContainer.getLifecycleState().isDisposed()).isTrue();
} }


private String cleanJdbcUrl() {
return StringUtils.lowerCase(StringUtils.substringBefore(db.getUrl(), "?"), Locale.ENGLISH);
}

private Properties getProperties() throws IOException { private Properties getProperties() throws IOException {
Properties properties = ProcessProperties.defaults(); Properties properties = ProcessProperties.defaults();
File homeDir = tempFolder.newFolder(); File homeDir = tempFolder.newFolder();
Expand Down
Expand Up @@ -26,11 +26,11 @@
import org.sonar.server.async.AsyncExecutionModule; import org.sonar.server.async.AsyncExecutionModule;
import org.sonar.server.organization.DefaultOrganizationProviderImpl; import org.sonar.server.organization.DefaultOrganizationProviderImpl;
import org.sonar.server.organization.OrganizationFlagsImpl; import org.sonar.server.organization.OrganizationFlagsImpl;
import org.sonar.server.platform.ServerIdManager;
import org.sonar.server.platform.ServerImpl; import org.sonar.server.platform.ServerImpl;
import org.sonar.server.platform.StartupMetadataPersister; import org.sonar.server.platform.StartupMetadataPersister;
import org.sonar.server.platform.WebCoreExtensionsInstaller; import org.sonar.server.platform.WebCoreExtensionsInstaller;
import org.sonar.server.platform.db.migration.NoopDatabaseMigrationImpl; import org.sonar.server.platform.db.migration.NoopDatabaseMigrationImpl;
import org.sonar.server.platform.serverid.ServerIdModule;
import org.sonar.server.setting.DatabaseSettingLoader; import org.sonar.server.setting.DatabaseSettingLoader;
import org.sonar.server.setting.DatabaseSettingsEnabler; import org.sonar.server.setting.DatabaseSettingsEnabler;


Expand All @@ -47,7 +47,7 @@ protected void configureLevel() {
addIfStartupLeader(StartupMetadataPersister.class); addIfStartupLeader(StartupMetadataPersister.class);
add( add(
NoopDatabaseMigrationImpl.class, NoopDatabaseMigrationImpl.class,
ServerIdManager.class, ServerIdModule.class,
ServerImpl.class, ServerImpl.class,
DatabaseSettingLoader.class, DatabaseSettingLoader.class,
DatabaseSettingsEnabler.class, DatabaseSettingsEnabler.class,
Expand Down
Expand Up @@ -17,32 +17,20 @@
* along with this program; if not, write to the Free Software Foundation, * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
package org.sonar.server.platform; package org.sonar.server.platform.serverid;


import com.google.common.annotations.VisibleForTesting;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.sonar.api.utils.KeyValueFormat; import org.sonar.api.utils.KeyValueFormat;


public class ServerIdChecksum { public class JdbcUrlSanitizer {

private static final String SQLSERVER_PREFIX = "jdbc:sqlserver://"; private static final String SQLSERVER_PREFIX = "jdbc:sqlserver://";


private ServerIdChecksum() { public String sanitize(String jdbcUrl) {
// only static methods
}

public static String of(String serverId, String jdbcUrl) {
return DigestUtils.sha256Hex(serverId + "|" + sanitizeJdbcUrl(jdbcUrl));
}

@VisibleForTesting
static String sanitizeJdbcUrl(String jdbcUrl) {
String result; String result;
if (jdbcUrl.startsWith(SQLSERVER_PREFIX)) { if (jdbcUrl.startsWith(SQLSERVER_PREFIX)) {
result = sanitizeSqlServerUrl(jdbcUrl); result = sanitizeSqlServerUrl(jdbcUrl);
Expand Down
@@ -0,0 +1,42 @@
/*
* SonarQube
* Copyright (C) 2009-2018 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.platform.serverid;

import org.apache.commons.codec.digest.DigestUtils;
import org.sonar.api.config.Configuration;

import static org.sonar.process.ProcessProperties.Property.JDBC_URL;

public class ServerIdChecksum {

private final Configuration config;
private final JdbcUrlSanitizer jdbcUrlSanitizer;

public ServerIdChecksum(Configuration config, JdbcUrlSanitizer jdbcUrlSanitizer) {
this.config = config;
this.jdbcUrlSanitizer = jdbcUrlSanitizer;
}

public String computeFor(String serverId) {
String jdbcUrl = config.get(JDBC_URL.getKey()).orElseThrow(() -> new IllegalStateException("Missing JDBC URL"));
return DigestUtils.sha256Hex(serverId + "|" + jdbcUrlSanitizer.sanitize(jdbcUrl));
}

}
@@ -0,0 +1,34 @@
/*
* SonarQube
* Copyright (C) 2009-2018 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.platform.serverid;

import org.sonar.core.platform.ServerId;

public interface ServerIdFactory {
/**
* Create a new ServerId from scratch.
*/
ServerId create();

/**
* Create a new ServerId from the current serverId.
*/
ServerId create(ServerId currentServerId);
}
@@ -0,0 +1,69 @@
/*
* SonarQube
* Copyright (C) 2009-2018 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.platform.serverid;

import com.google.common.annotations.VisibleForTesting;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.zip.CRC32;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.config.Configuration;
import org.sonar.core.platform.ServerId;
import org.sonar.core.util.UuidFactory;

import static org.sonar.process.ProcessProperties.Property.JDBC_URL;

public class ServerIdFactoryImpl implements ServerIdFactory {

private final Configuration config;
private final UuidFactory uuidFactory;
private final JdbcUrlSanitizer jdbcUrlSanitizer;

public ServerIdFactoryImpl(Configuration config, UuidFactory uuidFactory, JdbcUrlSanitizer jdbcUrlSanitizer) {
this.config = config;
this.uuidFactory = uuidFactory;
this.jdbcUrlSanitizer = jdbcUrlSanitizer;
}

@Override
public ServerId create() {
return ServerId.of(computeDatabaseId(), uuidFactory.create());
}

@Override
public ServerId create(ServerId currentServerId) {
return ServerId.of(computeDatabaseId(), currentServerId.getDatasetId());
}

private String computeDatabaseId() {
String jdbcUrl = config.get(JDBC_URL.getKey()).orElseThrow(() -> new IllegalStateException("Missing JDBC URL"));
return crc32Hex(jdbcUrlSanitizer.sanitize(jdbcUrl));
}

@VisibleForTesting
static String crc32Hex(String str) {
CRC32 crc32 = new CRC32();
crc32.update(str.getBytes(StandardCharsets.UTF_8));
long hash = crc32.getValue();
String s = Long.toHexString(hash).toUpperCase(Locale.ENGLISH);
return StringUtils.leftPad(s, ServerId.DATABASE_ID_LENGTH, "0");
}

}

0 comments on commit 45f6d41

Please sign in to comment.