Skip to content

Commit

Permalink
Merge pull request cdapio#15396 from cdapio/scm-multi-api
Browse files Browse the repository at this point in the history
Multiple applications push and pull API
  • Loading branch information
samdgupi authored Nov 22, 2023
2 parents 870bb4f + a00f520 commit 05cdf81
Show file tree
Hide file tree
Showing 11 changed files with 722 additions and 196 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@
import io.cdap.cdap.proto.ApplicationRecord;
import io.cdap.cdap.proto.id.ApplicationReference;
import io.cdap.cdap.proto.id.NamespaceId;
import io.cdap.cdap.proto.operation.OperationMeta;
import io.cdap.cdap.proto.operation.OperationRun;
import io.cdap.cdap.proto.sourcecontrol.PullMultipleAppsRequest;
import io.cdap.cdap.proto.sourcecontrol.PushAppRequest;
import io.cdap.cdap.proto.sourcecontrol.PushMultipleAppsRequest;
import io.cdap.cdap.proto.sourcecontrol.RemoteRepositoryValidationException;
import io.cdap.cdap.proto.sourcecontrol.RepositoryConfigRequest;
import io.cdap.cdap.proto.sourcecontrol.RepositoryConfigValidationException;
Expand All @@ -47,7 +51,6 @@
import io.cdap.http.HttpResponder;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
Expand Down Expand Up @@ -183,6 +186,49 @@ public void pushApp(FullHttpRequest request, HttpResponder responder,
}
}

/**
* Pushes application configs of requested applications to linked repository in Json format.
* It expects a post body that has a list of application ids and an optional commit message
* E.g.
*
* <pre>
* {@code
* {
* "appIds": ["app_id_1", "app_id_2"],
* "commitMessage": "pushed application XYZ"
* }
* }
*
* </pre>
* The response will be a {@link OperationMeta} object, which encapsulates the application name,
* version and fileHash.
*/
@POST
@Path("/apps/push")
public void pushApps(FullHttpRequest request, HttpResponder responder,
@PathParam("namespace-id") String namespaceId) throws Exception {
checkSourceControlMultiFeatureFlag();
PushMultipleAppsRequest appsRequest;
try {
appsRequest = parseBody(request, PushMultipleAppsRequest.class);
} catch (JsonSyntaxException e) {
throw new BadRequestException(String.format("Invalid request body: %s", e.getMessage()));
}

if (appsRequest == null) {
throw new BadRequestException("Invalid request body.");
}

if (Strings.isNullOrEmpty(appsRequest.getCommitMessage())) {
throw new BadRequestException("Please specify commit message in the request body.");
}

NamespaceId namespace = validateNamespaceId(namespaceId);

OperationRun operationMeta = sourceControlService.pushApps(namespace, appsRequest);
responder.sendJson(HttpResponseStatus.OK, GSON.toJson(operationMeta));
}

/**
* Pull the requested application from linked repository and deploy in current namespace.
*/
Expand All @@ -202,6 +248,31 @@ public void pullApp(FullHttpRequest request, HttpResponder responder,
}
}

/**
* Pull the requested applications from linked repository and deploy in current namespace.
*/
@POST
@Path("/apps/pull")
public void pullApps(FullHttpRequest request, HttpResponder responder,
@PathParam("namespace-id") String namespaceId) throws Exception {
checkSourceControlMultiFeatureFlag();
NamespaceId namespace = validateNamespaceId(namespaceId);

PullMultipleAppsRequest appsRequest;
try {
appsRequest = parseBody(request, PullMultipleAppsRequest.class);
} catch (JsonSyntaxException e) {
throw new BadRequestException("Invalid request body.", e);
}

if (appsRequest == null) {
throw new BadRequestException("Invalid request body.");
}

OperationRun operationRun = sourceControlService.pullApps(namespace, appsRequest);
responder.sendJson(HttpResponseStatus.OK, GSON.toJson(operationRun));
}

private PushAppRequest validateAndGetAppsRequest(FullHttpRequest request) throws BadRequestException {
PushAppRequest appRequest;
try {
Expand All @@ -217,16 +288,19 @@ private PushAppRequest validateAndGetAppsRequest(FullHttpRequest request) throws
return appRequest;
}

/**
*
* throws {@link ForbiddenException} if the feature is disabled
*/
private void checkSourceControlFeatureFlag() throws ForbiddenException {
if (!Feature.SOURCE_CONTROL_MANAGEMENT_GIT.isEnabled(featureFlagsProvider)) {
throw new ForbiddenException("Source Control Management feature is not enabled.");
}
}

private void checkSourceControlMultiFeatureFlag() throws ForbiddenException {
checkSourceControlFeatureFlag();
if (!Feature.SOURCE_CONTROL_MANAGEMENT_MULTI_APP.isEnabled(featureFlagsProvider)) {
throw new ForbiddenException("Source Control Management for multiple apps feature is not enabled.");
}
}

private NamespaceId validateNamespaceId(String namespaceId) throws BadRequestException {
try {
return new NamespaceId(namespaceId);
Expand Down
Loading

0 comments on commit 05cdf81

Please sign in to comment.