Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 2.4-micro/test/run-pytest
1 change: 1 addition & 0 deletions 2.4-micro/test/settings.py
1 change: 1 addition & 0 deletions 2.4-micro/test/test_container_httpd.py
1 change: 1 addition & 0 deletions 2.4-micro/test/test_container_httpd_s2i.py
1 change: 0 additions & 1 deletion 2.4-micro/test/test_httpd_ex_template.py

This file was deleted.

1 change: 0 additions & 1 deletion 2.4-micro/test/test_httpd_imagestream_s2i.py

This file was deleted.

1 change: 0 additions & 1 deletion 2.4-micro/test/test_httpd_imagestreams.py

This file was deleted.

1 change: 0 additions & 1 deletion 2.4-micro/test/test_httpd_integration.py

This file was deleted.

1 change: 0 additions & 1 deletion 2.4-micro/test/test_httpd_shared_helm_imagestreams.py

This file was deleted.

1 change: 0 additions & 1 deletion 2.4-micro/test/test_httpd_shared_helm_template.py

This file was deleted.

1 change: 1 addition & 0 deletions 2.4-micro/test/test_ocp_ex_template.py
1 change: 1 addition & 0 deletions 2.4-micro/test/test_ocp_imagestream_s2i.py
1 change: 1 addition & 0 deletions 2.4-micro/test/test_ocp_imagestreams.py
1 change: 1 addition & 0 deletions 2.4-micro/test/test_ocp_integration.py
1 change: 1 addition & 0 deletions 2.4-micro/test/test_ocp_shared_helm_imagestreams.py
1 change: 1 addition & 0 deletions 2.4-micro/test/test_ocp_shared_helm_template.py
1 change: 1 addition & 0 deletions 2.4/test/run-pytest
1 change: 1 addition & 0 deletions 2.4/test/settings.py
1 change: 1 addition & 0 deletions 2.4/test/test_container_httpd.py
1 change: 1 addition & 0 deletions 2.4/test/test_container_httpd_s2i.py
1 change: 0 additions & 1 deletion 2.4/test/test_httpd_ex_template.py

This file was deleted.

1 change: 0 additions & 1 deletion 2.4/test/test_httpd_imagestream_s2i.py

This file was deleted.

1 change: 0 additions & 1 deletion 2.4/test/test_httpd_imagestreams.py

This file was deleted.

1 change: 0 additions & 1 deletion 2.4/test/test_httpd_integration.py

This file was deleted.

1 change: 0 additions & 1 deletion 2.4/test/test_httpd_shared_helm_imagestreams.py

This file was deleted.

1 change: 0 additions & 1 deletion 2.4/test/test_httpd_shared_helm_template.py

This file was deleted.

1 change: 1 addition & 0 deletions 2.4/test/test_ocp_ex_template.py
1 change: 1 addition & 0 deletions 2.4/test/test_ocp_imagestream_s2i.py
1 change: 1 addition & 0 deletions 2.4/test/test_ocp_imagestreams.py
1 change: 1 addition & 0 deletions 2.4/test/test_ocp_integration.py
1 change: 1 addition & 0 deletions 2.4/test/test_ocp_shared_helm_imagestreams.py
1 change: 1 addition & 0 deletions 2.4/test/test_ocp_shared_helm_template.py
15 changes: 15 additions & 0 deletions test/run-pytest
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
#
# IMAGE_NAME specifies a name of the candidate image used for testing.
# The image has to be available before this script is executed.
# SINGLE_VERSION specifies the major version of httpd
# OS specifies RHEL version (e.g. OS=rhel8)
#

THISDIR=$(dirname ${BASH_SOURCE[0]})

PYTHON_VERSION="3.12"
if [[ ! -f "/usr/bin/python$PYTHON_VERSION" ]]; then
PYTHON_VERSION="3.13"
fi
cd "${THISDIR}" && "python${PYTHON_VERSION}" -m pytest -s -rA --showlocals -vv test_container_*.py
9 changes: 9 additions & 0 deletions test/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import os

from pathlib import Path


VERSION = os.getenv("VERSION")
OS = os.getenv("OS").lower()
IMAGE_NAME = os.getenv("IMAGE_NAME")
TEST_DIR = Path(__file__).parent.absolute()
116 changes: 116 additions & 0 deletions test/test_container_httpd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import re
import tempfile

import pytest

from container_ci_suite.container_lib import ContainerTestLib
from container_ci_suite.utils import ContainerTestLibUtils

from settings import IMAGE_NAME, TEST_DIR


class TestHttpdAppContainer:

def setup_method(self):
self.app = ContainerTestLib(image_name=IMAGE_NAME, s2i_image=True)

def teardown_method(self):
self.app.cleanup()

