Skip to content

Commit

Permalink
test : Add E2E test for buildpacks build strategy
Browse files Browse the repository at this point in the history
+ Added a test BuildPacksBuildStrategyK8sITCase that would be activated in
  others profile
+ Add a minimal test project in
  `projects-to-be-tested/maven/buildpacks/simple` directory for
  abovementioned integration test

Signed-off-by: Rohan Kumar <[email protected]>
  • Loading branch information
rohanKanojia committed May 31, 2024
1 parent a2db6df commit fafa459
Show file tree
Hide file tree
Showing 6 changed files with 330 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
*/
package org.eclipse.jkube.integrationtests.docker;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.eclipse.jkube.integrationtests.cli.CliUtils;
import org.eclipse.jkube.integrationtests.cli.CliUtils.CliResult;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -79,6 +81,23 @@ public static void loadTar(File dockerBuildTar) throws IOException, InterruptedE
}
}

public static List<String> listDockerVolumeNames() throws IOException, InterruptedException {
final CliResult result = CliUtils.runCommand("docker volume ls --format=\"{{.Name}}\"");
if (result.getExitCode() != 0) {
throw new IOException(String.format("Error in listing docker volumes: %s", result.getOutput()));
}
return Arrays.asList(result.getOutput().replace("\r", "").split("\n"));
}

public static Map<String, String> getLabels(String id) throws IOException, InterruptedException {
final CliResult result = CliUtils.runCommand(String.format("docker inspect -f \"{{json .Config.Labels}}\" %s", id));
if (result.getExitCode() != 0) {
throw new IOException(String.format("Error in getting labels: %s", result.getOutput()));
}
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(result.getOutput(), Map.class);
}

