Merge pull request #340 from zmiklank/exit_oc_tests_if_login_fails

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

108
test/check_imagestreams.py Executable file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

156
test/run Executable file
View file

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

60
test/run-openshift Executable file
View file

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

View file

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

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

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

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

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

View file

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

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

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

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

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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

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

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

File diff suppressed because it is too large Load diff

View file

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

1201
test/test-lib.sh Normal file

File diff suppressed because it is too large Load diff

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

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