Compare commits

..

6 commits

Author SHA1 Message Date
Marek Skalický
edd4dcf23d
Pull changes from upstream repository 2018-11-06 14:17:59 +00:00
Clement Verna
5943f8b0df Drop Release label in favor of OSBS release_bump plugin.
OSBS can automatically bump the release number, for that
we just need to drop the label from the Dockerfile

See https://pagure.io/ContainerSIG/container-sig/issue/1

Signed-off-by: Clement Verna <cverna@tutanota.com>
2018-08-27 09:59:05 +02:00
Mohan Boddu
bb4de6e898 "Bump RELEASE for automatic rebuild" 2018-07-24 18:50:45 +00:00
Mohan Boddu
b76966c1da "Bump RELEASE for automatic rebuild" 2018-07-23 13:09:11 +00:00
Mohan Boddu
0e46089967 "Bump RELEASE for automatic rebuild" 2018-07-09 13:31:07 +00:00
Mohan Boddu
737e6b7934 "Bump RELEASE for automatic rebuild" 2018-05-30 19:19:51 +00:00
17 changed files with 1055 additions and 1 deletions

0
.gitignore vendored Normal file
View file

1
5 Symbolic link
View file

@ -0,0 +1 @@
.

47
Dockerfile Normal file
View file

@ -0,0 +1,47 @@
FROM registry.fedoraproject.org/f28/s2i-core:latest
EXPOSE 8080
EXPOSE 8443
ENV SUMMARY="Platform for running Varnish or building Varnish-based application" \
DESCRIPTION="Varnish available as container is a base platform for \
running Varnish server or building Varnish-based application. \
Varnish Cache stores web pages in memory so web servers don't have to create \
the same web page over and over again. Varnish Cache serves pages much faster \
than any application server; giving the website a significant speed up." \
VERSION=0 \
VARNISH_CONFIGURATION_PATH=/etc/varnish
LABEL summary="$SUMMARY" \
description="$DESCRIPTION" \
io.k8s.description="$DESCRIPTION" \
io.k8s.display-name="Varnish 5" \
io.openshift.expose-services="8080:http,8443:https" \
io.openshift.tags="builder,varnish" \
version="$VERSION" \
com.redhat.component="varnish" \
usage="s2i build https://github.com/sclorg/varnish-container.git --context-dir=5/test/test-app/ $FGC/varnish sample-server" \
name="$FGC/varnish" \
maintainer="SoftwareCollections.org <sclorg@redhat.com>"
RUN INSTALL_PKGS="gettext hostname nss_wrapper bind-utils varnish" && \
dnf -y --setopt=tsflags=nodocs install $INSTALL_PKGS && \
rpm -V $INSTALL_PKGS && \
fix-permissions $VARNISH_CONFIGURATION_PATH && \
fix-permissions /var/lib/varnish && \
rm -f /etc/profile.d/lang.sh && \
rm -f /etc/profile.d/lang.csh && \
dnf -y clean all --enablerepo='*'
# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH
COPY 5/s2i/bin/ $STI_SCRIPTS_PATH
# Copy extra files to the image.
COPY 5/root/ /
# Reset permissions of filesystem to default values
RUN rpm-file-permissions
USER 1001
CMD $STI_SCRIPTS_PATH/usage

1
Dockerfile.fedora Symbolic link
View file

@ -0,0 +1 @@
Dockerfile

78
README.md Normal file
View file

