Merge pull request #340 from zmiklank/exit_oc_tests_if_login_fails

Exit oc tests gracefully if login fails
This commit is contained in:
phracek 2022-06-10 08:44:57 +00:00
commit 5bfde53a71
51 changed files with 5345 additions and 0 deletions

1
14 Symbolic link
View file

@ -0,0 +1 @@
.

71
Dockerfile Normal file
View file

@ -0,0 +1,71 @@
FROM quay.io/fedora/s2i-core:latest
# This image provides a Node.JS environment you can use to run your Node.JS
# applications.
EXPOSE 8080
# Add $HOME/node_modules/.bin to the $PATH, allowing user to make npm scripts
# available on the CLI without using npm's --global installation mode
# This image will be initialized with "npm run $NPM_RUN"
# See https://docs.npmjs.com/misc/scripts, and your repo's package.json
# file for possible values of NPM_RUN
# Description
# Environment:
# * $NPM_RUN - Select an alternate / custom runtime mode, defined in your package.json files' scripts section (default: npm run "start").
# Expose ports:
# * 8080 - Unprivileged port used by nodejs application
ENV NODEJS_VERSION=14 \
NPM_RUN=start \
NAME=nodejs \
NPM_CONFIG_PREFIX=$HOME/.npm-global \
PATH=$HOME/node_modules/.bin/:$HOME/.npm-global/bin/:$PATH
ENV SUMMARY="Platform for building and running Node.js $NODEJS_VERSION applications" \
DESCRIPTION="Node.js $NODEJS_VERSION available as container is a base platform for \
building and running various Node.js $NODEJS_VERSION applications and frameworks. \
Node.js is a platform built on Chrome's JavaScript runtime for easily building \
fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model \
that makes it lightweight and efficient, perfect for data-intensive real-time applications \
that run across distributed devices."
LABEL summary="$SUMMARY" \
description="$DESCRIPTION" \
io.k8s.description="$DESCRIPTION" \
io.k8s.display-name="Node.js $NODEJS_VERSION" \
io.openshift.expose-services="8080:http" \
io.openshift.tags="builder,$NAME,$NAME$NODEJS_VERSION" \
io.openshift.s2i.scripts-url="image:///usr/libexec/s2i" \
io.s2i.scripts-url="image:///usr/libexec/s2i" \
com.redhat.dev-mode="DEV_MODE:false" \
com.redhat.deployments-dir="${APP_ROOT}/src" \
com.redhat.dev-mode.port="DEBUG_PORT:5858"\
com.redhat.component="$NAME" \
name="$FGC/$NAME" \
version="$NODEJS_VERSION" \
maintainer="SoftwareCollections.org <sclorg@redhat.com>" \
help="For more information visit https://github.com/sclorg/s2i-nodejs-container" \
usage="oc new-app $FGC/$NAME~<SOURCE-REPOSITORY>"
RUN yum -y module enable nodejs:$NODEJS_VERSION && \
MODULE_DEPS="make gcc gcc-c++ libatomic_ops git openssl-devel" && \
INSTALL_PKGS="$MODULE_DEPS nodejs nodejs-nodemon npm nss_wrapper" && \
yum install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \
rpm -V $INSTALL_PKGS && \
yum -y clean all --enablerepo='*'
# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH
COPY ./s2i/bin/ $STI_SCRIPTS_PATH
# Copy extra files to the image, including help file.
COPY ./root/ /
# Drop the root user and make the content of /opt/app-root owned by user 1001
RUN chown -R 1001:0 ${APP_ROOT} && chmod -R ug+rwx ${APP_ROOT} && \
rpm-file-permissions
USER 1001
# Set the default CMD to print the usage of the language image
CMD $STI_SCRIPTS_PATH/usage

1
Dockerfile.fedora Symbolic link
View file

@ -0,0 +1 @@
Dockerfile

250
README.md Normal file
View file