@pytest.mark.parametrize(
"container_arg",
[
"",
"--user 0"
]
)
def test_default_page(self, container_arg):
assert self.app.create_container(cid_file_name="test_default_page", container_args=container_arg)
cip = self.app.get_cip("test_default_page")
assert cip
response = "HTTP Server"
assert self.app.test_response(url=cip, expected_code=403, expected_output=response, max_attempts=3)

def test_run_s2i_usage(self):
output = self.app.s2i_usage()
assert output

@pytest.mark.parametrize(
"dockerfile",
[
"Dockerfile",
"Dockerfile.s2i"
]
)
def test_dockerfiles(self, dockerfile):
assert self.app.build_test_container(
dockerfile=TEST_DIR / "examples" / dockerfile, app_url="https://github.com/sclorg/httpd-ex.git",
app_dir="app-src"
)
assert self.app.test_app_dockerfile()
cip = self.app.get_cip()
assert cip
assert self.app.test_response(url=cip, expected_code=200, expected_output="Welcome to your static httpd application on OpenShift")

@pytest.mark.parametrize(
"mpm_config",
[
"worker",
"event",
"prefork",
]
)
def test_mpm_config(self, mpm_config):
cid_name = f"test_mpm_{mpm_config}"
assert self.app.create_container(cid_file_name=cid_name, container_args=f"-e HTTPD_MPM={mpm_config} --user 1001")
cip = self.app.get_cip(cid_file_name=cid_name)
# Let's check that server really response HTTP-403
# See function here: in test/run `_run_mpm_config_test`
# https://github.com/sclorg/httpd-container/blob/master/test/run#L97
assert self.app.test_response(url=cip, port=8080, expected_code=403)
logs = self.app.get_logs(cid_file_name=cid_name)
assert re.search(f"mpm_{mpm_config}:notice.*resuming normal operations", logs)


def test_log_to_data_volume(self):
data_dir = tempfile.mkdtemp(prefix="/tmp/httpd-test_log_dir")
ContainerTestLibUtils.commands_to_run(
commands_to_run = [
f"mkdir -p {data_dir}",
f"chown -R 1001:1001 {data_dir}",
f"chcon -Rvt svirt_sandbox_file_t {data_dir}/"
]
)
assert self.app.create_container(
cid_file_name="test_log_dir",
container_args=f"-e HTTPD_LOG_TO_VOLUME=1 --user 0 -v {data_dir}:/var/log/httpd"
)
cip = self.app.get_cip(cid_file_name="test_log_dir")
assert self.app.test_response(url=cip, port=8080, expected_code=403)
assert ContainerTestLibUtils.check_files_are_present(
dir_name=data_dir, file_name_to_check=[
"access_log",
"error_log",
"ssl_access_log",
"ssl_error_log",
"ssl_request_log",
]
)

def test_data_volume(self):
data_dir = tempfile.mkdtemp(prefix="/tmp/httpd-test-volume")
ContainerTestLibUtils.commands_to_run(
commands_to_run = [
f"mkdir -p {data_dir}/html",
f"echo hello > {data_dir}/html/index.html",
f"chown -R 1001:1001 {data_dir}",
f"chcon -Rvt svirt_sandbox_file_t {data_dir}/"
]
)
assert self.app.create_container(
cid_file_name="doc_root",
container_args=f"-v {data_dir}:/var/www"
)
cip = self.app.get_cip(cid_file_name="doc_root")
assert cip
assert self.app.test_response(url=cip, port=8080, expected_code=200, expected_output="hello")
150 changes: 150 additions & 0 deletions test/test_container_httpd_s2i.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import time
import tempfile

from pathlib import Path

from container_ci_suite.container_lib import ContainerTestLib
from container_ci_suite.utils import ContainerTestLibUtils
from container_ci_suite.engines.podman_wrapper import PodmanCLIWrapper

from settings import IMAGE_NAME, TEST_DIR

pre_init_test_app = TEST_DIR / "pre-init-test-app"
sample_test_app = TEST_DIR / "sample-test-app"
self_cert_test = TEST_DIR / "self-signed-ssl"


def build_s2i_app(app_path: Path) -> ContainerTestLib:
container_lib = ContainerTestLib(IMAGE_NAME)
app_name = app_path.name
s2i_app = container_lib.build_as_df(
app_path=app_path,
s2i_args="--pull-policy=never",
src_image=IMAGE_NAME,
dst_image=f"{IMAGE_NAME}-{app_name}"
)
return s2i_app


class TestHttpdS2IPreInitContainer:

def setup_method(self):
self.s2i_app = build_s2i_app(pre_init_test_app)

def teardown_method(self):
self.s2i_app.cleanup()

def test_run_pre_init_test(self):
assert self.s2i_app.create_container(cid_file_name=self.s2i_app.app_name, container_args="--user 1000")
cip = self.s2i_app.get_cip(cid_file_name=self.s2i_app.app_name)
assert cip
assert self.s2i_app.test_response(
url=cip,
expected_code=200,
expected_output="This content was replaced by pre-init script."
)


