diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f417b6a443ca325a46580645212eaccca5c1c95a --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +IMAGE_NAME = codecentric/springboot-maven3-centos + +build: + docker build -t $(IMAGE_NAME) . + +.PHONY: test +test: + docker build -t $(IMAGE_NAME)-candidate . + IMAGE_NAME=$(IMAGE_NAME)-candidate test/run diff --git a/test/run b/test/run new file mode 100755 index 0000000000000000000000000000000000000000..224f80895fa27cbf5485ce52889e1a0273eff8f5 --- /dev/null +++ b/test/run @@ -0,0 +1,147 @@ +#!/bin/bash +# +# The 'run' performs a simple test that verifies that STI image. +# The main focus here is to excersise the STI scripts. +# +# IMAGE_NAME specifies a name of the candidate image used for testing. +# The image has to be available before this script is executed. +# +IMAGE_NAME=${IMAGE_NAME-codecentric/springboot-maven3-centos-candidate} + +test_dir="$(readlink -zf $(dirname "${BASH_SOURCE[0]}"))" +image_dir=$(readlink -zf ${test_dir}/..) +scripts_url="file://${image_dir}/.sti/bin" +cid_file=$(mktemp -u --suffix=.cid) + +# Since we built the candidate image locally, we don't want STI attempt to pull +# it from Docker hub +sti_args="--forcePull=false -s ${scripts_url}" + +# TODO: This should be part of the image metadata +test_port=8080 + +info() { + echo -e "\n\e[1m[INFO] $@...\e[0m\n" +} + +image_exists() { + docker inspect $1 &>/dev/null +} + +container_exists() { + image_exists $(cat $cid_file) +} + +container_ip() { + docker inspect --format="{{ .NetworkSettings.IPAddress }}" $(cat $cid_file) +} + +run_sti_build() { + sti build ${sti_args} file://${test_dir}/test-app ${IMAGE_NAME} ${IMAGE_NAME}-testapp +} + +prepare() { + if ! image_exists ${IMAGE_NAME}; then + echo "ERROR: The image ${IMAGE_NAME} must exist before this script is executed." + exit 1 + fi + # TODO: STI build require the application is a valid 'GIT' repository, we + # should remove this restriction in the future when a file:// is used. + info "Build the test application image" + pushd ${test_dir}/test-app >/dev/null + git init + git config user.email "build@localhost" && git config user.name "builder" + git add -A && git commit -m "Sample commit" + popd >/dev/null + run_sti_build +} + +run_test_application() { + docker run --rm --cidfile=${cid_file} -p ${test_port} ${IMAGE_NAME}-testapp +} + +cleanup() { + info "Cleaning up the test application image" + if [ -f $cid_file ]; then + if container_exists; then + docker stop $(cat $cid_file) + fi + fi + if image_exists ${IMAGE_NAME}-testapp; then + docker rmi ${IMAGE_NAME}-testapp + fi + rm -rf ${test_dir}/test-app/.git +} + +check_result() { + local result="$1" + if [[ "$result" != "0" ]]; then + info "TEST FAILED (${result})" + cleanup + exit $result + fi +} + +wait_for_cid() { + local max_attempts=10 + local sleep_time=1 + local attempt=1 + local result=1 + info "Waiting for application container to start" + while [ $attempt -le $max_attempts ]; do + [ -f $cid_file ] && break + attempt=$(( $attempt + 1 )) + sleep $sleep_time + done +} + +test_usage() { + info "Testing the 'sti usage' command" + sti usage ${sti_args} ${IMAGE_NAME} &>/dev/null +} + +test_connection() { + info "Testing the HTTP connection (http://$(container_ip):${test_port})" + local max_attempts=10 + local sleep_time=1 + local attempt=1 + local result=1 + while [ $attempt -le $max_attempts ]; do + response_code=$(curl -s -w %{http_code} -o /dev/null http://$(container_ip):${test_port}/) + status=$? + if [ $status -eq 0 ]; then + if [ $response_code -eq 200 ]; then + result=0 + fi + break + fi + attempt=$(( $attempt + 1 )) + sleep $sleep_time + done + return $result +} + +# Build the application image twice to ensure the 'save-artifacts' and +# 'restore-artifacts' scripts are working properly +prepare + +info "Testing STI incremental build" +run_sti_build +check_result $? + +# Verify the 'usage' script is working properly +test_usage +check_result $? + +# Verify that the HTTP connection can be established to test application container +run_test_application & + +# Wait for the container to write it's CID file +wait_for_cid + +test_connection +check_result $? + +cleanup + +info "All tests finished successfully." diff --git a/test/test-app/pom.xml b/test/test-app/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..3a3c5b5cf30e4ed5c6d734ffcb8add14634d9b88 --- /dev/null +++ b/test/test-app/pom.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>1.3.3.RELEASE</version> + </parent> + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + </dependencies> +</project diff --git a/test/test-app/src/main/java/de/codecentric/springbootmaven3centos/App.java b/test/test-app/src/main/java/de/codecentric/springbootmaven3centos/App.java new file mode 100644 index 0000000000000000000000000000000000000000..fc277c16217b39de548eaab180bbe6a45f3a02bc --- /dev/null +++ b/test/test-app/src/main/java/de/codecentric/springbootmaven3centos/App.java @@ -0,0 +1,21 @@ +package de.codecentric.springbootmaven3centos; + +import org.springframework.boot.*; +import org.springframework.boot.autoconfigure.*; +import org.springframework.stereotype.*; +import org.springframework.web.bind.annotation.*; + +@Controller +@EnableAutoConfiguration +public class App { + + @RequestMapping("/") + @ResponseBody + String home() { + return "Hello World!"; + } + + public static void main(String[] args) throws Exception { + SpringApplication.run(App.class, args); + } +}