Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple applications push and pull API #15396

Merged
merged 1 commit into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading