]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9939 implementation of api/editions/preview
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 17 Oct 2017 13:54:04 +0000 (15:54 +0200)
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>
Mon, 23 Oct 2017 15:01:13 +0000 (08:01 -0700)
server/sonar-server/src/main/java/org/sonar/server/edition/ws/PreviewAction.java
server/sonar-server/src/test/java/org/sonar/server/edition/ws/PreviewActionTest.java

index 150316349631added3a800cfaa8e749b42fdb129..b159e48d9c30567fa60f3246dfeb84ea018faa57 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.server.edition.ws;
 
-import java.util.Collections;
 import java.util.Optional;
 import javax.annotation.Nullable;
 import org.sonar.api.server.ws.Request;
@@ -28,6 +27,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.server.edition.EditionManagementState;
 import org.sonar.server.edition.License;
 import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.plugins.edition.EditionInstaller;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.ws.WsUtils;
 import org.sonarqube.ws.WsEditions;
@@ -42,10 +42,12 @@ public class PreviewAction implements EditionsWsAction {
 
   private final UserSession userSession;
   private final EditionManagementState editionManagementState;
+  private final EditionInstaller editionInstaller;
 
-  public PreviewAction(UserSession userSession, EditionManagementState editionManagementState) {
+  public PreviewAction(UserSession userSession, EditionManagementState editionManagementState, EditionInstaller editionInstaller) {
     this.userSession = userSession;
     this.editionManagementState = editionManagementState;
+    this.editionInstaller = editionInstaller;
   }
 
   @Override
@@ -71,10 +73,13 @@ public class PreviewAction implements EditionsWsAction {
       throw BadRequestException.create("Can't apply a license when applying one is already in progress");
     }
 
-    String license = request.mandatoryParam(PARAM_LICENSE);
-    License newLicense = new License(license, Collections.emptyList(), license);
-    NextState nextState = computeNextState(newLicense);
+    String licenseParam = request.mandatoryParam(PARAM_LICENSE);
+    if (licenseParam.isEmpty()) {
+      throw new IllegalArgumentException(String.format("The '%s' parameter is empty", PARAM_LICENSE));
+    }
+    License newLicense = License.parse(licenseParam).orElseThrow(() -> BadRequestException.create("The license provided is invalid"));
 
+    NextState nextState = computeNextState(newLicense);
     WsUtils.writeProtobuf(buildResponse(nextState), request, response);
   }
 
@@ -85,14 +90,14 @@ public class PreviewAction implements EditionsWsAction {
       .build();
   }
 
-  private static NextState computeNextState(License newLicense) {
-    String licenseContent = newLicense.getContent();
-    if (licenseContent.contains("manual")) {
-      return new NextState(newLicense.getEditionKey(), MANUAL_INSTALL);
-    } else if (licenseContent.contains("done")) {
+  private NextState computeNextState(License newLicense) {
+    if (!editionInstaller.requiresInstallationChange(newLicense.getPluginKeys())) {
       return new NextState(newLicense.getEditionKey(), NO_INSTALL);
+    } else if (editionInstaller.isOffline()) {
+      return new NextState(newLicense.getEditionKey(), MANUAL_INSTALL);
+    } else {
+      return new NextState(newLicense.getEditionKey(), AUTOMATIC_INSTALL);
     }
-    return new NextState(newLicense.getEditionKey(), AUTOMATIC_INSTALL);
   }
 
   private static final class NextState {
index 46efe099940d63d36d42f4c17d9c23ee3edf6b45..718b5207b238cc9ee19b32b5c5a7ed6c57e51087 100644 (file)
@@ -22,7 +22,13 @@ package org.sonar.server.edition.ws;
 import com.tngtech.java.junit.dataprovider.DataProvider;
 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
 import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.Properties;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -32,10 +38,16 @@ import org.sonar.server.edition.EditionManagementState;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.plugins.edition.EditionInstaller;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.TestResponse;
 import org.sonar.server.ws.WsActionTester;
 import org.sonar.test.JsonAssert;
+import org.sonarqube.ws.MediaTypes;
+import org.sonarqube.ws.WsEditions;
+import org.sonarqube.ws.WsEditions.PreviewResponse;
+import org.sonarqube.ws.WsEditions.PreviewStatus;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
@@ -52,7 +64,8 @@ public class PreviewActionTest {
   public UserSessionRule userSessionRule = UserSessionRule.standalone();
 
   private EditionManagementState editionManagementState = mock(EditionManagementState.class);
-  private PreviewAction underTest = new PreviewAction(userSessionRule, editionManagementState);
+  private EditionInstaller editionInstaller = mock(EditionInstaller.class);
+  private PreviewAction underTest = new PreviewAction(userSessionRule, editionManagementState, editionInstaller);
   private WsActionTester actionTester = new WsActionTester(underTest);
 
   @Test
@@ -104,6 +117,32 @@ public class PreviewActionTest {
 
     request.execute();
   }
+  
+  @Test
+  public void request_fails_if_license_param_is_empty() {
+    userSessionRule.logIn().setSystemAdministrator();
+    when(editionManagementState.getPendingInstallationStatus()).thenReturn(NONE);
+    TestRequest request = actionTester.newRequest()
+      .setParam(PARAM_LICENSE, "");
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("The 'license' parameter is empty");
+
+    request.execute();
+  }
+
+  @Test
+  public void request_fails_if_license_param_is_invalid() {
+    userSessionRule.logIn().setSystemAdministrator();
+    when(editionManagementState.getPendingInstallationStatus()).thenReturn(NONE);
+    TestRequest request = actionTester.newRequest()
+      .setParam(PARAM_LICENSE, "foo");
+
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("The license provided is invalid");
+
+    request.execute();
+  }
 
   @Test
   @UseDataProvider("notNonePendingInstallationStatuses")
@@ -120,16 +159,76 @@ public class PreviewActionTest {
   }
 
   @Test
-  public void verify_example() {
+  public void verify_example() throws IOException {
     userSessionRule.logIn().setSystemAdministrator();
     when(editionManagementState.getPendingInstallationStatus()).thenReturn(NONE);
+    when(editionInstaller.requiresInstallationChange(Collections.singleton("plugin1"))).thenReturn(true);
+    when(editionInstaller.isOffline()).thenReturn(false);
 
     TestRequest request = actionTester.newRequest()
-      .setParam(PARAM_LICENSE, "developer-edition");
+      .setParam(PARAM_LICENSE, createLicenseParam("developer-edition", "plugin1"));
 
     JsonAssert.assertJson(request.execute().getInput()).isSimilarTo(actionTester.getDef().responseExampleAsString());
   }
 
+  @Test
+  public void license_requires_no_installation() throws IOException {
+    userSessionRule.logIn().setSystemAdministrator();
+    when(editionManagementState.getPendingInstallationStatus()).thenReturn(NONE);
+    when(editionInstaller.requiresInstallationChange(Collections.singleton("plugin1"))).thenReturn(false);
+
+    TestRequest request = actionTester.newRequest()
+      .setMediaType(MediaTypes.PROTOBUF)
+      .setParam(PARAM_LICENSE, createLicenseParam("developer-edition", "plugin1"));
+
+    assertResponse(request.execute(), "developer-edition", PreviewStatus.NO_INSTALL);
+  }
+
+  @Test
+  public void license_will_result_in_auto_install() throws IOException {
+    userSessionRule.logIn().setSystemAdministrator();
+    when(editionManagementState.getPendingInstallationStatus()).thenReturn(NONE);
+    when(editionInstaller.requiresInstallationChange(Collections.singleton("plugin1"))).thenReturn(true);
+    when(editionInstaller.isOffline()).thenReturn(false);
+
+    TestRequest request = actionTester.newRequest()
+      .setMediaType(MediaTypes.PROTOBUF)
+      .setParam(PARAM_LICENSE, createLicenseParam("developer-edition", "plugin1"));
+
+    assertResponse(request.execute(), "developer-edition", PreviewStatus.AUTOMATIC_INSTALL);
+  }
+
+  @Test
+  public void license_will_result_in_manual_install() throws IOException {
+    userSessionRule.logIn().setSystemAdministrator();
+    when(editionManagementState.getPendingInstallationStatus()).thenReturn(NONE);
+    when(editionInstaller.requiresInstallationChange(Collections.singleton("plugin1"))).thenReturn(true);
+    when(editionInstaller.isOffline()).thenReturn(true);
+
+    TestRequest request = actionTester.newRequest()
+      .setMediaType(MediaTypes.PROTOBUF)
+      .setParam(PARAM_LICENSE, createLicenseParam("developer-edition", "plugin1"));
+
+    assertResponse(request.execute(), "developer-edition", PreviewStatus.MANUAL_INSTALL);
+  }
+
+  private void assertResponse(TestResponse response, String expectedNextEditionKey, PreviewStatus expectedPreviewStatus) throws IOException {
+    PreviewResponse parsedResponse = WsEditions.PreviewResponse.parseFrom(response.getInputStream());
+    assertThat(parsedResponse.getPreviewStatus()).isEqualTo(expectedPreviewStatus);
+    assertThat(parsedResponse.getNextEditionKey()).isEqualTo(expectedNextEditionKey);
+  }
+
+  private static String createLicenseParam(String editionKey, String... pluginKeys) throws IOException {
+    Properties props = new Properties();
+    props.setProperty("Plugins", String.join(",", pluginKeys));
+    props.setProperty("Edition", editionKey);
+    StringWriter writer = new StringWriter();
+    props.store(writer, "");
+
+    byte[] encoded = Base64.getEncoder().encode(writer.toString().getBytes());
+    return new String(encoded, StandardCharsets.UTF_8);
+  }
+
   @DataProvider
   public static Object[][] notNonePendingInstallationStatuses() {
     return Arrays.stream(EditionManagementState.PendingStatus.values())