Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
2 changes: 2 additions & 0 deletions api-gateway/api-composition/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ LABEL maintainer="Knot.x Project"

COPY ./out/knotx /usr/local/knotx

RUN sed -i 's/# JVM_DEBUG=/JVM_DEBUG=/g' /usr/local/knotx/bin/knotx
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this for functional tests?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, removed


HEALTHCHECK --interval=5s --timeout=2s --retries=12 \
CMD curl --silent --fail localhost:8092/healthcheck || exit 1

Expand Down
3 changes: 2 additions & 1 deletion api-gateway/caching/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ configurations {
dependencies {
subprojects.forEach { "dist"(project(":${it.name}")) }
"wiremockExtensions"("com.opentable:wiremock-body-transformer:1.1.3") { isTransitive = false }
testCompile("com.github.tomakehurst:wiremock:2.24.1")
}

sourceSets.named("test") {
Expand All @@ -50,5 +51,5 @@ tasks.named("build") {
dependsOn(downloadWireMockExtensions, "runFunctionalTest")
}

apply(from = "https://raw.githubusercontent.com/Knotx/knotx-starter-kit/${project.property("knotxVersion")}/gradle/docker.gradle.kts")
apply(from = "docker.gradle.kts")
apply(from = "https://raw.githubusercontent.com/Knotx/knotx-starter-kit/${project.property("knotxVersion")}/gradle/javaAndUnitTests.gradle.kts")
125 changes: 125 additions & 0 deletions api-gateway/caching/docker.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to copy this file?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've overriden some configs that allow dockerized Knot.x to reach localhost's wiremock server.

* Copyright (C) 2019 Knot.x Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import com.bmuschko.gradle.docker.shaded.io.netty.util.internal.PlatformDependent.isWindows
import com.bmuschko.gradle.docker.tasks.container.DockerCreateContainer
import com.bmuschko.gradle.docker.tasks.container.DockerStartContainer
import com.bmuschko.gradle.docker.tasks.container.DockerStopContainer
import com.bmuschko.gradle.docker.tasks.container.extras.DockerWaitHealthyContainer
import com.bmuschko.gradle.docker.tasks.image.DockerBuildImage
import com.bmuschko.gradle.docker.tasks.image.DockerRemoveImage
import org.apache.tools.ant.taskdefs.condition.Os.FAMILY_UNIX
import org.apache.tools.ant.taskdefs.condition.Os.isFamily

val dockerImageRef = "$buildDir/.docker/buildImage-imageId.txt"

tasks.register<Copy>("copyDockerfile") {
group = "docker"
from("docker")
into("$buildDir")
expand("knotx_version" to project.property("knotx.version"))
mustRunAfter("cleanDistribution")
}

tasks.register<DockerRemoveImage>("removeImage") {
group = "docker"
val spec = object : Spec<Task> {
override fun isSatisfiedBy(task: Task): Boolean {
return File(dockerImageRef).exists()
}
}
onlyIf(spec)

targetImageId(if (File(dockerImageRef).exists()) File(dockerImageRef).readText() else "")
onError {
if (!this.message!!.contains("No such image"))
throw this
}
}

tasks.register<DockerBuildImage> ("buildImage") {
group = "docker"
inputDir.set(file("$buildDir"))
tags.add("${project.property("docker.image.name")}:latest")
dependsOn("removeImage", "prepareDocker")
}
val buildImage = tasks.named<DockerBuildImage>("buildImage")

// FUNCTIONAL TESTS

tasks.register<DockerCreateContainer>("createContainer") {
group = "docker-functional-tests"
dependsOn(buildImage)
targetImageId(buildImage.get().imageId)
portBindings.set(listOf("8092:8092", "18092:18092"))
exposePorts("tcp", listOf(8092, 18092))
autoRemove.set(true)
// allow container to access host's network
dependsOn("configureUnix", "configureNonUnix")
}

tasks.register("configureUnix"){
doLast {
createContainer {
network.set("host")
withEnvVar("EXTERNAL_API_DOMAIN", "localhost")
}
}
onlyIf { isFamily(FAMILY_UNIX) }
}

tasks.register("configureNonUnix"){
doLast {
createContainer {
withEnvVar("EXTERNAL_API_DOMAIN", "host.docker.internal")
}
}
onlyIf { !isFamily(FAMILY_UNIX) }
}

val createContainer = tasks.named<DockerCreateContainer>("createContainer")

tasks.register<DockerStartContainer>("startContainer") {
group = "docker-functional-tests"
dependsOn(createContainer)
targetContainerId(createContainer.get().containerId)
}

tasks.register<DockerWaitHealthyContainer>("waitContainer") {
group = "docker-functional-tests"
dependsOn(tasks.named("startContainer"))
targetContainerId(createContainer.get().containerId)
}

tasks.register<DockerStopContainer>("stopContainer") {
group = "docker-functional-tests"
targetContainerId(createContainer.get().containerId)
}

/** Deprecated */
tasks.register("runTest", Test::class) {
dependsOn(tasks.named("runFunctionalTest"))
}

tasks.register("runFunctionalTest", Test::class) {
group = "docker-functional-tests"
dependsOn(tasks.named("waitContainer"))
finalizedBy(tasks.named("stopContainer"))
include("**/*ITCase*")
}

tasks.register("prepareDocker") {
dependsOn("cleanDistribution", "overwriteCustomFiles", "copyDockerfile")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.project.test.functional;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
import static io.restassured.RestAssured.given;

import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer;
import org.junit.Assert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;


class CacheITCase {

private WireMockServer wireMockServer = new WireMockServer(options()
.port(8080)
.usingFilesUnderDirectory("../../common-services/webapi")
.extensions(new ResponseTemplateTransformer(true)));

@BeforeEach
public void setup() {
wireMockServer.start();
wireMockServer.stubFor(get(urlEqualTo("/product/id"))
.willReturn(aResponse().withStatus(200)
.withTransformers("response-template")
.withBodyFile("product.json")));
}

@Test
@DisplayName("Expect the same response when invoking API twice.")
void callProxyApiAndExpectCachedResponse() {
// @formatter:off
String firstReponse =
given()
.port(8092)
.when()
.get("/product/id")
.then()
.statusCode(200)
.extract()
.asString();

String secondRespone =
given()
.port(8092)
.when()
.get("/product/id")
.then()
.statusCode(200)
.extract()
.asString();

Assert.assertEquals(firstReponse, secondRespone);
// @formatter:on
}

}
35 changes: 35 additions & 0 deletions api-gateway/caching/knotx/conf/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2019 Knot.x Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<configuration>
<property name="LOG_PATH" value="/var/log/knotx"/>

<include resource="io/knotx/logging/logback/defaults.xml"/>
<include resource="io/knotx/logging/logback/file-appender.xml"/>
<include resource="io/knotx/logging/logback/access.xml"/>

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
</Pattern>
</layout>
</appender>

<logger name="io.knotx" level="TRACE"/>
<logger name="io.vertx" level="TRACE"/>

<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ actions {
endpointOptions {
path = /product/id
domain = webapi
domain = ${?EXTERNAL_API_DOMAIN} // environment variable provided during functional tests
port = 8080
allowedRequestHeaders = ["Content-Type"]
}
Expand Down
11 changes: 6 additions & 5 deletions api-gateway/caching/knotx/conf/routes/operations.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
fragmentsHandler = {
name = fragmentsHandler
config = {include required(classpath("routes/handlers/fragments-handler.conf"))}
}

routingOperations = ${routingOperations} [
{
operationId = product-api-caching-proxy-operation
Expand All @@ -11,11 +16,7 @@ routingOperations = ${routingOperations} [
}
}
},
{
name = fragmentsHandler
config = { include required(classpath("routes/handlers/fragments-handler.conf")) }
},

${fragmentsHandler},
{
name = fragmentsAssembler
}
Expand Down