public static final class DockerImage {

private final String repository;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.integrationtests.buildpacks;

import io.fabric8.junit.jupiter.api.KubernetesTest;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.maven.shared.invoker.InvocationResult;
import org.eclipse.jkube.integrationtests.JKubeCase;
import org.eclipse.jkube.integrationtests.maven.MavenCase;
import org.eclipse.jkube.integrationtests.maven.MavenInvocationResult;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.parallel.ResourceLock;

import java.io.File;
import java.util.Map;
import java.util.stream.Collectors;

import static org.eclipse.jkube.integrationtests.Locks.CLUSTER_RESOURCE_INTENSIVE;
import static org.eclipse.jkube.integrationtests.Tags.KUBERNETES;
import static org.eclipse.jkube.integrationtests.assertions.InvocationResultAssertion.assertInvocation;
import static org.eclipse.jkube.integrationtests.assertions.JKubeAssertions.assertJKube;
import static org.eclipse.jkube.integrationtests.assertions.KubernetesListAssertion.assertListResource;
import static org.eclipse.jkube.integrationtests.assertions.PodAssertion.awaitPod;
import static org.eclipse.jkube.integrationtests.assertions.ServiceAssertion.awaitService;
import static org.eclipse.jkube.integrationtests.assertions.YamlAssertion.yaml;
import static org.eclipse.jkube.integrationtests.docker.DockerUtils.getLabels;
import static org.eclipse.jkube.integrationtests.docker.DockerUtils.listDockerVolumeNames;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.anEmptyMap;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.jupiter.api.parallel.ResourceAccessMode.READ_WRITE;

@Tag(KUBERNETES)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@KubernetesTest(createEphemeralNamespace = false)
class BuildPacksBuildStrategyK8sITCase implements JKubeCase, MavenCase {
private KubernetesClient kubernetesClient;
private static final String PROJECT_BUILDPACKS_SIMPLE = "projects-to-be-tested/maven/buildpacks/simple";

@Override
public KubernetesClient getKubernetesClient() {
return kubernetesClient;
}

@Override
public String getApplication() {
return "buildpacks-simple";
}

@Override
public String getProject() {
return PROJECT_BUILDPACKS_SIMPLE;
}

@Test
@Order(1)
@DisplayName("k8s:resource, should create manifests")
void k8sResource() throws Exception {
// When
final InvocationResult invocationResult = maven("k8s:resource");
// Then
assertInvocation(invocationResult);
final File metaInfDirectory = new File(
String.format("../%s/target/classes/META-INF", getProject()));
assertThat(metaInfDirectory.exists(), equalTo(true));
assertListResource(new File(metaInfDirectory, "jkube/kubernetes.yml"));
assertThat(new File(metaInfDirectory, "jkube/kubernetes/buildpacks-simple-deployment.yml"), yaml(not(anEmptyMap())));
assertThat(new File(metaInfDirectory, "jkube/kubernetes/buildpacks-simple-service.yml"), yaml(not(anEmptyMap())));
}

@Test
@Order(1)
@DisplayName("k8s:build, should create container image using buildpacks")
void k8sBuild() throws Exception {
// When
final MavenInvocationResult invocationResult = maven("k8s:build");
// Then
assertInvocation(invocationResult);
assertThat(invocationResult.getStdOut(), stringContainsInOrder(
"Delegating container image building process to BuildPacks",
"Using pack",
"base: Pulling from paketobuildpacks/builder",
"===> ANALYZING",
"===> DETECTING",
"===> EXPORTING",
"Successfully built image 'integration-tests/buildpacks-simple:latest'",
"[INFO] BUILD SUCCESS"
));
Map<String, String> imageLabels = getLabels("integration-tests/buildpacks-simple:latest");
assertThat(imageLabels, hasEntry("io.buildpacks.stack.id", "io.buildpacks.stacks.bionic"));
assertThat(imageLabels, hasEntry("io.buildpacks.project.metadata", "{}"));
assertThat(imageLabels, hasKey("io.buildpacks.build.metadata"));
assertThat(imageLabels, hasKey("io.buildpacks.lifecycle.metadata"));
assertThat(imageLabels, hasKey("io.buildpacks.stack.description"));
assertThat(listDockerVolumeNames().stream()
.filter(v -> v.endsWith(".build") || v.endsWith(".launch"))
.filter(v -> v.contains("integration-tests_buildpacks-simple"))
.collect(Collectors.toList()), hasSize(2));
}

@Test
@Order(2)
@ResourceLock(value = CLUSTER_RESOURCE_INTENSIVE, mode = READ_WRITE)
@DisplayName("k8s:apply, should deploy pod and service")
void k8sApply() throws Exception {
// Given
// When
final InvocationResult invocationResult = maven("k8s:apply");
// Then
assertInvocation(invocationResult);
final Pod pod = awaitPod(this).getKubernetesResource();
awaitService(this, pod.getMetadata().getNamespace())
.assertIsNodePort()
.assertPorts(hasSize(1))
.assertPort("http", 8080, true)
.assertNodePortResponse("http", containsString("Simple Application containerized using buildpacks with JKube!"), "");
}

@Test
@Order(3)
@DisplayName("k8s:undeploy, should delete all applied resources")
void k8sUndeploy() throws Exception {
// When
final InvocationResult invocationResult = maven("k8s:undeploy");
// Then
assertInvocation(invocationResult);
assertJKube(this)
.assertThatShouldDeleteAllAppliedResources()
.assertDeploymentDeleted();
}
}
3 changes: 3 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<jakarta.servlet.jsp-api.version>3.1.1</jakarta.servlet.jsp-api.version>
<javax.servlet-api.version>4.0.1</javax.servlet-api.version>
<javax.servlet.jsp-api.version>2.3.3</javax.servlet.jsp-api.version>
<!-- JKube version also needs to be updated in projects-to-be-tested/maven/buildpacks/simple/pom.xml -->
<jkube.version>1.17-SNAPSHOT</jkube.version>
<junit.version>5.10.0</junit.version>
<karaf.version>4.4.4</karaf.version>
Expand Down Expand Up @@ -290,6 +291,7 @@
<module>projects-to-be-tested/maven/vertx/simplest</module>
<module>projects-to-be-tested/maven/wildfly-jar/microprofile</module>
<module>projects-to-be-tested/maven/karaf/camel-log</module>
<module>projects-to-be-tested/maven/buildpacks/simple</module>
</modules>
<activation>
<file>
Expand All @@ -311,6 +313,7 @@
<include>**/integrationtests/wildfly/jar/**/*ITCase.java</include>
<include>**/integrationtests/karaf/**/*ITCase.java</include>
<include>**/integrationtests/dsl/**/*ITCase.java</include>
<include>**/integrationtests/buildpacks/**/*ITCase.java</include>
</includes>
</configuration>
</plugin>
Expand Down
81 changes: 81 additions & 0 deletions projects-to-be-tested/maven/buildpacks/simple/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2019 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at:
https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
Red Hat, Inc. - initial API and implementation
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--
This project does not have any parent pom at the moment because we are building container image using BuildPacks
build strategy. BuildPacks starts a fresh maven build inside a docker container where only the current project directory
is loaded, not the parent pom. Without excluding parent, it starts failing to resolve a property from parent pom; since
project is not compiled from root pom in BuildPacks build container, it’s unable to resolve property from root pom.
-->

<groupId>org.eclipse.jkube.integration-tests</groupId>
<artifactId>buildpacks-simple</artifactId>
<version>0.0.0-SNAPSHOT</version>
<name>JKube :: Integration Tests :: BuildPacks :: Simple</name>
<packaging>jar</packaging>

<properties>
<!-- Since there is no parent pom, we have to manually define JKube version here -->
<jkube.version>1.17-SNAPSHOT</jkube.version>
<jkube.build.strategy>buildpacks</jkube.build.strategy>
<jkube.enricher.jkube-service.type>NodePort</jkube.enricher.jkube-service.type>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<configuration>
<mainClass>org.eclipse.jkube.sample.helloworld.App</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<mainClass>org.eclipse.jkube.integrationtests.buildpacks.simple.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>

<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>kubernetes-maven-plugin</artifactId>
<version>${jkube.version}</version>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.integrationtests.buildpacks.simple;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.logging.Logger;
import java.util.logging.Level;

import com.sun.net.httpserver.HttpServer;

public class App {
private static final int PORT = 8080;

public static void main(String[] args) {

try {
HttpServer server = HttpServer.create(new InetSocketAddress(PORT), 0);
server.createContext("/", new RootHandler());
server.setExecutor(null);
server.start();
} catch (IOException e) {
throw new IllegalStateException(e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2019 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at:
*
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.jkube.integrationtests.buildpacks.simple;

import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Logger;
import java.util.logging.Level;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

public class RootHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) {
try (OutputStream outputStream = exchange.getResponseBody()) {
String response = "Simple Application containerized using buildpacks with JKube!";
exchange.sendResponseHeaders(200, response.length());
exchange.getResponseHeaders().set("Content-Type", "text/plain");
outputStream.write(response.getBytes());
} catch (IOException e) {
throw new IllegalStateException(e.getMessage());
}
}
}

0 comments on commit fafa459

Please sign in to comment.