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

feat(recordings): implement PATCH recordingOptions #183

Merged
merged 4 commits into from
Nov 28, 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
88 changes: 87 additions & 1 deletion src/main/java/io/cryostat/recordings/Recordings.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.cryostat.recordings;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
Expand All @@ -31,6 +32,8 @@
import java.util.Optional;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.openjdk.jmc.common.unit.IConstrainedMap;
import org.openjdk.jmc.common.unit.IOptionDescriptor;
Expand All @@ -42,6 +45,7 @@
import io.cryostat.ConfigProperties;
import io.cryostat.Producers;
import io.cryostat.V2Response;
import io.cryostat.core.RecordingOptionsCustomizer;
import io.cryostat.core.net.JFRConnection;
import io.cryostat.core.sys.Clock;
import io.cryostat.core.templates.TemplateType;
Expand Down Expand Up @@ -110,6 +114,7 @@ public class Recordings {
@Inject TargetConnectionManager connectionManager;
@Inject EventBus bus;
@Inject RecordingOptionsBuilderFactory recordingOptionsBuilderFactory;
@Inject RecordingOptionsCustomizer recordingOptionsCustomizer;
@Inject EventOptionsBuilder.Factory eventOptionsBuilderFactory;
@Inject Clock clock;
@Inject S3Client storage;
Expand Down Expand Up @@ -464,7 +469,12 @@ public String patch(@RestPath long targetId, @RestPath long remoteId, String bod
activeRecording.persist();
return null;
case "save":
return recordingHelper.saveRecording(activeRecording);
try {
return recordingHelper.saveRecording(activeRecording);
} catch (IOException ioe) {
logger.warn(ioe);
return null;
}
default:
throw new BadRequestException(body);
}
Expand Down Expand Up @@ -851,6 +861,82 @@ public Map<String, Object> getRecordingOptions(@RestPath long id) throws Excepti
});
}

@PATCH
@Blocking
@Path("/api/v1/targets/{connectUrl}/recordingOptions")
@RolesAllowed("write")
public Response patchRecordingOptionsV1(@RestPath URI connectUrl) {
Target target = Target.getTargetByConnectUrl(connectUrl);
return Response.status(RestResponse.Status.PERMANENT_REDIRECT)
.location(
URI.create(String.format("/api/v3/targets/%d/recordingOptions", target.id)))
.build();
}

@PATCH
@Blocking
@Path("/api/v3/targets/{id}/recordingOptions")
@RolesAllowed("read")
public Map<String, Object> patchRecordingOptions(
@RestPath long id,
@RestForm String toDisk,
@RestForm String maxAge,
@RestForm String maxSize)
throws Exception {
final String unsetKeyword = "unset";

Map<String, String> form = new HashMap<>();
Pattern bool = Pattern.compile("true|false|" + unsetKeyword);
if (toDisk != null) {
Matcher m = bool.matcher(toDisk);
if (!m.matches()) {
throw new BadRequestException("Invalid options");
}
form.put("toDisk", toDisk);
}
if (maxAge != null) {
if (!unsetKeyword.equals(maxAge)) {
try {
Long.parseLong(maxAge);
form.put("maxAge", maxAge);
} catch (NumberFormatException e) {
throw new BadRequestException("Invalid options");
}
}
}
if (maxSize != null) {
if (!unsetKeyword.equals(maxSize)) {
try {
Long.parseLong(maxSize);
form.put("maxSize", maxSize);
} catch (NumberFormatException e) {
throw new BadRequestException("Invalid options");
}
}
}
form.entrySet()
.forEach(
e -> {
RecordingOptionsCustomizer.OptionKey optionKey =
RecordingOptionsCustomizer.OptionKey.fromOptionName(e.getKey())
.get();
if ("unset".equals(e.getValue())) {
recordingOptionsCustomizer.unset(optionKey);
} else {
recordingOptionsCustomizer.set(optionKey, e.getValue());
}
});

Target target = Target.find("id", id).singleResult();
return connectionManager.executeConnectedTask(
target,
connection -> {
RecordingOptionsBuilder builder =
recordingOptionsBuilderFactory.create(connection.getService());
return getRecordingOptions(connection.getService(), builder);
});
}

@GET
@Blocking
@Path("/api/v3/activedownload/{id}")
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/io/cryostat/recordings/RecordingsModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import io.cryostat.core.RecordingOptionsCustomizer;

import io.quarkus.arc.DefaultBean;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import jakarta.inject.Singleton;
import org.slf4j.Logger;
Expand All @@ -29,21 +29,21 @@
public class RecordingsModule {

@Produces
@DefaultBean
@ApplicationScoped
public RecordingOptionsBuilderFactory provideRecordingOptionsBuilderFactory(
RecordingOptionsCustomizer customizer) {
return service -> customizer.apply(new RecordingOptionsBuilder(service));
}

@Produces
@DefaultBean
@ApplicationScoped
public EventOptionsBuilder.Factory provideEventOptionsBuilderFactory() {
Logger log = LoggerFactory.getLogger(EventOptionsBuilder.class);
return new EventOptionsBuilder.Factory(log::debug);
}

@Produces
@DefaultBean
@ApplicationScoped
public RecordingOptionsCustomizer provideRecordingOptionsCustomizer() {
Logger log = LoggerFactory.getLogger(RecordingOptionsCustomizer.class);
return new RecordingOptionsCustomizer(log::debug);
Expand Down
3 changes: 2 additions & 1 deletion src/test/java/itest/RecordingWorkflowTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest;
import io.vertx.core.MultiMap;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpHeaders;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
Expand Down Expand Up @@ -129,7 +130,7 @@ public void testWorkflow() throws Exception {
TEST_RECORDING_NAME),
true,
saveHeaders,
"SAVE",
Buffer.buffer("SAVE"),
REQUEST_TIMEOUT_SECONDS)
.bodyAsString();
archivedRecordingFilenames.add(archivedRecordingFilename);
Expand Down
157 changes: 0 additions & 157 deletions src/test/java/itest/TargetRecordingPatchIT.java

This file was deleted.

Loading