]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7271 add "Server ID validated" to sysinfo page
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 17 May 2016 12:49:08 +0000 (14:49 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Wed, 18 May 2016 09:04:36 +0000 (11:04 +0200)
server/sonar-server/src/main/java/org/sonar/server/platform/ServerId.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/platform/ServerIdGenerator.java
server/sonar-server/src/main/java/org/sonar/server/platform/ServerIdLoader.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java
server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitorMBean.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel3.java
server/sonar-server/src/test/java/org/sonar/server/platform/ServerIdLoaderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SonarQubeMonitorTest.java
sonar-core/src/test/java/org/sonar/core/config/CorePropertyDefinitionsTest.java

diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerId.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerId.java
new file mode 100644 (file)
index 0000000..656cc94
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+public final class ServerId {
+  private final String id;
+  private final boolean valid;
+
+  public ServerId(String id, boolean valid) {
+    this.id = id;
+    this.valid = valid;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public boolean isValid() {
+    return valid;
+  }
+}
index 3b848db52eb7b05be1c9d494e8d2bed82bee49e6..099e142f8ff0bfbe14df8b4b38e883c3663ccb08 100644 (file)
 package org.sonar.server.platform;
 
 import com.google.common.collect.Lists;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.utils.log.Loggers;
-
 import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
@@ -32,6 +28,9 @@ import java.net.UnknownHostException;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.regex.Pattern;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.utils.log.Loggers;
 
 /**
  * @since 2.11
@@ -91,7 +90,7 @@ public class ServerIdGenerator {
     }
   }
 
-  public InetAddress toValidAddress(String ipAddress) {
+  private InetAddress toValidAddress(String ipAddress) {
     if (StringUtils.isNotBlank(ipAddress)) {
       List<InetAddress> validAddresses = getAvailableAddresses();
       try {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerIdLoader.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerIdLoader.java
new file mode 100644 (file)
index 0000000..37f9fd5
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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;
+
+import com.google.common.base.Optional;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+
+import static com.google.common.base.Optional.fromNullable;
+
+public class ServerIdLoader {
+
+  private final Settings settings;
+  private final ServerIdGenerator idGenerator;
+
+  public ServerIdLoader(Settings settings, ServerIdGenerator idGenerator) {
+    this.settings = settings;
+    this.idGenerator = idGenerator;
+  }
+
+  public Optional<String> getRaw() {
+    return fromNullable(settings.getString(CoreProperties.PERMANENT_SERVER_ID));
+  }
+
+  public Optional<ServerId> get() {
+    Optional<String> rawId = getRaw();
+    if (!rawId.isPresent()) {
+      return Optional.absent();
+    }
+
+    String organisation = settings.getString(CoreProperties.ORGANISATION);
+    String ipAddress = settings.getString(CoreProperties.SERVER_ID_IP_ADDRESS);
+    boolean validated;
+    if (organisation == null || ipAddress == null) {
+      validated = false;
+    } else {
+      String generatedId = idGenerator.generate(organisation, ipAddress);
+      validated = generatedId != null && generatedId.equals(rawId.get());
+    }
+    return Optional.of(new ServerId(rawId.get(), validated));
+  }
+}
index 4671717239b94cba1ac0a95ff9b58a3c42e82b99..36b0fed9ec2011ef06414961f77b9a79b099911b 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.server.platform.monitoring;
 
 import com.google.common.base.Function;
 import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import java.io.File;
 import java.util.LinkedHashMap;
@@ -36,6 +37,8 @@ import org.sonar.api.security.SecurityRealm;
 import org.sonar.api.server.authentication.IdentityProvider;
 import org.sonar.process.ProcessProperties;
 import org.sonar.server.authentication.IdentityProviderRepository;
+import org.sonar.server.platform.ServerId;
+import org.sonar.server.platform.ServerIdLoader;
 import org.sonar.server.platform.ServerLogging;
 import org.sonar.server.user.SecurityRealmFactory;
 
@@ -52,19 +55,22 @@ public class SonarQubeMonitor extends BaseMonitorMBean implements SonarQubeMonit
   private final IdentityProviderRepository identityProviderRepository;
   private final Server server;
   private final ServerLogging serverLogging;
+  private final ServerIdLoader serverIdLoader;
 
   public SonarQubeMonitor(Settings settings, SecurityRealmFactory securityRealmFactory,
-    IdentityProviderRepository identityProviderRepository, Server server, ServerLogging serverLogging) {
+    IdentityProviderRepository identityProviderRepository, Server server, ServerLogging serverLogging,
+    ServerIdLoader serverIdLoader) {
     this.settings = settings;
     this.securityRealmFactory = securityRealmFactory;
     this.identityProviderRepository = identityProviderRepository;
     this.server = server;
     this.serverLogging = serverLogging;
+    this.serverIdLoader = serverIdLoader;
   }
 
   @Override
   public String getServerId() {
-    return settings.getString(CoreProperties.PERMANENT_SERVER_ID);
+    return serverIdLoader.getRaw().orNull();
   }
 
   @Override
@@ -126,7 +132,7 @@ public class SonarQubeMonitor extends BaseMonitorMBean implements SonarQubeMonit
   @Override
   public Map<String, Object> attributes() {
     Map<String, Object> attributes = new LinkedHashMap<>();
-    attributes.put("Server ID", getServerId());
+    completeWithServerIdAttributes(attributes);
     attributes.put("Version", getVersion());
     addIfNotNull("External User Authentication", getExternalUserAuthentication(), attributes);
     addIfNotEmpty("Accepted external identity providers", getEnabledIdentityProviders(), attributes);
@@ -143,6 +149,14 @@ public class SonarQubeMonitor extends BaseMonitorMBean implements SonarQubeMonit
     return attributes;
   }
 
+  private void completeWithServerIdAttributes(Map<String, Object> attributes) {
+    Optional<ServerId> serverId = serverIdLoader.get();
+    if (serverId.isPresent()) {
+      attributes.put("Server ID", serverId.get().getId());
+      attributes.put("Server ID validated", serverId.get().isValid());
+    }
+  }
+
   private static void addIfNotNull(String key, @Nullable String value, Map<String, Object> attributes) {
     if (value != null) {
       attributes.put(key, value);
index 253402ab2588a342cdaedeff323a06b0ddd74dbd..9c901e04a66e01ea5ebf753c55dffca18fa62317 100644 (file)
  */
 package org.sonar.server.platform.monitoring;
 
+import javax.annotation.CheckForNull;
+
 public interface SonarQubeMonitorMBean {
+  @CheckForNull
   String getServerId();
 
   String getVersion();
index 5ea1a716b6cfb112b00a39414f29dccced65191c..060eae8ee9c8832ea54c11a9b81b4e66b09a8f26 100644 (file)
@@ -24,6 +24,7 @@ import org.sonar.core.util.DefaultHttpDownloader;
 import org.sonar.server.db.CheckDatabaseCharsetAfterMigration;
 import org.sonar.server.platform.PersistentSettings;
 import org.sonar.server.platform.ServerIdGenerator;
+import org.sonar.server.platform.ServerIdLoader;
 import org.sonar.server.startup.ServerMetadataPersister;
 
 public class PlatformLevel3 extends PlatformLevel {
@@ -39,6 +40,7 @@ public class PlatformLevel3 extends PlatformLevel {
       ServerMetadataPersister.class,
       DefaultHttpDownloader.class,
       UriReader.class,
+      ServerIdLoader.class,
       ServerIdGenerator.class);
   }
 }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ServerIdLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ServerIdLoaderTest.java
new file mode 100644 (file)
index 0000000..f95f896
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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;
+
+import com.google.common.base.Optional;
+import org.junit.Test;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+public class ServerIdLoaderTest {
+
+  private static final String AN_ID = "ABC";
+  private static final String AN_IP = "1.2.3.4";
+  public static final String AN_ORGANISATION = "corp";
+
+  Settings settings = new Settings();
+  ServerIdGenerator idGenerator = mock(ServerIdGenerator.class);
+  ServerIdLoader underTest = new ServerIdLoader(settings, idGenerator);
+
+  @Test
+  public void get_returns_absent_if_id_property_is_not_set() {
+    settings.setProperty(CoreProperties.ORGANISATION, AN_ORGANISATION);
+    settings.setProperty(CoreProperties.SERVER_ID_IP_ADDRESS, AN_IP);
+
+    Optional<ServerId> serverIdOpt = underTest.get();
+    assertThat(serverIdOpt.isPresent()).isFalse();
+    verifyZeroInteractions(idGenerator);
+  }
+
+  @Test
+  public void get_returns_valid_id() {
+    settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+    settings.setProperty(CoreProperties.ORGANISATION, AN_ORGANISATION);
+    settings.setProperty(CoreProperties.SERVER_ID_IP_ADDRESS, AN_IP);
+    when(idGenerator.generate(AN_ORGANISATION, AN_IP)).thenReturn(AN_ID);
+
+    Optional<ServerId> serverIdOpt = underTest.get();
+    verifyServerId(serverIdOpt.get(), AN_ID, true);
+    verify(idGenerator).generate(AN_ORGANISATION, AN_IP);
+  }
+
+  @Test
+  public void get_returns_invalid_id_if_id_cant_be_generated_because_missing_organisation() {
+    settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+    settings.setProperty(CoreProperties.SERVER_ID_IP_ADDRESS, AN_IP);
+
+    Optional<ServerId> serverIdOpt = underTest.get();
+
+    verifyServerId(serverIdOpt.get(), AN_ID, false);
+  }
+
+  @Test
+  public void get_returns_invalid_id_if_id_cant_be_generated_because_missing_ip() {
+    settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+    settings.setProperty(CoreProperties.ORGANISATION, AN_ORGANISATION);
+
+    Optional<ServerId> serverIdOpt = underTest.get();
+
+    verifyServerId(serverIdOpt.get(), AN_ID, false);
+    verifyZeroInteractions(idGenerator);
+  }
+
+  @Test
+  public void get_returns_invalid_id_if_id_cant_be_generated_because_missing_ip_and_organisation() {
+    settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+
+    Optional<ServerId> serverIdOpt = underTest.get();
+
+    verifyServerId(serverIdOpt.get(), AN_ID, false);
+    verifyZeroInteractions(idGenerator);
+  }
+
+  @Test
+  public void get_returns_invalid_id_if_input_is_different_than_newly_generated_id() {
+    settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+    settings.setProperty(CoreProperties.ORGANISATION, AN_ORGANISATION);
+    settings.setProperty(CoreProperties.SERVER_ID_IP_ADDRESS, AN_IP);
+    when(idGenerator.generate(AN_ORGANISATION, AN_IP)).thenReturn("OTHER");
+
+    Optional<ServerId> serverIdOpt = underTest.get();
+
+    verifyServerId(serverIdOpt.get(), AN_ID, false);
+    verify(idGenerator).generate(AN_ORGANISATION, AN_IP);
+  }
+
+  @Test
+  public void getRaw_loads_id_from_settings() {
+    assertThat(underTest.getRaw().isPresent()).isFalse();
+
+    settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, AN_ID);
+    assertThat(underTest.getRaw().isPresent()).isTrue();
+  }
+
+  private static void verifyServerId(ServerId serverId, String expectedId, boolean expectedValid) {
+    assertThat(serverId.getId()).isEqualTo(expectedId);
+    assertThat(serverId.isValid()).isEqualTo(expectedValid);
+  }
+}
index 2de59d3a6c950596385cc5d0d185873a5ec403c2..aa50419bf76e1869a78c1f2a82490273a85628f0 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.platform.monitoring;
 
+import com.google.common.base.Optional;
 import java.io.File;
 import java.util.Map;
 import org.apache.commons.io.FileUtils;
@@ -29,19 +30,25 @@ import org.junit.rules.TemporaryFolder;
 import org.sonar.api.config.Settings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.security.SecurityRealm;
-import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.server.authentication.IdentityProviderRepositoryRule;
 import org.sonar.server.authentication.TestIdentityProvider;
+import org.sonar.server.platform.ServerId;
+import org.sonar.server.platform.ServerIdLoader;
 import org.sonar.server.platform.ServerLogging;
 import org.sonar.server.user.SecurityRealmFactory;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.data.MapEntry.entry;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 public class SonarQubeMonitorTest {
 
+  private static final String SERVER_ID_PROPERTY = "Server ID";
+  private static final String SERVER_ID_VALIDATED_PROPERTY = "Server ID validated";
+
   @Rule
   public TemporaryFolder temp = new TemporaryFolder();
 
@@ -50,10 +57,12 @@ public class SonarQubeMonitorTest {
 
   Settings settings = new Settings();
   Server server = mock(Server.class);
+  ServerIdLoader serverIdLoader = mock(ServerIdLoader.class, RETURNS_DEEP_STUBS);
   ServerLogging serverLogging = mock(ServerLogging.class);
   SecurityRealmFactory securityRealmFactory = mock(SecurityRealmFactory.class);
 
-  SonarQubeMonitor underTest = new SonarQubeMonitor(settings, securityRealmFactory, identityProviderRepository, server, serverLogging);
+  SonarQubeMonitor underTest = new SonarQubeMonitor(settings, securityRealmFactory, identityProviderRepository, server,
+    serverLogging, serverIdLoader);
 
   @Before
   public void setUp() throws Exception {
@@ -66,11 +75,36 @@ public class SonarQubeMonitorTest {
   }
 
   @Test
-  public void getServerId() {
-    when(server.getStartedAt()).thenReturn(DateUtils.parseDate("2015-01-01"));
+  public void test_getServerId() {
+    when(serverIdLoader.getRaw()).thenReturn(Optional.of("ABC"));
+    assertThat(underTest.getServerId()).isEqualTo("ABC");
+
+    when(serverIdLoader.getRaw()).thenReturn(Optional.<String>absent());
+    assertThat(underTest.getServerId()).isNull();
+  }
+
+  @Test
+  public void attributes_contain_information_about_valid_server_id() {
+    when(serverIdLoader.get()).thenReturn(Optional.of(new ServerId("ABC", true)));
+
+    Map<String, Object> attributes = underTest.attributes();
+    assertThat(attributes).contains(entry(SERVER_ID_PROPERTY, "ABC"), entry(SERVER_ID_VALIDATED_PROPERTY, true));
+  }
+
+  @Test
+  public void attributes_contain_information_about_non_valid_server_id() {
+    when(serverIdLoader.get()).thenReturn(Optional.of(new ServerId("ABC", false)));
+
+    Map<String, Object> attributes = underTest.attributes();
+    assertThat(attributes).contains(entry(SERVER_ID_PROPERTY, "ABC"), entry(SERVER_ID_VALIDATED_PROPERTY, false));
+  }
+
+  @Test
+  public void attributes_do_not_contain_information_about_server_id_if_absent() {
+    when(serverIdLoader.get()).thenReturn(Optional.<ServerId>absent());
 
     Map<String, Object> attributes = underTest.attributes();
-    assertThat(attributes).containsKeys("Server ID", "Version");
+    assertThat(attributes).doesNotContainKeys(SERVER_ID_PROPERTY, SERVER_ID_VALIDATED_PROPERTY);
   }
 
   @Test
index 3791869abe1e74bb79dd7bfffb8c2172001757e6..4e66c693efbbba91d67a83a530a2dc97e53a33fe 100644 (file)
@@ -42,7 +42,6 @@ public class CorePropertyDefinitionsTest {
   public void jdbc_password_property_has_password_type() {
     List<PropertyDefinition> defs = CorePropertyDefinitions.all();
     Optional<PropertyDefinition> prop = from(defs).filter(new HasKeyPredicate(DatabaseProperties.PROP_PASSWORD)).first();
-    assertThat(prop.isPresent()).isTrue();
     assertThat(prop.get().type()).isEqualTo(PropertyType.PASSWORD);
   }