@ -0,0 +1,78 @@
Varnish Cache 5.0 HTTP reverse proxy Container image
=====================================================
This container image includes Varnish 5.0 Cache server and a reverse proxy for OpenShift and general usage.
Users can choose between RHEL and CentOS based images.
The RHEL image is available in the [Red Hat Container Catalog](https://access.redhat.com/containers/#/registry.access.redhat.com/rhscl/varnish-5-rhel7)
as registry.access.redhat.com/rhscl/varnish-5-rhel7.
The CentOS image is then available on [Docker Hub](https://hub.docker.com/r/centos/varnish-5-centos7/)
as centos/varnish-5-centos7.
Description
-----------
Varnish available as container is a base platform for
running Varnish server or building Varnish-based application.
Varnish Cache stores web pages in memory so web servers don't have to create
the same web page over and over again. Varnish Cache serves pages much faster
than any application server, giving the website a significant speed up.
The image can be used as a base image for other applications based on Varnish Cache 5.0 or using s2i tool.
Usage
-----
To build a simple [sample-app](https://github.com/sclorg/varnish-container/tree/generated/5/test/test-app) application
using standalone [S2I](https://github.com/openshift/source-to-image) and then run the
resulting image with [Docker](http://docker.io) execute:
* **For RHEL based image**
```
$ docker pull registry.access.redhat.com/rhscl/varnish-5-rhel7
$ s2i build https://github.com/sclorg/varnish-container.git --context-dir=5/test/test-app/ registry.access.redhat.com/rhscl/varnish-5-rhel7 sample-server
$ docker run -p 8080:8080 sample-server
```
* **For CentOS based image**
```
$ docker pull centos/varnish-5-centos7
$ s2i build https://github.com/sclorg/varnish-container.git --context-dir=5/test/test-app/ centos/varnish-5-centos7 sample-server
$ docker run -p 8080:8080 sample-server
```
**Accessing the application:**
```
$ curl 127.0.0.1:8080
```
Configuration
-------------
No further configuration is required.
S2I build support
-------------
The Varnish Cache 5.0 Container image supports the S2I tool (see Usage section).
Note that the default.vcl configuration file in the directory accessed by S2I needs
to be in the VCL format.
Environment variables and volumes
-------------
No special environment variables or volumes available.
Troubleshooting
---------------
Varnish logs into standard output, so the log is available in the container log. The log can be examined by running:
docker logs <container>
See also
--------
Dockerfile and other sources for this container image are available on
https://github.com/sclorg/varnish-container.
In that repository, Dockerfile for CentOS is called Dockerfile, Dockerfile
for RHEL is called Dockerfile.rhel7.

View file

@ -1 +0,0 @@
container sources not used for building fedora containers anymore

1
help.md Symbolic link
View file

@ -0,0 +1 @@
README.md

105
root/help.1 Normal file
View file

@ -0,0 +1,105 @@
.TH Varnish Cache 5.0 HTTP reverse proxy Container image
.PP
This container image includes Varnish 5.0 Cache server and a reverse proxy for OpenShift and general usage.
Users can choose between RHEL and CentOS based images.
The RHEL image is available in the Red Hat Container Catalog
\[la]https://access.redhat.com/containers/#/registry.access.redhat.com/rhscl/varnish-5-rhel7\[ra]
as registry.access.redhat.com/rhscl/varnish\-5\-rhel7.
The CentOS image is then available on Docker Hub
\[la]https://hub.docker.com/r/centos/varnish-5-centos7/\[ra]
as centos/varnish\-5\-centos7.
.SH Description
.PP
Varnish available as container is a base platform for
running Varnish server or building Varnish\-based application.
Varnish Cache stores web pages in memory so web servers don't have to create
the same web page over and over again. Varnish Cache serves pages much faster
than any application server, giving the website a significant speed up.
.PP
The image can be used as a base image for other applications based on Varnish Cache 5.0 or using s2i tool.
.SH Usage
.PP
To build a simple sample\-app
\[la]https://github.com/sclorg/varnish-container/tree/generated/5/test/test-app\[ra] application
using standalone S2I
\[la]https://github.com/openshift/source-to-image\[ra] and then run the
resulting image with Docker
\[la]http://docker.io\[ra] execute:
.IP \(bu 2
.PP
\fBFor RHEL based image\fP
.PP
.RS
.nf
$ docker pull registry.access.redhat.com/rhscl/varnish\-5\-rhel7
$ s2i build https://github.com/sclorg/varnish\-container.git \-\-context\-dir=5/test/test\-app/ registry.access.redhat.com/rhscl/varnish\-5\-rhel7 sample\-server
$ docker run \-p 8080:8080 sample\-server
.fi
.RE
.IP \(bu 2
.PP
\fBFor CentOS based image\fP
.PP
.RS
.nf
$ docker pull centos/varnish\-5\-centos7
$ s2i build https://github.com/sclorg/varnish\-container.git \-\-context\-dir=5/test/test\-app/ centos/varnish\-5\-centos7 sample\-server
$ docker run \-p 8080:8080 sample\-server
.fi
.RE
.PP
\fBAccessing the application:\fP
.PP
.RS
.nf
$ curl 127.0.0.1:8080
.fi
.RE
.SH Configuration
.PP
No further configuration is required.
.SH S2I build support
.PP
The Varnish Cache 5.0 Container image supports the S2I tool (see Usage section).
Note that the default.vcl configuration file in the directory accessed by S2I needs
to be in the VCL format.
.SH Environment variables and volumes
.PP
No special environment variables or volumes available.
.SH Troubleshooting
.PP
Varnish logs into standard output, so the log is available in the container log. The log can be examined by running:
.PP
.RS
.nf
docker logs <container>
.fi
.RE
.SH See also
.PP
Dockerfile and other sources for this container image are available on
\[la]https://github.com/sclorg/varnish-container\[ra]\&.
In that repository, Dockerfile for CentOS is called Dockerfile, Dockerfile
for RHEL is called Dockerfile.rhel7.

View file

@ -0,0 +1,9 @@
# Set current user in nss_wrapper
PASSWD_DIR="${APP_ROOT}/etc"
export USER_ID=$(id -u)
export GROUP_ID=$(id -g)
envsubst < ${PASSWD_DIR}/passwd.template > ${PASSWD_DIR}/passwd
export LD_PRELOAD=libnss_wrapper.so
export NSS_WRAPPER_PASSWD=${PASSWD_DIR}/passwd
export NSS_WRAPPER_GROUP=/etc/group

View file

@ -0,0 +1,15 @@
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
default:x:${USER_ID}:${GROUP_ID}:Default Application User:${HOME}:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin

View file

@ -0,0 +1,3 @@
# This will make scl collection binaries work out of box.
unset BASH_ENV PROMPT_COMMAND ENV
source scl_source enable rh-varnish5

22
s2i/bin/assemble Executable file
View file

@ -0,0 +1,22 @@
#!/bin/bash
set -e
echo "---> Copying varnish configuration files..."
rm -rf "${VARNISH_CONFIGURATION_PATH}/default.vcl"
cp -Rfv /tmp/src/. "${VARNISH_CONFIGURATION_PATH}"
if [ ! -f "${VARNISH_CONFIGURATION_PATH}/default.vcl" ]; then
echo "Error: The varnish configuration must contain 'default.vcl' file."
exit 1
fi
if [ ! -f "${VARNISH_CONFIGURATION_PATH}/varnish.params" ]; then
echo "Error: The varnish configuration must contain 'varnish.params' file."
exit 1
fi
cat "${VARNISH_CONFIGURATION_PATH}/default.vcl"
# Fix source directory permissions
fix-permissions ./
fix-permissions ${VARNISH_CONFIGURATION_PATH}

32
s2i/bin/run Executable file
View file

@ -0,0 +1,32 @@
#!/bin/bash
source /opt/app-root/etc/generate_container_user
set -e
. ${VARNISH_CONFIGURATION_PATH}/varnish.params
VERSION=$(varnishd -V 2>&1 | egrep -o "varnish-[0-9]")
VARNISH_TTL=${VARNISH_TTL:-120}
if [ "${VERSION}" == "varnish-4" ]; then
PORT_EXPOSE="-a :8080,:8443"
USER_GROUP='-u default -g root'
elif [ "${VERSION}" == "varnish-5" ]; then
PORT_EXPOSE="-a :8080 -a :8443"
USER_GROUP='-j unix,user=default,ccgroup=root'
else
echo "Unsupported version of varnishd: ${VERSION}"
exit 3
fi
exec varnishd \
-F \
-f $VARNISH_VCL_CONF \
${PORT_EXPOSE} \
-T 127.0.0.1:8081 \
-t $VARNISH_TTL \
-S $VARNISH_SECRET_FILE \
-s $VARNISH_STORAGE \
$DAEMON_OPTS

18
s2i/bin/usage Executable file
View file

@ -0,0 +1,18 @@
#!/bin/sh
DISTRO=`cat /etc/*-release | grep ^ID= | sed s/ID=// | tr -d '"'`
IMAGE=centos/varnish-5-$DISTRO
[[ $DISTRO =~ rhel* ]] && IMAGE=rhscl/varnish-5-$DISTRO
[[ $DISTRO =~ fedora* ]] && IMAGE=${FGC}/varnish
cat <<EOF
This is a S2I ${IMAGE_DESCRIPTION} ${DISTRO} base image:
To use it, install S2I: https://github.com/openshift/source-to-image
Sample invocation:
s2i build https://github.com/sclorg/varnish-container.git --context-dir=5/test/test-app/ ${IMAGE} varnish-sample-app
You can then run the resulting image via:
docker run -p 8080:8080 varnish-sample-app
EOF

200
test/run Executable file
View file

@ -0,0 +1,200 @@
#!/bin/bash
#
# The 'run' performs a simple test that verifies that S2I image.
# The main focus here is to excersise the S2I 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}
# TODO: Make command compatible for Mac users
test_dir="$(readlink -zf $(dirname "${BASH_SOURCE[0]}"))"
image_dir=$(readlink -zf ${test_dir}/..)
. "$test_dir/test-lib.sh"
# 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_s2i_build() {
ct_s2i_build_as_df file://${test_dir}/test-app ${IMAGE_NAME} ${IMAGE_NAME}-testapp ${s2i_args}
}
prepare() {
if ! image_exists ${IMAGE_NAME}; then
echo "ERROR: The image ${IMAGE_NAME} must exist before this script is executed."
exit 1
fi
# TODO: S2I 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_test_application() {
run_args=${CONTAINER_ARGS:-}
docker run --user=100001 ${run_args} --cidfile=${cid_file} ${IMAGE_NAME}-testapp
}
cleanup_test_app() {
info "Cleaning up the test application"
if [ -f $cid_file ]; then
if container_exists; then
docker stop $(cat $cid_file)
docker rm $(cat $cid_file)
fi
rm $cid_file
fi
}
cleanup() {
info "Cleaning up the test application image"
if image_exists ${IMAGE_NAME}-testapp; then
docker rmi -f ${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 ] && [ -s $cid_file ] && break
attempt=$(( $attempt + 1 ))
sleep $sleep_time
done
}
test_s2i_usage() {
info "Testing 's2i usage'"
ct_s2i_usage ${IMAGE_NAME} ${s2i_args} &>/dev/null
}
test_docker_run_usage() {
info "Testing 'docker run' usage"
docker run ${IMAGE_NAME} &>/dev/null
}
test_scl_usage() {
local run_cmd="$1"
local expected="$2"
info "Testing the image SCL enable"
out=$(docker run --rm ${IMAGE_NAME} /bin/bash -c "${run_cmd} 2>&1")
if ! echo "${out}" | grep -q "${expected}"; then
echo "ERROR[/bin/bash -c "${run_cmd}"] Expected '${expected}', got '${out}'"
return 1
fi
out=$(docker exec $(cat ${cid_file}) /bin/bash -c "${run_cmd}" 2>&1)
if ! echo "${out}" | grep -q "${expected}"; then
echo "ERROR[exec /bin/bash -c "${run_cmd}"] Expected '${expected}', got '${out}'"
return 1
fi
out=$(docker exec $(cat ${cid_file}) /bin/sh -ic "${run_cmd}" 2>&1)
if ! echo "${out}" | grep -q "${expected}"; then
echo "ERROR[exec /bin/sh -ic "${run_cmd}"] Expected '${expected}', got '${out}'"
return 1
fi
}
test_connection() {
cat $cid_file
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=$(curl -s -w "%{redirect_url}" -H "Host:oldexample.com" http://$(container_ip):${test_port}/)
echo "${response}"
status=$?
if [ $status -eq 0 ]; then
if echo "${response}" | grep -q "http://example.org"; then
result=0
break
else
echo "Response: ${response}"
fi
fi
attempt=$(( $attempt + 1 ))
sleep $sleep_time
done
return $result
}
test_application() {
# 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_scl_usage "varnishd -V" "varnish-$VERSION"
check_result $?
test_connection
check_result $?
cleanup_test_app
}
cid_file=$(mktemp -u --suffix=.cid)
# Since we built the candidate image locally, we don't want S2I attempt to pull
# it from Docker hub
s2i_args="--pull-policy=never"
prepare
run_s2i_build
check_result $?
# Verify the 'usage' script is working properly when running the base image with 's2i usage ...'
test_s2i_usage
check_result $?
# Verify the 'usage' script is working properly when running the base image with 'docker run ...'
test_docker_run_usage
check_result $?
# Test application with default uid
test_application
# Test application with random uid
CONTAINER_ARGS="--user 12345" test_application
cleanup
info "All tests finished successfully."

16
test/test-app/default.vcl Normal file
View file

@ -0,0 +1,16 @@
vcl 4.0;
backend default {
.host = "127.0.0.1";
.port = "80";
}
sub vcl_recv {
return(synth(301, "Page moved"));
}
sub vcl_synth {
if (resp.status == 301) {
set resp.http.Location = "http://example.org";
return (deliver);
}
}

507
test/test-lib.sh Normal file
View file

@ -0,0 +1,507 @@
#
# Test a container image.
#
# Always use sourced from a specific container testfile
#
# reguires definition of CID_FILE_DIR
# CID_FILE_DIR=$(mktemp --suffix=<container>_test_cidfiles -d)
# reguires definition of TEST_LIST
# TEST_LIST="\
# ctest_container_creation
# ctest_doc_content"
# Container CI tests
# abbreviated as "ct"
# may be redefined in the specific container testfile
EXPECTED_EXIT_CODE=0
# ct_cleanup
# --------------------
# Cleans up containers used during tests. Stops and removes all containers
# referenced by cid_files in CID_FILE_DIR. Dumps logs if a container exited
# unexpectedly. Removes the cid_files and CID_FILE_DIR as well.
# Uses: $CID_FILE_DIR - path to directory containing cid_files
# Uses: $EXPECTED_EXIT_CODE - expected container exit code
function ct_cleanup() {
for cid_file in $CID_FILE_DIR/* ; do
local container=$(cat $cid_file)
: "Stopping and removing container $container..."
docker stop $container
exit_status=$(docker inspect -f '{{.State.ExitCode}}' $container)
if [ "$exit_status" != "$EXPECTED_EXIT_CODE" ]; then
: "Dumping logs for $container"
docker logs $container
fi
docker rm -v $container
rm $cid_file
done
rmdir $CID_FILE_DIR
: "Done."
}
# ct_enable_cleanup
# --------------------
# Enables automatic container cleanup after tests.
function ct_enable_cleanup() {
trap ct_cleanup EXIT SIGINT
}
# ct_get_cid [name]
# --------------------
# Prints container id from cid_file based on the name of the file.
# Argument: name - name of cid_file where the container id will be stored
# Uses: $CID_FILE_DIR - path to directory containing cid_files
function ct_get_cid() {
local name="$1" ; shift || return 1
echo $(cat "$CID_FILE_DIR/$name")
}
# ct_get_cip [id]
# --------------------
# Prints container ip address based on the container id.
# Argument: id - container id
function ct_get_cip() {
local id="$1" ; shift
docker inspect --format='{{.NetworkSettings.IPAddress}}' $(ct_get_cid "$id")
}
# ct_wait_for_cid [cid_file]
# --------------------
# Holds the execution until the cid_file is created. Usually run after container
# creation.
# Argument: cid_file - name of the cid_file that should be created
function ct_wait_for_cid() {
local cid_file=$1
local max_attempts=10
local sleep_time=1
local attempt=1
local result=1
while [ $attempt -le $max_attempts ]; do
[ -f $cid_file ] && [ -s $cid_file ] && return 0
: "Waiting for container start..."
attempt=$(( $attempt + 1 ))
sleep $sleep_time
done
return 1
}
# ct_assert_container_creation_fails [container_args]
# --------------------
# The invocation of docker run should fail based on invalid container_args
# passed to the function. Returns 0 when container fails to start properly.
# Argument: container_args - all arguments are passed directly to dokcer run
# Uses: $CID_FILE_DIR - path to directory containing cid_files
function ct_assert_container_creation_fails() {
local ret=0
local max_attempts=10
local attempt=1
local cid_file=assert
set +e
local old_container_args="${CONTAINER_ARGS-}"
CONTAINER_ARGS="$@"
ct_create_container $cid_file
if [ $? -eq 0 ]; then
local cid=$(ct_get_cid $cid_file)
while [ "$(docker inspect -f '{{.State.Running}}' $cid)" == "true" ] ; do
sleep 2
attempt=$(( $attempt + 1 ))
if [ $attempt -gt $max_attempts ]; then
docker stop $cid
ret=1
break
fi
done
exit_status=$(docker inspect -f '{{.State.ExitCode}}' $cid)
if [ "$exit_status" == "0" ]; then
ret=1
fi
docker rm -v $cid
rm $CID_FILE_DIR/$cid_file
fi
[ ! -z $old_container_args ] && CONTAINER_ARGS="$old_container_args"
set -e
return $ret
}
# ct_create_container [name, command]
# --------------------
# Creates a container using the IMAGE_NAME and CONTAINER_ARGS variables. Also
# stores the container id to a cid_file located in the CID_FILE_DIR, and waits
# for the creation of the file.
# Argument: name - name of cid_file where the container id will be stored
# Argument: command - optional command to be executed in the container
# Uses: $CID_FILE_DIR - path to directory containing cid_files
# Uses: $CONTAINER_ARGS - optional arguments passed directly to docker run
# Uses: $IMAGE_NAME - name of the image being tested
function ct_create_container() {
local cid_file="$CID_FILE_DIR/$1" ; shift
# create container with a cidfile in a directory for cleanup
docker run --cidfile="$cid_file" -d ${CONTAINER_ARGS:-} $IMAGE_NAME "$@"
ct_wait_for_cid $cid_file || return 1
: "Created container $(cat $cid_file)"
}
# ct_scl_usage_old [name, command, expected]
# --------------------
# Tests three ways of running the SCL, by looking for an expected string
# in the output of the command
# Argument: name - name of cid_file where the container id will be stored
# Argument: command - executed inside the container
# Argument: expected - string that is expected to be in the command output
# Uses: $CID_FILE_DIR - path to directory containing cid_files
# Uses: $IMAGE_NAME - name of the image being tested
function ct_scl_usage_old() {
local name="$1"
local command="$2"
local expected="$3"
local out=""
: " Testing the image SCL enable"
out=$(docker run --rm ${IMAGE_NAME} /bin/bash -c "${command}")
if ! echo "${out}" | grep -q "${expected}"; then
echo "ERROR[/bin/bash -c "${command}"] Expected '${expected}', got '${out}'" >&2
return 1
fi
out=$(docker exec $(ct_get_cid $name) /bin/bash -c "${command}" 2>&1)
if ! echo "${out}" | grep -q "${expected}"; then
echo "ERROR[exec /bin/bash -c "${command}"] Expected '${expected}', got '${out}'" >&2
return 1
fi
out=$(docker exec $(ct_get_cid $name) /bin/sh -ic "${command}" 2>&1)
if ! echo "${out}" | grep -q "${expected}"; then
echo "ERROR[exec /bin/sh -ic "${command}"] Expected '${expected}', got '${out}'" >&2
return 1
fi
}
# ct_doc_content_old [strings]
# --------------------
# Looks for occurence of stirngs in the documentation files and checks
# the format of the files. Files examined: help.1
# Argument: strings - strings expected to appear in the documentation
# Uses: $IMAGE_NAME - name of the image being tested
function ct_doc_content_old() {
local tmpdir=$(mktemp -d)
local f
: " Testing documentation in the container image"
# Extract the help files from the container
for f in help.1 ; do
docker run --rm ${IMAGE_NAME} /bin/bash -c "cat /${f}" >${tmpdir}/$(basename ${f})
# Check whether the files contain some important information
for term in $@ ; do
if ! cat ${tmpdir}/$(basename ${f}) | grep -F -q -e "${term}" ; then
echo "ERROR: File /${f} does not include '${term}'." >&2
return 1
fi
done
# Check whether the files use the correct format
for term in TH PP SH ; do
if ! grep -q "^\.${term}" ${tmpdir}/help.1 ; then
echo "ERROR: /help.1 is probably not in troff or groff format, since '${term}' is missing." >&2
return 1
fi
done
done
: " Success!"
}
# ct_npm_works
# --------------------
# Checks existance of the npm tool and runs it.
function ct_npm_works() {
local tmpdir=$(mktemp -d)
: " Testing npm in the container image"
docker run --rm ${IMAGE_NAME} /bin/bash -c "npm --version" >${tmpdir}/version
if [ $? -ne 0 ] ; then
echo "ERROR: 'npm --version' does not work inside the image ${IMAGE_NAME}." >&2
return 1
fi
docker run --rm ${IMAGE_NAME} /bin/bash -c "npm install jquery && test -f node_modules/jquery/src/jquery.js"
if [ $? -ne 0 ] ; then
echo "ERROR: npm could not install jquery inside the image ${IMAGE_NAME}." >&2
return 1
fi
: " Success!"
}
# ct_path_append PATH_VARNAME DIRECTORY
# -------------------------------------
# Append DIRECTORY to VARIABLE of name PATH_VARNAME, the VARIABLE must consist
# of colon-separated list of directories.
ct_path_append ()
{
if eval "test -n \"\${$1-}\""; then
eval "$1=\$2:\$$1"
else
eval "$1=\$2"
fi
}
# ct_path_foreach PATH ACTION [ARGS ...]
# --------------------------------------
# For each DIR in PATH execute ACTION (path is colon separated list of
# directories). The particular calls to ACTION will look like
# '$ ACTION directory [ARGS ...]'
ct_path_foreach ()
{
local dir dirlist action save_IFS
save_IFS=$IFS
IFS=:
dirlist=$1
action=$2
shift 2
for dir in $dirlist; do "$action" "$dir" "$@" ; done
IFS=$save_IFS
}
# ct_run_test_list
# --------------------
# Execute the tests specified by TEST_LIST
# Uses: $TEST_LIST - list of test names
function ct_run_test_list() {
for test_case in $TEST_LIST; do
: "Running test $test_case"
[ -f test/$test_case ] && source test/$test_case
[ -f ../test/$test_case ] && source ../test/$test_case
$test_case
done;
}
# ct_gen_self_signed_cert_pem
# ---------------------------
# Generates a self-signed PEM certificate pair into specified directory.
# Argument: output_dir - output directory path
# Argument: base_name - base name of the certificate files
# Resulted files will be those:
# <output_dir>/<base_name>-cert-selfsigned.pem -- public PEM cert
# <output_dir>/<base_name>-key.pem -- PEM private key
ct_gen_self_signed_cert_pem() {
local output_dir=$1 ; shift
local base_name=$1 ; shift
mkdir -p ${output_dir}
openssl req -newkey rsa:2048 -nodes -keyout ${output_dir}/${base_name}-key.pem -subj '/C=GB/ST=Berkshire/L=Newbury/O=My Server Company' > ${base_name}-req.pem
openssl req -new -x509 -nodes -key ${output_dir}/${base_name}-key.pem -batch > ${output_dir}/${base_name}-cert-selfsigned.pem
}
# ct_obtain_input FILE|DIR|URL
# --------------------
# Either copies a file or a directory to a tmp location for local copies, or
# downloads the file from remote location.
# Resulted file path is printed, so it can be later used by calling function.
# Arguments: input - local file, directory or remote URL
function ct_obtain_input() {
local input=$1
local extension="${input##*.}"
# Try to use same extension for the temporary file if possible
[[ "${extension}" =~ ^[a-z0-9]*$ ]] && extension=".${extension}" || extension=""
local output=$(mktemp "/var/tmp/test-input-XXXXXX$extension")
if [ -f "${input}" ] ; then
cp -f "${input}" "${output}"
elif [ -d "${input}" ] ; then
rm -f "${output}"
cp -r -LH "${input}" "${output}"
elif echo "${input}" | grep -qe '^http\(s\)\?://' ; then
curl "${input}" > "${output}"
else
echo "ERROR: file type not known: ${input}" >&2
return 1
fi
echo "${output}"
}
# ct_test_response
# ----------------
# Perform GET request to the application container, checks output with
# a reg-exp and HTTP response code.
# Argument: url - request URL path
# Argument: expected_code - expected HTTP response code
# Argument: body_regexp - PCRE regular expression that must match the response body
# Argument: max_attempts - Optional number of attempts (default: 20), three seconds sleep between
# Argument: ignore_error_attempts - Optional number of attempts when we ignore error output (default: 10)
ct_test_response() {
local url="$1"
local expected_code="$2"
local body_regexp="$3"
local max_attempts=${4:-20}
local ignore_error_attempts=${5:-10}
: " Testing the HTTP(S) response for <${url}>"
local sleep_time=3
local attempt=1
local result=1
local status
local response_code
local response_file=$(mktemp /tmp/ct_test_response_XXXXXX)
while [ ${attempt} -le ${max_attempts} ]; do
curl --connect-timeout 10 -s -w '%{http_code}' "${url}" >${response_file} && status=0 || status=1
if [ ${status} -eq 0 ]; then
response_code=$(cat ${response_file} | tail -c 3)
if [ "${response_code}" -eq "${expected_code}" ]; then
result=0
fi
cat ${response_file} | grep -qP -e "${body_regexp}" || result=1;
# Some services return 40x code until they are ready, so let's give them
# some chance and not end with failure right away
# Do not wait if we already have expected outcome though
if [ ${result} -eq 0 -o ${attempt} -gt ${ignore_error_attempts} -o ${attempt} -eq ${max_attempts} ] ; then
break
fi
fi
attempt=$(( ${attempt} + 1 ))
sleep ${sleep_time}
done
rm -f ${response_file}
return ${result}
}
# ct_registry_from_os OS
# ----------------
# Transform operating system string [os] into registry url
# Argument: OS - string containing the os version
ct_registry_from_os() {
local registry=""
case $1 in
rhel7)
registry=registry.access.redhat.com
;;
*)
registry=docker.io
;;
esac
echo "$registry"
}
# ct_assert_cmd_success CMD
# ----------------
# Evaluates [cmd] and fails if it does not succeed.
# Argument: CMD - Command to be run
function ct_assert_cmd_success() {
echo "Checking '$*' for success ..."
if ! eval "$@" &>/dev/null; then
echo " FAIL"
return 1
fi
echo " PASS"
return 0
}
# ct_assert_cmd_failure CMD
# ----------------
# Evaluates [cmd] and fails if it succeeds.
# Argument: CMD - Command to be run
function ct_assert_cmd_failure() {
echo "Checking '$*' for failure ..."
if eval "$@" &>/dev/null; then
echo " FAIL"
return 1
fi
echo " PASS"
return 0
}
# ct_random_string [LENGTH=10]
# ----------------------------
# Generate pseudorandom alphanumeric string of LENGTH bytes, the
# default length is 10. The string is printed on stdout.
ct_random_string()
(
export LC_ALL=C
dd if=/dev/urandom count=1 bs=10k 2>/dev/null \
| tr -dc 'a-z0-9' \
| fold -w "${1-10}" \
| head -n 1
)
# ct_s2i_usage IMG_NAME [S2I_ARGS]
# ----------------------------
# Create a container and run the usage script inside
# Argument: IMG_NAME - name of the image to be used for the container run
# Argument: S2I_ARGS - Additional list of source-to-image arguments, currently unused.
ct_s2i_usage()
{
local img_name=$1; shift
local s2i_args="$*";
local usage_command="/usr/libexec/s2i/usage"
docker run --rm "$img_name" bash -c "$usage_command"
}
# ct_s2i_build_as_df APP_PATH SRC_IMAGE DST_IMAGE [S2I_ARGS]
# ----------------------------
# Create a new s2i app image from local sources in a similar way as source-to-image would have used.
# Argument: APP_PATH - local path to the app sources to be used in the test
# Argument: SRC_IMAGE - image to be used as a base for the s2i build
# Argument: DST_IMAGE - image name to be used during the tagging of the s2i build result
# Argument: S2I_ARGS - Additional list of source-to-image arguments.
# Only used to check for pull-policy=never and environment variable definitions.
ct_s2i_build_as_df()
{
local app_path=$1; shift
local src_image=$1; shift
local dst_image=$1; shift
local s2i_args="$*";
local local_app=upload/src/
local local_scripts=upload/scripts/
local user_id=
local df_name=
local tmpdir=
# Use /tmp to not pollute cwd
tmpdir=$(mktemp -d)
df_name=$(mktemp -p "$tmpdir" Dockerfile.XXXX)
pushd "$tmpdir"
# Check if the image is available locally and try to pull it if it is not
docker images "$src_image" &>/dev/null || echo "$s2i_args" | grep -q "pull-policy=never" || docker pull "$src_image"
user_id=$(docker inspect -f "{{.ContainerConfig.User}}" "$src_image")
# Strip file:// from APP_PATH and copy its contents into current context
mkdir -p "$local_app"
cp -r "${app_path/file:\/\//}/." "$local_app"
[ -d "$local_app/.s2i/bin/" ] && mv "$local_app/.s2i/bin" "$local_scripts"
# Create a Dockerfile named df_name and fill it with proper content
#FIXME: Some commands could be combined into a single layer but not sure if worth the trouble for testing purposes
cat <<EOF >"$df_name"
FROM $src_image
LABEL "io.openshift.s2i.build.image"="$src_image" \\
"io.openshift.s2i.build.source-location"="$app_path"
USER root
COPY $local_app /tmp/src
EOF
[ -d "$local_scripts" ] && echo "COPY $local_scripts /tmp/scripts" >> "$df_name" &&
echo "RUN chown -R $user_id:0 /tmp/scripts" >>"$df_name"
echo "RUN chown -R $user_id:0 /tmp/src" >>"$df_name"
# Check for custom environment variables inside .s2i/ folder
if [ -e "$local_app/.s2i/environment" ]; then
# Remove any comments and add the contents as ENV commands to the Dockerfile
sed '/^\s*#.*$/d' "$local_app/.s2i/environment" | while read -r line; do
echo "ENV $line" >>"$df_name"
done
fi
# Filter out env var definitions from $s2i_args and create Dockerfile ENV commands out of them
echo "$s2i_args" | grep -o -e '\(-e\|--env\)[[:space:]=]\S*=\S*' | sed -e 's/-e /ENV /' -e 's/--env[ =]/ENV /' >>"$df_name"
echo "USER $user_id" >>"$df_name"
# If exists, run the custom assemble script, else default to /usr/libexec/s2i/assemble
if [ -x "$local_scripts/assemble" ]; then
echo "RUN /tmp/scripts/assemble" >>"$df_name"
else
echo "RUN /usr/libexec/s2i/assemble" >>"$df_name"
fi
# If exists, set the custom run script as CMD, else default to /usr/libexec/s2i/run
if [ -x "$local_scripts/run" ]; then
echo "CMD /tmp/scripts/run" >>"$df_name"
else
echo "CMD /usr/libexec/s2i/run" >>"$df_name"
fi
# Run the build and tag the result
docker build -f "$df_name" -t "$dst_image" .
popd
}