diff --git a/.github/workflows/pr-ci.yml b/.github/workflows/pr-ci.yml index 8c24b975dd..c527778d1d 100644 --- a/.github/workflows/pr-ci.yml +++ b/.github/workflows/pr-ci.yml @@ -12,7 +12,7 @@ on: jobs: check-before-build: runs-on: ubuntu-latest - if: github.repository_owner == 'cryostatio' && github.event.issue.pull_request && (startsWith(github.event.comment.body, '/build_test') || startsWith(github.event.comment.body, '/retest')) + if: github.event.issue.pull_request && (startsWith(github.event.comment.body, '/build_test') || startsWith(github.event.comment.body, '/retest')) permissions: pull-requests: write steps: diff --git a/.github/workflows/push-ci.yml b/.github/workflows/push-ci.yml index d619d18a08..79defafa47 100644 --- a/.github/workflows/push-ci.yml +++ b/.github/workflows/push-ci.yml @@ -16,7 +16,6 @@ on: jobs: code-analysis: uses: ./.github/workflows/ci-code-analysis.yml - if: github.repository_owner == 'cryostatio' with: checkout-repo: ${{ github.event.pull_request.head.repo.full_name }} checkout-ref: ${{ github.event.pull_request.head.ref }} @@ -25,7 +24,6 @@ jobs: uses: ./.github/workflows/ci-build-image.yml permissions: pull-requests: write - if: github.repository_owner == 'cryostatio' with: build-arch: amd64 @@ -33,7 +31,6 @@ jobs: uses: ./.github/workflows/ci-build-image.yml permissions: pull-requests: write - if: github.repository_owner == 'cryostatio' with: build-arch: arm64 @@ -88,3 +85,4 @@ jobs: password: ${{ secrets.REGISTRY_PASSWORD }} - name: Print image URL run: echo "Image pushed to ${{ steps.push-to-quay.outputs.registry-paths }}" +#test diff --git a/src/test/java/itest/CustomTargetsIT.java b/src/test/java/itest/CustomTargetsIT.java index c071e5817d..d67f158636 100644 --- a/src/test/java/itest/CustomTargetsIT.java +++ b/src/test/java/itest/CustomTargetsIT.java @@ -47,353 +47,352 @@ @TestMethodOrder(OrderAnnotation.class) public class CustomTargetsIT extends StandardSelfTest { - private final ExecutorService worker = ForkJoinPool.commonPool(); - static final Map NULL_RESULT = new HashMap<>(); - private String itestJvmId; - private static StoredCredential storedCredential; - - static { - NULL_RESULT.put("result", null); - } - - @BeforeEach - void setup() throws InterruptedException, ExecutionException, TimeoutException { - itestJvmId = - JvmIdWebRequest.jvmIdRequest( - "service:jmx:rmi:///jndi/rmi://cryostat-itests:9091/jmxrmi"); - } - - @AfterAll - static void cleanup() throws Exception { - // Delete credentials to clean up - CompletableFuture deleteResponse = new CompletableFuture<>(); - webClient - .delete("/api/v2.2/credentials/" + storedCredential.id) - .send( - ar -> { - if (assertRequestStatus(ar, deleteResponse)) { - deleteResponse.complete(ar.result().bodyAsJsonObject()); - } - }); - - JsonObject expectedDeleteResponse = - new JsonObject( - Map.of( - "meta", - Map.of("type", HttpMimeType.JSON.mime(), "status", "OK"), - "data", - NULL_RESULT)); - try { - MatcherAssert.assertThat( - deleteResponse.get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS), - Matchers.equalTo(expectedDeleteResponse)); - } catch (Exception e) { - throw new ITestCleanupFailedException( - String.format("Failed to clean up credential with ID %d", storedCredential.id), - e); + private final ExecutorService worker = ForkJoinPool.commonPool(); + static final Map NULL_RESULT = new HashMap<>(); + private String itestJvmId; + private static StoredCredential storedCredential; + + static { + NULL_RESULT.put("result", null); + } + + @BeforeEach + void setup() throws InterruptedException, ExecutionException, TimeoutException { + itestJvmId = JvmIdWebRequest.jvmIdRequest( + "service:jmx:rmi:///jndi/rmi://cryostat-itests:9091/jmxrmi"); } - } - - @Test - @Order(1) - void shouldBeAbleToTestTargetConnection() throws InterruptedException, ExecutionException { - MultiMap form = MultiMap.caseInsensitiveMultiMap(); - form.add("connectUrl", "localhost:0"); - form.add("alias", "self"); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v2/targets?dryrun=true") - .sendForm( - form, - ar -> { - assertRequestStatus(ar, response); - // Assert 202 since localhost:0 jvm already exists - MatcherAssert.assertThat( - ar.result().statusCode(), Matchers.equalTo(202)); - response.complete(ar.result().bodyAsJsonObject()); - }); - JsonObject body = response.get().getJsonObject("data").getJsonObject("result"); - MatcherAssert.assertThat(body.getString("connectUrl"), Matchers.equalTo("localhost:0")); - MatcherAssert.assertThat(body.getString("alias"), Matchers.equalTo("self")); - } - - @Test - @Order(2) - void targetShouldNotAppearInListing() throws InterruptedException, ExecutionException { - CompletableFuture response = new CompletableFuture<>(); - webClient - .get("/api/v1/targets") - .send( - ar -> { - assertRequestStatus(ar, response); - response.complete(ar.result().bodyAsJsonArray()); - }); - JsonArray body = response.get(); - MatcherAssert.assertThat(body, Matchers.notNullValue()); - MatcherAssert.assertThat(body.size(), Matchers.equalTo(1)); - - JsonObject selfJdp = - new JsonObject( - Map.of( - "jvmId", - itestJvmId, - "alias", - "io.cryostat.Cryostat", - "connectUrl", - "service:jmx:rmi:///jndi/rmi://cryostat-itests:9091/jmxrmi", - "labels", - Map.of(), - "annotations", + + @AfterAll + static void cleanup() throws Exception { + // Delete credentials to clean up + CompletableFuture deleteResponse = new CompletableFuture<>(); + webClient + .delete("/api/v2.2/credentials/" + storedCredential.id) + .send( + ar -> { + if (assertRequestStatus(ar, deleteResponse)) { + deleteResponse.complete(ar.result().bodyAsJsonObject()); + } + }); + + JsonObject expectedDeleteResponse = new JsonObject( Map.of( - "cryostat", - Map.of( - "REALM", - "JDP", - "HOST", - "cryostat-itests", - "PORT", - "9091", - "JAVA_MAIN", - "io.cryostat.Cryostat"), - "platform", - Map.of()))); - MatcherAssert.assertThat(body, Matchers.contains(selfJdp)); - } - - @Test - @Order(3) - void shouldBeAbleToDefineTarget() - throws TimeoutException, ExecutionException, InterruptedException { - MultiMap form = MultiMap.caseInsensitiveMultiMap(); - form.add("connectUrl", "localhost:0"); - form.add("alias", "self"); - form.add("username", "username"); - form.add("password", "password"); - - CountDownLatch latch = new CountDownLatch(3); - - Future resultFuture1 = - worker.submit( - () -> { - try { - return expectNotification("CredentialsStored", 15, TimeUnit.SECONDS) - .get(); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - latch.countDown(); - } - }); - - Future resultFuture2 = - worker.submit( - () -> { - try { - return expectNotification( - "TargetJvmDiscovery", 15, TimeUnit.SECONDS) - .get(); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - latch.countDown(); - } - }); - - Thread.sleep(5000); // Sleep to setup notification listening before query resolves - - CompletableFuture response = new CompletableFuture<>(); - webClient - .post("/api/v2/targets?storeCredentials=true") - .sendForm( - form, - ar -> { - assertRequestStatus(ar, response); - response.complete(ar.result().bodyAsJsonObject()); - latch.countDown(); - }); - latch.await(30, TimeUnit.SECONDS); - - JsonObject body = response.get().getJsonObject("data").getJsonObject("result"); - MatcherAssert.assertThat(body.getString("connectUrl"), Matchers.equalTo("localhost:0")); - MatcherAssert.assertThat(body.getString("alias"), Matchers.equalTo("self")); - - JsonObject result1 = resultFuture1.get(); - - JsonObject message = result1.getJsonObject("message"); - - storedCredential = - new StoredCredential( - message.getInteger("id"), - message.getString("matchExpression"), - message.getInteger("numMatchingTargets")); - - MatcherAssert.assertThat(storedCredential.id, Matchers.any(Integer.class)); - MatcherAssert.assertThat( - storedCredential.matchExpression, - Matchers.equalTo("target.connectUrl == \"localhost:0\"")); - MatcherAssert.assertThat( - storedCredential.numMatchingTargets, Matchers.equalTo(Integer.valueOf(1))); - - JsonObject result2 = resultFuture2.get(); - JsonObject event = result2.getJsonObject("message").getJsonObject("event"); - MatcherAssert.assertThat(event.getString("kind"), Matchers.equalTo("FOUND")); - MatcherAssert.assertThat( - event.getJsonObject("serviceRef").getString("connectUrl"), - Matchers.equalTo("localhost:0")); - MatcherAssert.assertThat( - event.getJsonObject("serviceRef").getString("alias"), Matchers.equalTo("self")); - } - - @Test - @Order(4) - void targetShouldAppearInListing() - throws ExecutionException, InterruptedException, TimeoutException { - CompletableFuture response = new CompletableFuture<>(); - webClient - .get("/api/v1/targets") - .send( - ar -> { - assertRequestStatus(ar, response); - response.complete(ar.result().bodyAsJsonArray()); - }); - JsonArray body = response.get(); - MatcherAssert.assertThat(body, Matchers.notNullValue()); - MatcherAssert.assertThat(body.size(), Matchers.equalTo(2)); - - JsonObject selfJdp = - new JsonObject( - Map.of( - "jvmId", - itestJvmId, - "alias", - "io.cryostat.Cryostat", - "connectUrl", - "service:jmx:rmi:///jndi/rmi://cryostat-itests:9091/jmxrmi", - "labels", - Map.of(), - "annotations", + "meta", + Map.of("type", HttpMimeType.JSON.mime(), "status", "OK"), + "data", + NULL_RESULT)); + try { + MatcherAssert.assertThat( + deleteResponse.get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS), + Matchers.equalTo(expectedDeleteResponse)); + } catch (Exception e) { + throw new ITestCleanupFailedException( + String.format("Failed to clean up credential with ID %d", storedCredential.id), + e); + } + } + + @Test + @Order(1) + void shouldBeAbleToTestTargetConnection() throws InterruptedException, ExecutionException { + MultiMap form = MultiMap.caseInsensitiveMultiMap(); + form.add("connectUrl", "localhost:0"); + form.add("alias", "self"); + + CompletableFuture response = new CompletableFuture<>(); + webClient + .post("/api/v2/targets?dryrun=true") + .sendForm( + form, + ar -> { + assertRequestStatus(ar, response); + // Assert 202 since localhost:0 jvm already exists + MatcherAssert.assertThat( + ar.result().statusCode(), + Matchers.equalTo(202)); + response.complete(ar.result().bodyAsJsonObject()); + }); + String expectedConnectUrl = "service:jmx:rmi:///jndi/rmi://localhost:0/jmxrmi"; + JsonObject body = response.get().getJsonObject("data").getJsonObject("result"); + MatcherAssert.assertThat(body.getString("connectUrl"), Matchers.equalTo(expectedConnectUrl)); + MatcherAssert.assertThat(body.getString("alias"), Matchers.equalTo("self")); + } + + @Test + @Order(2) + void targetShouldNotAppearInListing() throws InterruptedException, ExecutionException { + CompletableFuture response = new CompletableFuture<>(); + webClient + .get("/api/v1/targets") + .send( + ar -> { + assertRequestStatus(ar, response); + response.complete(ar.result().bodyAsJsonArray()); + }); + JsonArray body = response.get(); + MatcherAssert.assertThat(body, Matchers.notNullValue()); + MatcherAssert.assertThat(body.size(), Matchers.equalTo(1)); + + JsonObject selfJdp = new JsonObject( + Map.of( + "jvmId", + itestJvmId, + "alias", + "io.cryostat.Cryostat", + "connectUrl", + "service:jmx:rmi:///jndi/rmi://cryostat-itests:9091/jmxrmi", + "labels", + Map.of(), + "annotations", + Map.of( + "cryostat", + Map.of( + "REALM", + "JDP", + "HOST", + "cryostat-itests", + "PORT", + "9091", + "JAVA_MAIN", + "io.cryostat.Cryostat"), + "platform", + Map.of()))); + MatcherAssert.assertThat(body, Matchers.contains(selfJdp)); + } + + @Test + @Order(3) + void shouldBeAbleToDefineTarget() + throws TimeoutException, ExecutionException, InterruptedException { + MultiMap form = MultiMap.caseInsensitiveMultiMap(); + form.add("connectUrl", "localhost:0"); + form.add("alias", "self"); + form.add("username", "username"); + form.add("password", "password"); + + CountDownLatch latch = new CountDownLatch(3); + + Future resultFuture1 = worker.submit( + () -> { + try { + return expectNotification("CredentialsStored", 15, TimeUnit.SECONDS) + .get(); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + latch.countDown(); + } + }); + + Future resultFuture2 = worker.submit( + () -> { + try { + return expectNotification( + "TargetJvmDiscovery", 15, TimeUnit.SECONDS) + .get(); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + latch.countDown(); + } + }); + + Thread.sleep(5000); // Sleep to setup notification listening before query resolves + + CompletableFuture response = new CompletableFuture<>(); + webClient + .post("/api/v2/targets?storeCredentials=true") + .sendForm( + form, + ar -> { + assertRequestStatus(ar, response); + response.complete(ar.result().bodyAsJsonObject()); + latch.countDown(); + }); + latch.await(30, TimeUnit.SECONDS); + + String expectedConnectUrl = "service:jmx:rmi:///jndi/rmi://localhost:0/jmxrmi"; + + JsonObject body = response.get().getJsonObject("data").getJsonObject("result"); + MatcherAssert.assertThat(body.getString("connectUrl"), Matchers.equalTo(expectedConnectUrl)); + MatcherAssert.assertThat(body.getString("alias"), Matchers.equalTo("self")); + + JsonObject result1 = resultFuture1.get(); + + JsonObject message = result1.getJsonObject("message"); + + storedCredential = new StoredCredential( + message.getInteger("id"), + message.getString("matchExpression"), + message.getInteger("numMatchingTargets")); + + MatcherAssert.assertThat(storedCredential.id, Matchers.any(Integer.class)); + MatcherAssert.assertThat( + storedCredential.matchExpression, + Matchers.equalTo("target.connectUrl == \"" + expectedConnectUrl + "\"")); + MatcherAssert.assertThat( + storedCredential.numMatchingTargets, Matchers.equalTo(Integer.valueOf(1))); + + JsonObject result2 = resultFuture2.get(); + JsonObject event = result2.getJsonObject("message").getJsonObject("event"); + MatcherAssert.assertThat(event.getString("kind"), Matchers.equalTo("FOUND")); + MatcherAssert.assertThat( + event.getJsonObject("serviceRef").getString("connectUrl"), + Matchers.equalTo(expectedConnectUrl)); + MatcherAssert.assertThat( + event.getJsonObject("serviceRef").getString("alias"), Matchers.equalTo("self")); + } + + @Test + @Order(4) + void targetShouldAppearInListing() + throws ExecutionException, InterruptedException, TimeoutException { + CompletableFuture response = new CompletableFuture<>(); + webClient + .get("/api/v1/targets") + .send( + ar -> { + assertRequestStatus(ar, response); + response.complete(ar.result().bodyAsJsonArray()); + }); + JsonArray body = response.get(); + MatcherAssert.assertThat(body, Matchers.notNullValue()); + MatcherAssert.assertThat(body.size(), Matchers.equalTo(2)); + + JsonObject selfJdp = new JsonObject( Map.of( - "cryostat", - Map.of( - "REALM", - "JDP", - "HOST", - "cryostat-itests", - "PORT", - "9091", - "JAVA_MAIN", - "io.cryostat.Cryostat"), - "platform", - Map.of()))); - JsonObject selfCustom = - new JsonObject( - Map.of( - "jvmId", - itestJvmId, - "alias", - "self", - "connectUrl", - "localhost:0", - "labels", - Map.of(), - "annotations", + "jvmId", + itestJvmId, + "alias", + "io.cryostat.Cryostat", + "connectUrl", + "service:jmx:rmi:///jndi/rmi://cryostat-itests:9091/jmxrmi", + "labels", + Map.of(), + "annotations", + Map.of( + "cryostat", + Map.of( + "REALM", + "JDP", + "HOST", + "cryostat-itests", + "PORT", + "9091", + "JAVA_MAIN", + "io.cryostat.Cryostat"), + "platform", + Map.of()))); + JsonObject selfCustom = new JsonObject( Map.of( - "cryostat", - Map.of("REALM", "Custom Targets"), - "platform", - Map.of()))); - MatcherAssert.assertThat(body, Matchers.containsInAnyOrder(selfJdp, selfCustom)); - } - - @Test - @Order(5) - void shouldBeAbleToDeleteTarget() - throws TimeoutException, ExecutionException, InterruptedException { - CountDownLatch latch = new CountDownLatch(2); - - worker.submit( - () -> { - try { - expectNotification("TargetJvmDiscovery", 5, TimeUnit.SECONDS) - .thenAcceptAsync( - notification -> { - JsonObject event = - notification - .getJsonObject("message") - .getJsonObject("event"); - MatcherAssert.assertThat( - event.getString("kind"), - Matchers.equalTo("LOST")); - MatcherAssert.assertThat( - event.getJsonObject("serviceRef") - .getString("connectUrl"), - Matchers.equalTo("localhost:0")); - MatcherAssert.assertThat( - event.getJsonObject("serviceRef") - .getString("alias"), - Matchers.equalTo("self")); - latch.countDown(); - }) - .get(); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - - CompletableFuture response = new CompletableFuture<>(); - webClient - .delete("/api/v2/targets/localhost:0") - .send( - ar -> { - assertRequestStatus(ar, response); - response.complete(null); - latch.countDown(); - }); - - latch.await(5, TimeUnit.SECONDS); - } - - @Test - @Order(6) - void targetShouldNoLongerAppearInListing() throws ExecutionException, InterruptedException { - CompletableFuture response = new CompletableFuture<>(); - webClient - .get("/api/v1/targets") - .send( - ar -> { - assertRequestStatus(ar, response); - response.complete(ar.result().bodyAsJsonArray()); - }); - JsonArray body = response.get(); - MatcherAssert.assertThat(body, Matchers.notNullValue()); - MatcherAssert.assertThat(body.size(), Matchers.equalTo(1)); - - JsonObject selfJdp = - new JsonObject( - Map.of( - "jvmId", - itestJvmId, - "alias", - "io.cryostat.Cryostat", - "connectUrl", - "service:jmx:rmi:///jndi/rmi://cryostat-itests:9091/jmxrmi", - "labels", - Map.of(), - "annotations", + "jvmId", + itestJvmId, + "alias", + "self", + "connectUrl", + "service:jmx:rmi:///jndi/rmi://localhost:0/jmxrmi", + "labels", + Map.of(), + "annotations", + Map.of( + "cryostat", + Map.of("REALM", "Custom Targets"), + "platform", + Map.of()))); + MatcherAssert.assertThat(body, Matchers.containsInAnyOrder(selfJdp, selfCustom)); + } + + @Test + @Order(5) + void shouldBeAbleToDeleteTarget() + throws TimeoutException, ExecutionException, InterruptedException { + CountDownLatch latch = new CountDownLatch(2); + + worker.submit( + () -> { + try { + expectNotification("TargetJvmDiscovery", 5, TimeUnit.SECONDS) + .thenAcceptAsync( + notification -> { + JsonObject event = notification + .getJsonObject("message") + .getJsonObject("event"); + MatcherAssert.assertThat( + event.getString("kind"), + Matchers.equalTo( + "LOST")); + MatcherAssert.assertThat( + event.getJsonObject( + "serviceRef") + .getString("connectUrl"), + Matchers.equalTo( + "localhost:0")); + MatcherAssert.assertThat( + event.getJsonObject( + "serviceRef") + .getString("alias"), + Matchers.equalTo( + "self")); + latch.countDown(); + }) + .get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + + CompletableFuture response = new CompletableFuture<>(); + webClient + .delete("/api/v2/targets/service:jmx:rmi:///jndi/rmi://localhost:0/jmxrmi") + .send( + ar -> { + assertRequestStatus(ar, response); + response.complete(null); + latch.countDown(); + }); + + latch.await(5, TimeUnit.SECONDS); + } + + @Test + @Order(6) + void targetShouldNoLongerAppearInListing() throws ExecutionException, InterruptedException { + CompletableFuture response = new CompletableFuture<>(); + webClient + .get("/api/v1/targets") + .send( + ar -> { + assertRequestStatus(ar, response); + response.complete(ar.result().bodyAsJsonArray()); + }); + JsonArray body = response.get(); + MatcherAssert.assertThat(body, Matchers.notNullValue()); + MatcherAssert.assertThat(body.size(), Matchers.equalTo(1)); + + JsonObject selfJdp = new JsonObject( Map.of( - "cryostat", - Map.of( - "REALM", - "JDP", - "HOST", - "cryostat-itests", - "PORT", - "9091", - "JAVA_MAIN", - "io.cryostat.Cryostat"), - "platform", - Map.of()))); - MatcherAssert.assertThat(body, Matchers.contains(selfJdp)); - } + "jvmId", + itestJvmId, + "alias", + "io.cryostat.Cryostat", + "connectUrl", + "service:jmx:rmi:///jndi/rmi://cryostat-itests:9091/jmxrmi", + "labels", + Map.of(), + "annotations", + Map.of( + "cryostat", + Map.of( + "REALM", + "JDP", + "HOST", + "cryostat-itests", + "PORT", + "9091", + "JAVA_MAIN", + "io.cryostat.Cryostat"), + "platform", + Map.of()))); + MatcherAssert.assertThat(body, Matchers.contains(selfJdp)); + } }