@ -0,0 +1,250 @@
NodeJS 14 container image
=========================
This container image includes Node.JS 14 as a [S2I](https://github.com/openshift/source-to-image) base image for your Node.JS 14 applications.
Users can choose between RHEL, CentOS and Fedora based images.
The RHEL images are available in the [Red Hat Container Catalog](https://access.redhat.com/containers/),
the CentOS images are available on [Quay.io](https://quay.io/organization/centos7),
and the Fedora images are available in [Fedora Registry](https://registry.fedoraproject.org/).
The resulting image can be run using [podman](https://github.com/containers/libpod).
Note: while the examples in this README are calling `podman`, you can replace any such calls by `docker` with the same arguments
Description
-----------
Node.js 14 available as container is a base platform for
building and running various Node.js 14 applications and frameworks.
Node.js is a platform built on Chrome's JavaScript runtime for easily building
fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model
that makes it lightweight and efficient, perfect for data-intensive real-time applications
that run across distributed devices.
Usage in OpenShift
------------------
In this example, we will assume that you are using the `ubi8/nodejs-14` image, available via `nodejs:14` imagestream tag in Openshift.
To build a simple [nodejs-sample-app](https://github.com/sclorg/nodejs-ex.git) application in Openshift:
```
oc new-app nodejs:14~https://github.com/sclorg/nodejs-ex.git
```
To access the application:
```
$ oc get pods
$ oc exec <pod> -- curl 127.0.0.1:8080
```
Source-to-Image framework and scripts
-------------------------------------
This image supports the [Source-to-Image](https://docs.openshift.com/container-platform/3.11/creating_images/s2i.html)
(S2I) strategy in OpenShift. The Source-to-Image is an OpenShift framework
which makes it easy to write images that take application source code as
an input, use a builder image like this Node.js container image, and produce
a new image that runs the assembled application as an output.
To support the Source-to-Image framework, important scripts are included in the builder image:
* The `/usr/libexec/s2i/assemble` script inside the image is run to produce a new image with the application artifacts. The script takes sources of a given application and places them into appropriate directories inside the image. It utilizes some common patterns in Node.js application development (see the **Environment variables** section below).
* The `/usr/libexec/s2i/run` script is set as the default command in the resulting container image (the new image with the application artifacts). It runs `npm run` for production, or `nodemon` if `DEV_MODE` is set to `true` (see the **Environment variables** section below).
Building an application using a Dockerfile
------------------------------------------
Compared to the Source-to-Image strategy, using a Dockerfile is a more
flexible way to build a Node.js container image with an application.
Use a Dockerfile when Source-to-Image is not sufficiently flexible for you or
when you build the image outside of the OpenShift environment.
To use the Node.js image in a Dockerfile, follow these steps:
#### 1. Pull a base builder image to build on
```
podman pull ubi8/nodejs-14
```
An UBI image `ubi8/nodejs-14` is used in this example. This image is usable and freely redistributable under the terms of the UBI End User License Agreement (EULA). See more about UBI at [UBI FAQ](https://developers.redhat.com/articles/ubi-faq).
#### 2. Pull an application code
An example application available at https://github.com/sclorg/nodejs-ex.git is used here. Feel free to clone the repository for further experiments.
```
git clone https://github.com/sclorg/nodejs-ex.git app-src
```
#### 3. Prepare an application inside a container
This step usually consists of at least these parts:
* putting the application source into the container
* installing the dependencies
* setting the default command in the resulting image
For all these three parts, users can either setup all manually and use commands `nodejs` and `npm` explicitly in the Dockerfile ([3.1.](#31-to-use-your-own-setup-create-a-dockerfile-with-this-content)), or users can use the Source-to-Image scripts inside the image ([3.2.](#32-to-use-the-source-to-image-scripts-and-build-an-image-using-a-dockerfile-create-a-dockerfile-with-this-content); see more about these scripts in the section "Source-to-Image framework and scripts" above), that already know how to set-up and run some common Node.js applications.
##### 3.1. To use your own setup, create a Dockerfile with this content:
```
FROM ubi8/nodejs-14
# Add application sources
ADD app-src .
# Install the dependencies
RUN npm install
# Run script uses standard ways to run the application
CMD npm run -d start
```
##### 3.2. To use the Source-to-Image scripts and build an image using a Dockerfile, create a Dockerfile with this content:
```
FROM ubi8/nodejs-14
# Add application sources to a directory that the assemble script expects them
# and set permissions so that the container runs without root access
USER 0
ADD app-src /tmp/src
RUN chown -R 1001:0 /tmp/src
USER 1001
# Install the dependencies
RUN /usr/libexec/s2i/assemble
# Set the default command for the resulting image
CMD /usr/libexec/s2i/run
```
#### 4. Build a new image from a Dockerfile prepared in the previous step
```
podman build -t node-app .
```
#### 5. Run the resulting image with the final application
```
podman run -d node-app
```
Environment variables for Source-to-Image
---------------------
Application developers can use the following environment variables to configure the runtime behavior of this image in OpenShift:
**`NODE_ENV`**
NodeJS runtime mode (default: "production")
**`DEV_MODE`**
When set to "true", `nodemon` will be used to automatically reload the server while you work (default: "false"). Setting `DEV_MODE` to "true" will change the `NODE_ENV` default to "development" (if not explicitly set).
**`NPM_RUN`**
Select an alternate / custom runtime mode, defined in your `package.json` file's [`scripts`](https://docs.npmjs.com/misc/scripts) section (default: npm run "start"). These user-defined run-scripts are unavailable while `DEV_MODE` is in use.
**`HTTP_PROXY`**
Use an npm proxy during assembly
**`HTTPS_PROXY`**
Use an npm proxy during assembly
**`NPM_MIRROR`**
Use a custom NPM registry mirror to download packages during the build process
One way to define a set of environment variables is to include them as key value pairs in your repo's `.s2i/environment` file.
Example: DATABASE_USER=sampleUser
#### NOTE: Define your own "`DEV_MODE`":
The following `package.json` example includes a `scripts.dev` entry. You can define your own custom [`NPM_RUN`](https://docs.npmjs.com/cli/run-script) scripts in your application's `package.json` file.
#### Note: Setting logging output verbosity
To alter the level of logs output during an `npm install` the npm_config_loglevel environment variable can be set. See [npm-config](https://docs.npmjs.com/misc/config).
Development Mode
----------------
This image supports development mode. This mode can be switched on and off with the environment variable `DEV_MODE`. `DEV_MODE` can either be set to `true` or `false`.
Development mode supports two features:
* Hot Deploy
* Debugging
The debug port can be specified with the environment variable `DEBUG_PORT`. `DEBUG_PORT` is only valid if `DEV_MODE=true`.
A simple example command for running the container in development mode is:
```
podman run --env DEV_MODE=true my-image-id
```
To run the container in development mode with a debug port of 5454, run:
```
$ podman run --env DEV_MODE=true DEBUG_PORT=5454 my-image-id
```
To run the container in production mode, run:
```
$ podman run --env DEV_MODE=false my-image-id
```
By default, `DEV_MODE` is set to `false`, and `DEBUG_PORT` is set to `5858`, however the `DEBUG_PORT` is only relevant if `DEV_MODE=true`.
Hot deploy
----------
As part of development mode, this image supports hot deploy. If development mode is enabled, any souce code that is changed in the running container will be immediately reflected in the running nodejs application.
### Using Podman's exec
To change your source code in a running container, use Podman's [exec](https://github.com/containers/libpod) command:
```
$ podman exec -it <CONTAINER_ID> /bin/bash
```
After you [Podman exec](https://github.com/containers/libpod) into the running container, your current directory is set to `/opt/app-root/src`, where the source code for your application is located.
### Using OpenShift's rsync
If you have deployed the container to OpenShift, you can use [oc rsync](https://docs.openshift.org/latest/dev_guide/copy_files_to_container.html) to copy local files to a remote container running in an OpenShift pod.
#### Warning:
The default behaviour of the s2i-nodejs container image is to run the Node.js application using the command `npm start`. This runs the _start_ script in the _package.json_ file. In developer mode, the application is run using the command `nodemon`. The default behaviour of nodemon is to look for the _main_ attribute in the _package.json_ file, and execute that script. If the _main_ attribute doesn't appear in the _package.json_ file, it executes the _start_ script. So, in order to achieve some sort of uniform functionality between production and development modes, the user should remove the _main_ attribute.
Below is an example _package.json_ file with the _main_ attribute and _start_ script marked appropriately:
```json
{
"name": "node-echo",
"version": "0.0.1",
"description": "node-echo",
"main": "example.js", <--- main attribute
"dependencies": {
},
"devDependencies": {
"nodemon": "*"
},
"engine": {
"node": "*",
"npm": "*"
},
"scripts": {
"dev": "nodemon --ignore node_modules/ server.js",
"start": "node server.js" <-- start script
},
"keywords": [
"Echo"
],
"license": "",
}
```
#### Note:
`oc rsync` is only available in versions 3.1+ of OpenShift.
See also
--------
Dockerfile and other sources are available on https://github.com/sclorg/s2i-nodejs-container.
In that repository you also can find another versions of Node.js environment Dockerfiles.
Dockerfile for CentOS is called `Dockerfile`, Dockerfile for RHEL7 is called `Dockerfile.rhel7`,
for RHEL8 it's `Dockerfile.rhel8` and the Fedora Dockerfile is called Dockerfile.fedora.

1
help.md Symbolic link
View file

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

View file

@ -0,0 +1,17 @@
# Set current user in nss_wrapper
USER_ID=$(id -u)
GROUP_ID=$(id -g)
if [ x"$USER_ID" != x"0" -a x"$USER_ID" != x"1001" ]; then
NSS_WRAPPER_PASSWD=/opt/app-root/etc/passwd
NSS_WRAPPER_GROUP=/etc/group
cat /etc/passwd | sed -e 's/^default:/builder:/' > $NSS_WRAPPER_PASSWD
echo "default:x:${USER_ID}:${GROUP_ID}:Default Application User:${HOME}:/sbin/nologin" >> $NSS_WRAPPER_PASSWD
export NSS_WRAPPER_PASSWD
export NSS_WRAPPER_GROUP
export LD_PRELOAD=libnss_wrapper.so
fi

View file

@ -0,0 +1,5 @@
async
mime
mkdirp
qs
minimatch

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-nodejs${NODEJS_VERSION}

116
s2i/bin/assemble Executable file
View file

@ -0,0 +1,116 @@
#!/bin/bash
# Prevent running assemble in builders different than official STI image.
# The official nodejs:8-onbuild already run npm install and use different
# application folder.
[ -d "/usr/src/app" ] && exit 0
set -e
# FIXME: Linking of global modules is disabled for now as it causes npm failures
# under RHEL7
# Global modules good to have
# npmgl=$(grep "^\s*[^#\s]" ../etc/npm_global_module_list | sort -u)
# Available global modules; only match top-level npm packages
#global_modules=$(npm ls -g 2> /dev/null | perl -ne 'print "$1\n" if /^\S+\s(\S+)\@[\d\.-]+/' | sort -u)
# List all modules in common
#module_list=$(/usr/bin/comm -12 <(echo "${global_modules}") | tr '\n' ' ')
# Link the modules
#npm link $module_list
safeLogging () {
if [[ $1 =~ http[s]?://.*@.*$ ]]; then
echo $1 | sed 's/^.*@/redacted@/'
else
echo $1
fi
}
shopt -s dotglob
if [ -d /tmp/artifacts ] && [ "$(ls /tmp/artifacts/ 2>/dev/null)" ]; then
echo "---> Restoring previous build artifacts ..."
mv -T --verbose /tmp/artifacts/node_modules "${HOME}/node_modules"
fi
echo "---> Installing application source ..."
mv /tmp/src/* ./
# Fix source directory permissions
fix-permissions ./
if [ ! -z $HTTP_PROXY ]; then
echo "---> Setting npm http proxy to" $(safeLogging $HTTP_PROXY)
npm config set proxy $HTTP_PROXY
fi
if [ ! -z $http_proxy ]; then
echo "---> Setting npm http proxy to" $(safeLogging $http_proxy)
npm config set proxy $http_proxy
fi
if [ ! -z $HTTPS_PROXY ]; then
echo "---> Setting npm https proxy to" $(safeLogging $HTTPS_PROXY)
npm config set https-proxy $HTTPS_PROXY
fi
if [ ! -z $https_proxy ]; then
echo "---> Setting npm https proxy to" $(safeLogging $https_proxy)
npm config set https-proxy $https_proxy
fi
# Change the npm registry mirror if provided
if [ -n "$NPM_MIRROR" ]; then
npm config set registry $NPM_MIRROR
fi
# Set the DEV_MODE to false by default.
if [ -z "$DEV_MODE" ]; then
export DEV_MODE=false
fi
# If NODE_ENV is not set by the user, then NODE_ENV is determined by whether
# the container is run in development mode.
if [ -z "$NODE_ENV" ]; then
if [ "$DEV_MODE" == true ]; then
export NODE_ENV=development
else
export NODE_ENV=production
fi
fi
if [ "$NODE_ENV" != "production" ]; then
echo "---> Building your Node application from source"
npm install
else
echo "---> Installing all dependencies"
NODE_ENV=development npm install
#do not fail when there is no build script
echo "---> Building in production mode"
npm run build --if-present
echo "---> Pruning the development dependencies"
npm prune
NPM_TMP=$(npm config get tmp)
if ! mountpoint $NPM_TMP; then
echo "---> Cleaning the $NPM_TMP/npm-*"
rm -rf $NPM_TMP/npm-*
fi
# Clear the npm's cache and tmp directories only if they are not a docker volumes
NPM_CACHE=$(npm config get cache)
if ! mountpoint $NPM_CACHE; then
echo "---> Cleaning the npm cache $NPM_CACHE"
#As of npm@5 even the 'npm cache clean --force' does not fully remove the cache directory
# instead of $NPM_CACHE* use $NPM_CACHE/*.
# We do not want to delete .npmrc file.
rm -rf "${NPM_CACHE:?}/"
fi
fi
# Fix source directory permissions
fix-permissions ./

60
s2i/bin/run Executable file
View file

@ -0,0 +1,60 @@
#!/bin/bash
# S2I run script for the 'nodejs' image.
# The run script executes the server that runs your application.
#
# For more information see the documentation:
# https://github.com/openshift/source-to-image/blob/master/docs/builder_image.md
#
set -e
if [ -e "/opt/app-root/etc/generate_container_user" ]; then
source /opt/app-root/etc/generate_container_user
fi
# Runs the nodejs application server. If the container is run in development mode,
# hot deploy and debugging are enabled.
run_node() {
echo -e "Environment: \n\tDEV_MODE=${DEV_MODE}\n\tNODE_ENV=${NODE_ENV}\n\tDEBUG_PORT=${DEBUG_PORT}"
if [ "$DEV_MODE" == true ]; then
echo "Launching via nodemon..."
exec nodemon --inspect="$DEBUG_PORT"
else
echo "Launching via npm..."
exec npm run -d $NPM_RUN
fi
}
#Set the debug port to 5858 by default.
if [ -z "$DEBUG_PORT" ]; then
export DEBUG_PORT=5858
fi
# Set the environment to development by default.
if [ -z "$DEV_MODE" ]; then
export DEV_MODE=false
fi
# If NODE_ENV is not set by the user, then NODE_ENV is determined by whether
# the container is run in development mode.
if [ -z "$NODE_ENV" ]; then
if [ "$DEV_MODE" == true ]; then
export NODE_ENV=development
else
export NODE_ENV=production
fi
fi
# If the official dockerhub node image is used, skip the SCL setup below
# and just run the nodejs server
if [ -d "/usr/src/app" ]; then
run_node
fi
# Allow users to inspect/debug the builder image itself, by using:
# $ docker run -i -t openshift/centos-nodejs-builder --debug
#
[ "$1" == "--debug" ] && exec /bin/bash
run_node

5
s2i/bin/save-artifacts Executable file
View file

@ -0,0 +1,5 @@
#!/bin/bash
if [ -d "${HOME}/node_modules" ] && [ "$(ls "${HOME}/node_modules" 2>/dev/null)" ]; then
tar -C "${HOME}" -cf - node_modules
fi

15
s2i/bin/usage Executable file
View file

@ -0,0 +1,15 @@
#!/bin/sh
DISTRO=`cat /etc/*-release | grep ^ID= | grep -Po '".*?"' | tr -d '"'`
cat <<EOF
This is a S2I nodejs-14 ${DISTRO} base image:
To use it, install S2I: https://github.com/openshift/source-to-image
Sample invocation:
s2i build https://github.com/sclorg/s2i-nodejs-container.git --context-dir=14/test/test-app/ ${NAMESPACE}/nodejs-14-${DISTRO}7 nodejs-sample-app
You can then run the resulting image via:
podman run -p 8080:8080 nodejs-sample-app
EOF

108
test/check_imagestreams.py Executable file
View file

@ -0,0 +1,108 @@
#!/bin/env python3
# MIT License
#
# Copyright (c) 2018-2019 Red Hat, Inc.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import sys
import json
import logging
import os
from pathlib import Path
from typing import Dict, List, Any
IMAGESTREAMS_DIR: str = "imagestreams"
class ImageStreamChecker(object):
version: str = ""
def __init__(self, version: str):
self.version = version
self.results: Dict[Any, Any] = {}
def load_json_file(self, filename: Path) -> Any:
with open(str(filename)) as f:
data = json.load(f)
isinstance(data, Dict)
return data
def check_version(self, json_dict: Dict[Any, Any]) -> List[str]:
res = []
for tags in json_dict["spec"]["tags"]:
print(
f"check_version: Compare tags['name']:'{tags['name']}' against version:'{self.version}'"
)
# The name can be"<stream>" or "<stream>-elX" or "<stream>-ubiX"
if tags["name"] == self.version or tags["name"].startswith(
self.version + "-"
):
res.append(tags)
return res
def check_latest_tag(self, json_dict: Dict[Any, Any]) -> bool:
latest_tag_correct: bool = False
for tags in json_dict["spec"]["tags"]:
if tags["name"] != "latest":
continue
print(
f"check_latest_tag: Compare tags['name']:'{tags['name']}' against version:'{self.version}'"
)
# The latest can link to either "<stream>" or "<stream>-elX" or "<stream>-ubiX"
if tags["from"]["name"] == self.version or tags["from"]["name"].startswith(
self.version + "-"
):
latest_tag_correct = True
print(f"Latest tag found.")
return latest_tag_correct
def check_imagestreams(self) -> int:
p = Path(".")
json_files = p.glob(f"{IMAGESTREAMS_DIR}/*.json")
if not json_files:
print(f"No json files present in {IMAGESTREAMS_DIR}.")
return 0
for f in json_files:
if os.environ.get("TARGET") in ("rhel7", "centos7") and "aarch64" in str(f):
print("Imagestream aarch64 is not supported on rhel7")
continue
print(f"Checking file {str(f)}.")
json_dict = self.load_json_file(f)
if not (self.check_version(json_dict) and self.check_latest_tag(json_dict)):
print(
f"The latest version is not present in {str(f)} or in latest tag."
)
self.results[f] = False
if self.results:
return 1
print("Imagestreams contains the latest version.")
return 0
if __name__ == "__main__":
if len(sys.argv) != 2:
logging.fatal("%s: %s", sys.argv[0], "VERSION as an argument was not provided")
sys.exit(1)
print(f"Version to check is {sys.argv[1]}.")
isc = ImageStreamChecker(version=sys.argv[1])
sys.exit(isc.check_imagestreams())

View file

@ -0,0 +1,2 @@
app-src

View file

@ -0,0 +1,10 @@
FROM registry.access.redhat.com/ubi8/nodejs-12
# Add application sources
ADD app-src .
# Install the dependencies
RUN npm install
# Run script uses standard ways to run the application
CMD npm run -d start

View file

@ -0,0 +1,25 @@
FROM registry.access.redhat.com/ubi8/nodejs-12
# This image supports the Source-to-Image
# (see more at https://docs.openshift.com/container-platform/3.11/creating_images/s2i.html).
# In order to support the Source-to-Image framework, there are some interesting
# scripts inside the builder image, that can be run in a Dockerfile directly as well:
# * The `/usr/libexec/s2i/assemble` script inside the image is run in order
# to produce a new image with the application artifacts.
# The script takes sources of a given application and places them into
# appropriate directories inside the image.
# * The `/usr/libexec/s2i/run` script executes the application and is set as
# a default command in the resulting container image.
# Add application sources to a directory that the assemble script expects them
# and set permissions so that the container runs without root access
USER 0
ADD app-src /tmp/src
RUN chown -R 1001:0 /tmp/src
USER 1001
# Let the assemble script to install the dependencies
RUN /usr/libexec/s2i/assemble
# Run script uses standard ways to run the application
CMD /usr/libexec/s2i/run

View file

@ -0,0 +1,22 @@
Dockerfile examples
===================
This directory contains example Dockerfiles that demonstrate how to use the image with a Dockerfile and `docker build`.
For demonstration, we use an application code available at https://github.com/sclorg/nodejs-ex.git.
Pull the source to the local machine first:
```
git clone https://github.com/sclorg/nodejs-ex.git app-src
```
Then, build a new image from a Dockerfile in this directory:
```
docker build -f Dockerfile -t node-app .
```
And run the resulting image with the final application:
```
docker run -ti --rm node-app
```

View file

@ -0,0 +1,166 @@
{
"kind": "ImageStream",
"apiVersion": "image.openshift.io/v1",
"metadata": {
"name": "nodejs",
"annotations": {
"openshift.io/display-name": "Node.js"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": {
"openshift.io/display-name": "Node.js (Latest)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js applications on UBI. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Node.js available on OpenShift, including major version updates.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"supports":"nodejs",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "ImageStreamTag",
"name": "16-ubi8"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi9",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 9)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 9. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.access.redhat.com/ubi9/nodejs-16:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi9-minimal",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 9 Minimal)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 9 Minimal. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16-minimal/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.access.redhat.com/ubi9/nodejs-16-minimal:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi8",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 8)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 8. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.access.redhat.com/ubi8/nodejs-16:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi8-minimal",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 8 Minimal)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 8 Minimal. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16-minimal/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.access.redhat.com/ubi8/nodejs-16-minimal:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "14-ubi8",
"annotations": {
"openshift.io/display-name": "Node.js 14 (UBI 8)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 14 applications on UBI 8. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/14/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "14",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.access.redhat.com/ubi8/nodejs-14:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "14-ubi8-minimal",
"annotations": {
"openshift.io/display-name": "Node.js 14 (UBI 8 Minimal)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 14 applications on UBI 8 Minimal. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/14-minimal/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "14",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.access.redhat.com/ubi8/nodejs-14-minimal:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "14-ubi7",
"annotations": {
"openshift.io/display-name": "Node.js 14 (UBI 7)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 14 applications on UBI 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/14/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs,hidden",
"version": "14",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.access.redhat.com/ubi7/nodejs-14:latest"
},
"referencePolicy": {
"type": "Local"
}
}
]
}
}

View file

@ -0,0 +1,147 @@
{
"kind": "ImageStream",
"apiVersion": "image.openshift.io/v1",
"metadata": {
"name": "nodejs",
"annotations": {
"openshift.io/display-name": "Node.js"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": {
"openshift.io/display-name": "Node.js (Latest)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js applications on UBI. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Node.js available on OpenShift, including major version updates.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"supports":"nodejs",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "ImageStreamTag",
"name": "16-ubi8"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi9",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 9)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 9. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi9/nodejs-16:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi9-minimal",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 9 Minimal)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 9 Minimal. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16-minimal/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi9/nodejs-16-minimal:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi8",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 8)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 8. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi8/nodejs-16:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi8-minimal",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 8 Minimal)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 8 Minimal. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16-minimal/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi8/nodejs-16-minimal:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "14-ubi8",
"annotations": {
"openshift.io/display-name": "Node.js 14 (UBI 8)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 14 applications on UBI 8. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/14/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "14",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi8/nodejs-14:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "14-ubi8-minimal",
"annotations": {
"openshift.io/display-name": "Node.js 14 (UBI 8 Minimal)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 14 applications on UBI 8 Minimal. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/14-minimal/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "14",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi8/nodejs-14-minimal:latest"
},
"referencePolicy": {
"type": "Local"
}
}
]
}
}

View file

@ -0,0 +1,166 @@
{
"kind": "ImageStream",
"apiVersion": "image.openshift.io/v1",
"metadata": {
"name": "nodejs",
"annotations": {
"openshift.io/display-name": "Node.js"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": {
"openshift.io/display-name": "Node.js (Latest)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js applications on UBI. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Node.js available on OpenShift, including major version updates.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"supports":"nodejs",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "ImageStreamTag",
"name": "16-ubi8"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi9",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 9)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 9. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi9/nodejs-16:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi9-minimal",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 9 Minimal)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 9 Minimal. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16-minimal/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi9/nodejs-16-minimal:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi8",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 8)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 8. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi8/nodejs-16:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "16-ubi8-minimal",
"annotations": {
"openshift.io/display-name": "Node.js 16 (UBI 8 Minimal)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 16 applications on UBI 8 Minimal. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/16-minimal/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "16",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi8/nodejs-16-minimal:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "14-ubi8",
"annotations": {
"openshift.io/display-name": "Node.js 14 (UBI 8)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 14 applications on UBI 8. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/14/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "14",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi8/nodejs-14:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "14-ubi8-minimal",
"annotations": {
"openshift.io/display-name": "Node.js 14 (UBI 8 Minimal)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 14 applications on UBI 8 Minimal. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/14-minimal/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs",
"version": "14",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi8/nodejs-14-minimal:latest"
},
"referencePolicy": {
"type": "Local"
}
},
{
"name": "14-ubi7",
"annotations": {
"openshift.io/display-name": "Node.js 14 (UBI 7)",
"openshift.io/provider-display-name": "Red Hat, Inc.",
"description": "Build and run Node.js 14 applications on UBI 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-nodejs-container/blob/master/14/README.md.",
"iconClass": "icon-nodejs",
"tags": "builder,nodejs,hidden",
"version": "14",
"sampleRepo": "https://github.com/sclorg/nodejs-ex.git"
},
"from": {
"kind": "DockerImage",
"name": "registry.redhat.io/ubi7/nodejs-14:latest"
},
"referencePolicy": {
"type": "Local"
}
}
]
}
}

156
test/run Executable file
View file

@ -0,0 +1,156 @@
#!/bin/bash
#
# The 'run' performs a simple test that verifies that STI image.
# The main focus here is to exercise 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.
#
# For each client package test, XXX_REVISION specifies which
# branch or tag should be tested; by default it uses the latest
# released version as reported by `npm show XXX version` where
# XXX is the name of the npm package.
#
# For each client package XXX_REPO must be defined in this
# test file to set the repository that corresponds to the
# npm package XXX.
THISDIR=$(dirname ${BASH_SOURCE[0]})
TEST_LIST_APP="\
test_run_app_application
test_s2i_usage
test_scl_usage
test_connection
test_docker_run_usage
test_scl_variables_in_dockerfile
test_npm_functionality
test_check_build_using_dockerfile
test_nodemon_removed
test_npm_cache_cleared
test_npm_tmp_cleared
kill_test_application
test_dev_mode_true_development
test_dev_mode_false_production
"
TEST_LIST_BINARY="\
test_run_binary_application
"
TEST_LIST_NODE_ENV="\
test_run_app_application
test_connection
test_nodemon_present
test_npm_cache_exists
kill_test_application
test_dev_mode_true_development
test_dev_mode_false_development
"
TEST_LIST_DEV_MODE="\
test_run_app_application
test_connection
test_nodemon_present
test_npm_cache_exists
kill_test_application
test_dev_mode_true_development
test_dev_mode_false_production
"
TEST_LIST_HW="\
test_safe_logging
test_run_hw_application
test_incremental_build
test_build_express_webapp
"
# define the client npm packages to be tested. For
# each entry XXX in the list a corresponding value for
# XXX_REVISION and XXX_REPO must be defined below
TEST_LIST_CLIENTS="\
express
pino
prom-client
opossum
kube-service-bindings
"
CLIENT_LIST=($TEST_LIST_CLIENTS)
readonly EXPRESS_REVISION="${EXPRESS_REVISION:-$(docker run --rm "${IMAGE_NAME}" -- npm show express version)}"
readonly EXPRESS_REPO="https://github.com/expressjs/express.git"
readonly PINO_REVISION=v"${PINO_REVISION:-$(docker run --rm "${IMAGE_NAME}" -- npm show pino version)}"
readonly PINO_REPO="https://github.com/pinojs/pino.git"
readonly PROMCLIENT_REVISION=v"${PROMCLIENT_REVISION:-$(docker run --rm "${IMAGE_NAME}" -- npm show prom-client version)}"
readonly PROMCLIENT_REPO="https://github.com/siimon/prom-client.git"
readonly OPOSSUM_REVISION="v${OPOSSUM_REVISION:-$(docker run --rm "${IMAGE_NAME}" -- npm show opossum version)}"
readonly OPOSSUM_REPO="https://github.com/nodeshift/opossum.git"
readonly KUBESERVICEBINDINGS_REVISION="v${KUBESERVICEBINDINGS_REVISION:-$(docker run --rm "${IMAGE_NAME}" -- npm show kube-service-bindings version)}"
readonly KUBESERVICEBINDINGS_REPO="https://github.com/nodeshift/kube-service-bindings.git"
source "${THISDIR}/test-lib.sh"
source "${THISDIR}/test-lib-nodejs.sh"
test -n $IMAGE_NAME \
-a -n $VERSION
test_dir="$(readlink -f $(dirname ${BASH_SOURCE[0]}))"
image_dir="$(readlink -f ${test_dir}/..)"
test_short_summary=''
TESTSUITE_RESULT=0
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 "
# TODO: This should be part of the image metadata
test_port=8080
# Common git configuration
readonly -A gitconfig=(
[user.name]="builder"
[user.email]="build@localhost"
[commit.gpgsign]="false"
)
if [ "$DEBUG" != "" ]; then
set -x
fi
# Build the application image twice to ensure the 'save-artifacts' and
# 'restore-artifacts' scripts are working properly
prepare app
echo "Testing the production image build"
run_s2i_build
check_result $?
TEST_SET=${TESTS:-$TEST_LIST_APP} run_all_tests "app"
echo "Testing the development image build: s2i build -e \"NODE_ENV=development\")"
run_s2i_build "-e NODE_ENV=development"
check_result $?
TEST_SET=${TESTS:-$TEST_LIST_NODE_ENV} run_all_tests "node_env_development"
echo "Testing the development image build: s2i build -e \"DEV_MODE=true\")"
run_s2i_build "-e DEV_MODE=true"
check_result $?
TEST_SET=${TESTS:-$TEST_LIST_DEV_MODE} run_all_tests "dev_mode"
echo "Testing proxy safe logging..."
prepare hw
run_s2i_build_proxy http://user.password@0.0.0.0:8000 https://user.password@0.0.0.0:8000 > /tmp/build-log 2>&1
check_result $?
TEST_SET=${TESTS:-$TEST_LIST_HW} run_all_tests "hw"
check_result $?
TEST_SET=${TESTS:-$TEST_LIST_CLIENTS} run_all_tests "clients"
TEST_SET=${TESTS:-$TEST_LIST_BINARY} run_all_tests "binary"
echo "Success!"
cleanup

60
test/run-openshift Executable file
View file

@ -0,0 +1,60 @@
#!/bin/bash
#
# Test the NodeJS image in OpenShift.
#
# IMAGE_NAME specifies a name of the candidate image used for testing.
# The image has to be available before this script is executed.
#
THISDIR=$(dirname ${BASH_SOURCE[0]})
source "${THISDIR}/test-lib.sh"
source "${THISDIR}/test-lib-openshift.sh"
source "${THISDIR}/test-lib-nodejs.sh"
# change the branch to a different value if a new change in the example
# app needs to be tested
BRANCH_TO_TEST=master
test_dir="$(readlink -f $(dirname ${BASH_SOURCE[0]}))"
set -eo nounset
trap ct_os_cleanup EXIT SIGINT
test_latest_imagestreams() {
local result=1
# Switch to root directory of a container
pushd "${test_dir}/.." >/dev/null || return 1
ct_check_latest_imagestreams
result=$?
popd >/dev/null || return 1
return $result
}
ct_os_check_compulsory_vars
ct_os_enable_print_logs
ct_os_cluster_up
# TODO: We can make the tests work against examples inside the same PR
ct_os_test_s2i_app "${IMAGE_NAME}" "https://github.com/sclorg/s2i-nodejs-container.git" test/test-app "This is a node.js echo service"
ct_os_test_s2i_app "${IMAGE_NAME}" "https://github.com/sclorg/nodejs-ex.git" . "Welcome to your Node.js application on OpenShift"
for template in nodejs.json nodejs-mongodb.json nodejs-mongodb-persistent.json ; do
ct_os_test_template_app ${IMAGE_NAME} \
https://raw.githubusercontent.com/sclorg/nodejs-ex/${BRANCH_TO_TEST}/openshift/templates/${template} \
nodejs \
"Welcome to your Node.js application on OpenShift" \
8080 http 200 "-p SOURCE_REPOSITORY_REF=${BRANCH_TO_TEST} -p SOURCE_REPOSITORY_URL=https://github.com/sclorg/nodejs-ex.git -p NODEJS_VERSION=${VERSION} -p NAME=nodejs-testing"
done
# Check the imagestream
test_nodejs_imagestream
# check if latest imagestream version is correct
test_latest_imagestreams
ct_os_cluster_down
# vim: set tabstop=2:shiftwidth=2:expandtab:

View file

@ -0,0 +1,49 @@
#!/bin/bash
#
# Test the NodeJS image in OpenShift.
#
# IMAGE_NAME specifies a name of the candidate image used for testing.
# The image has to be available before this script is executed.
#
THISDIR=$(dirname ${BASH_SOURCE[0]})
source "${THISDIR}/test-lib.sh"
source "${THISDIR}/test-lib-openshift.sh"
source "${THISDIR}/test-lib-nodejs.sh"
source "${THISDIR}/test-lib-remote-openshift.sh"
TEST_LIST="\
test_nodejs_s2i_container
test_nodejs_s2i_app_ex
test_nodejs_s2i_templates
test_nodejs_imagestream
"
# change the branch to a different value if a new change in the example
# app needs to be tested
BRANCH_TO_TEST=master
trap ct_os_cleanup EXIT SIGINT
ct_os_set_ocp4
ct_os_check_compulsory_vars
ct_os_check_login || exit 1
set -u
test -n "${IMAGE_NAME-}" || false 'make sure $IMAGE_NAME is defined'
test -n "${VERSION-}" || false 'make sure $VERSION is defined'
# For testing on OpenShift 4 we use internal registry
export CT_OCP4_TEST=true
export CT_SKIP_UPLOAD_IMAGE=true
TEST_SUMMARY=''
TEST_SET=${TESTS:-$TEST_LIST} ct_run_tests_from_testset "openshift-remote-cluster"
# vim: set tabstop=2:shiftwidth=2:expandtab:

4
test/test-app/README.md Normal file
View file

@ -0,0 +1,4 @@
node-echo
=========
node.js echo server, returns request data to response

27
test/test-app/iisnode.yml Normal file
View file

@ -0,0 +1,27 @@
# For documentation see https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/iisnode.yml
# loggingEnabled: false
# debuggingEnabled: false
# devErrorsEnabled: false
node_env: production
# nodeProcessCountPerApplication: 1
# maxConcurrentRequestsPerProcess: 1024
# maxNamedPipeConnectionRetry: 24
# namedPipeConnectionRetryDelay: 250
# maxNamedPipeConnectionPoolSize: 512
# maxNamedPipePooledConnectionAge: 30000
# asyncCompletionThreadCount: 0
# initialRequestBufferSize: 4096
# maxRequestBufferSize: 65536
watchedFiles: iisnode.yml;node_modules\*;*.js
# uncFileChangesPollingInterval: 5000
# gracefulShutdownTimeout: 60000
# logDirectoryNameSuffix: logs
# debuggerPortRange: 5058-6058
# debuggerPathSegment: debug
# maxLogFileSizeInKB: 128
# appendToExistingLog: false
# logFileFlushInterval: 5000
# flushResponse: false
# enableXFF: false
# promoteServerVars:

View file

@ -0,0 +1,32 @@
{
"name": "node-echo",
"version": "0.0.1",
"description": "node-echo",
"main": "server.js",
"dependencies": {
},
"devDependencies": {
"nodemon": "*"
},
"engine": {
"node": "*",
"npm": "*"
},
"scripts": {
"dev": "nodemon --ignore node_modules/ server.js",
"start": "node server.js"
},
"repository": {
"type": "git",
"url": "http://github.com/bettiolo/node-echo.git"
},
"keywords": [
"Echo"
],
"author": "Marco Bettiolo <marco@bettiolo.it>",
"license": "",
"bugs": {
"url": "http://github.com/bettiolo/node-echo/issues"
},
"homepage": "http://apilb.com"
}

50
test/test-app/server.js Normal file
View file

@ -0,0 +1,50 @@
var util = require('util');
var http = require('http');
var url = require('url');
var qs = require('querystring');
var os = require('os')
var port = process.env.PORT || process.env.port || process.env.OPENSHIFT_NODEJS_PORT || 8080;
var ip = process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';
var nodeEnv = process.env.NODE_ENV || 'unknown';
var server = http.createServer(function (req, res) {
var url_parts = url.parse(req.url, true);
var body = '';
req.on('data', function (data) {
body += data;
});
req.on('end', function () {
var formattedBody = qs.parse(body);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('This is a node.js echo service\n');
res.write('Host: ' + req.headers.host + '\n');
res.write('\n');
res.write('node.js Production Mode: ' + (nodeEnv == 'production' ? 'yes' : 'no') + '\n');
res.write('\n');
res.write('HTTP/' + req.httpVersion +'\n');
res.write('Request headers:\n');
res.write(util.inspect(req.headers, null) + '\n');
res.write('Request query:\n');
res.write(util.inspect(url_parts.query, null) + '\n');
res.write('Request body:\n');
res.write(util.inspect(formattedBody, null) + '\n');
res.write('\n');
res.write('Host: ' + os.hostname() + '\n');
res.write('OS Type: ' + os.type() + '\n');
res.write('OS Platform: ' + os.platform() + '\n');
res.write('OS Arch: ' + os.arch() + '\n');
res.write('OS Release: ' + os.release() + '\n');
res.write('OS Uptime: ' + os.uptime() + '\n');
res.write('OS Free memory: ' + os.freemem() / 1024 / 1024 + 'mb\n');
res.write('OS Total memory: ' + os.totalmem() / 1024 / 1024 + 'mb\n');
res.write('OS CPU count: ' + os.cpus().length + '\n');
res.write('OS CPU model: ' + os.cpus()[0].model + '\n');
res.write('OS CPU speed: ' + os.cpus()[0].speed + 'mhz\n');
res.end('\n');
});
});
server.listen(port);
console.log('Server running on ' + ip + ':' + port);

17
test/test-app/web.config Normal file
View file

@ -0,0 +1,17 @@
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<iisnode loggingEnabled="false" />
<rewrite>
<rules>
<rule name="myapp">
<match url="/*" />
<action type="Rewrite" url="server.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

11
test/test-binary/hw.js Normal file
View file

@ -0,0 +1,11 @@
var http = require('http');
var ip = process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';
var port = process.env.PORT || process.env.port || process.env.OPENSHIFT_NODEJS_PORT || 8080;
var server = http.createServer(function(req, res) {
res.writeHead(200);
res.end('Hello World!');
});
server.listen(port);
console.log("Server running on " + ip + ":" + port);

View file

@ -0,0 +1,17 @@
{
"name": "hello-world",
"version": "0.0.1",
"main": "hw.js",
"engine": {
"node": "*",
"npm": "*"
},
"dependencies": {
"node-rdkafka": "*"
},
"scripts": {
"start": "node hw.js",
"dev": "node hw.js"
},
"license": ""
}

View file

@ -0,0 +1,41 @@
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;

View file

@ -0,0 +1,90 @@
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('test-express-webapp:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '8080');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}

View file

@ -0,0 +1,16 @@
{
"name": "test-express-webapp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"cookie-parser": "*",
"debug": "*",
"express": "*",
"http-errors": "*",
"jade": "*",
"morgan": "*"
}
}

View file

@ -0,0 +1,8 @@
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}

View file

@ -0,0 +1,9 @@
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express Testing Application' });
});
module.exports = router;

View file

@ -0,0 +1,9 @@
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;

View file

@ -0,0 +1,6 @@
extends layout
block content
h1= message
h2= error.status
pre #{error.stack}

View file

@ -0,0 +1,5 @@
extends layout
block content
h1= title
p Welcome to #{title}

View file

@ -0,0 +1,7 @@
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
block content

11
test/test-hw/hw.js Normal file
View file

@ -0,0 +1,11 @@
var http = require('http');
var ip = process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';
var port = process.env.PORT || process.env.port || process.env.OPENSHIFT_NODEJS_PORT || 8080;
var server = http.createServer(function(req, res) {
res.writeHead(200);
res.end('Hello World!');
});
server.listen(port);
console.log("Server running on " + ip + ":" + port);

14
test/test-hw/package.json Normal file
View file

@ -0,0 +1,14 @@
{
"name": "hello-world",
"version": "0.0.1",
"main": "hw.js",
"engine": {
"node": "*",
"npm": "*"
},
"scripts": {
"start": "node hw.js",
"dev": "node hw.js"
},
"license": ""
}

View file

@ -0,0 +1,4 @@
node-echo
=========
node.js echo server, returns request data to response

View file

@ -0,0 +1,27 @@
# For documentation see https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/iisnode.yml
# loggingEnabled: false
# debuggingEnabled: false
# devErrorsEnabled: false
node_env: production
# nodeProcessCountPerApplication: 1
# maxConcurrentRequestsPerProcess: 1024
# maxNamedPipeConnectionRetry: 24
# namedPipeConnectionRetryDelay: 250
# maxNamedPipeConnectionPoolSize: 512
# maxNamedPipePooledConnectionAge: 30000
# asyncCompletionThreadCount: 0
# initialRequestBufferSize: 4096
# maxRequestBufferSize: 65536
watchedFiles: iisnode.yml;node_modules\*;*.js
# uncFileChangesPollingInterval: 5000
# gracefulShutdownTimeout: 60000
# logDirectoryNameSuffix: logs
# debuggerPortRange: 5058-6058
# debuggerPathSegment: debug
# maxLogFileSizeInKB: 128
# appendToExistingLog: false
# logFileFlushInterval: 5000
# flushResponse: false
# enableXFF: false
# promoteServerVars:

View file

@ -0,0 +1,33 @@
{
"name": "node-echo",
"version": "0.0.1",
"description": "node-echo",
"main": "server.js",
"dependencies": {
"yarn": "*"
},
"devDependencies": {
"nodemon": "*"
},
"engine": {
"node": "*",
"npm": "*"
},
"scripts": {
"dev": "nodemon --ignore node_modules/ server.js",
"start": "node server.js"
},
"repository": {
"type": "git",
"url": "http://github.com/bettiolo/node-echo.git"
},
"keywords": [
"Echo"
],
"author": "Marco Bettiolo <marco@bettiolo.it>",
"license": "",
"bugs": {
"url": "http://github.com/bettiolo/node-echo/issues"
},
"homepage": "http://apilb.com"
}

View file

@ -0,0 +1,50 @@
var util = require('util');
var http = require('http');
var url = require('url');
var qs = require('querystring');
var os = require('os')
var port = process.env.PORT || process.env.port || process.env.OPENSHIFT_NODEJS_PORT || 8080;
var ip = process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';
var nodeEnv = process.env.NODE_ENV || 'unknown';
var server = http.createServer(function (req, res) {
var url_parts = url.parse(req.url, true);
var body = '';
req.on('data', function (data) {
body += data;
});
req.on('end', function () {
var formattedBody = qs.parse(body);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('This is a node.js echo service\n');
res.write('Host: ' + req.headers.host + '\n');
res.write('\n');
res.write('node.js Production Mode: ' + (nodeEnv == 'production' ? 'yes' : 'no') + '\n');
res.write('\n');
res.write('HTTP/' + req.httpVersion +'\n');
res.write('Request headers:\n');
res.write(util.inspect(req.headers, null) + '\n');
res.write('Request query:\n');
res.write(util.inspect(url_parts.query, null) + '\n');
res.write('Request body:\n');
res.write(util.inspect(formattedBody, null) + '\n');
res.write('\n');
res.write('Host: ' + os.hostname() + '\n');
res.write('OS Type: ' + os.type() + '\n');
res.write('OS Platform: ' + os.platform() + '\n');
res.write('OS Arch: ' + os.arch() + '\n');
res.write('OS Release: ' + os.release() + '\n');
res.write('OS Uptime: ' + os.uptime() + '\n');
res.write('OS Free memory: ' + os.freemem() / 1024 / 1024 + 'mb\n');
res.write('OS Total memory: ' + os.totalmem() / 1024 / 1024 + 'mb\n');
res.write('OS CPU count: ' + os.cpus().length + '\n');
res.write('OS CPU model: ' + os.cpus()[0].model + '\n');
res.write('OS CPU speed: ' + os.cpus()[0].speed + 'mhz\n');
res.end('\n');
});
});
server.listen(port);
console.log('Server running on ' + ip + ':' + port);

View file

@ -0,0 +1,17 @@
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<iisnode loggingEnabled="false" />
<rewrite>
<rules>
<rule name="myapp">
<match url="/*" />
<action type="Rewrite" url="server.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

594
test/test-lib-nodejs.sh Normal file
View file

@ -0,0 +1,594 @@
#!/bin/bash
#
# Functions for tests for the Node.js image.
#
# IMAGE_NAME specifies a name of the candidate image used for testing.
# The image has to be available before this script is executed.
#
THISDIR=$(dirname ${BASH_SOURCE[0]})
source "${THISDIR}/test-lib.sh"
source "${THISDIR}/test-lib-openshift.sh"
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)
}
container_logs() {
docker logs $(cat $cid_file)
}
run_s2i_build() {
ct_s2i_build_as_df file://${test_dir}/test-app ${IMAGE_NAME} ${IMAGE_NAME}-testapp ${s2i_args} $(ct_build_s2i_npm_variables) $1
}
run_s2i_build_proxy() {
ct_s2i_build_as_df file://${test_dir}/test-hw ${IMAGE_NAME} ${IMAGE_NAME}-testhw ${s2i_args} $(ct_build_s2i_npm_variables) -e HTTP_PROXY=$1 -e http_proxy=$1 -e HTTPS_PROXY=$2 -e https_proxy=$2
}
run_s2i_build_client() {
ct_s2i_build_as_df \
"file://${test_dir}/$1" "${IMAGE_NAME}" "${IMAGE_NAME}-$1" \
${s2i_args} \
$(ct_build_s2i_npm_variables) -e NODE_ENV=development
}
run_s2i_build_binary() {
ct_s2i_build_as_df file://${test_dir}/test-binary ${IMAGE_NAME} ${IMAGE_NAME}-testbinary ${s2i_args} $(ct_build_s2i_npm_variables) $1
}
run_s2i_multistage_build() {
ct_s2i_multistage_build file://${test_dir}/test-app ${FULL_IMAGE} ${IMAGE_NAME} ${IMAGE_NAME}-testapp $(ct_build_s2i_npm_variables)
}
prepare_dummy_git_repo() {
git init
for key in "${!gitconfig[@]}"; do
git config --local "$key" "${gitconfig[$key]}"
done
git add --all
git commit -m "Sample commit"
}
prepare_client_repo() {
git clone \
--config advice.detachedHead="false" \
--branch "$3" --depth 1 \
"$2" "$1"
pushd "$1" >/dev/null || return
for key in "${!gitconfig[@]}"; do
git config --local "$key" "${gitconfig[$key]}"
done
popd >/dev/null || return
}
prepare_minimal_build() {
suffix=$1
# Build the app using the full assemble-capable image
[ -z "$(docker images -q "$FULL_IMAGE")" ] && docker pull "$FULL_IMAGE"
case "$suffix" in
testapp)
run_s2i_multistage_build #>/tmp/build-log 2>&1
;;
testhw)
IMAGE_NAME=$FULL_IMAGE run_s2i_build_proxy http://user.password@0.0.0.0:8000 https://user.password@0.0.0.0:8000 >/tmp/build-log 2>&1
# Get the application from the assembled image and into the minimal
tempdir=$(mktemp -d)
chown 1001:0 "$tempdir"
docker run -u 0 --rm -ti -v "$tempdir:$tempdir:Z" "$FULL_IMAGE-$suffix" bash -c "cp -ar /opt/app-root/src $tempdir"
pushd "$tempdir" >/dev/null || return
cat <<EOF >Dockerfile
FROM $IMAGE_NAME
ADD src/* /opt/app-root/src
CMD /usr/libexec/s2i/run
EOF
# Check if CA autority is present on host and add it into Dockerfile
[ -f "$(full_ca_file_path)" ] && cat <<EOF >>Dockerfile
USER 0
RUN cd /etc/pki/ca-trust/source/anchors && update-ca-trust extract
USER 1001
EOF
docker build -t "$IMAGE_NAME-$suffix" $(ct_build_s2i_npm_variables | grep -o -e '\(-v\)[[:space:]]\.*\S*') .
popd >/dev/null || return
;;
*)
echo "Please specify a valid test application"
exit 1
;;
esac
}
prepare() {
if ! image_exists ${IMAGE_NAME}; then
echo "ERROR: The image ${IMAGE_NAME} must exist before this script is executed."
exit 1
fi
case "$1" in
# TODO: STI build require the application is a valid 'GIT' repository, we
# should remove this restriction in the future when a file:// is used.
app|hw|express-webapp|binary)
pushd "${test_dir}/test-${1}" >/dev/null
prepare_dummy_git_repo
popd >/dev/null
;;
*)
if [[ " ${CLIENT_LIST[*]} " =~ "${test_case} " ]];
then
PREFIX=$1
PREFIX=${PREFIX//-/}
REPO="${PREFIX^^}"_REPO
REVISION="${PREFIX^^}"_REVISION
prepare_client_repo "${test_dir}/$1" "${!REPO}" "${!REVISION}"
else
echo "Please specify a valid test application"
exit 1
fi
;;
esac
}
run_test_application() {
case "$1" in
app|hw|express-webapp|binary)
docker run -d --user=100001 $(ct_mount_ca_file) --rm --cidfile=${cid_file} $2 ${IMAGE_NAME}-test$1
;;
*)
echo "No such test application"
exit 1
;;
esac
}
run_client_test_suite() {
docker run --user=100001 $(ct_mount_ca_file) --rm --cidfile=${cid_file} ${IMAGE_NAME}-$1 npm test
}
kill_test_application() {
docker kill $(cat $cid_file)
rm $cid_file
}
cleanup() {
if [ -f $cid_file ]; then
if container_exists; then
docker stop $(cat $cid_file)
fi
fi
for image in "${IMAGE_NAME}"-{test{app,hw,express-webapp,binary}}; do
image_exists "$image" || continue
docker rmi -f "$image"
done
for client in "${CLIENT_LIST[@]}"; do
image="${IMAGE_NAME}-${client}"
image_exists "$image" || continue
docker rmi -f "$image"
done
rm -rf ${test_dir}/test-app/.git
rm -rf ${test_dir}/test-hw/.git
rm -rf ${test_dir}/test-binary/.git
for client in "${CLIENT_LIST[@]}"; do
rm -rf "${test_dir}/${client}"
done
rm -rf ${test_dir}/test-express-webapp/.git
echo "$test_short_summary"
if [ $TESTSUITE_RESULT -eq 0 ] ; then
echo "Tests for ${IMAGE_NAME} succeeded."
else
echo "Tests for ${IMAGE_NAME} failed."
fi
exit $TESTSUITE_RESULT
}
check_result() {
local result="$1"
if [[ "$result" != "0" ]]; then
echo "S2I image '${IMAGE_NAME}' test FAILED (exit code: ${result})"
TESTCASE_RESULT=1
fi
return $result
}
wait_for_cid() {
local max_attempts=20
local sleep_time=1
local attempt=1
local result=1
while [ $attempt -le $max_attempts ]; do
[ -f $cid_file ] && [ -s $cid_file ] && break
echo "Waiting for container start..."
attempt=$(( $attempt + 1 ))
sleep $sleep_time
done
}
test_s2i_usage() {
echo "Testing 's2i usage'..."
ct_s2i_usage ${IMAGE_NAME} ${s2i_args} &>/dev/null
check_result $?
}
test_docker_run_usage() {
echo "Testing 'docker run' usage..."
docker run --rm ${IMAGE_NAME} &>/dev/null
check_result $?
}
test_connection() {
echo "Testing HTTP connection..."
local max_attempts=10
local sleep_time=1
local attempt=1
local result=1
while [ $attempt -le $max_attempts ]; do
echo "Sending GET request to http://$(container_ip):${test_port}/"
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
}
scl_usage() {
# Verify the 'usage' script is working properly when running the base image with 's2i usage ...'
local run_cmd="$1"
local expected="$2"
echo "Testing the image SCL enable ..."
out=$(docker run --rm ${IMAGE_NAME} /bin/bash -c "${run_cmd}")
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
}
function test_scl_usage() {
scl_usage "node --version" "v${VERSION//-minimal/}."
check_result $?
}
validate_default_value() {
local label=$1
IFS=':' read -a label_vals <<< $(docker inspect -f "{{index .Config.Labels \"$label\"}}" ${IMAGE_NAME})
label_var=${label_vals[0]}
default_label_val=${label_vals[1]}
actual_label_val=$(docker run --rm $IMAGE_NAME /bin/bash -c "echo $"$label_var)
if [ "$actual_label_val" != "$default_label_val" ]; then
echo "ERROR default value for $label with environment variable $label_var; Expected $default_label_val, got $actual_label_val"
return 1
fi
}
# Gets the NODE_ENV environment variable from the container.
get_node_env_from_container() {
local dev_mode="$1"
local node_env="$2"
IFS=':' read -a label_val <<< $(docker inspect -f '{{index .Config.Labels "com.redhat.dev-mode"}}' $IMAGE_NAME)
dev_mode_label_var="${label_val[0]}"
echo $(docker run --rm --env $dev_mode_label_var=$dev_mode --env NODE_ENV=$node_env $IMAGE_NAME /bin/bash -c 'echo "$NODE_ENV"')
}
# Ensures that a docker container run with '--env NODE_ENV=$current_val' produces a NODE_ENV value of $expected when
# DEV_MODE=dev_mode.
validate_node_env() {
local current_val="$1"
local dev_mode_val="$2"
local expected="$3"
actual=$(get_node_env_from_container "$dev_mode_val" "$current_val")
if [ "$actual" != "$expected" ]; then
echo "ERROR default value for NODE_ENV when development mode is $dev_mode_val; should be $expected but is $actual"
return 1
fi
}
test_dev_mode() {
local app=$1
local dev_mode=$2
local node_env=$3
echo "Testing $app DEV_MODE=$dev_mode NODE_ENV=$node_env"
run_test_application $app "-e DEV_MODE=$dev_mode"
wait_for_cid
test_connection
check_result $?
logs=$(container_logs)
echo ${logs} | grep -q DEV_MODE=$dev_mode
check_result $?
echo ${logs} | grep -q DEBUG_PORT=5858
check_result $?
echo ${logs} | grep -q NODE_ENV=$node_env
check_result $?
kill_test_application
}
test_incremental_build() {
npm_variables=$(ct_build_s2i_npm_variables)
build_log1=$(ct_s2i_build_as_df file://${test_dir}/test-incremental ${IMAGE_NAME} ${IMAGE_NAME}-testapp ${s2i_args} ${npm_variables})
check_result $?
build_log2=$(ct_s2i_build_as_df file://${test_dir}/test-incremental ${IMAGE_NAME} ${IMAGE_NAME}-testapp ${s2i_args} ${npm_variables} --incremental)
check_result $?
if [ "$VERSION" == "6" ]; then
# Different npm output for version 6
if echo "$build_log2" | grep -e "\-\- yarn@[0-9\.]*"; then
echo "ERROR Incremental build failed: yarn package is getting installed in incremental build"
check_result 1
fi
else
first=$(echo "$build_log1" | grep -o -e "added [0-9]* packages" | awk '{ print $2 }')
second=$(echo "$build_log2" | grep -o -e "added [0-9]* packages" | awk '{ print $2 }')
if [ "$first" == "$second" ]; then
echo "ERROR Incremental build failed: both builds installed $first packages"
check_result 1
fi
fi
}
function test_scl_variables_in_dockerfile() {
if [ "$OS" == "rhel7" ] || [ "$OS" == "centos7" ]; then
# autocleanup only enabled here as only the following tests so far use it
CID_FILE_DIR=$(mktemp -d)
ct_enable_cleanup
echo "Testing npm availability in Dockerfile"
ct_binary_found_from_df npm
check_result $?
info "Testing variable presence during \`docker exec\`"
ct_check_exec_env_vars
check_result $?
info "Checking if all scl variables are defined in Dockerfile"
ct_check_scl_enable_vars
check_result $?
fi
}
# test express webapp
run_s2i_build_express_webapp() {
local result
prepare express-webapp
ct_s2i_build_as_df file://${test_dir}/test-express-webapp ${IMAGE_NAME} ${IMAGE_NAME}-testexpress-webapp ${s2i_args} $(ct_build_s2i_npm_variables)
run_test_application express-webapp
wait_for_cid
ct_test_response http://$(container_ip):${test_port} 200 'Welcome to Express Testing Application'
result=$?
kill_test_application
return $result
}
function test_build_express_webapp() {
echo "Running express webapp test"
run_s2i_build_express_webapp
check_result $?
}
function test_running_client_js {
echo "Running $1 test suite"
prepare "$1"
run_s2i_build_client "$1"
check_result $?
run_client_test_suite "$1"
check_result $?
}
function test_check_build_using_dockerfile() {
info "Check building using a Dockerfile"
ct_test_app_dockerfile ${THISDIR}/examples/from-dockerfile/Dockerfile 'https://github.com/sclorg/nodejs-ex.git' 'Welcome to your Node.js application on OpenShift' app-src
check_result $?
ct_test_app_dockerfile ${THISDIR}/examples/from-dockerfile/Dockerfile.s2i 'https://github.com/sclorg/nodejs-ex.git' 'Welcome to your Node.js application on OpenShift' app-src
check_result $?
}
function test_npm_functionality() {
echo "Testing npm availability"
ct_npm_works
check_result $?
}
function test_nodemon_removed() {
# Test that the development dependencies (nodemon) have been removed (npm prune)
devdep=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "! test -d ./node_modules/nodemon")
check_result "$?"
}
function test_nodemon_present() {
# Test that the development dependencies (nodemon) have been removed (npm prune)
devdep=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "test -d ./node_modules/nodemon")
check_result "$?"
}
function test_npm_cache_cleared() {
# Test that the npm cache has been cleared
cache_loc=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "npm config get cache")
devdep=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "! test -d $cache_loc")
check_result "$?"
}
function test_npm_cache_exists() {
# Test that the npm cache has been cleared
devdep=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "test -d \$(npm config get cache)")
check_result "$?"
}
function test_npm_tmp_cleared() {
# Test that the npm tmp has been cleared
devdep=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "! ls \$(npm config get tmp)/npm-* 2>/dev/null")
check_result "$?"
}
function test_dev_mode_false_production() {
# DEV_MODE=false NODE_ENV=production
test_dev_mode app false production
}
function test_dev_mode_true_development() {
# DEV_MODE=true NODE_ENV=development
test_dev_mode app true development
}
function test_dev_mode_false_development() {
# DEV_MODE=false NODE_ENV=development
test_dev_mode app false development
}
function test_run_app_application() {
# Verify that the HTTP connection can be established to test application container
run_test_application app
# Wait for the container to write it's CID file
wait_for_cid
}
function test_run_hw_application() {
# Verify that the HTTP connection can be established to test application container
run_test_application hw
# Wait for the container to write it's CID file
wait_for_cid
check_result $?
kill_test_application
}
function test_run_binary_application() {
# Test is suppressed because of https://github.com/Blizzard/node-rdkafka/issues/910
# The newest version of node-rdkafka works only with gcc-8 and higher
# On RHEL7 and CentOS7 is gcc-4.8
if [ "$OS" != "rhel7" ] && [ "$OS" != "centos7" ]; then
prepare binary
run_s2i_build_binary
check_result $?
# Verify that the HTTP connection can be established to test application container
run_test_application binary
# Wait for the container to write it's CID file
wait_for_cid
kill_test_application
fi
}
function test_safe_logging() {
if [[ $(grep redacted /tmp/build-log | wc -l) -eq 4 ]]; then
grep redacted /tmp/build-log
check_result 0
else
echo "Some proxy log-in credentials were left in log file"
grep Setting /tmp/build-log
check_result 1
fi
}
function run_all_tests() {
local APP_NAME="$1"
for test_case in $TEST_SET; do
info "Running test $test_case ...."
TESTCASE_RESULT=0
if [[ " ${CLIENT_LIST[*]} " =~ "${test_case} " ]];
then
rm -f $cid_file
test_running_client_js "${test_case}"
else
$test_case
fi
check_result $?
local test_msg
if [ $TESTCASE_RESULT -eq 0 ]; then
test_msg="[PASSED]"
else
test_msg="[FAILED]"
TESTSUITE_RESULT=1
fi
printf -v test_short_summary "%s %s for '%s' %s\n" "${test_short_summary}" "${test_msg}" "${APP_NAME}" "$test_case"
[ -n "${FAIL_QUICKLY:-}" ] && cleanup "${APP_NAME}" && return 1
done;
}
# Check the imagestream
function test_nodejs_imagestream() {
case ${OS} in
rhel7|centos7) ;;
*) echo "Imagestream testing not supported for $OS environment." ; return 0 ;;
esac
ct_os_test_image_stream_quickstart \
"${THISDIR}/../imagestreams/nodejs-${OS%[0-9]*}.json" \
"https://raw.githubusercontent.com/sclorg/nodejs-ex/master/openshift/templates/nodejs.json" \
"${IMAGE_NAME}" \
'nodejs' \
"Welcome to your Node.js application on OpenShift" \
8080 http 200 \
"-p SOURCE_REPOSITORY_REF=master -p SOURCE_REPOSITORY_URL=https://github.com/sclorg/nodejs-ex.git -p NODEJS_VERSION=${VERSION} -p NAME=nodejs-testing"
}
function test_nodejs_s2i_container() {
ct_os_test_s2i_app "${IMAGE_NAME}" \
"https://github.com/sclorg/s2i-nodejs-container.git" \
"test/test-app" \
"This is a node.js echo service"
}
function test_nodejs_s2i_app_ex() {
ct_os_test_s2i_app "${IMAGE_NAME}" \
"https://github.com/sclorg/nodejs-ex.git" \
"." \
"Welcome to your Node.js application on OpenShift"
}
function test_nodejs_s2i_templates() {
local ret_val=0
for template in nodejs.json nodejs-mongodb.json nodejs-mongodb-persistent.json ; do
ct_os_test_template_app ${IMAGE_NAME} \
https://raw.githubusercontent.com/sclorg/nodejs-ex/${BRANCH_TO_TEST}/openshift/templates/${template} \
nodejs \
"Welcome to your Node.js application on OpenShift" \
8080 http 200 \
"-p SOURCE_REPOSITORY_REF=${BRANCH_TO_TEST} -p SOURCE_REPOSITORY_URL=https://github.com/sclorg/nodejs-ex.git -p NODEJS_VERSION=${VERSION} -p NAME=nodejs-testing" || ret_val=1
done
return $ret_val
}
# vim: set tabstop=2:shiftwidth=2:expandtab:

1414
test/test-lib-openshift.sh Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,104 @@
# shellcheck shell=bash
# some functions are used from test-lib.sh, that is usually in the same dir
# shellcheck source=/dev/null
source "$(dirname "${BASH_SOURCE[0]}")"/test-lib.sh
# Set of functions for testing docker images in OpenShift using 'oc' command
# A variable containing the overall test result
# TESTSUITE_RESULT=0
# And the following trap must be set, in the beginning of the test script:
# trap ct_os_cleanup EXIT SIGINT
# ct_os_set_path_oc_4 OC_VERSION
# --------------------
# This is a trick that helps using correct version 4 of the `oc`:
# The input is version of the openshift in format 4.4 etc.
# If the currently available version of oc is not of this version,
# it first takes a look into /usr/local/oc-<ver>/bin directory,
# Arguments: oc_version - X.Y part of the version of OSE (e.g. 3.9)
function ct_os_set_path_oc_4() {
echo "Setting OCP4 client"
local oc_version=$1
local installed_oc_path="/usr/local/oc-v${oc_version}/bin"
echo "PATH ${installed_oc_path}"
if [ -x "${installed_oc_path}/oc" ] ; then
oc_path="${installed_oc_path}"
echo "Binary oc found in ${installed_oc_path}" >&2
else
echo "OCP4 not found"
return 1
fi
export PATH="${oc_path}:${PATH}"
}
# ct_os_prepare_ocp4
# ------------------
# Prepares environment for testing images in OpenShift 4 environment
#
#
function ct_os_set_ocp4() {
if [ "${CVP:-0}" -eq "1" ]; then
echo "Testing in CVP environment. No need to login to OpenShift cluster. This is already done by CVP pipeline."
return
fi
local login
OS_OC_CLIENT_VERSION=${OS_OC_CLIENT_VERSION:-4.4}
ct_os_set_path_oc_4 "${OS_OC_CLIENT_VERSION}"
login=$(cat "$KUBEPASSWORD")
oc login -u kubeadmin -p "$login"
oc version
if ! oc version | grep -q "Client Version: ${OS_OC_CLIENT_VERSION}." ; then
echo "ERROR: something went wrong, oc located at ${oc_path}, but oc of version ${OS_OC_CLIENT_VERSION} not found in PATH ($PATH)" >&1
return 1
else
echo "PATH set correctly, binary oc found in version ${OS_OC_CLIENT_VERSION}: $(command -v oc)"
fi
echo "Login to OpenShift ${OS_OC_CLIENT_VERSION} is DONE"
# let openshift cluster to sync to avoid some race condition errors
sleep 3
}
function ct_os_upload_image_external_registry() {
local input_name="${1}" ; shift
local image_name=${input_name##*/}
local imagestream=${1:-$image_name:latest}
local output_name
ct_os_login_external_registry
output_name="${INTERNAL_DOCKER_REGISTRY}/rhscl-ci-testing/$imagestream"
docker images
docker tag "${input_name}" "${output_name}"
docker push "${output_name}"
}
function ct_os_import_image_ocp4() {
local image_name="${1}"; shift
local imagestream=${1:-$image_name:latest}
echo "Uploading image ${image_name} as ${imagestream} into OpenShift internal registry."
ct_os_upload_image_v4 "${image_name}" "${imagestream}"
}
# ct_os_check_login
# ---------------
# function checks if the login to openshift was successful
# if successful returns 0
# if not, write error message, sets test result to 1
# and exits with non-zero
# Uses: $TESTSUITE_RESULT - overall result of all tests
function ct_os_check_login() {
oc status || {
echo "-------------------------------------------"
echo "It looks like oc is not properly logged in."
# shellcheck disable=SC2034
TESTSUITE_RESULT=1
return 1
}
}

1201
test/test-lib.sh Normal file

File diff suppressed because it is too large Load diff

71
test/test-openshift.yaml Normal file
View file

@ -0,0 +1,71 @@
---
###
#
# This playbook is used for testing SCLORG images in OpenShift 4
# by Container Verification Pipeline (CVP).
#
#
# The Ansible log created when this playbook is run is archived by CVP as an artifact.
#
###
- hosts: all # At runtime this playbook will be executed on a Jenkins slave against 'localhost'
gather_facts: false
tags:
- openshift
# Here's an example of setting environment vars that will be picked up by
# the runtest.sh shell script below.
environment:
VERSION: 14
OS: fedora
IMAGE_FULL_NAME: "{{ image_full_name }}"
IMAGE_REGISTRY_URL: "{{ image_registry_url }}"
IMAGE_NAMESPACE: "{{ image_namespace }}"
IMAGE_NAME: "{{ image_name }}"
IMAGE_TAG: "{{ image_tag }}"
IMAGE_DIGEST: "{{ image_digest }}"
OPENSHIFT_CLUSTER_URL: "{{ openshift_cluster_url }}"
OPENSHIFT_AUTH_TOKEN: "{{ openshift_auth_token }}"
OPENSHIFT_USERNAME: "{{ openshift_username }}"
OPENSHIFT_PROJECT_NAME: "{{ openshift_project_name }}"
CVP_ARTIFACTS_DIR: "{{ cvp_artifacts_dir }}"
tasks:
# CVP should have created the artifacts directory already, but it's always good to check.
- name: "Make sure the artifacts directory exists"
file:
path: "{{ cvp_artifacts_dir }}"
state: directory
# This block is an example of a solely Ansible approach to test a container image in OpenShift.
# It demonstrates how to interact with the unique 'sandbox' project created by CVP in OpenShift
# to import, run, and interact with your container image.
- name: "Run sclorg image name tests in OpenShift 4 environment."
block:
# Log into the cluster where CVP is running
- name: Log into the OpenShift cluster
shell: oc login {{ openshift_cluster_url }} --token="{{ openshift_auth_token }}" --insecure-skip-tls-verify
# Connect to the newly-created temporary 'sandbox' project in OpenShift to run your tests
- name: Select the project {{ openshift_project_name }}
shell: oc project {{ openshift_project_name }}
- name: Import the image into OpenShift
shell: oc import-image {{ image_name }} --from={{ image_full_name }} --insecure=true --confirm
retries: 3
delay: 10
# Derive fully qualified image name of your newly imported image for the next step
- name: Get imported image registry URL
shell: oc get is {{ image_name }} --output=jsonpath='{ .status.dockerImageRepository }'
register: imported_image_url
# Ensure that we can access the /apis/config.openshift.io/v1/clusterversions/version endpoint on OCP4.x
- name: Test the version command on v4.x
shell: oc get clusterversions
register: oc_version_cmd
when: openshift_cluster_version == "v4.x"
# Run tests on OpenShift 4
- name: Run a sclorg test suite in OpenShift 4
shell: VERSION={{ environment[0]['VERSION'] }} IMAGE_NAME={{ image_name }} OS={{ environment[0]['OS'] }} CVP=1 bash test/run-openshift-remote-cluster | tee {{ cvp_artifacts_dir }}/{{ image_name }}.log