From: Sébastien Lesaint Date: Tue, 17 Oct 2017 13:54:04 +0000 (+0200) Subject: SONAR-9939 implementation of api/editions/preview X-Git-Tag: 6.7-RC1~97 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a39dc29dc095f88afc2a9b3b6122c13718ba1714;p=sonarqube.git SONAR-9939 implementation of api/editions/preview --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/edition/ws/PreviewAction.java b/server/sonar-server/src/main/java/org/sonar/server/edition/ws/PreviewAction.java index 15031634963..b159e48d9c3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/edition/ws/PreviewAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/edition/ws/PreviewAction.java @@ -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 { diff --git a/server/sonar-server/src/test/java/org/sonar/server/edition/ws/PreviewActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/edition/ws/PreviewActionTest.java index 46efe099940..718b5207b23 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/edition/ws/PreviewActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/edition/ws/PreviewActionTest.java @@ -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())