class TestHttpdS2ISampleAppContainer:

def setup_method(self):
self.s2i_app = build_s2i_app(sample_test_app)

def teardown_method(self):
self.s2i_app.cleanup()

def test_sample_app(self):
assert self.s2i_app.create_container(cid_file_name=self.s2i_app.app_name, container_args="--user 1000")
cip = self.s2i_app.get_cip(cid_file_name=self.s2i_app.app_name)
assert cip
response = "This is a sample s2i application with static content."
assert self.s2i_app.test_response(
url=cip,
expected_code=200,
expected_output=response
)
assert self.s2i_app.test_response(
url=f"https://{cip}",
port=8443,
expected_output=response
)


class TestHttpdCertAgeContainer:

def setup_method(self):
self.s2i_app = build_s2i_app(sample_test_app)

def teardown_method(self):
self.s2i_app.cleanup()

def test_cert_age(self):
"""
We need to make sure the certificate is generated no sooner than in assemble phase,
because shipping the same certs in the image would make it easy to exploit
Let's see how old the certificate is and compare with how old the image is
"""
assert self.s2i_app.create_container(cid_file_name=self.s2i_app.app_name, container_args="--user 1000")
image_age_s = PodmanCLIWrapper.podman_inspect(
field="{{.Created}}", src_image=IMAGE_NAME
).strip().split(' ')
image_age = time.time() - float(ContainerTestLibUtils.run_command(
cmd=f"date -d '{image_age_s[0]} {image_age_s[1]} {image_age_s[2]}' '+%s'"
))
cid = self.s2i_app.get_cid(self.s2i_app.app_name)
# Testing of not presence of a certificate in the production image
certificate_content = PodmanCLIWrapper.podman_exec_shell_command(
cid_file_name=cid, cmd="cat \\$HTTPD_TLS_CERT_PATH/localhost.crt"
)
assert certificate_content
certificate_dir = tempfile.mkdtemp(prefix="/tmp/cert_dir")
with open(Path(certificate_dir) / "cert", mode="w") as f:
f.write(certificate_content.strip())
certificate_age_s = ContainerTestLibUtils.run_command(
cmd=f"openssl x509 -startdate -noout -in {Path(certificate_dir)}/cert"
).strip().replace("notBefore=", "")
certificate_age = time.time() - float(ContainerTestLibUtils.run_command(
cmd=f"date '+%s' --date='{certificate_age_s}'")
)
# Testing whether the certificate was freshly generated after the image
assert certificate_age < image_age
# Testing presence and permissions of the generated certificate
assert PodmanCLIWrapper.podman_exec_shell_command(
cid_file_name=cid, cmd="ls -l \\$HTTPD_TLS_CERT_PATH/localhost.crt"
)
# Testing presence and permissions of the generated certificate
assert PodmanCLIWrapper.podman_exec_shell_command(
cid_file_name=cid, cmd="ls -l \\$HTTPD_TLS_CERT_PATH/localhost.key"
)

class TestHttpdS2ISslSelfSignedAppContainer:

def setup_method(self):
self.s2i_app = build_s2i_app(self_cert_test)

def teardown_method(self):
self.s2i_app.cleanup()

def test_self_cert_test(self):
"""
Test s2i use case #3 - using own ssl certs
Since we built the candidate image locally, we don't want S2I attempt to pull
it from Docker hub
"""
self.s2i_app.set_new_image(image_name=f"{IMAGE_NAME}-{self.s2i_app.app_name}")
assert self.s2i_app.create_container(cid_file_name=self.s2i_app.app_name, container_args="--user 1000")
cip = self.s2i_app.get_cip(cid_file_name=self.s2i_app.app_name)
assert cip
assert self.s2i_app.test_response(url=cip, expected_code=200, expected_output="SSL test works")
assert self.s2i_app.test_response(url=f"https://{cip}", port=8443, expected_output="SSL test works")
server_cmd = f"openssl s_client -showcerts -servername {cip} -connect {cip}:8443 2>/dev/null"
server_output = ContainerTestLibUtils.run_command(cmd=server_cmd)
certificate_dir = tempfile.mkdtemp(prefix="/tmp/server_cert_dir")
with open(Path(certificate_dir) / "output", mode="wt+") as f:
f.write(server_output)
server_cert = ContainerTestLibUtils.run_command(
cmd=f"openssl x509 -inform pem -noout -text -in {Path(certificate_dir)}/output"
)
config_cmd = f"openssl x509 -in {TEST_DIR}/{self.s2i_app.app_name}/httpd-ssl/certs/server-cert-selfsigned.pem -inform pem -noout -text"
config_cert = ContainerTestLibUtils.run_command(cmd=config_cmd)
assert server_cert == config_cert
Loading