Compare commits

..

2 commits

Author SHA1 Message Date
Honza Horak
50d809fe91 container sources not used for building fedora containers anymore 2025-07-08 17:39:40 +02:00
Petr "Stone" Hracek
ec99273a20 This commit adds support for syncing upstream repository to Fedora land
Signed-off-by: Petr "Stone" Hracek <phracek@redhat.com>
2020-06-03 10:28:48 +02:00
63 changed files with 1 additions and 4677 deletions

0
.gitignore vendored
View file

View file

@ -1,48 +0,0 @@
#!/bin/bash -e
#
# S2I assemble script for the 'nodejs-fedora' image.
# The 'assemble' script builds your application source so that it is ready to run.
#
# For more information refer to the documentation:
# https://github.com/openshift/source-to-image/blob/master/docs/builder_image.md
#
if [[ "$1" == "-h" ]]; then
# If the 'nodejs' assemble script is executed with '-h' flag,
# print the usage.
exec /usr/local/s2i/usage
fi
echo "---> Installing application source..."
mv /tmp/src/* ./
if [ ! -z $HTTP_PROXY ]; then
echo "---> Setting npm http proxy to $HTTP_PROXY"
npm config set proxy $HTTP_PROXY
fi
if [ ! -z $http_proxy ]; then
echo "---> Setting npm http proxy to $http_proxy"
npm config set proxy $http_proxy
fi
if [ ! -z $HTTPS_PROXY ]; then
echo "---> Setting npm https proxy to $HTTPS_PROXY"
npm config set https-proxy $HTTPS_PROXY
fi
if [ ! -z $https_proxy ]; then
echo "---> Setting npm https proxy to $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
echo "---> Building application from source..."
npm install
# Fix permissions
chmod -Rf g+w /opt/app-root/ || true

View file

@ -1,49 +0,0 @@
#!/bin/bash -e
#
# 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
#
# 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 --debug="$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
# 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

View file

@ -1,12 +0,0 @@
#!/bin/bash -e
cat <<EOF
This is the nodejs S2I image:
To use it, install S2I: https://github.com/openshift/source-to-image
Sample invocation:
s2i build <source code path/URL> nodejs:6 <application image>
You can then run the resulting image via:
docker run <application image>
EOF

View file

@ -1,78 +0,0 @@
FROM registry.fedoraproject.org/f31/s2i-base: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=12 \
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="s2i build <SOURCE-REPOSITORY> centos/$NAME-$NODEJS_VERSION-centos7:latest <APP-NAME>"
RUN yum -y module enable nodejs:$NODEJS_VERSION && \
INSTALL_PKGS="nodejs npm nss_wrapper" && \
yum remove $INSTALL_PKGS -y && \
yum install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \
rpm -V $INSTALL_PKGS && \
yum -y clean all --enablerepo='*'
# TODO: Add nodejs-nodemon into Fedora
# https://bugzilla.redhat.com/show_bug.cgi?id=1433784
#RUN NPM_CONFIG_PREFIX=$HOME/../ npm install -g nodemon && \
# rm $(npm config get cache)/* -rf && \
# rm -rf $(npm config get tmp)/npm-*
# 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

163
README.md
View file

@ -1,163 +0,0 @@
NodeJS 10 container image
===================
This container image includes Node.JS 10 as a [S2I](https://github.com/openshift/source-to-image) base image for your Node.JS 10 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 [Podman Hub](https://hub.docker.com/r/centos/),
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 10 available as container is a base platform for
building and running various Node.js 10 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
---------------------
For this, we will assume that you are using the `ubi8/nodejs-10 image`, available via `nodejs:10` imagestream tag in Openshift.
Building a simple [nodejs-sample-app](https://github.com/sclorg/s2i-nodejs-container/tree/master/10/test/test-app) application
in Openshift can be achieved with the following step:
```
oc new-app nodejs:10~https://github.com/sclorg/s2i-nodejs-container.git --context-dir=10/test/test-app/
```
The same application can also be built using the standalone [S2I](https://github.com/openshift/source-to-image) application on systems that have it available:
```
$ s2i build https://github.com/sclorg/s2i-nodejs-container.git --context-dir=10/test/test-app/ ubi8/nodejs-10 nodejs-sample-app
```
**Accessing the application:**
```
$ curl 127.0.0.1:8080
```
Environment variables
---------------------
Application developers can use the following environment variables to configure the runtime behavior of this image:
**`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 Python 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.

View file

@ -1,23 +0,0 @@
version: "1"
betka:
# is betka enabled for this repository
# optional - defaults to false
enabled: true
# optional
notifications:
email_addresses: [phracek@redhat.com, zsvetlik@redhat.com]
# Specify if master branch in upstream repository is synced
master_checker: true
# Should pull requests be synced?
# optional
pr_checker: false
# Either 'upstream_branch_name' or 'upstream_git_path' has to be specified
# Branch name which is used for sync
upstream_branch_name: master
# Path to directory with dockerfile withing upstream repository
upstream_git_path: "12"
# Github comment message to enforce sync of a pull request
# required if pr_checker is true otherwise optional
pr_comment_message: "[test]"
# optional
image_url: quay.io/rhscl/cwt-generator

View file

@ -1,4 +0,0 @@
language: shell
os: linux
script:
- make shellcheck

View file

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -1,43 +0,0 @@
SHELL := /usr/bin/env bash
all:
@echo >&2 "Only 'make check' allowed"
TESTED_IMAGES = \
postgresql-container \
s2i-python-container \
s2i-nodejs-container
.PHONY: check test all check-failures
TEST_LIB_TESTS = \
path_foreach \
random_string \
test_npm \
image_availability \
public_image_name
$(TEST_LIB_TESTS):
@echo " RUN TEST '$@'" ; \
$(SHELL) tests/test-lib/$@ || $(SHELL) -x tests/lib/$@
test-lib-foreach:
check-test-lib: $(TEST_LIB_TESTS)
test: check
shellcheck:
./run-shellcheck.sh `git ls-files *.sh`
check-failures: check-test-lib
cd tests/failures/check && make tag && ! make check && make clean
grep -q "Red Hat Enterprise Linux release 8" /etc/system-release || cd tests/failures/check && make tag SKIP_SQUASH=0
check-squash:
./tests/squash/squash.sh
check: check-failures check-squash
TESTED_IMAGES="$(TESTED_IMAGES)" tests/remote-containers.sh

View file

@ -1,100 +0,0 @@
Common build helpers for sclorg containers
==========================================
This repository is aimed to be added as git submodule into particular
containers' source repositories. By default, the path to submodule should be
named 'common'.
Usage
-----
This section explains the usage of the shared scripts in this repository when
it is used as a submodule in a container source repository.
Once you have the repository set as a submodule include `common.mk` into your
root Makefile in order to access the default rules used to call shared scripts.
**Default rules:**
`make` or `make build`
This rule will build an image without tagging it with any tags after it is built.
After the image finishes building the scripts will squash the image using `docker-squash`.
`make build` will also expect a `README.md` so that it can transfrom it into
a man page that gets added to the image so make sure it is available and that
you have the `go-md2man` tool installed on your host.
`make tag`
Use this rule if you want to tag an image after it is built. It will be tagged with
two tags - name:latest and name:version.
Depends on `build`
`make test` or `make check`
This rule will run the testsuite scripts contained in the container source repositories.
It expects the test to be available at `$gitroot/$version/test/run`
Depends on `tag` as some tests might need to have the images tagged (s2i).
`make test-openshift`
Similar to `make test` but runs testsuite for Openshift, expected to be found at
`$gitroot/$version/test/run-openshift`
`make test-with-conu`
The rule is similar to `make test`. It runs a test suite written using [conu
library](https://github.com/user-cont/conu). The path to the test script is
meant to be at `$gitroot/$version/test/run-conu`. By default the test suite is
being run in the current environment. You can also run the tests in a container
by defining variable `CONU_IMAGE`. Container images with conu are available in
[this docker hub repository](docker.io/usercont/conu:0.6.2), a good value for
the variable is `docker.io/usercont/conu:0.6.2`.
`make clean`
Runs scripts that clean-up the working dir. Depends on the `clean-images` rule by default
and additional clean rules can be provided through the `clean-hook` variable.
`make clean-images`
Best-effort to remove the last set of images that have been built using the scripts.
**There are additional variables that you can use that the default rules are prepared to
work with:**
`VERSIONS`
Names of the directories in which the Dockerfiles are contained. Needs to be defined in your
Dockerfile for the scripts to know which versions to build.
`OS`
OS version you want to build the images for. Currently the scripts are able to build for
centos (default), centos6, rhel7 and fedora.
`SKIP_SQUASH`
When set to 1 the build script will skip the squash phase of the build.
`CUSTOM_REPO`
Set this variable to the path to your local .repo files you want to have available inside
the image while building. Useful for building rhel-based images on an unsubscribed box.
Be aware that you cannot write to any .repo files used this way inside the image as they
will be mounted into the image as read-only.
`UPDATE_BASE`
Set to 1 if you want the build script to always pull the base image when available.
`DOCKER_BUILD_CONTEXT`
Use this variable in case you want to have a different context for your builds. By default
the context of the build is the versioned directory the Dockerfiles are contained in.
`clean-hook`
Append Makefile rules to this variable to make sure additional cleaning actions are run
when `make clean` is called.
Regression tests
----------------
Just run `make check`
Dependencies for testsuite:
- docker
- docker-squash
- git
- go-md2man
- make
- source-to-image

View file

@ -1,183 +0,0 @@
#!/bin/bash
# This script is used to build the OpenShift Docker images.
#
# OS - Specifies distribution - "rhel7", "centos7" or "fedora"
# VERSION - Specifies the image version - (must match with subdirectory in repo)
# VERSIONS - Must be set to a list with possible versions (subdirectories)
set -e
script_name=$(readlink -f "$0")
script_dir=$(dirname "$script_name")
OS=${1-$OS}
VERSION=${2-$VERSION}
error() { echo "ERROR: $*" ; false ; }
# _parse_output_inner
# -------------------
# Helper function for 'parse_output'.
# We need to avoid case statements in $() for older Bash versions (per issue
# postgresql-container#35, mac ships with 3.2).
# Example of problematic statement: echo $(case i in i) echo i;; esac)
_parse_output_inner ()
{
set -o pipefail
{
case $stream in
stdout|1|"")
eval "$command" | tee >(cat - >&"$stdout_fd")
;;
stderr|2)
set +x # avoid stderr pollution
eval "$command" {free_fd}>&1 1>&"$stdout_fd" 2>&"$free_fd" | tee >(cat - >&"$stderr_fd")
;;
esac
# Inherit correct exit status.
(exit "${PIPESTATUS[0]}")
} | eval "$filter"
}
# parse_output COMMAND FILTER_COMMAND OUTVAR [STREAM={stderr|stdout}]
# -------------------------------------------------------------------
# Parse standard (error) output of COMMAND with FILTER_COMMAND and store the
# output into variable named OUTVAR. STREAM might be 'stdout' or 'stderr',
# defaults to 'stdout'. The filtered output stays (live) printed to terminal.
# This method doesn't create any explicit temporary files.
# Defines:
# ${$OUTVAR}: Set to FILTER_COMMAND output.
parse_output ()
{
local command=$1 filter=$2 var=$3 stream=$4
local raw_output='' rc=0
{
# shellcheck disable=SC2034
raw_output=$(_parse_output_inner)
} {stdout_fd}>&1 {stderr_fd}>&2
rc=$?
eval "$var=\$raw_output"
(exit $rc)
}
# "best-effort" cleanup of previous image
function clean_image {
if test -f .image-id.raw; then
local previous_id
previous_id=$(cat .image-id.raw)
if test "$IMAGE_ID" != "$previous_id"; then
# Also remove squashed image since it will change anyway
docker rmi "$previous_id" "$(cat .image-id)" || :
rm -f ".image-id.raw" ".image-id" || :
fi
fi
}
# Perform docker build but append the LABEL with GIT commit id at the end
function docker_build_with_version {
local dockerfile="$1"
local exclude=.exclude-${OS}
if [ -e "$exclude" ]; then
echo "-> $exclude file exists for version $dir, skipping build."
clean_image
return
fi
if [ ! -e "$dockerfile" ]; then
echo "-> $dockerfile for version $dir does not exist, skipping build."
clean_image
return
fi
echo "-> Version ${dir}: building image from '${dockerfile}' ..."
git_version=$(git rev-parse --short HEAD)
BUILD_OPTIONS+=" --label io.openshift.builder-version=\"${git_version}\""
if [[ "${UPDATE_BASE}" == "1" ]]; then
BUILD_OPTIONS+=" --pull=true"
fi
if [ -n "$CUSTOM_REPO" ]; then
if [ -f "$CUSTOM_REPO" ]; then
BUILD_OPTIONS+=" -v $CUSTOM_REPO:/etc/yum.repos.d/sclorg_custom.repo:Z"
elif [ -d "$CUSTOM_REPO" ]; then
BUILD_OPTIONS+=" -v $CUSTOM_REPO:/etc/yum.repos.d/:Z"
else
echo "ERROR: file type not known: $CUSTOM_REPO" >&2
fi
fi
# shellcheck disable=SC2016
parse_output 'docker build '"$BUILD_OPTIONS"' -f "$dockerfile" "${DOCKER_BUILD_CONTEXT}"' \
"tail -n 1 | awk '/Successfully built|(^--> )?(Using cache )?[a-fA-F0-9]+$/{print \$NF}'" \
IMAGE_ID
clean_image
echo "$IMAGE_ID" > .image-id.raw
squash "${dockerfile}"
echo "$IMAGE_ID" > .image-id
}
# squash DOCKERFILE
# -----------------
# Use python library docker_squash[1] and squash the result image
# when necessary.
# [1] https://github.com/goldmann/docker-squash
# Reads:
# $IMAGE_ID
# Sets:
# $IMAGE_ID
squash ()
{
local base squashed_from squashed='' unsquashed=$IMAGE_ID
test "$SKIP_SQUASH" = 1 && return 0
if test -f .image-id.squashed; then
squashed=$(cat .image-id.squashed)
# We (maybe) already have squashed file.
if test -f .image-id.squashed_from; then
squashed_from=$(cat .image-id.squashed_from)
if test "$squashed_from" = "$IMAGE_ID"; then
# $squashed is up2date
IMAGE_ID=$squashed
echo "Image '$unsquashed' already squashed as '$squashed'"
return 0
fi
fi
# We are going to squash now, so if there's existing squashed image, try
# to do the best-effort 'rmi' to not waste memory unnecessarily.
docker rmi "$squashed" || :
fi
base=$(awk '/^FROM/{print $2}' "$1")
echo "Squashing the image '$unsquashed' from '$base' layer."
IMAGE_ID=$("${PYTHON-python3}" "$script_dir"/squash.py "$unsquashed" "$base")
echo "Squashed as '$IMAGE_ID'."
echo "$unsquashed" > .image-id.squashed_from
echo "$IMAGE_ID" > .image-id.squashed
}
# Versions are stored in subdirectories. You can specify VERSION variable
# to build just one single version. By default we build all versions
dirs=${VERSION:-$VERSIONS}
for dir in ${dirs}; do
pushd "${dir}" > /dev/null
if [ "$OS" == "rhel8" ] || [ "$OS" == "rhel8-candidate" ]; then
docker_build_with_version Dockerfile.rhel8
elif [ "$OS" == "rhel7" ] || [ "$OS" == "rhel7-candidate" ]; then
docker_build_with_version Dockerfile.rhel7
elif [ "$OS" == "fedora" ] || [ "$OS" == "fedora-candidate" ]; then
docker_build_with_version Dockerfile.fedora
elif [ "$OS" == "centos6" ] || [ "$OS" == "centos6-candidate" ]; then
docker_build_with_version Dockerfile.centos6
else
docker_build_with_version Dockerfile
fi
popd > /dev/null
done

View file

@ -1,21 +0,0 @@
#! /bin/sh
set -e
test -f auto_targets.mk && rm auto_targets.mk
for version
do
remove_images=
for idfile in .image-id.raw .image-id.squashed; do
# shellcheck disable=SC2039
test ! -f "$version/$idfile" || remove_images+=" $(cat "$version/$idfile")"
done
for image in $remove_images; do
# shellcheck disable=SC2046
docker rm -f $(docker ps -q -a -f "ancestor=$image") 2>/dev/null || :
docker rmi -f "$image" || :
done
rm -rf "$version"/.image-id*
done

View file

@ -1,146 +0,0 @@
# SKIP_SQUASH = 0/1
# =================
# If set to '0', images are automatically squashed. '1' disables
# squashing. By default only RHEL containers are squashed.
SHELL := /usr/bin/env bash
ifndef common_dir
common_dir = common
endif
build = $(SHELL) $(common_dir)/build.sh
test = $(SHELL) $(common_dir)/test.sh
testr = $(SHELL) $(common_dir)/test-remote-cluster.sh
shellcheck = $(SHELL) $(common_dir)/run-shellcheck.sh
tag = $(SHELL) $(common_dir)/tag.sh
clean = $(SHELL) $(common_dir)/clean.sh
DG ?= /bin/dg
generator = DG="$(DG)" $(SHELL) $(common_dir)/generate.sh
# pretty printers
# ---------------
__PROLOG = $(if $(VERBOSE),,@echo " $(1) " $@;)
V_LN = $(call __PROLOG,LN )
V_DG = $(call __PROLOG,DG )
V_DGM = $(call __PROLOG,DGM)
V_CP = $(call __PROLOG,CP )
CDIR = mkdir -p "$$(dirname "$@")" || exit 1 ;
ifeq ($(TARGET),rhel8)
SKIP_SQUASH ?= 1
OS := rhel8
DOCKERFILE ?= Dockerfile.rhel8
else ifeq ($(TARGET),rhel7)
SKIP_SQUASH ?= 0
OS := rhel7
DOCKERFILE ?= Dockerfile.rhel7
else ifeq ($(TARGET),fedora)
OS := fedora
DOCKERFILE ?= Dockerfile.fedora
else ifeq ($(TARGET),centos6)
OS := centos6
DOCKERFILE ?= Dockerfile.centos6
else
OS := centos7
DOCKERFILE ?= Dockerfile
endif
SKIP_SQUASH ?= 1
DOCKER_BUILD_CONTEXT ?= .
SHELLCHECK_FILES ?= .
script_env = \
SKIP_SQUASH=$(SKIP_SQUASH) \
UPDATE_BASE=$(UPDATE_BASE) \
OS=$(OS) \
CLEAN_AFTER=$(CLEAN_AFTER) \
DOCKER_BUILD_CONTEXT=$(DOCKER_BUILD_CONTEXT) \
OPENSHIFT_NAMESPACES="$(OPENSHIFT_NAMESPACES)" \
CUSTOM_REPO="$(CUSTOM_REPO)"
# TODO: switch to 'build: build-all' once parallel builds are relatively safe
.PHONY: build build-serial build-all
build: build-serial
build-serial:
@$(MAKE) -j1 build-all
build-all: $(VERSIONS)
@for i in $(VERSIONS); do \
test -f $$i/.image-id || continue ; \
echo -n "$(BASE_IMAGE_NAME) $$i => " ; \
cat $$i/.image-id ; \
done
.PHONY: $(VERSIONS)
$(VERSIONS): % : %/root/help.1
VERSION="$@" $(script_env) $(build)
.PHONY: test check
check: test
test: script_env += TEST_MODE=true
# The tests should ideally depend on $IMAGE_ID only, but see PR#19 for more info
# while we need to depend on 'tag' instead of 'build'.
test: tag
VERSIONS="$(VERSIONS)" $(script_env) $(test)
.PHONY: test-with-conu
test-with-conu: script_env += TEST_CONU_MODE=true
test-with-conu: tag
VERSIONS="$(VERSIONS)" $(script_env) $(test)
.PHONY: test-openshift-remote-cluster
test-openshift-remote-cluster:
VERSIONS="$(VERSIONS)" BASE_IMAGE_NAME="$(BASE_IMAGE_NAME)" $(script_env) $(testr)
.PHONY: test-openshift
test-openshift: script_env += TEST_OPENSHIFT_MODE=true
test-openshift: tag
VERSIONS="$(VERSIONS)" BASE_IMAGE_NAME="$(BASE_IMAGE_NAME)" $(script_env) $(test)
.PHONY: shellcheck
shellcheck:
$(shellcheck) $(SHELLCHECK_FILES)
.PHONY: tag
tag: build
VERSIONS="$(VERSIONS)" $(script_env) $(tag)
.PHONY: clean clean-hook clean-images clean-versions
clean: clean-images
@$(MAKE) --no-print-directory clean-hook
clean-images:
$(clean) $(VERSIONS)
clean-versions:
rm -rf $(VERSIONS)
%root/help.1: %README.md
mkdir -p $(@D)
go-md2man -in "$^" -out "$@"
chmod a+r "$@"
generate-all: generate
MANIFEST_FILE ?= manifest.sh
auto_targets.mk: $(MANIFEST_FILE)
MANIFEST_FILE="$(MANIFEST_FILE)" \
VERSIONS="$(VERSIONS)" \
$(generator)
# triggers build of auto_targets.mk automatically
-include auto_targets.mk
# We have to remove auto_targets.mk here, otherwise subsequent make calls
# with different VERSIONS=* option keeps the auto_targets.mk unchanged.
.PHONY: generate
generate: $(DISTGEN_TARGETS) $(DISTGEN_MULTI_TARGETS) $(COPY_TARGETS) $(SYMLINK_TARGETS)
rm auto_targets.mk

View file

@ -1,180 +0,0 @@
#!/bin/bash
# This script is used to create image directories using distgen, cp or ln
# It requires "$MANIFEST_FILE" (defaults to manifest.sh) file to be present in
# image repository.
# The manifest file should contain set of rules in form:
# <rules_type>="
# src=<path to source>
# dest=<path to destination>
# mode=<destination file mode (optional)>;
# ...;
# "
#
# Supported type rules are now COPY_RULES, DISTGEN_RULES and SYMLINKS_RULES
# for real example see https://github.com/sclorg/postgresql-container/blob/master/manifest.sh
# shellcheck disable=SC1090
source "$MANIFEST_FILE"
die () { echo "FATAL: $*" ; exit 1 ; }
nl='
'
test -f auto_targets.mk && rm auto_targets.mk
DG="${DG-/bin/dg}"
[ ! -x "$DG" ] && echo " Error: distgen binary not found or not executable in $DG" && \
echo " Make sure distgen is properly installed on your host in $DG, or provide a path to your distgen binary via \$DG" && exit 1
DISTGEN_COMBINATIONS=$("$DG" --multispec specs/multispec.yml --multispec-combinations)
clean_rule_variables(){
src=""
dest=""
mode=""
link_target=""
link_name=""
}
parse_rules() {
targets=""
OLD_IFS=$IFS
IFS=";"
for rule in $rules; do
if [ -z "$(echo "$rule"| tr -d '[:space:]')" ]; then
continue
fi
clean_rule_variables
eval "$rule"
# shellcheck disable=SC2016
cdir='$(CDIR)'
case "$creator" in
copy)
[[ -z "$src" ]] && echo "src has to be specified in copy rule" && exit 1
[[ -z "$dest" ]] && echo "dest has to be specified in copy rule" && exit 1
core_subst=$core
prolog="\$(V_CP)$cdir"
;;
distgen)
[[ -z "$src" ]] && echo "src has to be specified in distgen rule" && exit 1
[[ -z "$dest" ]] && echo "dest has to be specified in distgen rule" && exit 1
core_subst=$core
prolog="\$(V_DG)$cdir"
;;
distgen_multi)
[[ -z "$src" ]] && echo "src has to be specified in distgen rule" && exit 1
[[ -z "$dest" ]] && echo "dest has to be specified in distgen rule" && exit 1
if [[ "$dest" == "Dockerfile.rhel7" ]]; then
if ! [[ "$DG_CONF" =~ rhel-7-x86_64.yaml ]]; then
continue
fi
elif [[ "$dest" == "Dockerfile.rhel8" ]]; then
if ! [[ "$DG_CONF" =~ rhel-8-x86_64.yaml ]]; then
continue
fi
elif [[ "$dest" == *"Dockerfile.fedora" ]]; then
if ! [[ "$DG_CONF" =~ fedora-[0-9]{,2}-x86_64.yaml ]]; then
continue
fi
elif [[ "$dest" == *"Dockerfile" ]]; then
if ! [[ "$DG_CONF" =~ centos-[0-9]{,2}-x86_64.yaml ]]; then
continue
fi
fi
prolog="\$(V_DGM)$cdir"
core_subst=$core
;;
link)
[[ -z "$link_name" ]] && echo "link_name has to be specified in link rule" && exit 1
[[ -z "$link_target" ]] && echo "link_target has to be specified in link rule" && exit 1
dest="$link_name"
# shellcheck disable=SC2001
core_subst=$(echo "$core" | sed -e "s~__link_target__~${link_target}~g")
prolog="\$(V_LN)$cdir"
;;
esac
case $version$dest$src in
*' '*) die "space not allowed in version, dest, src" ;;
esac
target=$version/$dest
targets+="\\$nl $target"
cat >> auto_targets.mk << EOF
$nl$target: $src \$(MANIFEST_FILE)
$prolog \\
$core_subst${mode:+"; \\
chmod $mode '\$@'"}
EOF
done
IFS=$OLD_IFS
}
for version in ${VERSIONS}; do
# Get a working combination of distgen options for this version
while read -r combination; do
# line looks like: --distro rhel-7-x86_64.yaml --multispec-selector version=9.4
echo "$combination" | grep "version=$version" &>/dev/null && break
done <<< "$DISTGEN_COMBINATIONS"
[ -z "$combination" ] && die "Could not find a working distgen options combination for version $version"
# copy targets
rules="$COPY_RULES"
core="cp \$< \$@"
creator="copy"
parse_rules
COPY_TARGETS+="$targets"
# distgen targets
rules="$DISTGEN_RULES"
core="\$(DG) --multispec specs/multispec.yml \\
--template \"\$<\" $combination --output \"\$@\""
creator="distgen"
parse_rules
DISTGEN_TARGETS+="$targets"
rules=$SYMLINK_RULES
core="ln -nfs __link_target__ \$@"
creator="link"
parse_rules
SYMLINK_TARGETS+="$targets"
done
while read -r combination; do
# line looks like: --distro rhel-7-x86_64.yaml --multispec-selector version=9.4
eval 'set -- $combination'
case $4 in
version=*) version=${4##*=} ;;
*) die "version not found"
esac
case $2 in
*x86_64*) DG_CONF=$2 ;;
*) die "invalid --distro option"
esac
# distgen multi targets
rules="$DISTGEN_MULTI_RULES"
core="\$(DG) --multispec specs/multispec.yml \\
--template \"\$<\" \\
--output \"\$@\" \\
$combination"
creator="distgen_multi"
parse_rules
DISTGEN_MULTI_TARGETS+="$targets"
done <<< "$DISTGEN_COMBINATIONS"
cat -v >> auto_targets.mk <<EOF
COPY_TARGETS = $COPY_TARGETS
DISTGEN_TARGETS = $DISTGEN_TARGETS
DISTGEN_MULTI_TARGETS = $DISTGEN_MULTI_TARGETS
SYMLINK_TARGETS = $SYMLINK_TARGETS
EOF

View file

@ -1,44 +0,0 @@
#!/bin/bash
VERBOSE_OUTPUT=0
usage() {
echo "Usage: $(basename "$0") [ -v|--verbose ] <dir|file> [ <dir|file> ... ]"
}
verbose() {
if [ "${VERBOSE_OUTPUT}" -eq 1 ] ; then
echo "$@" >&2
fi
}
if [ $# -eq 0 ] ; then
echo "ERROR: No arguments given."
usage
exit 1
fi
case $1 in
-v|--verbose) VERBOSE_OUTPUT=1; shift ;;
esac
filter_files() {
while read -r file ; do
if [ -L "$file" ] ; then
verbose "Ignoring symlink $file."
continue
fi
verbose "Will scan $file"
echo "$file"
done
}
detect_shell_files() {
find -H "$@" -type f -not -path '*/\.git/*' -exec grep -l '^#!/bin/\(bash\|sh\)' {} +
find -H "$@" -name '*.sh' -not -path '*/\.git/*'
}
# Run shellcheck on all files (we should also ignore symlinks)
detect_shell_files "$@" | filter_files | sort -u | xargs shellcheck
# vim: set tabstop=2:shiftwidth=2:expandtab:

View file

@ -1,23 +0,0 @@
#! /bin/python
import sys
import logging
from platform import python_version
try:
from docker_squash import squash
except ImportError:
logging.fatal("please install 'docker_squash' for Python {0}".format(python_version()))
sys.exit(1)
if __name__ == "__main__":
if len(sys.argv) != 3:
logging.fatal("%s: %s", sys.argv[0], msg)
sys.exit(1)
print(squash.Squash(
log=logging.getLogger(),
image=sys.argv[1],
from_layer=sys.argv[2]).run()
)

View file

@ -1,34 +0,0 @@
#!/bin/bash
# This script is used to tag the OpenShift Docker images.
#
# Resulting image will be tagged: 'name:version' and 'name:latest'. Name and version
# are values of labels from resulted image
#
# VERSIONS - Must be set to a list with possible versions (subdirectories)
set -e
for dir in ${VERSIONS}; do
[ ! -e "${dir}/.image-id" ] && echo "-> Image for version $dir not built, skipping tag." && continue
pushd "${dir}" > /dev/null
IMAGE_ID=$(cat .image-id)
name=$(docker inspect -f "{{.Config.Labels.name}}" "$IMAGE_ID")
version=$(docker inspect -f "{{.Config.Labels.version}}" "$IMAGE_ID")
commit_date=$(git show -s HEAD --format=%cd --date=short | sed 's/-//g')
date_and_hash="${commit_date}-$(git rev-parse --short HEAD)"
echo "-> Tagging image '$IMAGE_ID' as '$name:$version' and '$name:latest' and '$name:$date_and_hash'"
docker tag "$IMAGE_ID" "$name:$version"
docker tag "$IMAGE_ID" "$name:latest"
docker tag "$IMAGE_ID" "$name:$date_and_hash"
for suffix in squashed raw; do
id_file=.image-id.$suffix
if test -f "$id_file"; then
docker tag "$(cat "$id_file")" "$name:$suffix" || rm .image-id."$suffix"
fi
done
popd > /dev/null
done

File diff suppressed because it is too large Load diff

View file

@ -1,653 +0,0 @@
# shellcheck shell=bash
#
# 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
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
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-}"
# we really work with CONTAINER_ARGS as with a string
# shellcheck disable=SC2124
CONTAINER_ARGS="$@"
if ct_create_container "$cid_file" ; then
local cid
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
[ -n "$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
# shellcheck disable=SC2086
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
tmpdir=$(mktemp -d)
local f
: " Testing documentation in the container image"
# Extract the help files from the container
# shellcheck disable=SC2043
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 ! grep -F -q -e "${term}" "${tmpdir}/$(basename "${f}")" ; 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!"
}
# full_ca_file_path
# Return string for full path to CA file
function full_ca_file_path()
{
echo "/etc/pki/ca-trust/source/anchors/RH-IT-Root-CA.crt"
}
# ct_mount_ca_file
# ------------------
# Check if /etc/pki/certs/RH-IT-Root-CA.crt file exists
# return mount string for containers or empty string
function ct_mount_ca_file()
{
# mount CA file only if NPM_REGISTRY variable is present.
local mount_parameter=""
if [ -n "$NPM_REGISTRY" ] && [ -f "$(full_ca_file_path)" ]; then
mount_parameter="-v $(full_ca_file_path):$(full_ca_file_path):Z"
fi
echo "$mount_parameter"
}
# ct_build_s2i_npm_variables URL_TO_NPM_JS_SERVER
# ------------------------------------------
# Function returns -e NPM_MIRROR and -v MOUNT_POINT_FOR_CAFILE
# or empty string
function ct_build_s2i_npm_variables()
{
npm_variables=""
if [ -n "$NPM_REGISTRY" ] && [ -f "$(full_ca_file_path)" ]; then
npm_variables="-e NPM_MIRROR=$NPM_REGISTRY $(ct_mount_ca_file)"
fi
echo "$npm_variables"
}
# ct_npm_works
# --------------------
# Checks existance of the npm tool and runs it.
function ct_npm_works() {
local tmpdir
tmpdir=$(mktemp -d)
: " Testing npm in the container image"
local cid_file="${tmpdir}/cid"
if ! docker run --rm "${IMAGE_NAME}" /bin/bash -c "npm --version" >"${tmpdir}/version" ; then
echo "ERROR: 'npm --version' does not work inside the image ${IMAGE_NAME}." >&2
return 1
fi
# shellcheck disable=SC2046
docker run -d $(ct_mount_ca_file) --rm --cidfile="$cid_file" "${IMAGE_NAME}-testapp"
# Wait for the container to write it's CID file
ct_wait_for_cid "$cid_file" || return 1
if ! docker exec "$(cat "$cid_file")" /bin/bash -c "npm --verbose install jquery && test -f node_modules/jquery/src/jquery.js" >"${tmpdir}/jquery" 2>&1 ; then
echo "ERROR: npm could not install jquery inside the image ${IMAGE_NAME}." >&2
return 1
fi
if [ -n "$NPM_REGISTRY" ] && [ -f "$(full_ca_file_path)" ]; then
if ! grep -qo "$NPM_REGISTRY" "${tmpdir}/jquery"; then
echo "ERROR: Internal repository is NOT set. Even it is requested."
return 1
fi
fi
if [ -f "$cid_file" ]; then
docker stop "$(cat "$cid_file")"
rm "$cid_file"
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"
# shellcheck source=/dev/null
[ -f "test/$test_case" ] && source "test/$test_case"
# shellcheck source=/dev/null
[ -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
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
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=$(tail -c 3 "${response_file}")
if [ "${response_code}" -eq "${expected_code}" ]; then
result=0
fi
grep -qP -e "${body_regexp}" "${response_file}" || 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 ] || [ "${attempt}" -gt "${ignore_error_attempts}" ] || [ "${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
rhel*)
registry=registry.redhat.io
;;
*)
registry=docker.io
;;
esac
echo "$registry"
}
# ct_get_public_image_name OS BASE_IMAGE_NAME VERSION
# ----------------
# Transform the arguments into public image name
# Argument: OS - string containing the os version
# Argument: BASE_IMAGE_NAME - string containing the base name of the image as defined in the Makefile
# Argument: VERSION - string containing the version of the image as defined in the Makefile
ct_get_public_image_name() {
local os=$1; shift
local base_image_name=$1; shift
local version=$1; shift
local public_image_name
local registry
registry=$(ct_registry_from_os "$os")
if [ "x$os" == "xrhel7" ]; then
public_image_name=$registry/rhscl/$base_image_name-${version//./}-rhel7
elif [ "x$os" == "xrhel8" ]; then
public_image_name=$registry/rhel8/$base_image_name-${version//./}
elif [ "x$os" == "xcentos7" ]; then
public_image_name=$registry/centos/$base_image_name-${version//./}-centos7
fi
echo "$public_image_name"
}
# 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=
local incremental=false
local mount_options=""
# Run the entire thing inside a subshell so that we do not leak shell options outside of the function
(
# Error out if any part of the build fails
set -e
# Use /tmp to not pollute cwd
tmpdir=$(mktemp -d)
df_name=$(mktemp -p "$tmpdir" Dockerfile.XXXX)
cd "$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=$(docker inspect -f "{{.Config.User}}" "$src_image")
# Default to root if no user is set by the image
user=${user:-0}
# run the user through the image in case it is non-numeric or does not exist
# NOTE: The '-eq' test is used to check if $user is numeric as it will fail if $user is not an integer
if ! [ "$user" -eq "$user" ] 2>/dev/null && ! user_id=$(docker run --rm "$src_image" bash -c "id -u $user 2>/dev/null"); then
echo "ERROR: id of user $user not found inside image $src_image."
echo "Terminating s2i build."
return 1
else
user_id=${user_id:-$user}
fi
echo "$s2i_args" | grep -q "\-\-incremental" && incremental=true
if $incremental; then
inc_tmp=$(mktemp -d --tmpdir incremental.XXXX)
setfacl -m "u:$user_id:rwx" "$inc_tmp"
# Check if the image exists, build should fail (for testing use case) if it does not
docker images "$dst_image" &>/dev/null || (echo "Image $dst_image not found."; false)
# Run the original image with a mounted in volume and get the artifacts out of it
cmd="if [ -s /usr/libexec/s2i/save-artifacts ]; then /usr/libexec/s2i/save-artifacts > \"$inc_tmp/artifacts.tar\"; else touch \"$inc_tmp/artifacts.tar\"; fi"
docker run --rm -v "$inc_tmp:$inc_tmp:Z" "$dst_image" bash -c "$cmd"
# Move the created content into the $tmpdir for the build to pick it up
mv "$inc_tmp/artifacts.tar" "$tmpdir/"
fi
# 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"
# Check if CA autority is present on host and add it into Dockerfile
[ -f "$(full_ca_file_path)" ] && echo "RUN cd /etc/pki/ca-trust/source/anchors && update-ca-trust extract" >>"$df_name"
# Add in artifacts if doing an incremental build
if $incremental; then
{ echo "RUN mkdir /tmp/artifacts"
echo "ADD artifacts.tar /tmp/artifacts"
echo "RUN chown -R $user_id:0 /tmp/artifacts" ; } >>"$df_name"
fi
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
# Check if -v parameter is present in s2i_args and add it into docker build command
mount_options=$(echo "$s2i_args" | grep -o -e '\(-v\)[[:space:]]\.*\S*' || true)
# Run the build and tag the result
# shellcheck disable=SC2086
docker build $mount_options -f "$df_name" --no-cache=true -t "$dst_image" .
)
}
# ct_check_image_availability PUBLIC_IMAGE_NAME
# ----------------------------
# Pull an image from the public repositories to see if the image is already available.
# Argument: PUBLIC_IMAGE_NAME - string containing the public name of the image to pull
ct_check_image_availability() {
local public_image_name=$1;
# Try pulling the image to see if it is accessible
if ! docker pull "$public_image_name" &>/dev/null; then
echo "$public_image_name could not be downloaded via 'docker'"
return 1
fi
}
# vim: set tabstop=2:shiftwidth=2:expandtab:

View file

@ -1,33 +0,0 @@
#!/bin/bash
# This script is used to test container images integrated in the OpenShift.
#
# VERSIONS - Must be set to a list with possible versions (subdirectories)
#
# This script expects oc command to exist and logged in to a working cluster.
set -e
export OS=${OS:-rhel7}
if [ "${OS}" == "rhel7" ] ; then
NAMESPACE=${NAMESPACE:-rhscl/}
REGISTRY=${REGISTRY:-registry.access.redhat.com/}
else
NAMESPACE=${NAMESPACE:-centos/}
fi
export NAMESPACE
export REGISTRY
for dir in ${VERSIONS}; do
pushd "${dir}" > /dev/null
export IMAGE_NAME="${REGISTRY}${NAMESPACE}${BASE_IMAGE_NAME}-${dir//./}-${OS}"
VERSION=$dir test/run-openshift-remote-cluster
popd > /dev/null
done
# vim: set tabstop=2:shiftwidth=2:expandtab:

View file

@ -1,58 +0,0 @@
#!/bin/bash
# This script is used to test the OpenShift Docker images.
#
# TEST_MODE - If set, run regular test suite
# TEST_OPENSHIFT_MODE - If set, run OpenShift tests (if present)
# VERSIONS - Must be set to a list with possible versions (subdirectories)
set -e
for dir in ${VERSIONS}; do
[ ! -e "${dir}/.image-id" ] && echo "-> Image for version $dir not built, skipping tests." && continue
pushd "${dir}" > /dev/null
IMAGE_ID=$(cat .image-id)
export IMAGE_ID
# Kept also IMAGE_NAME as some tests might still use that.
IMAGE_NAME=$(docker inspect -f "{{.Config.Labels.name}}" "$IMAGE_ID")
export IMAGE_NAME
if [ -n "${TEST_MODE}" ]; then
VERSION=$dir test/run
fi
if [ -n "${TEST_CONU_MODE}" ]; then
if [[ -x test/run-conu ]]; then
if [ -n "${CONU_IMAGE}" ]; then
echo "-> Running conu tests in a container"
docker run \
--net=host \
-e VERSION="${dir}" \
-e IMAGE_NAME \
--rm \
--security-opt label=disable \
-ti \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "${PWD}"/../:/src \
-w "/src/${dir}/" \
-ti \
"${CONU_IMAGE}" \
./test/run-conu
else
VERSION="${dir}" ./test/run-conu
fi
else
echo "-> conu tests are not present, skipping"
fi
fi
if [ -n "${TEST_OPENSHIFT_MODE}" ]; then
if [[ -x test/run-openshift ]]; then
VERSION=$dir test/run-openshift
else
echo "-> OpenShift tests are not present, skipping"
fi
fi
popd > /dev/null
done

View file

@ -1,2 +0,0 @@
.image-id*
help.1

View file

@ -1,4 +0,0 @@
# Variables are documented in common/build.sh.
BASE_IMAGE_NAME = test-container
VERSIONS = v0
include common/common.mk

View file

@ -1 +0,0 @@
../../..

View file

@ -1,2 +0,0 @@
FROM centos/s2i-core-centos7
LABEL name=test-image

View file

@ -1 +0,0 @@
This is just no-op-build container.

View file

@ -1,3 +0,0 @@
#! /bin/sh -x
false this must fail the whole testsuite

View file

@ -1,103 +0,0 @@
#! /bin/bash
set -e
declare -A IMAGES
for image in ${TESTED_IMAGES}; do
IMAGES[$image]=master
done
OS=centos7
MERGE_INTO=origin/master
# This is the Fedora default, some users' boxes have more strict
# defaults (e.g. 0077).
umask 0022
die () { echo >&2 " # FATAL: $*"; exit 1; }
info () { echo " * $*"; }
error () { echo >&2 " # ERROR: $*"; }
test -f common.mk -a -f build.sh -a -d .git \
|| die "Doesn't seem to be run from common's git directory"
analyse_commits ()
{
# TODO: If we wanted to test "after PR merge", this needs to take some
# argument specifying how long we should look in the commit history.
git merge-base --is-ancestor "$MERGE_INTO" HEAD \
|| die "Please rebase the commit '$(git rev-parse --short HEAD)'" \
"to allow --ff merge into '$MERGE_INTO' branch"
while read line; do
case $line in
Required-by:\ *)
set -- $line
old_IFS=$IFS
IFS=\#
set -- $2
IFS=$old_IFS
set -- $1 $2
info "PR commits ask for testing $1 from PR $2"
IMAGES[$1]=$2
;;
esac
done < <(git log --format=%B --reverse "$MERGE_INTO"..HEAD)
}
analyse_commits
for image in "${!IMAGES[@]}"; do
# We don't want to remove user's WIP stuff.
test -e "$image" && die "directory '$image' exists"
( set -e
testdir=$PWD
cleanup () {
set -x
# Ensure the cleanup finishes!
trap '' INT
# Go back, wherever we are.
cd "$testdir"
# Try to cleanup, if available (and if needed).
make clean -C "$image" || :
# Drop the image sources.
test ! -d "$image" || rm -rf "$image"
}
trap cleanup EXIT
info "Testing $image image"
# Use --recursive even if we remove 'common', because there might be
# other git submodules which need to be tested.
git clone --recursive -q https://github.com/sclorg/"$image".git
cd "$image"
revision=${IMAGES[$image]}
if ! test "$revision" = master; then
info "Fetching $image PR $revision"
git fetch origin "pull/$revision/head":PR_BRANCH
git checkout PR_BRANCH
git submodule update
fi
# We fail if the 'common' directory doesn't exist.
test -d common
rm -rf common
info "Replacing common with PR's version"
ln -s ../ common
# TODO: Do we have to test all $(VERSION)s?
# TODO: The PS4 hack doesn't work if we run the testsuite as UID=0.
PS4="+ [$image] " make TARGET="$OS" test
# Cleanup.
make clean
)
if test $? -ne 0; then
die "Tests for $image failed"
fi
done

View file

@ -1 +0,0 @@
Dockerfile

View file

@ -1,24 +0,0 @@
#! /bin/sh
set -e
if grep -q "Red Hat Enterprise Linux release 8" /etc/system-release; then
# No use testing squash.py on rhel8 for now as it does not work at all
echo " ! test case ignored on RHEL8 host"
exit 0
fi
origin=busybox
squash=$(dirname "$(readlink -f "$0")")/../../squash.py
cd "$(dirname "$0")"
cat > Dockerfile <<EOF
FROM $origin
ENV test=test
CMD /bin/echo test
EOF
out=`docker build . | awk '/Successfully built/{print $NF}'`
echo "$out"
squashed=$("${PYTHON-python3}" "$squash" "$out" "$origin")
output=$(docker run --rm $squashed)
test "$output" = "test"

View file

@ -1,17 +0,0 @@
#!/bin/bash
set -e
. test-lib.sh
# This should succeed
if ! ct_check_image_availability docker.io/centos/postgresql-10-centos7; then
echo "image_availability test failed"
fi
# This should fail
if ct_check_image_availability docker.io/centos/postgresql-98-centos7; then
echo "image_availability test failed"
fi
echo "image_availability test completed successfully."

View file

@ -1,24 +0,0 @@
#! /bin/bash
set -e
. test-lib.sh
path='a b c:d x:y'
exp_output="==a b c==
==.==
==d x==
==.==
==y==
==.=="
wrap() { for arg; do echo "==$arg=="; done; }
test "$(ct_path_foreach "$path" wrap .)" == "$exp_output"
ct_path_append path '/a'
exp_output="==/a==
==.==
$exp_output"
test "$(ct_path_foreach "$path" wrap .)" == "$exp_output"

View file

@ -1,17 +0,0 @@
#!/bin/bash
set -e
. test-lib.sh
combinations="rhel7:registry.redhat.io/rhscl/postgresql-10-rhel7
centos7:docker.io/centos/postgresql-10-centos7
rhel8:registry.redhat.io/rhel8/postgresql-10
"
for c in $combinations; do
public_name=$(ct_get_public_image_name "${c%%:*}" postgresql 10)
[ "$public_name" == "${c#*:}" ]
done
echo "public_image_name test completed successfully."

View file

@ -1,17 +0,0 @@
#! /bin/bash
set -e
. test-lib.sh
x=$(ct_random_string)
test ${#x} -eq 10
for i in 5 9 11 13; do
x=$(ct_random_string $i)
test ${#x} -eq $i
done
# Even with ignored sigpipe we have to succeed promptly (#70).
trap '' SIGPIPE
x=$(ct_random_string 20)
test ${#x} -eq 20

View file

@ -1,16 +0,0 @@
#! /bin/bash
set -ex
. test-lib.sh
NPM_REGISTRY=""
output=$(ct_build_s2i_npm_variables)
test x"$output" == "x"
ca_file="/etc/pki/ca-trust/source/anchors/RH-IT-Root-CA.crt"
NPM_REGISTRY="https://foobar.registry.org"
if [ -f "$ca_file" ]; then
output=$(ct_build_s2i_npm_variables)
test x"$output" == "x-e NPM_MIRROR=$NPM_REGISTRY -v $ca_file:$ca_file:Z"
fi

View file

@ -1,72 +0,0 @@
#!/bin/bash
set -ex
shopt -s extglob
COMMIT=$(git rev-parse HEAD)
# import generated content from this git reference ..
SOURCE_BRANCH=${1:-$COMMIT}
# into this git branch
GENERATED_BRANCH=${2:-generated}
git clean -f -d
# switch to generated branch for working env; and switch back later
git checkout "$GENERATED_BRANCH"
git submodule update
# Clean everything in generated branch.
rm -rf -- *
srcdir=srcdir
cleanup ()
{
exit_status=$?
rm -rf "$srcdir"
# switch back to initial ranch
git checkout "$SOURCE_BRANCH"
git submodule update
return $exit_status
}
trap cleanup EXIT
(
# Copy the actual repo into $srcdir, and generate there
mkdir "$srcdir"
cd "$srcdir"
git clone .. .
git checkout "$SOURCE_BRANCH"
git submodule update --init
make generate-all
)
# copy the relevant (generated) content from $srcdir
versions=$(sed -n 's/^VERSIONS[[:space:]]*=//p' "$srcdir"/Makefile)
for i in $versions; do
cp -r "$srcdir/$i" .
done
# source directory is not needed anymore
rm -rf "$srcdir"
# shellcheck disable=SC2086
git add $versions
# Add deleted files to the index as well
(
IFS=$'\n'
for i in $(git ls-files --deleted) ;do
git add --all "$i"
done
)
if ! git diff --cached --exit-code --quiet ; then
git commit -m "auto-sync: master commit $COMMIT"
else
echo "Nothing changed"
fi

1
dead.package Normal file
View file

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

View file

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

View file

@ -1,247 +0,0 @@
.TH NodeJS 12 container image
.PP
This container image includes Node.JS 12 as a S2I
\[la]https://github.com/openshift/source-to-image\[ra] base image for your Node.JS 12 applications.
Users can choose between RHEL, CentOS and Fedora based images.
The RHEL images are available in the Red Hat Container Catalog
\[la]https://access.redhat.com/containers/\[ra],
the CentOS images are available on Podman Hub
\[la]https://hub.docker.com/r/centos/\[ra],
and the Fedora images are available in Fedora Registry
\[la]https://registry.fedoraproject.org/\[ra]\&.
The resulting image can be run using podman
\[la]https://github.com/containers/libpod\[ra]\&.
.PP
Note: while the examples in this README are calling \fB\fCpodman\fR, you can replace any such calls by \fB\fCdocker\fR with the same arguments
.SH Description
.PP
Node.js 12 available as container is a base platform for
building and running various Node.js 12 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.
.SH Usage
.PP
For this, we will assume that you are using the \fB\fCubi8/nodejs\-12 image\fR, available via \fB\fCnodejs:12\fR imagestream tag in Openshift.
Building a simple nodejs\-sample\-app
\[la]https://github.com/sclorg/s2i-nodejs-container/tree/master/12/test/test-app\[ra] application
in Openshift can be achieved with the following step:
.PP
.RS
.nf
```
oc new\-app nodejs:12\~https://github.com/sclorg/s2i\-nodejs\-container.git \-\-context\-dir=12/test/test\-app/
```
.fi
.RE
.PP
The same application can also be built using the standalone S2I
\[la]https://github.com/openshift/source-to-image\[ra] application on systems that have it available:
.PP
.RS
.nf
```
$ s2i build https://github.com/sclorg/s2i\-nodejs\-container.git \-\-context\-dir=12/test/test\-app/ ubi8/nodejs\-12 nodejs\-sample\-app
```
.fi
.RE
.PP
\fBAccessing the application:\fP
.PP
.RS
.nf
$ curl 127.0.0.1:8080
.fi
.RE
.SH Environment variables
.PP
Application developers can use the following environment variables to configure the runtime behavior of this image:
.PP
\fB\fB\fCNODE\_ENV\fR\fP
.br
NodeJS runtime mode (default: "production")
.PP
\fB\fB\fCDEV\_MODE\fR\fP
.br
When set to "true", \fB\fCnodemon\fR will be used to automatically reload the server while you work (default: "false"). Setting \fB\fCDEV\_MODE\fR to "true" will change the \fB\fCNODE\_ENV\fR default to "development" (if not explicitly set).
.PP
\fB\fB\fCNPM\_RUN\fR\fP
.br
Select an alternate / custom runtime mode, defined in your \fB\fCpackage.json\fR file's \fB\fCscripts\fR
\[la]https://docs.npmjs.com/misc/scripts\[ra] section (default: npm run "start"). These user\-defined run\-scripts are unavailable while \fB\fCDEV\_MODE\fR is in use.
.PP
\fB\fB\fCHTTP\_PROXY\fR\fP
.br
Use an npm proxy during assembly
.PP
\fB\fB\fCHTTPS\_PROXY\fR\fP
.br
Use an npm proxy during assembly
.PP
\fB\fB\fCNPM\_MIRROR\fR\fP
.br
Use a custom NPM registry mirror to download packages during the build process
.PP
One way to define a set of environment variables is to include them as key value pairs in your repo's \fB\fC\&.s2i/environment\fR file.
.PP
Example: DATABASE\_USER=sampleUser
.SS NOTE: Define your own "\fB\fCDEV\_MODE\fR":
.PP
The following \fB\fCpackage.json\fR example includes a \fB\fCscripts.dev\fR entry. You can define your own custom \fB\fCNPM\_RUN\fR
\[la]https://docs.npmjs.com/cli/run-script\[ra] scripts in your application's \fB\fCpackage.json\fR file.
.SS Note: Setting logging output verbosity
.PP
To alter the level of logs output during an \fB\fCnpm install\fR the npm\_config\_loglevel environment variable can be set. See npm\-config
\[la]https://docs.npmjs.com/misc/config\[ra]\&.
.SH Development Mode
.PP
This image supports development mode. This mode can be switched on and off with the environment variable \fB\fCDEV\_MODE\fR\&. \fB\fCDEV\_MODE\fR can either be set to \fB\fCtrue\fR or \fB\fCfalse\fR\&.
Development mode supports two features:
* Hot Deploy
* Debugging
.PP
The debug port can be specified with the environment variable \fB\fCDEBUG\_PORT\fR\&. \fB\fCDEBUG\_PORT\fR is only valid if \fB\fCDEV\_MODE=true\fR\&.
.PP
A simple example command for running the container in development mode is:
.PP
.RS
.nf
podman run \-\-env DEV\_MODE=true my\-image\-id
.fi
.RE
.PP
To run the container in development mode with a debug port of 5454, run:
.PP
.RS
.nf
$ podman run \-\-env DEV\_MODE=true DEBUG\_PORT=5454 my\-image\-id
.fi
.RE
.PP
To run the container in production mode, run:
.PP
.RS
.nf
$ podman run \-\-env DEV\_MODE=false my\-image\-id
.fi
.RE
.PP
By default, \fB\fCDEV\_MODE\fR is set to \fB\fCfalse\fR, and \fB\fCDEBUG\_PORT\fR is set to \fB\fC5858\fR, however the \fB\fCDEBUG\_PORT\fR is only relevant if \fB\fCDEV\_MODE=true\fR\&.
.SH Hot deploy
.PP
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.
.SS Using Podman's exec
.PP
To change your source code in a running container, use Podman's exec
\[la]https://github.com/containers/libpod\[ra] command:
.PP
.RS
.nf
$ podman exec \-it <CONTAINER\_ID> /bin/bash
.fi
.RE
.PP
After you Podman exec
\[la]https://github.com/containers/libpod\[ra] into the running container, your current directory is set to \fB\fC/opt/app\-root/src\fR, where the source code for your application is located.
.SS Using OpenShift's rsync
.PP
If you have deployed the container to OpenShift, you can use oc rsync
\[la]https://docs.openshift.org/latest/dev_guide/copy_files_to_container.html\[ra] to copy local files to a remote container running in an OpenShift pod.
.SS Warning:
.PP
The default behaviour of the s2i\-nodejs container image is to run the Node.js application using the command \fB\fCnpm start\fR\&. This runs the \fIstart\fP script in the \fIpackage.json\fP file. In developer mode, the application is run using the command \fB\fCnodemon\fR\&. The default behaviour of nodemon is to look for the \fImain\fP attribute in the \fIpackage.json\fP file, and execute that script. If the \fImain\fP attribute doesn't appear in the \fIpackage.json\fP file, it executes the \fIstart\fP script. So, in order to achieve some sort of uniform functionality between production and development modes, the user should remove the \fImain\fP attribute.
.PP
Below is an example \fIpackage.json\fP file with the \fImain\fP attribute and \fIstart\fP script marked appropriately:
.PP
.RS
.nf
{
"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": "",
}
.fi
.RE
.SS Note:
.PP
\fB\fCoc rsync\fR is only available in versions 3.1+ of OpenShift.
.SH See also
.PP
Dockerfile and other sources are available on
\[la]https://github.com/sclorg/s2i-nodejs-container\[ra]\&.
In that repository you also can find another versions of Python environment Dockerfiles.
Dockerfile for CentOS is called \fB\fCDockerfile\fR, Dockerfile for RHEL7 is called \fB\fCDockerfile.rhel7\fR,
for RHEL8 it's \fB\fCDockerfile.rhel8\fR and the Fedora Dockerfile is called Dockerfile.fedora.

View file

@ -1,17 +0,0 @@
# 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

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

View file

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

View file

@ -1,116 +0,0 @@
#!/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
# 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
NPM_TMP=$(npm config get tmp)
if ! mountpoint $NPM_TMP; then
echo "---> Cleaning the $NPM_TMP/npm-*"
rm -rf $NPM_TMP/npm-*
fi
fi
# Fix source directory permissions
fix-permissions ./

View file

@ -1,60 +0,0 @@
#!/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

View file

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

View file

@ -1,15 +0,0 @@
#!/bin/sh
DISTRO=`cat /etc/*-release | grep ^ID= | grep -Po '".*?"' | tr -d '"'`
cat <<EOF
This is a S2I nodejs-8 ${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=8/test/test-app/ ${NAMESPACE}/nodejs-8-${DISTRO}7 nodejs-sample-app
You can then run the resulting image via:
podman run -p 8080:8080 nodejs-sample-app
EOF

444
test/run
View file

@ -1,444 +0,0 @@
#!/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.
#
# EXPRESS_REVISION specifies which express.js branch or tag should be tested;
# by default it uses the latest released version as reported by
# `npm show express version`.
THISDIR=$(dirname ${BASH_SOURCE[0]})
source "${THISDIR}/test-lib.sh"
test -n $IMAGE_NAME \
-a -n $VERSION
readonly EXPRESS_REVISION="${EXPRESS_REVISION:-$(docker run --rm "${IMAGE_NAME}" -- npm show express version)}"
test_dir="$(readlink -f $(dirname ${BASH_SOURCE[0]}))"
image_dir="$(readlink -f ${test_dir}/..)"
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"
)
info() {
echo -e "\n\e[1m[INFO] $@...\e[0m\n"
}
if [ "$DEBUG" != "" ]; then
set -x
fi
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_express() {
ct_s2i_build_as_df \
"file://${test_dir}/express.js" "${IMAGE_NAME}" "${IMAGE_NAME}-express" \
${s2i_args} \
$(ct_build_s2i_npm_variables) -e NODE_ENV=development
}
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_express_repo() {
git clone \
--config advice.detachedHead="false" \
--branch "${EXPRESS_REVISION}" --depth 1 \
'https://github.com/expressjs/express.git' "$1"
pushd "$1" >/dev/null || return
for key in "${!gitconfig[@]}"; do
git config --local "$key" "${gitconfig[$key]}"
done
popd "$1" >/dev/null || return
}
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)
pushd "${test_dir}/test-${1}" >/dev/null
prepare_dummy_git_repo
popd >/dev/null
;;
express)
prepare_express_repo "${test_dir}/express.js"
;;
*)
echo "Please specify a valid test application"
exit 1
;;
esac
}
run_test_application() {
if [[ $1 == app ]]; then
docker run --user=100001 $(ct_mount_ca_file) --rm --cidfile=${cid_file} $2 ${IMAGE_NAME}-testapp
elif [[ $1 == hw ]]; then
docker run --user=100001 $(ct_mount_ca_file) --rm --cidfile=${cid_file} $2 ${IMAGE_NAME}-testhw
else
echo "No such test application"
exit 1
fi
}
run_express_test_suite() {
docker run --user=100001 $(ct_mount_ca_file) --rm --cidfile=${cid_file} ${IMAGE_NAME}-express 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}; do
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}/express.js"
}
check_result() {
local result="$1"
if [[ "$result" != "0" ]]; then
echo "S2I image '${IMAGE_NAME}' test FAILED (exit code: ${result})"
cleanup
exit $result
fi
}
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
}
test_docker_run_usage() {
echo "Testing 'docker run' usage..."
docker run --rm ${IMAGE_NAME} &>/dev/null
}
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
}
test_scl_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
}
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
}
# 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 $?
# 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 $?
# 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
test_scl_usage "node --version" "v$VERSION."
check_result $?
test_connection
check_result $?
# 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 $?
# 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 $?
# 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 $?
kill_test_application
test_dev_mode app false production
test_dev_mode app true development
echo "Testing the development image build: s2i build -e \"NODE_ENV=development\")"
run_s2i_build "-e NODE_ENV=development"
check_result $?
# Verify that the HTTP connection can be established to test application container
run_test_application app &
wait_for_cid
test_connection
check_result $?
# Test that the development dependencies (nodemon) have NOT been removed
devdep=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "test -d ~/node_modules/nodemon")
check_result $?
# Test that the npm cache has NOT been cleared
devdep=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "test -d \$(npm config get cache)")
check_result $?
kill_test_application
test_dev_mode app true development
test_dev_mode app false development
echo "Testing the development image build: s2i build -e \"DEV_MODE=true\")"
run_s2i_build "-e DEV_MODE=true"
check_result $?
# Verify that the HTTP connection can be established to test application container
run_test_application app &
wait_for_cid
test_connection
check_result $?
# Test that the development dependencies (nodemon) have NOT been removed
devdep=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "test -d ~/node_modules/nodemon")
check_result $?
# Test that the npm cache has NOT been cleared
devdep=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "test -d \$(npm config get cache)")
check_result $?
kill_test_application
test_dev_mode app true development
test_dev_mode app false production
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
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
run_test_application hw &
wait_for_cid
kill_test_application
echo "Testing incremental build"
test_incremental_build
echo "Testing npm availability"
ct_npm_works
check_result $?
echo "Running express.js test suite"
prepare express
run_s2i_build_express; check_result $?
run_express_test_suite; check_result $?
echo "Success!"
cleanup

View file

@ -1,35 +0,0 @@
#!/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"
# change the branch to a different value if a new change in the example
# app needs to be tested
BRANCH_TO_TEST=master
set -eo nounset
test -n "${IMAGE_NAME-}" || false 'make sure $IMAGE_NAME is defined'
test -n "${VERSION-}" || false 'make sure $VERSION is defined'
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

View file

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

View file

@ -1,27 +0,0 @@
# 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

@ -1,32 +0,0 @@
{
"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"
}

View file

@ -1,50 +0,0 @@
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

@ -1,17 +0,0 @@
<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>

View file

@ -1,11 +0,0 @@
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

@ -1,14 +0,0 @@
{
"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

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

View file

@ -1,27 +0,0 @@
# 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

@ -1,33 +0,0 @@
{
"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

@ -1,50 +0,0 @@
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

@ -1,17 +0,0 @@
<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>

View file

@ -1 +0,0 @@
../common/test-lib-openshift.sh

View file

@ -1 +0,0 @@
../common/test-lib.sh