Commit cc6855cc authored by Jason Song's avatar Jason Song Committed by GitHub

add operator to rollback release open api (#2636)

parent 15714ac9
...@@ -187,10 +187,11 @@ public class ApolloOpenApiClient { ...@@ -187,10 +187,11 @@ public class ApolloOpenApiClient {
/** /**
* Rollback the release * Rollback the release
* *
* @param operator the user who rollbacks the release
* @since 1.5.0 * @since 1.5.0
*/ */
public void rollbackRelease(String env, long releaseId) { public void rollbackRelease(String env, long releaseId, String operator) {
releaseService.rollbackRelease(env, releaseId); releaseService.rollbackRelease(env, releaseId, operator);
} }
......
package com.ctrip.framework.apollo.openapi.client.service; package com.ctrip.framework.apollo.openapi.client.service;
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.openapi.dto.OpenClusterDTO; import com.ctrip.framework.apollo.openapi.dto.OpenClusterDTO;
import com.google.common.base.Strings;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
...@@ -15,7 +17,10 @@ public class ClusterOpenApiService extends AbstractOpenApiService { ...@@ -15,7 +17,10 @@ public class ClusterOpenApiService extends AbstractOpenApiService {
public OpenClusterDTO getCluster(String appId, String env, String clusterName) { public OpenClusterDTO getCluster(String appId, String env, String clusterName) {
checkNotEmpty(appId, "App id"); checkNotEmpty(appId, "App id");
checkNotEmpty(env, "Env"); checkNotEmpty(env, "Env");
checkNotEmpty(clusterName, "Cluster name");
if (Strings.isNullOrEmpty(clusterName)) {
clusterName = ConfigConsts.CLUSTER_NAME_DEFAULT;
}
String path = String.format("envs/%s/apps/%s/clusters/%s", escapePath(env), escapePath(appId), String path = String.format("envs/%s/apps/%s/clusters/%s", escapePath(env), escapePath(appId),
escapePath(clusterName)); escapePath(clusterName));
......
...@@ -64,10 +64,12 @@ public class ReleaseOpenApiService extends AbstractOpenApiService { ...@@ -64,10 +64,12 @@ public class ReleaseOpenApiService extends AbstractOpenApiService {
} }
} }
public void rollbackRelease(String env, long releaseId) { public void rollbackRelease(String env, long releaseId, String operator) {
checkNotEmpty(env, "Env"); checkNotEmpty(env, "Env");
checkNotEmpty(operator, "Operator");
String path = String.format("envs/%s/releases/%s/rollback", escapePath(env), releaseId); String path = String.format("envs/%s/releases/%s/rollback?operator=%s", escapePath(env), releaseId,
escapeParam(operator));
try (CloseableHttpResponse ignored = put(path, null)) { try (CloseableHttpResponse ignored = put(path, null)) {
} catch (Throwable ex) { } catch (Throwable ex) {
......
...@@ -100,25 +100,28 @@ public class ReleaseOpenApiServiceTest extends AbstractOpenApiServiceTest { ...@@ -100,25 +100,28 @@ public class ReleaseOpenApiServiceTest extends AbstractOpenApiServiceTest {
@Test @Test
public void testRollbackRelease() throws Exception { public void testRollbackRelease() throws Exception {
long someReleaseId = 1L; long someReleaseId = 1L;
String someOperator = "someOperator";
final ArgumentCaptor<HttpPut> request = ArgumentCaptor.forClass(HttpPut.class); final ArgumentCaptor<HttpPut> request = ArgumentCaptor.forClass(HttpPut.class);
releaseOpenApiService.rollbackRelease(someEnv, someReleaseId); releaseOpenApiService.rollbackRelease(someEnv, someReleaseId, someOperator);
verify(httpClient, times(1)).execute(request.capture()); verify(httpClient, times(1)).execute(request.capture());
HttpPut put = request.getValue(); HttpPut put = request.getValue();
assertEquals(String assertEquals(
.format("%s/envs/%s/releases/%s/rollback", someBaseUrl, someEnv, someReleaseId), put.getURI().toString()); String.format("%s/envs/%s/releases/%s/rollback?operator=%s", someBaseUrl, someEnv, someReleaseId, someOperator),
put.getURI().toString());
} }
@Test(expected = RuntimeException.class) @Test(expected = RuntimeException.class)
public void testRollbackReleaseWithError() throws Exception { public void testRollbackReleaseWithError() throws Exception {
long someReleaseId = 1L; long someReleaseId = 1L;
String someOperator = "someOperator";
when(statusLine.getStatusCode()).thenReturn(400); when(statusLine.getStatusCode()).thenReturn(400);
releaseOpenApiService.rollbackRelease(someEnv, someReleaseId); releaseOpenApiService.rollbackRelease(someEnv, someReleaseId, someOperator);
} }
} }
...@@ -15,6 +15,7 @@ import com.ctrip.framework.apollo.portal.entity.model.NamespaceGrayDelReleaseMod ...@@ -15,6 +15,7 @@ import com.ctrip.framework.apollo.portal.entity.model.NamespaceGrayDelReleaseMod
import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel; import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.service.NamespaceBranchService; import com.ctrip.framework.apollo.portal.service.NamespaceBranchService;
import com.ctrip.framework.apollo.portal.service.ReleaseService; import com.ctrip.framework.apollo.portal.service.ReleaseService;
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
import com.ctrip.framework.apollo.portal.spi.UserService; import com.ctrip.framework.apollo.portal.spi.UserService;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.AccessDeniedException;
...@@ -160,7 +161,14 @@ public class ReleaseController { ...@@ -160,7 +161,14 @@ public class ReleaseController {
@PutMapping(path = "/releases/{releaseId}/rollback") @PutMapping(path = "/releases/{releaseId}/rollback")
public void rollback(@PathVariable String env, public void rollback(@PathVariable String env,
@PathVariable long releaseId, HttpServletRequest request) { @PathVariable long releaseId, @RequestParam String operator, HttpServletRequest request) {
RequestPrecondition.checkArguments(!StringUtils.isContainEmpty(operator),
"Param operator can not be empty");
if (userService.findByUserId(operator) == null) {
throw new BadRequestException("user(operator) not exists");
}
ReleaseDTO release = releaseService.findReleaseById(Env.fromString(env), releaseId); ReleaseDTO release = releaseService.findReleaseById(Env.fromString(env), releaseId);
if (release == null) { if (release == null) {
...@@ -171,7 +179,7 @@ public class ReleaseController { ...@@ -171,7 +179,7 @@ public class ReleaseController {
throw new AccessDeniedException("Forbidden operation. you don't have release permission"); throw new AccessDeniedException("Forbidden operation. you don't have release permission");
} }
releaseService.rollback(Env.fromString(env), releaseId); releaseService.rollback(Env.fromString(env), releaseId, operator);
} }
......
...@@ -3,7 +3,6 @@ package com.ctrip.framework.apollo.portal.controller; ...@@ -3,7 +3,6 @@ package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.dto.ReleaseDTO;
import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.common.exception.NotFoundException;
import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.component.PermissionValidator; import com.ctrip.framework.apollo.portal.component.PermissionValidator;
import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.component.config.PortalConfig;
...@@ -12,6 +11,7 @@ import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel; ...@@ -12,6 +11,7 @@ import com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel;
import com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult; import com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult;
import com.ctrip.framework.apollo.portal.listener.ConfigPublishEvent; import com.ctrip.framework.apollo.portal.listener.ConfigPublishEvent;
import com.ctrip.framework.apollo.portal.service.ReleaseService; import com.ctrip.framework.apollo.portal.service.ReleaseService;
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.Positive; import javax.validation.constraints.Positive;
import javax.validation.constraints.PositiveOrZero; import javax.validation.constraints.PositiveOrZero;
...@@ -29,9 +29,6 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -29,9 +29,6 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;
@Validated @Validated
@RestController @RestController
...@@ -41,16 +38,19 @@ public class ReleaseController { ...@@ -41,16 +38,19 @@ public class ReleaseController {
private final ApplicationEventPublisher publisher; private final ApplicationEventPublisher publisher;
private final PortalConfig portalConfig; private final PortalConfig portalConfig;
private final PermissionValidator permissionValidator; private final PermissionValidator permissionValidator;
private final UserInfoHolder userInfoHolder;
public ReleaseController( public ReleaseController(
final ReleaseService releaseService, final ReleaseService releaseService,
final ApplicationEventPublisher publisher, final ApplicationEventPublisher publisher,
final PortalConfig portalConfig, final PortalConfig portalConfig,
final PermissionValidator permissionValidator) { final PermissionValidator permissionValidator,
final UserInfoHolder userInfoHolder) {
this.releaseService = releaseService; this.releaseService = releaseService;
this.publisher = publisher; this.publisher = publisher;
this.portalConfig = portalConfig; this.portalConfig = portalConfig;
this.permissionValidator = permissionValidator; this.permissionValidator = permissionValidator;
this.userInfoHolder = userInfoHolder;
} }
@PreAuthorize(value = "@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName, #env)") @PreAuthorize(value = "@permissionValidator.hasReleaseNamespacePermission(#appId, #namespaceName, #env)")
...@@ -164,7 +164,7 @@ public class ReleaseController { ...@@ -164,7 +164,7 @@ public class ReleaseController {
throw new AccessDeniedException("Access is denied"); throw new AccessDeniedException("Access is denied");
} }
releaseService.rollback(Env.valueOf(env), releaseId); releaseService.rollback(Env.valueOf(env), releaseId, userInfoHolder.getUser().getUserId());
ConfigPublishEvent event = ConfigPublishEvent.instance(); ConfigPublishEvent event = ConfigPublishEvent.instance();
event.withAppId(release.getAppId()) event.withAppId(release.getAppId())
......
...@@ -140,8 +140,8 @@ public class ReleaseService { ...@@ -140,8 +140,8 @@ public class ReleaseService {
return releaseAPI.loadLatestRelease(appId, env, clusterName, namespaceName); return releaseAPI.loadLatestRelease(appId, env, clusterName, namespaceName);
} }
public void rollback(Env env, long releaseId) { public void rollback(Env env, long releaseId, String operator) {
releaseAPI.rollback(env, releaseId, userInfoHolder.getUser().getUserId()); releaseAPI.rollback(env, releaseId, operator);
} }
public ReleaseCompareResult compare(Env env, long baseReleaseId, long toCompareReleaseId) { public ReleaseCompareResult compare(Env env, long baseReleaseId, long toCompareReleaseId) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment