diff --git a/api/pom.xml b/api/pom.xml index 8e21e9ffc..ae9ed5b6c 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -71,6 +71,15 @@ assertj-core test + + org.awaitility + awaitility + test + + + io.quarkus + quarkus-hibernate-validator + diff --git a/api/src/main/java/io/kaoto/backend/api/resource/v1/DeploymentsResource.java b/api/src/main/java/io/kaoto/backend/api/resource/v1/DeploymentsResource.java index 6268965a5..303866ec5 100644 --- a/api/src/main/java/io/kaoto/backend/api/resource/v1/DeploymentsResource.java +++ b/api/src/main/java/io/kaoto/backend/api/resource/v1/DeploymentsResource.java @@ -22,6 +22,7 @@ import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Instance; import javax.inject.Inject; +import javax.validation.constraints.NotNull; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -150,8 +151,10 @@ private String securityCheck(final String crd) { @Operation(summary = "Get CRD", description = "Returns the custom resource identified by name.") public String resource( - final @Parameter(description = "Name of the resource to get.") @PathParam("name") String name, - final @Parameter(description = "Type of the resource to get") @QueryParam("type") String type, + final @Parameter(description = "Name of the resource to get.") @PathParam("name") + String name, + final @Parameter(description = "Type of the resource to get", required = true) @NotNull @QueryParam("type") + String type, final @Parameter(description = "Namespace of the cluster where the resource is running.") @QueryParam("namespace") String namespace) { CustomResource cr = clusterService.get(namespace, name, type); @@ -192,8 +195,10 @@ public String resource( @Operation(summary = "Stop/Remove", description = "Remove the resource identified by name.") public boolean stop( - final @Parameter(description = "Name of the resource to get.") @PathParam("name") String name, - final @Parameter(description = "Type of the resource to get") @QueryParam("type") String type, + final @Parameter(description = "Name of the resource to get.") @PathParam("name") + String name, + final @Parameter(description = "Type of the resource to get", required = true) @NotNull @QueryParam("type") + String type, final @Parameter(description = "Namespace of the cluster where the resource is running.") @QueryParam("namespace") String namespace) { return clusterService.stop(name, namespace, type); diff --git a/api/src/test/java/io/kaoto/backend/api/resource/support/NativeHelper.java b/api/src/test/java/io/kaoto/backend/api/resource/support/NativeHelper.java new file mode 100644 index 000000000..b98929e13 --- /dev/null +++ b/api/src/test/java/io/kaoto/backend/api/resource/support/NativeHelper.java @@ -0,0 +1,42 @@ +package io.kaoto.backend.api.resource.support; + +import org.awaitility.Awaitility; +import org.awaitility.Durations; +import org.jboss.logging.Logger; + +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Duration; + +import static io.quarkus.bootstrap.util.IoUtils.readFile; + +/** + * Functions that help native testing to use the same functionality as JVM testing does with injection + */ +public class NativeHelper { + + private static final Logger log = Logger.getLogger(NativeHelper.class); + + + public static void waitForWarmUpCatalog(String catalogClassName) { + // when quarkus run native image before native tests, they set path to log to api/target/quarkus.log + // and it cannot be overridden + Path quarkusNativeLog = Paths.get("target", "quarkus.log"); + log.info("Using Quarkus log file from " + quarkusNativeLog); + Awaitility.await() + .timeout(Duration.ofSeconds(20)) + .pollDelay(Durations.ONE_SECOND) + .dontCatchUncaughtExceptions() + .until(() -> { + try { + return readFile(quarkusNativeLog).contains( + String.format("Catalog class %s_Subclass warmed up in", catalogClassName)); + } catch (NoSuchFileException e) { + throw new IllegalStateException("The quarkus.log file doesn't exist in the api/target! " + + "This can happen when integration tests are executing against a running application. " + + "Usage NativeHelper in remote native testing is not implemented yet!"); + } + }); + } +} diff --git a/api/src/test/java/io/kaoto/backend/api/resource/v1/DeploymentsResourceIT.java b/api/src/test/java/io/kaoto/backend/api/resource/v1/DeploymentsResourceIT.java new file mode 100644 index 000000000..b42ccf3bc --- /dev/null +++ b/api/src/test/java/io/kaoto/backend/api/resource/v1/DeploymentsResourceIT.java @@ -0,0 +1,15 @@ +package io.kaoto.backend.api.resource.v1; + +import io.kaoto.backend.api.metadata.catalog.StepCatalog; +import io.kaoto.backend.api.resource.support.NativeHelper; +import io.quarkus.test.junit.QuarkusIntegrationTest; + + +@QuarkusIntegrationTest +public class DeploymentsResourceIT extends DeploymentsResourceTestAbstract { + + @Override + protected void waitForWarmUpCatalog() { + NativeHelper.waitForWarmUpCatalog(StepCatalog.class.getCanonicalName()); + } +} diff --git a/api/src/test/java/io/kaoto/backend/api/resource/v1/DeploymentsResourceTest.java b/api/src/test/java/io/kaoto/backend/api/resource/v1/DeploymentsResourceTest.java index 10be7945f..38c5c4e2a 100644 --- a/api/src/test/java/io/kaoto/backend/api/resource/v1/DeploymentsResourceTest.java +++ b/api/src/test/java/io/kaoto/backend/api/resource/v1/DeploymentsResourceTest.java @@ -1,110 +1,23 @@ package io.kaoto.backend.api.resource.v1; import io.kaoto.backend.api.metadata.catalog.StepCatalog; -import io.quarkus.test.common.http.TestHTTPEndpoint; import io.quarkus.test.junit.QuarkusTest; -import io.quarkus.test.kubernetes.client.WithKubernetesTestServer; -import org.junit.jupiter.api.Test; import javax.inject.Inject; -import javax.ws.rs.core.Response; -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Files; -import java.nio.file.Path; - -import static io.restassured.RestAssured.given; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; @QuarkusTest -@WithKubernetesTestServer -@TestHTTPEndpoint(DeploymentsResource.class) -class DeploymentsResourceTest { +class DeploymentsResourceTest extends DeploymentsResourceTestAbstract { private StepCatalog catalog; - @Test - void test() throws URISyntaxException, IOException { - - catalog.waitForWarmUp().join(); - - var res = given() - .when() - .contentType("application/json") - .get() - .then() - .statusCode(Response.Status.OK.getStatusCode()); - assertEquals("[]", res.extract().response().asString()); - - - String yamlBinding = Files.readString(Path.of( - DeploymentsResourceTest.class.getResource( - "../twitter-search-source-binding.yaml") - .toURI())); - final var name = "integration-4"; - - given() - .when() - .get("/{name}", name) - .then() - .statusCode(Response.Status.NOT_FOUND.getStatusCode()); - - given() - .when() - .contentType("application/json") - .delete("/{name}", name) - .then() - .statusCode(Response.Status.NOT_FOUND.getStatusCode()); - - given() - .when().body(yamlBinding) - .contentType("text/yaml") - .post("/{name}", "Updated integration") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - - res = given() - .when() - .contentType("application/json") - .get() - .then() - .statusCode(Response.Status.OK.getStatusCode()); - assertNotEquals("[]", res.extract().response().asString()); - - res = given() - .when() - .get("/{name}", name) - .then() - .statusCode(Response.Status.OK.getStatusCode()); - var yaml = res.extract().response().asString(); - assertNotNull(yaml); - assertTrue(yaml.contains("kind: KameletBinding")); - assertTrue(yaml.contains("name: twitter-search-source")); - assertTrue(yaml.contains("name: aws-translate-action")); - - res = given() - .when() - .contentType("application/json") - .delete("/{name}", name) - .then() - .statusCode(Response.Status.OK.getStatusCode()); - assertTrue(Boolean.valueOf(res.extract().response().asString())); - - res = given() - .when() - .contentType("application/json") - .get() - .then() - .statusCode(Response.Status.OK.getStatusCode()); - assertEquals("[]", res.extract().response().asString()); - } - @Inject public void setCatalog(final StepCatalog catalog) { this.catalog = catalog; } + + @Override + protected void waitForWarmUpCatalog() { + catalog.waitForWarmUp().join(); + } } diff --git a/api/src/test/java/io/kaoto/backend/api/resource/v1/DeploymentsResourceTestAbstract.java b/api/src/test/java/io/kaoto/backend/api/resource/v1/DeploymentsResourceTestAbstract.java new file mode 100644 index 000000000..7a01605bc --- /dev/null +++ b/api/src/test/java/io/kaoto/backend/api/resource/v1/DeploymentsResourceTestAbstract.java @@ -0,0 +1,451 @@ +package io.kaoto.backend.api.resource.v1; + +import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.fabric8.kubernetes.client.server.mock.KubernetesServer; +import io.kaoto.backend.model.deployment.camelroute.Integration; +import io.kaoto.backend.model.deployment.kamelet.Kamelet; +import io.kaoto.backend.model.deployment.kamelet.KameletBinding; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.kubernetes.client.KubernetesTestServer; +import io.quarkus.test.kubernetes.client.WithKubernetesTestServer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; + +@WithKubernetesTestServer +@TestHTTPEndpoint(DeploymentsResource.class) +public abstract class DeploymentsResourceTestAbstract { + + @KubernetesTestServer + KubernetesServer mockServer; + + private static final String DEFAULT_NAMESPACE = "default"; + private static final String OTHER_NAMESPACE = "other"; + private static final String BINDING_NAME = "integration-4"; + + protected abstract void waitForWarmUpCatalog(); + + @BeforeEach + void setupTest() { + waitForWarmUpCatalog(); + } + + @AfterEach + void cleanUp() { + mockServer.getClient().resources(KameletBinding.class).inAnyNamespace().list().getItems() + .forEach(kameletBinding -> mockServer.getClient().resource(kameletBinding).delete()); + mockServer.getClient().resources(Kamelet.class).inAnyNamespace().list().getItems() + .forEach(kamelet -> mockServer.getClient().resource(kamelet).delete()); + mockServer.getClient().resources(Integration.class).inAnyNamespace().list().getItems() + .forEach(integration -> mockServer.getClient().resource(integration).delete()); + } + + @Test + void getAllTest() { + List res = given() + .when() + .get() + .then() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().body().jsonPath().getList("type", String.class); + assertThat(res).isEmpty(); + + createTestKameletBinding(DEFAULT_NAMESPACE); + createTestKamelet(DEFAULT_NAMESPACE); + createTestIntegration(DEFAULT_NAMESPACE); + res = given() + .when() + .get() + .then() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().body().jsonPath().getList("type", String.class); + assertThat(res) + .isNotEmpty() + .hasSize(3) + .containsExactlyInAnyOrder("KameletBinding", "Kamelet", "Integration"); + } + + @Test + void getAllNamespaceQueryTest() { + List res = given() + .queryParam("namespace", OTHER_NAMESPACE) + .when() + .get() + .then() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().body().jsonPath().getList("type", String.class); + assertThat(res).isEmpty(); + + createTestKameletBinding(DEFAULT_NAMESPACE); + res = given() + .queryParam("namespace", OTHER_NAMESPACE) + .when() + .get() + .then() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().body().jsonPath().getList("type", String.class); + assertThat(res).isEmpty(); + + createTestKameletBinding(OTHER_NAMESPACE); + createTestKamelet(OTHER_NAMESPACE); + createTestIntegration(OTHER_NAMESPACE); + res = given() + .queryParam("namespace", OTHER_NAMESPACE) + .when() + .get() + .then() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().body().jsonPath().getList("type", String.class); + assertThat(res) + .isNotEmpty() + .hasSize(3) + .containsExactlyInAnyOrder("KameletBinding", "Kamelet", "Integration"); + } + + @Test + void getExceptionsTest() { + String response = given() + .queryParam("type", "KameletBinding") + .when() + .get("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.NOT_FOUND.getStatusCode()) + .extract().body().asString(); + assertThat(response).isEqualTo( + String.format("Error processing deployment: Resource with name %s not found.", BINDING_NAME)); + response = given() + .when() + .get("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.BAD_REQUEST.getStatusCode()) + .extract().body().asString(); + assertThat(response).isEqualTo("Error processing deployment: resource.type: must not be null"); + createTestKameletBinding(DEFAULT_NAMESPACE); + response = given() + .when() + .get("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.BAD_REQUEST.getStatusCode()) + .extract().body().asString(); + assertThat(response).isEqualTo("Error processing deployment: resource.type: must not be null"); + } + + @Test + void getTest() { + given() + .queryParam("type", "KameletBinding") + .when() + .get("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.NOT_FOUND.getStatusCode()); + createTestKameletBinding(DEFAULT_NAMESPACE); + String resource = given() + .queryParam("type", "KameletBinding") + .when() + .get("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().body().asString(); + assertThat(resource) + .contains("kind: KameletBinding") + .contains("name: twitter-search-source"); + } + + @Test + void getNamespaceQueryTest() { + createTestKameletBinding(OTHER_NAMESPACE); + String differentTestKb = createDifferentTestKameletBinding(OTHER_NAMESPACE); + given() + .queryParam("namespace", OTHER_NAMESPACE) + .queryParam("type", "Kamelet") + .when() + .get("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.NOT_FOUND.getStatusCode()); + given() + .queryParam("namespace", DEFAULT_NAMESPACE) + .queryParam("type", "KameletBinding") + .when() + .get("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.NOT_FOUND.getStatusCode()); + given() + .queryParam("namespace", DEFAULT_NAMESPACE) + .queryParam("type", "KameletBinding") + .when() + .get("/{name}", differentTestKb) + .then() + .statusCode(Response.Status.NOT_FOUND.getStatusCode()); + String resource = given() + .queryParam("namespace", OTHER_NAMESPACE) + .queryParam("type", "KameletBinding") + .when() + .get("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().response().asString(); + assertThat(resource) + .contains("kind: KameletBinding") + .contains("name: twitter-search-source"); + + String kameletName = createTestKamelet(DEFAULT_NAMESPACE); + resource = given() + .queryParam("type", "Kamelet") + .when() + .get("/{name}", kameletName) + .then() + .contentType("text/yaml") + .statusCode(Response.Status.OK.getStatusCode()) + .extract().response().asString(); + assertThat(resource).contains("kind: Kamelet"); + } + + @Test + void startKameletTest() { + assertThat(mockServer.getClient().resources(Kamelet.class).inNamespace(DEFAULT_NAMESPACE).list() + .getItems()).isEmpty(); + given() + .when().body(getTestKameletBinding("../eip.kamelet.yaml")) + .contentType("text/yaml") + .post("/{name}", "Not needed anymore") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + assertThat(mockServer.getClient().resources(Kamelet.class).inNamespace(DEFAULT_NAMESPACE).list() + .getItems()) + .extracting(Kamelet::getMetadata) + .extracting(ObjectMeta::getName) + .as("Check that Kamelet was created") + .containsExactly("eip-action"); + } + + @Test + void startKameletBindingsTest() { + assertThat(mockServer.getClient().resources(KameletBinding.class).inNamespace(DEFAULT_NAMESPACE).list() + .getItems()).isEmpty(); + given() + .when().body(getTestKameletBinding("../twitter-search-source-binding.yaml")) + .contentType("text/yaml") + .post("/{name}", "Not needed anymore") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + assertThat(mockServer.getClient().resources(KameletBinding.class).inNamespace(DEFAULT_NAMESPACE).list() + .getItems()) + .extracting(KameletBinding::getMetadata) + .extracting(ObjectMeta::getName) + .as("Check that Kamelet Bindings was created") + .containsExactly(BINDING_NAME); + } + + @Test + void startIntegrationTest() { + assertThat(mockServer.getClient().resources(Integration.class).inNamespace(DEFAULT_NAMESPACE).list() + .getItems()).isEmpty(); + given() + .when().body(getTestKameletBinding("../integration.yaml")) + .contentType("text/yaml") + .post("/{name}", "Not needed anymore") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + assertThat(mockServer.getClient().resources(Integration.class).inNamespace(DEFAULT_NAMESPACE).list() + .getItems()) + .extracting(Integration::getMetadata) + .extracting(ObjectMeta::getName) + .as("Check that Integration was created") + .containsExactly("integration"); + } + + @Test + void startInvalidTest() { + String response = given() + .when().body(getTestKameletBinding("../route-with-beans.yaml")) + .contentType("text/yaml") + .post("/{name}", "Not needed anymore") + .then() + .statusCode(Response.Status.BAD_REQUEST.getStatusCode()) + .extract().response().asString(); + assertThat(response).isEqualTo( + "Error processing deployment: Couldn't understand the yaml sent. Check the syntax and try again."); + } + + @Test + void startNamespaceQueryTest() { + assertThat(mockServer.getClient().resources(KameletBinding.class).inNamespace(DEFAULT_NAMESPACE).list() + .getItems()).isEmpty(); + assertThat(mockServer.getClient().resources(KameletBinding.class).inNamespace(OTHER_NAMESPACE).list() + .getItems()).isEmpty(); + given() + .queryParam("namespace", OTHER_NAMESPACE) + .when().body(getTestKameletBinding("../twitter-search-source-binding.yaml")) + .contentType("text/yaml") + .post("/{name}", "Not needed anymore") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + assertThat(mockServer.getClient().resources(KameletBinding.class).inNamespace(DEFAULT_NAMESPACE).list() + .getItems()).isEmpty(); + assertThat(mockServer.getClient().resources(KameletBinding.class).inNamespace(OTHER_NAMESPACE).list() + .getItems()) + .extracting(KameletBinding::getMetadata) + .extracting(ObjectMeta::getName) + .as("Check that kamelet binding was created") + .containsExactly(BINDING_NAME); + } + @Test + void deleteExceptionsTest() { + String response = given() + .queryParam("type", "KameletBinding") + .when() + .get("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.NOT_FOUND.getStatusCode()) + .extract().body().asString(); + assertThat(response).isEqualTo( + String.format("Error processing deployment: Resource with name %s not found.", BINDING_NAME)); + response = given() + .when() + .delete("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.BAD_REQUEST.getStatusCode()) + .extract().body().asString(); + assertThat(response).isEqualTo("Error processing deployment: stop.type: must not be null"); + } + + + @Test + void deleteTest() { + createTestKameletBinding(DEFAULT_NAMESPACE); + createTestKameletBinding(OTHER_NAMESPACE); + String differentKbName = createDifferentTestKameletBinding(DEFAULT_NAMESPACE); + String kameletName = createTestKamelet(DEFAULT_NAMESPACE); + + Boolean result = given() + .queryParam("type", "KameletBinding") + .when() + .delete("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().body().as(Boolean.class); + assertThat(result).isTrue(); + assertThat( + mockServer.getClient().resources(KameletBinding.class).inNamespace(DEFAULT_NAMESPACE).list() + .getItems()) + .extracting(KameletBinding::getMetadata) + .extracting(ObjectMeta::getName) + .as("Check that kamelet binding was deleted") + .doesNotContain(BINDING_NAME) + .as("Check that other kamelet binding was not deleted") + .containsExactly(differentKbName); + assertThat( + mockServer.getClient().resources(Kamelet.class).inNamespace(DEFAULT_NAMESPACE).list() + .getItems()) + .extracting(Kamelet::getMetadata) + .extracting(ObjectMeta::getName) + .as("Check that kamelet was not deleted") + .containsExactly(kameletName); + assertThat( + mockServer.getClient().resources(KameletBinding.class).inNamespace(OTHER_NAMESPACE).list() + .getItems()) + .extracting(KameletBinding::getMetadata) + .extracting(ObjectMeta::getName) + .as("Check that kamelet binding with the same name in different namespace was not deleted") + .containsExactly(BINDING_NAME); + } + + @Test + void deleteNamespaceAndTypeQueryTest() { + createTestKameletBinding(DEFAULT_NAMESPACE); + createTestKameletBinding(OTHER_NAMESPACE); + String differentKbName = createDifferentTestKameletBinding(OTHER_NAMESPACE); + String kameletName = createTestKamelet(OTHER_NAMESPACE); + + Boolean result = given() + .queryParam("namespace", OTHER_NAMESPACE) + .queryParam("type", "KameletBinding") + .when() + .delete("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.OK.getStatusCode()) + .extract().body().as(Boolean.class); + assertThat(result).isTrue(); + + assertThat( + mockServer.getClient().resources(KameletBinding.class).inNamespace(OTHER_NAMESPACE).list() + .getItems()) + .extracting(KameletBinding::getMetadata) + .extracting(ObjectMeta::getName) + .as("Check that kamelet binding was deleted from specified namespace") + .doesNotContain(BINDING_NAME) + .as("Check that other kamelet binding was not deleted from specified namespace") + .containsExactly(differentKbName); + assertThat( + mockServer.getClient().resources(Kamelet.class).inNamespace(OTHER_NAMESPACE).list() + .getItems()) + .extracting(Kamelet::getMetadata) + .extracting(ObjectMeta::getName) + .as("Check that kamelet was not deleted from specified namespace") + .containsExactly(kameletName); + assertThat( + mockServer.getClient().resources(KameletBinding.class).inNamespace(DEFAULT_NAMESPACE).list() + .getItems()) + .extracting(KameletBinding::getMetadata) + .extracting(ObjectMeta::getName) + .as("Check that kamelet binding with the same name in default namespace was not deleted") + .containsExactly(BINDING_NAME); + given() + .queryParam("namespace", OTHER_NAMESPACE) + .queryParam("type", "KameletBinding") + .when() + .delete("/{name}", BINDING_NAME) + .then() + .statusCode(Response.Status.NOT_FOUND.getStatusCode()); + } + + private void createTestKameletBinding(String namespace) { + mockServer.getClient().resources(KameletBinding.class).inNamespace(namespace) + .load(DeploymentsResourceTestAbstract.class.getResourceAsStream( + "../twitter-search-source-binding.yaml")).create(); + } + + private String getTestKameletBinding(String pathToFileInResources) { + try { + return Files.readString(Path.of(Objects.requireNonNull( + DeploymentsResourceTestAbstract.class.getResource(pathToFileInResources)).toURI())); + } catch (IOException | URISyntaxException e) { + throw new IllegalStateException("Problem with processing kamelet binding file: " + e.getMessage()); + } + } + + private String createDifferentTestKameletBinding(String namespace) { + mockServer.getClient().resources(KameletBinding.class).inNamespace(namespace) + .load(DeploymentsResourceTestAbstract.class.getResourceAsStream( + "../camel-conector-example.yaml")).create(); + return "camel-conector-example"; + } + + private String createTestKamelet(String namespace) { + mockServer.getClient().resources(Kamelet.class).inNamespace(namespace) + .load(DeploymentsResourceTestAbstract.class.getResourceAsStream( + "../eip.kamelet.yaml")).create(); + return "eip-action"; + } + + private String createTestIntegration(String namespace) { + mockServer.getClient().resources(Integration.class).inNamespace(namespace) + .load(DeploymentsResourceTestAbstract.class.getResourceAsStream( + "../integration.yaml")).create(); + return "integration"; + } +} diff --git a/api/src/test/java/io/kaoto/backend/api/resource/v1/IntegrationsResourceIT.java b/api/src/test/java/io/kaoto/backend/api/resource/v1/IntegrationsResourceIT.java index b956d82e0..731277b4a 100644 --- a/api/src/test/java/io/kaoto/backend/api/resource/v1/IntegrationsResourceIT.java +++ b/api/src/test/java/io/kaoto/backend/api/resource/v1/IntegrationsResourceIT.java @@ -1,8 +1,13 @@ package io.kaoto.backend.api.resource.v1; +import io.kaoto.backend.api.metadata.catalog.StepCatalog; +import io.kaoto.backend.api.resource.support.NativeHelper; import io.quarkus.test.junit.QuarkusIntegrationTest; @QuarkusIntegrationTest -class IntegrationsResourceIT extends IntegrationsResourceTest { - +class IntegrationsResourceIT extends IntegrationsResourceTestAbstract { + @Override + protected void waitForWarmUpCatalog() { + NativeHelper.waitForWarmUpCatalog(StepCatalog.class.getCanonicalName()); + } } diff --git a/api/src/test/java/io/kaoto/backend/api/resource/v1/IntegrationsResourceTest.java b/api/src/test/java/io/kaoto/backend/api/resource/v1/IntegrationsResourceTest.java index 288ac76d9..07bfb7b9d 100644 --- a/api/src/test/java/io/kaoto/backend/api/resource/v1/IntegrationsResourceTest.java +++ b/api/src/test/java/io/kaoto/backend/api/resource/v1/IntegrationsResourceTest.java @@ -1,365 +1,21 @@ package io.kaoto.backend.api.resource.v1; -import static io.restassured.RestAssured.given; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URISyntaxException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Map; - -import javax.ws.rs.core.Response; - -import org.junit.jupiter.api.Test; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.Constructor; - -import io.kaoto.backend.api.resource.v1.model.Integration; -import io.kaoto.backend.api.service.deployment.generator.kamelet.KameletRepresenter; -import io.kaoto.backend.model.deployment.kamelet.KameletBinding; -import io.kaoto.backend.model.step.Step; -import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.kaoto.backend.api.metadata.catalog.StepCatalog; import io.quarkus.test.junit.QuarkusTest; -@QuarkusTest -@TestHTTPEndpoint(IntegrationsResource.class) -class IntegrationsResourceTest { - - @Test - void complexEIP() throws URISyntaxException, IOException { - - String yaml = Files.readString(Path.of( - DeploymentsResourceTest.class.getResource( - "../eip.kamelet.yaml") - .toURI())); - - var res = given() - .when() - .contentType("text/yaml") - .body(yaml) - .post("?dsl=Kamelet") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - - String json = res.extract().body().asString(); - - res = given() - .when() - .contentType("application/json") - .body(json) - .post("?dsl=Kamelet") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - - assertThat(res.extract().body().asString()).isEqualToNormalizingNewlines(yaml); - } - - @Test - void amqAmq() throws Exception { - String yaml = Files.readString(Path.of( - DeploymentsResourceTest.class.getResource("../amq-amq.yaml").toURI())); - - var res = given() - .when() - .contentType("text/yaml") - .body(yaml) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - - var flow = res.extract().body().as(Integration.class); - assertEquals(2, flow.getSteps().size()); - Step amq1 = flow.getSteps().get(0); - Step amq2 = flow.getSteps().get(1); - assertEquals("START", amq1.getType()); - assertEquals("activemq", amq1.getName()); - assertEquals("activemq", amq2.getName()); - assertEquals("MIDDLE", amq2.getType()); - assertTrue(amq1.getParameters().stream() - .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationType") - && parameter.getValue().toString().equalsIgnoreCase("queue"))); - assertTrue(amq1.getParameters().stream() - .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationName") - && parameter.getValue().toString().equalsIgnoreCase("myQueueName"))); - assertTrue(amq2.getParameters().stream() - .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationType") - && parameter.getValue().toString().equalsIgnoreCase("topic"))); - assertTrue(amq2.getParameters().stream() - .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationName") - && parameter.getValue().toString().equalsIgnoreCase("anotherOne"))); - - - String json = res.extract().body().asString(); - - res = given() - .when() - .contentType("application/json") - .body(json) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - - assertThat(res.extract().body().asString()).isEqualToNormalizingNewlines(yaml); - } - - @Test - void amqAmqFromJson() throws Exception { - String json = Files.readString(Path.of( - DeploymentsResourceTest.class.getResource("../amq-amq.json").toURI())); - - var res = given() - .when() - .contentType("application/json") - .body(json) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); +import javax.inject.Inject; - String yaml = res.extract().body().asString(); - - res = given() - .when() - .contentType("text/yaml") - .body(yaml) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - - var flow = res.extract().body().as(Integration.class); - assertEquals(2, flow.getSteps().size()); - Step amq1 = flow.getSteps().get(0); - Step amq2 = flow.getSteps().get(1); - assertEquals("START", amq1.getType()); - assertEquals("activemq", amq1.getName()); - assertEquals("activemq", amq2.getName()); - assertEquals("MIDDLE", amq2.getType()); - - assertTrue(amq1.getParameters().stream() - .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationType") - && parameter.getValue().toString().equalsIgnoreCase("topic"))); - assertTrue(amq1.getParameters().stream() - .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationName") - && parameter.getValue() == null)); - assertTrue(amq2.getParameters().stream() - .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationType") - && parameter.getValue().toString().equalsIgnoreCase("queue"))); - assertTrue(amq2.getParameters().stream() - .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationName") - && parameter.getValue().toString().equalsIgnoreCase("sdfg"))); - } - - @Test - void newBranchStep() throws Exception { - String json = Files.readString(Path.of( - IntegrationsResourceTest.class.getResource( - "../new-branch-step.json") - .toURI())); - var res = given() - .when() - .contentType("application/json") - .body(json) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - Yaml yaml = new Yaml( - new Constructor(KameletBinding.class), - new KameletRepresenter()); - yaml.parse(new InputStreamReader(res.extract().body().asInputStream())); - } - - @Test - void scriptStep() throws Exception { - String json = Files.readString(Path.of( - IntegrationsResourceTest.class.getResource( - "../script.json") - .toURI())); - var res = given() - .when() - .contentType("application/json") - .body(json) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - String yaml = res.extract().body().asString(); - - res = given() - .when() - .contentType("text/yaml") - .body(yaml) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - - var flow = res.extract().body().as(Integration.class); - assertEquals(2, flow.getSteps().size()); - Step script = flow.getSteps().get(1); - var groovy = script.getParameters().stream().filter(p -> "groovy".equals(p.getId())).findAny(); - assertTrue(groovy.isPresent()); - assertEquals("some groovy script", groovy.get().getValue()); - } - - @Test - void expressionObject() throws Exception { - String yaml = Files.readString(Path.of( - IntegrationsResourceTest.class.getResource( - "../expression-object.yaml") - .toURI())); - var res = given() - .when() - .contentType("text/yaml") - .body(yaml) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - String json = res.extract().body().asString(); - - res = given() - .when() - .contentType("application/json") - .body(json) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - - var yaml2 = res.extract().body().asString(); - List parsed = new Yaml().load(yaml2); - List steps = (List) ((Map)((Map)parsed.get(0)).get("from")).get("steps"); - assertEquals(20, steps.size()); - var choice = (Map) ((Map) steps.get(0)).get("choice"); - var when0 = (Map) ((List)choice.get("when")).get(0); - assertExpression("choice", "simple", when0); - var delay = (Map) ((Map) steps.get(1)).get("delay"); - assertExpression("delay", "simple", delay); - var drouter = (Map) ((Map) steps.get(2)).get("dynamic-router"); - assertExpression("dynamic-router", "simple", drouter); - var enrich = (Map) ((Map) steps.get(3)).get("enrich"); - assertExpression("enrich", "simple", enrich); - var filter = (Map) ((Map) steps.get(4)).get("filter"); - assertExpression("filter", "simple", filter); - var penrich = (Map) ((Map) steps.get(5)).get("poll-enrich"); - assertExpression("poll-enrich", "simple", penrich); - var rlist = (Map) ((Map) steps.get(6)).get("recipient-list"); - assertExpression("recipient-list", "simple", rlist); - var resequence = (Map) ((Map) steps.get(7)).get("resequence"); - assertExpression("resequence", "simple", resequence); - var rslip = (Map) ((Map) steps.get(8)).get("routing-slip"); - assertExpression("routing-slip", "simple", rslip); - var script = (Map) ((Map) steps.get(9)).get("script"); - assertExpression("script", "groovy", script); - var scall = (Map) ((Map) steps.get(10)).get("service-call"); - assertExpression("service-call", "jsonpath", scall); - var sbody = (Map) ((Map) steps.get(11)).get("set-body"); - assertExpression("set-body", "constant", sbody); - var sheader = (Map) ((Map) steps.get(12)).get("set-header"); - assertExpression("set-header", "jq", sheader); - var sprop = (Map) ((Map) steps.get(13)).get("set-property"); - assertExpression("set-property", "jq", sprop); - var sort = (Map) ((Map) steps.get(14)).get("sort"); - assertExpression("sort", "simple", sort); - var split = (Map) ((Map) steps.get(15)).get("split"); - assertExpression("split", "simple", split); - var throttle = (Map) ((Map) steps.get(16)).get("throttle"); - assertExpression("throttle", "simple", throttle); - var transform = (Map) ((Map) steps.get(17)).get("transform"); - assertExpression("transform", "jq", transform); - var validate = (Map) ((Map) steps.get(18)).get("validate"); - assertExpression("validate", "simple", validate); - var dotry = (Map) ((Map) steps.get(19)).get("do-try"); - var docatch0 = (Map) ((List) dotry.get("do-catch")).get(0); - var onwhen = (Map) docatch0.get("on-when"); - assertExpression("on-when", "simple", onwhen); - } - - private void assertExpression(String name, String syntax, Map step) { - var nested = (Map) ((Map)step.get("expression")).get(syntax); - assertEquals(name, nested.get("expression")); - assertNull(nested.get("result-type")); - } - - @Test - void kameletUri() throws Exception { - String yaml = Files.readString(Path.of( - IntegrationsResourceTest.class.getResource( - "../kamelet-uri.yaml") - .toURI())); - var res = given() - .when() - .contentType("text/yaml") - .body(yaml) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - String json = res.extract().body().asString(); - - res = given() - .when() - .contentType("application/json") - .body(json) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - - var yaml2 = res.extract().body().asString(); - List parsed = new Yaml().load(yaml2); - var uri = (String) ((Map)((Map)parsed.get(0)).get("from")).get("uri"); - assertEquals("kamelet:telegram-source:test/", uri); - } - - @Test - void uriLogStop() throws Exception { - String yaml = Files.readString(Path.of( - IntegrationsResourceTest.class.getResource( - "../uri-log-stop.yaml") - .toURI())); - var res = given() - .when() - .contentType("text/yaml") - .body(yaml) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); +@QuarkusTest +public class IntegrationsResourceTest extends IntegrationsResourceTestAbstract { + private StepCatalog catalog; - var flow = res.extract().body().as(Integration.class); - var filter = flow.getSteps().get(1); - var log = filter.getBranches().get(0).getSteps().get(0); - assertEquals("MIDDLE", log.getType()); - var filter2 = flow.getSteps().get(2); - var stop = filter2.getBranches().get(0).getSteps().get(0); - assertEquals("stop", stop.getName()); - // @FIXME a workaround for https://github.com/KaotoIO/kaoto-ui/issues/1587 - // Fix StopFlowStep once above is implemented - assertEquals("MIDDLE", stop.getType()); - var log2 = flow.getSteps().get(3); - assertEquals("MIDDLE", log2.getType()); + @Inject + public void setCatalog(final StepCatalog catalog) { + this.catalog = catalog; } - @Test - void noFrom() throws Exception { - String json = Files.readString(Path.of( - IntegrationsResourceTest.class.getResource( - "../no-from.json") - .toURI())); - var res = given() - .when() - .contentType("application/json") - .body(json) - .post("?dsl=Camel Route") - .then() - .statusCode(Response.Status.OK.getStatusCode()); - var yaml = res.extract().body().asString(); - List parsed = new Yaml().load(yaml); - var from = (Map) ((Map)parsed.get(0)).get("from"); - var fromUri = (String) from.get("uri"); - assertNull(fromUri); - var steps = (List) from.get("steps"); - assertEquals(1, steps.size()); - var to = (Map) ((Map) steps.get(0)).get("to"); - assertEquals("log:", to.get("uri")); + @Override + protected void waitForWarmUpCatalog() { + catalog.waitForWarmUp().join(); } } diff --git a/api/src/test/java/io/kaoto/backend/api/resource/v1/IntegrationsResourceTestAbstract.java b/api/src/test/java/io/kaoto/backend/api/resource/v1/IntegrationsResourceTestAbstract.java new file mode 100644 index 000000000..d2d4b6759 --- /dev/null +++ b/api/src/test/java/io/kaoto/backend/api/resource/v1/IntegrationsResourceTestAbstract.java @@ -0,0 +1,370 @@ +package io.kaoto.backend.api.resource.v1; + +import io.kaoto.backend.api.resource.v1.model.Integration; +import io.kaoto.backend.api.service.deployment.generator.kamelet.KameletRepresenter; +import io.kaoto.backend.model.deployment.kamelet.KameletBinding; +import io.kaoto.backend.model.step.Step; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; + +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestHTTPEndpoint(IntegrationsResource.class) +abstract class IntegrationsResourceTestAbstract { + + protected abstract void waitForWarmUpCatalog(); + + @BeforeEach + void setupTest() { + waitForWarmUpCatalog(); + } + + @Test + void complexEIP() throws URISyntaxException, IOException { + + String yaml = Files.readString(Path.of( + DeploymentsResourceTest.class.getResource( + "../eip.kamelet.yaml") + .toURI())); + + var res = given() + .when() + .contentType("text/yaml") + .body(yaml) + .post("?dsl=Kamelet") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + String json = res.extract().body().asString(); + + res = given() + .when() + .contentType("application/json") + .body(json) + .post("?dsl=Kamelet") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + assertThat(res.extract().body().asString()).isEqualToNormalizingNewlines(yaml); + } + + @Test + void amqAmq() throws Exception { + String yaml = Files.readString(Path.of( + DeploymentsResourceTest.class.getResource("../amq-amq.yaml").toURI())); + + var res = given() + .when() + .contentType("text/yaml") + .body(yaml) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + var flow = res.extract().body().as(Integration.class); + assertEquals(2, flow.getSteps().size()); + Step amq1 = flow.getSteps().get(0); + Step amq2 = flow.getSteps().get(1); + assertEquals("START", amq1.getType()); + assertEquals("activemq", amq1.getName()); + assertEquals("activemq", amq2.getName()); + assertEquals("MIDDLE", amq2.getType()); + assertTrue(amq1.getParameters().stream() + .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationType") + && parameter.getValue().toString().equalsIgnoreCase("queue"))); + assertTrue(amq1.getParameters().stream() + .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationName") + && parameter.getValue().toString().equalsIgnoreCase("myQueueName"))); + assertTrue(amq2.getParameters().stream() + .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationType") + && parameter.getValue().toString().equalsIgnoreCase("topic"))); + assertTrue(amq2.getParameters().stream() + .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationName") + && parameter.getValue().toString().equalsIgnoreCase("anotherOne"))); + + + String json = res.extract().body().asString(); + + res = given() + .when() + .contentType("application/json") + .body(json) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + assertThat(res.extract().body().asString()).isEqualToNormalizingNewlines(yaml); + } + + @Test + void amqAmqFromJson() throws Exception { + String json = Files.readString(Path.of( + DeploymentsResourceTest.class.getResource("../amq-amq.json").toURI())); + + var res = given() + .when() + .contentType("application/json") + .body(json) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + String yaml = res.extract().body().asString(); + + res = given() + .when() + .contentType("text/yaml") + .body(yaml) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + var flow = res.extract().body().as(Integration.class); + assertEquals(2, flow.getSteps().size()); + Step amq1 = flow.getSteps().get(0); + Step amq2 = flow.getSteps().get(1); + assertEquals("START", amq1.getType()); + assertEquals("activemq", amq1.getName()); + assertEquals("activemq", amq2.getName()); + assertEquals("MIDDLE", amq2.getType()); + + assertTrue(amq1.getParameters().stream() + .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationType") + && parameter.getValue().toString().equalsIgnoreCase("topic"))); + assertTrue(amq1.getParameters().stream() + .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationName") + && parameter.getValue() == null)); + assertTrue(amq2.getParameters().stream() + .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationType") + && parameter.getValue().toString().equalsIgnoreCase("queue"))); + assertTrue(amq2.getParameters().stream() + .anyMatch(parameter -> parameter.getId().equalsIgnoreCase("destinationName") + && parameter.getValue().toString().equalsIgnoreCase("sdfg"))); + } + + @Test + void newBranchStep() throws Exception { + String json = Files.readString(Path.of( + IntegrationsResourceTestAbstract.class.getResource( + "../new-branch-step.json") + .toURI())); + var res = given() + .when() + .contentType("application/json") + .body(json) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + Yaml yaml = new Yaml( + new Constructor(KameletBinding.class), + new KameletRepresenter()); + yaml.parse(new InputStreamReader(res.extract().body().asInputStream())); + } + + @Test + void scriptStep() throws Exception { + String json = Files.readString(Path.of( + IntegrationsResourceTestAbstract.class.getResource( + "../script.json") + .toURI())); + var res = given() + .when() + .contentType("application/json") + .body(json) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + String yaml = res.extract().body().asString(); + + res = given() + .when() + .contentType("text/yaml") + .body(yaml) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + var flow = res.extract().body().as(Integration.class); + assertEquals(2, flow.getSteps().size()); + Step script = flow.getSteps().get(1); + var groovy = script.getParameters().stream().filter(p -> "groovy".equals(p.getId())).findAny(); + assertTrue(groovy.isPresent()); + assertEquals("some groovy script", groovy.get().getValue()); + } + + @Test + void expressionObject() throws Exception { + String yaml = Files.readString(Path.of( + IntegrationsResourceTestAbstract.class.getResource( + "../expression-object.yaml") + .toURI())); + var res = given() + .when() + .contentType("text/yaml") + .body(yaml) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + String json = res.extract().body().asString(); + + res = given() + .when() + .contentType("application/json") + .body(json) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + var yaml2 = res.extract().body().asString(); + List parsed = new Yaml().load(yaml2); + List steps = (List) ((Map) ((Map) parsed.get(0)).get("from")).get("steps"); + assertEquals(20, steps.size()); + var choice = (Map) ((Map) steps.get(0)).get("choice"); + var when0 = (Map) ((List) choice.get("when")).get(0); + assertExpression("choice", "simple", when0); + var delay = (Map) ((Map) steps.get(1)).get("delay"); + assertExpression("delay", "simple", delay); + var drouter = (Map) ((Map) steps.get(2)).get("dynamic-router"); + assertExpression("dynamic-router", "simple", drouter); + var enrich = (Map) ((Map) steps.get(3)).get("enrich"); + assertExpression("enrich", "simple", enrich); + var filter = (Map) ((Map) steps.get(4)).get("filter"); + assertExpression("filter", "simple", filter); + var penrich = (Map) ((Map) steps.get(5)).get("poll-enrich"); + assertExpression("poll-enrich", "simple", penrich); + var rlist = (Map) ((Map) steps.get(6)).get("recipient-list"); + assertExpression("recipient-list", "simple", rlist); + var resequence = (Map) ((Map) steps.get(7)).get("resequence"); + assertExpression("resequence", "simple", resequence); + var rslip = (Map) ((Map) steps.get(8)).get("routing-slip"); + assertExpression("routing-slip", "simple", rslip); + var script = (Map) ((Map) steps.get(9)).get("script"); + assertExpression("script", "groovy", script); + var scall = (Map) ((Map) steps.get(10)).get("service-call"); + assertExpression("service-call", "jsonpath", scall); + var sbody = (Map) ((Map) steps.get(11)).get("set-body"); + assertExpression("set-body", "constant", sbody); + var sheader = (Map) ((Map) steps.get(12)).get("set-header"); + assertExpression("set-header", "jq", sheader); + var sprop = (Map) ((Map) steps.get(13)).get("set-property"); + assertExpression("set-property", "jq", sprop); + var sort = (Map) ((Map) steps.get(14)).get("sort"); + assertExpression("sort", "simple", sort); + var split = (Map) ((Map) steps.get(15)).get("split"); + assertExpression("split", "simple", split); + var throttle = (Map) ((Map) steps.get(16)).get("throttle"); + assertExpression("throttle", "simple", throttle); + var transform = (Map) ((Map) steps.get(17)).get("transform"); + assertExpression("transform", "jq", transform); + var validate = (Map) ((Map) steps.get(18)).get("validate"); + assertExpression("validate", "simple", validate); + var dotry = (Map) ((Map) steps.get(19)).get("do-try"); + var docatch0 = (Map) ((List) dotry.get("do-catch")).get(0); + var onwhen = (Map) docatch0.get("on-when"); + assertExpression("on-when", "simple", onwhen); + } + + private void assertExpression(String name, String syntax, Map step) { + var nested = (Map) ((Map) step.get("expression")).get(syntax); + assertEquals(name, nested.get("expression")); + assertNull(nested.get("result-type")); + } + + @Test + void kameletUri() throws Exception { + String yaml = Files.readString(Path.of( + IntegrationsResourceTestAbstract.class.getResource( + "../kamelet-uri.yaml") + .toURI())); + var res = given() + .when() + .contentType("text/yaml") + .body(yaml) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + String json = res.extract().body().asString(); + + res = given() + .when() + .contentType("application/json") + .body(json) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + var yaml2 = res.extract().body().asString(); + List parsed = new Yaml().load(yaml2); + var uri = (String) ((Map) ((Map) parsed.get(0)).get("from")).get("uri"); + assertEquals("kamelet:telegram-source:test/", uri); + } + + @Test + void uriLogStop() throws Exception { + String yaml = Files.readString(Path.of( + IntegrationsResourceTestAbstract.class.getResource( + "../uri-log-stop.yaml") + .toURI())); + var res = given() + .when() + .contentType("text/yaml") + .body(yaml) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + + var flow = res.extract().body().as(Integration.class); + var filter = flow.getSteps().get(1); + var log = filter.getBranches().get(0).getSteps().get(0); + assertEquals("MIDDLE", log.getType()); + var filter2 = flow.getSteps().get(2); + var stop = filter2.getBranches().get(0).getSteps().get(0); + assertEquals("stop", stop.getName()); + // @FIXME a workaround for https://github.com/KaotoIO/kaoto-ui/issues/1587 + // Fix StopFlowStep once above is implemented + assertEquals("MIDDLE", stop.getType()); + var log2 = flow.getSteps().get(3); + assertEquals("MIDDLE", log2.getType()); + } + + @Test + void noFrom() throws Exception { + String json = Files.readString(Path.of( + IntegrationsResourceTestAbstract.class.getResource( + "../no-from.json") + .toURI())); + var res = given() + .when() + .contentType("application/json") + .body(json) + .post("?dsl=Camel Route") + .then() + .statusCode(Response.Status.OK.getStatusCode()); + var yaml = res.extract().body().asString(); + List parsed = new Yaml().load(yaml); + var from = (Map) ((Map) parsed.get(0)).get("from"); + var fromUri = (String) from.get("uri"); + assertNull(fromUri); + var steps = (List) from.get("steps"); + assertEquals(1, steps.size()); + var to = (Map) ((Map) steps.get(0)).get("to"); + assertEquals("log:", to.get("uri")); + } +} diff --git a/api/src/test/resources/io/kaoto/backend/api/resource/integration.yaml b/api/src/test/resources/io/kaoto/backend/api/resource/integration.yaml new file mode 100644 index 000000000..662608d8d --- /dev/null +++ b/api/src/test/resources/io/kaoto/backend/api/resource/integration.yaml @@ -0,0 +1,15 @@ +apiVersion: camel.apache.org/v1 +kind: Integration +metadata: + name: integration +spec: + flows: + - from: + uri: timer:tick + parameters: + period: '5000' + steps: + - to: + uri: activemq:queue:myQueue + - to: + uri: log:save