]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10594 fail to drop ES index on blue/green deployments
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 3 May 2018 09:57:35 +0000 (11:57 +0200)
committerSonarTech <sonartech@sonarsource.com>
Thu, 10 May 2018 18:20:55 +0000 (20:20 +0200)
server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java
server/sonar-server/src/main/java/org/sonar/server/es/IndexCreator.java
server/sonar-server/src/test/java/org/sonar/server/es/IndexCreatorTest.java

index a2c62187550afc85fa768e1137d7f75c33cbe342..b4d76fa889d56262afcf43215fafabd4cc3dfd22 100644 (file)
@@ -112,7 +112,12 @@ public class ProcessProperties {
     /**
      * Used by Orchestrator to ask for shutdown of monitor process
      */
-    ENABLE_STOP_COMMAND("sonar.enableStopCommand");
+    ENABLE_STOP_COMMAND("sonar.enableStopCommand"),
+
+    // whether the blue/green deployment of server is enabled
+    BLUE_GREEN_ENABLED("sonar.blueGreenEnabled", "false");
+
+
 
     private final String key;
     private final String defaultValue;
index 9cfc6b3559b0db8b7f413b5ca5945de5896ef469..ac295a599befd79db45b9f5bf4d71f45689bbe72 100644 (file)
@@ -35,6 +35,7 @@ import org.sonar.api.config.Configuration;
 import org.sonar.api.server.ServerSide;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
+import org.sonar.process.ProcessProperties;
 import org.sonar.server.es.IndexDefinitions.Index;
 import org.sonar.server.es.metadata.EsDbCompatibility;
 import org.sonar.server.es.metadata.MetadataIndex;
@@ -82,6 +83,7 @@ public class IndexCreator implements Startable {
     for (Index index : definitions.getIndices().values()) {
       boolean exists = client.prepareIndicesExist(index.getName()).get().isExists();
       if (exists && !index.getName().equals(MetadataIndexDefinition.INDEX_TYPE_METADATA.getIndex()) && hasDefinitionChange(index)) {
+        verifyNotBlueGreenDeployment(index.getName());
         LOGGER.info("Delete Elasticsearch index {} (structure changed)", index.getName());
         deleteIndex(index.getName());
         exists = false;
@@ -92,6 +94,12 @@ public class IndexCreator implements Startable {
     }
   }
 
+  private void verifyNotBlueGreenDeployment(String indexToBeDeleted) {
+    if (configuration.getBoolean(ProcessProperties.Property.BLUE_GREEN_ENABLED.getKey()).orElse(false)) {
+      throw new IllegalStateException("Blue/green deployment is not supported. Elasticsearch index [" + indexToBeDeleted + "] changed and needs to be dropped.");
+    }
+  }
+
   @Override
   public void stop() {
     // nothing to do
index a689dc6e34446167fdcd14bbf6a0640868cb02e8..5c5aeb3fa8d0f4cb3a359486a4ea64ef868af3a4 100644 (file)
@@ -28,6 +28,7 @@ import org.elasticsearch.cluster.metadata.MappingMetaData;
 import org.elasticsearch.common.collect.ImmutableOpenMap;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
@@ -46,7 +47,8 @@ public class IndexCreatorTest {
 
   @Rule
   public LogTester logTester = new LogTester();
-
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
   @Rule
   public EsTester es = EsTester.createCustom();
 
@@ -60,18 +62,22 @@ public class IndexCreatorTest {
     IndexCreator underTest = startNewCreator(new FakeIndexDefinition());
 
     // check that index is created with related mapping
-    ImmutableOpenMap<String, ImmutableOpenMap<String, MappingMetaData>> mappings = mappings();
-    MappingMetaData mapping = mappings.get("fakes").get("fake");
-    assertThat(mapping.type()).isEqualTo("fake");
-    assertThat(mapping.getSourceAsMap()).isNotEmpty();
-    assertThat(countMappingFields(mapping)).isEqualTo(2);
-    assertThat(field(mapping, "updatedAt").get("type")).isEqualTo("date");
+    verifyFakeIndex();
 
     // of course do not delete indices on stop
     underTest.stop();
     assertThat(mappings()).isNotEmpty();
   }
 
+  @Test
+  public void creation_of_new_index_is_supported_in_blue_green_deployment() {
+    enableBlueGreenDeployment();
+
+    startNewCreator(new FakeIndexDefinition());
+
+    verifyFakeIndex();
+  }
+
   @Test
   public void mark_all_non_existing_index_types_as_uninitialized() {
     startNewCreator(context -> {
@@ -107,6 +113,24 @@ public class IndexCreatorTest {
     assertThat(es.client().prepareGet(fakeIndexType, id).get().isExists()).isFalse();
   }
 
+  @Test
+  public void fail_to_recreate_index_on_definition_changes_if_blue_green_deployment() {
+    enableBlueGreenDeployment();
+
+    // v1
+    startNewCreator(new FakeIndexDefinition());
+
+    // v2
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Blue/green deployment is not supported. Elasticsearch index [fakes] changed and needs to be dropped.");
+
+    startNewCreator(new FakeIndexDefinitionV2());
+  }
+
+  private void enableBlueGreenDeployment() {
+    settings.setProperty("sonar.blueGreenEnabled", "true");
+  }
+
   @Test
   public void do_not_recreate_index_on_unchanged_definition() {
     // v1
@@ -219,7 +243,17 @@ public class IndexCreatorTest {
     es.putDocuments(FakeIndexDefinition.INDEX_TYPE, ImmutableMap.of("key", "foo"));
   }
 
+  private void verifyFakeIndex() {
+    ImmutableOpenMap<String, ImmutableOpenMap<String, MappingMetaData>> mappings = mappings();
+    MappingMetaData mapping = mappings.get("fakes").get("fake");
+    assertThat(mapping.type()).isEqualTo("fake");
+    assertThat(mapping.getSourceAsMap()).isNotEmpty();
+    assertThat(countMappingFields(mapping)).isEqualTo(2);
+    assertThat(field(mapping, "updatedAt").get("type")).isEqualTo("date");
+  }
+
   private static class FakeIndexDefinition implements IndexDefinition {
+
     private static final IndexType INDEX_TYPE = new IndexType("fakes", "fake");
 
     @Override
@@ -230,8 +264,8 @@ public class IndexCreatorTest {
       mapping.createDateTimeField("updatedAt");
     }
   }
-
   private static class FakeIndexDefinitionV2 implements IndexDefinition {
+
     @Override
     public void define(IndexDefinitionContext context) {
       NewIndex index = context.create("fakes", SETTINGS_CONFIGURATION);