Skip to content
This repository has been archived by the owner on Aug 25, 2024. It is now read-only.

Commit

Permalink
Add app GET and DELETE (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoloboschi authored Jun 30, 2023
1 parent c250fd3 commit 7f03f8d
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 33 deletions.
47 changes: 46 additions & 1 deletion cli/src/main/java/com/datastax/oss/sga/cli/commands/BaseCmd.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import java.io.File;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
import lombok.SneakyThrows;
import picocli.CommandLine;
Expand All @@ -20,7 +23,6 @@ public abstract class BaseCmd implements Runnable {
private SgaCLIConfig config;



@SneakyThrows
protected SgaCLIConfig getConfig() {
if (config == null) {
Expand Down Expand Up @@ -54,6 +56,49 @@ protected synchronized HttpClient getHttpClient() {
return httpClient;
}

@SneakyThrows
protected HttpResponse<String> http(HttpRequest httpRequest) {
return http(httpRequest, HttpResponse.BodyHandlers.ofString());
}

@SneakyThrows
protected <T> HttpResponse<T> http(HttpRequest httpRequest, HttpResponse.BodyHandler<T> bodyHandler) {
final HttpResponse<T> response = getHttpClient().send(httpRequest, bodyHandler);
final int status = response.statusCode();
if (status >= 200 && status < 300) {
return response;
}
if (status >= 400) {
log("Request failed: " + response.statusCode());
log(response.body());
throw new RuntimeException("Request failed");
}
throw new RuntimeException("Unexpected status code: " + status);
}

protected HttpRequest newGet(String uri) {
return HttpRequest.newBuilder()
.uri(URI.create("%s/api%s".formatted(getBaseWebServiceUrl(), uri)))
.GET()
.build();
}

protected HttpRequest newDelete(String uri) {
return HttpRequest.newBuilder()
.uri(URI.create("%s/api%s".formatted(getBaseWebServiceUrl(), uri)))
.DELETE()
.build();
}

protected HttpRequest newPut(String uri, String contentType, HttpRequest.BodyPublisher bodyPublisher) {
return HttpRequest.newBuilder()
.uri(URI.create("%s/api%s".formatted(getBaseWebServiceUrl(), uri)))
.header("Content-Type", contentType)
.PUT(bodyPublisher)
.build();
}


protected void log(Object log) {
System.out.println(log);
}
Expand Down
19 changes: 19 additions & 0 deletions cli/src/main/java/com/datastax/oss/sga/cli/commands/DeleteCmd.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.datastax.oss.sga.cli.commands;

import lombok.SneakyThrows;
import picocli.CommandLine;

@CommandLine.Command(name = "delete",
description = "Delete an application")
public class DeleteCmd extends BaseCmd {

@CommandLine.Parameters(description = "Name of the application")
private String name;

@Override
@SneakyThrows
public void run() {
http(newDelete("/applications/%s".formatted(name)));
log("Application deleted");
}
}
26 changes: 9 additions & 17 deletions cli/src/main/java/com/datastax/oss/sga/cli/commands/DeployCmd.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,11 @@ public void run() {
}


String boundary = new BigInteger(256, new Random()).toString();
final HttpResponse<String> response = getHttpClient().send(
HttpRequest.newBuilder()
.uri(URI.create("%s/api/applications/%s".formatted(getBaseWebServiceUrl(), name)))
.header("Content-Type", "multipart/form-data;boundary=" + boundary)
.PUT(multiPartBodyPublisher(tempZip, boundary))
.build(),
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
log("Application deployed");
} else {
log("Application not deployed, error: "+ response.statusCode());
log(response.body());
}
String boundary = new BigInteger(256, new Random()).toString();
http(newPut("/applications/%s".formatted(name),
"multipart/form-data;boundary=%s".formatted(boundary),
multiPartBodyPublisher(tempZip, boundary)));
log("Application deployed");

}

Expand All @@ -81,10 +72,11 @@ private File checkFileExists(String path) {

public static HttpRequest.BodyPublisher multiPartBodyPublisher(Path path, String boundary) throws IOException {
List<byte[]> byteArrays = new ArrayList<>();
final String beforeFile = "--%s\r\nContent-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\nContent-Type: %s\r\n\r\n"
.formatted(boundary, path.getFileName(), Files.probeContentType(path));
final String beforeFile =
"--%s\r\nContent-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\nContent-Type: %s\r\n\r\n"
.formatted(boundary, path.getFileName(), Files.probeContentType(path));
byteArrays.add(beforeFile.getBytes(StandardCharsets.UTF_8));
byteArrays.add(Files.readAllBytes(path));
byteArrays.add(Files.readAllBytes(path));
byteArrays.add("\r\n--%s--\r\n".formatted(boundary).getBytes(StandardCharsets.UTF_8));
return HttpRequest.BodyPublishers.ofByteArrays(byteArrays);
}
Expand Down
19 changes: 19 additions & 0 deletions cli/src/main/java/com/datastax/oss/sga/cli/commands/GetCmd.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.datastax.oss.sga.cli.commands;

import lombok.SneakyThrows;
import picocli.CommandLine;

@CommandLine.Command(name = "get",
description = "Get SGA application status")
public class GetCmd extends BaseCmd {

@CommandLine.Parameters(description = "Name of the application")
private String name;

@Override
@SneakyThrows
public void run() {
final String body = http(newGet("/applications/%s".formatted(name))).body();
log(body);
}
}
13 changes: 2 additions & 11 deletions cli/src/main/java/com/datastax/oss/sga/cli/commands/ListCmd.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,7 @@ public class ListCmd extends BaseCmd {
@Override
@SneakyThrows
public void run() {
final HttpResponse<String> response = getHttpClient().send(
HttpRequest.newBuilder()
.uri(URI.create("%s/api/applications".formatted(getBaseWebServiceUrl())))
.GET()
.build(),
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
log("Error: " + response.statusCode());
}
log(response.body());

final String body = http(newGet("/applications")).body();
log(body);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

@CommandLine.Command(name = "", mixinStandardHelpOptions = true, version = "checksum 4.0",
description = "Prints the checksum (SHA-256 by default) of a file to STDOUT.",
subcommands = { DeployCmd.class, ListCmd.class })
subcommands = { DeployCmd.class, ListCmd.class, DeleteCmd.class, GetCmd.class })
public class RootCmd {


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import net.lingala.zip4j.ZipFile;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.server.ResponseStatusException;

@RestController
@Tag(name = "applications")
Expand All @@ -46,9 +49,9 @@ Map<String, ApplicationInstance> getApplications() {
}

@PutMapping(value = "/{name}", consumes = "multipart/form-data")
@Operation(summary = "Get all applications")
@Operation(summary = "Create and deploy an application")
void deployApplication(@NotBlank @PathVariable("name") String name,
@NotNull @RequestParam("file") MultipartFile file) throws Exception {
@NotNull @RequestParam("file") MultipartFile file) throws Exception {
createApplicationFromZip(name, file);
}

Expand All @@ -72,4 +75,27 @@ private void createApplicationFromZip(String name, MultipartFile file) throws Ex
tempZip.toFile().delete();
}
}
}

@DeleteMapping("/{name}")
@Operation(summary = "Delete application by name")
void deleteApplication(@NotBlank @PathVariable("name") String name) {
final ApplicationInstance applicationInstance = apps.get(name);
// not supported yet
// deployer.delete(applicationInstance, deployer.createImplementation(applicationInstance));
apps.remove(name);
log.info("Deleted application {}", name);
}

@GetMapping("/{name}")
@Operation(summary = "Get an application by name")
ApplicationInstance getApplication(@NotBlank @PathVariable("name") String name) {
final ApplicationInstance applicationInstance = apps.get(name);
if (applicationInstance == null) {
throw new ResponseStatusException(
HttpStatus.NOT_FOUND, "application not found"
);
}
return applicationInstance;
}

}

0 comments on commit 7f03f8d

Please sign in to comment.