-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding Test Capability for Docker images (#227)
Add a framework for running tests on each individual docker image.
- Loading branch information
Showing
43 changed files
with
1,085 additions
and
36 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,8 @@ | |
{%- set docker_version = '20.10.11' -%} | ||
--- | ||
version: 2.1 | ||
orbs: | ||
python: circleci/[email protected] | ||
workflows: | ||
version: 2.1 | ||
vendor-build: | ||
|
@@ -16,11 +18,18 @@ workflows: | |
requires: | ||
- approve-{{ directory }} | ||
- run_pre_commit | ||
- test: | ||
name: test-{{ directory }} | ||
directory: {{ directory }} | ||
test_script: bin/test.py | ||
test_requirements: requirements/test-requirements.txt | ||
requires: | ||
- build-{{ directory }} | ||
- scan-trivy: | ||
name: scan-trivy-{{ directory }} | ||
directory: {{ directory }} | ||
requires: | ||
- build-{{ directory }} | ||
- test-{{ directory }} | ||
- release: | ||
name: release-{{ directory }} | ||
directory: {{ directory }} | ||
|
@@ -69,6 +78,25 @@ jobs: | |
image_name: ap-<< parameters.directory >> | ||
dockerfile: Dockerfile | ||
path: << parameters.directory >> | ||
test: | ||
executor: docker-executor | ||
description: "Test the docker image" | ||
parameters: | ||
directory: | ||
description: "The directory of the image to build" | ||
type: string | ||
test_script: | ||
description: "The pytest test script" | ||
type: string | ||
test_requirements: | ||
description: "The python requirement file." | ||
type: string | ||
steps: | ||
- docker-test: | ||
image_name: ap-<< parameters.directory >> | ||
path: << parameters.directory >> | ||
test_script: << parameters.test_script >> | ||
test_requirements: << parameters.test_requirements >> | ||
scan-trivy: | ||
docker: | ||
- image: docker:{{ docker_version }}-git | ||
|
@@ -159,6 +187,47 @@ commands: | |
root: . | ||
paths: | ||
- "./*.tar" | ||
docker-test: | ||
description: "Test a Docker image" | ||
parameters: | ||
path: | ||
type: string | ||
default: "." | ||
image_name: | ||
type: string | ||
default: $CIRCLE_PROJECT_REPONAME | ||
test_script: | ||
type: string | ||
default: bin/test.py | ||
test_requirements: | ||
type: string | ||
default: requirements/test-requirements.txt | ||
steps: | ||
- checkout | ||
- python/install-packages: | ||
pip-dependency-file: << parameters.test_requirements >> | ||
pkg-manager: pip | ||
- setup_remote_docker: | ||
docker_layer_caching: true | ||
version: {{ docker_version }} | ||
- attach_workspace: | ||
at: /tmp/workspace | ||
- run: | ||
name: Load archived Docker image | ||
command: | | ||
set -x | ||
docker load -i /tmp/workspace/<< parameters.image_name >>.tar | ||
docker images | grep << parameters.image_name >> | ||
- run: | ||
name: Run Docker image test | ||
environment: | ||
ASTRO_IMAGE_NAME: << parameters.image_name >> | ||
ASTRO_IMAGE_TEST_CONFIG_PATH: << parameters.path >>/test.yaml | ||
command: | | ||
mkdir test-results | ||
pytest -v --junitxml=test-results/junit.xml << parameters.test_script>> | ||
- store_test_results: | ||
path: test-results | ||
push-to-quay-io: | ||
description: "Push a Docker image to Quay.io" | ||
parameters: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
tests: | ||
root_user_test: True | ||
default_user: nobody | ||
users_config: | ||
- name: nobody | ||
group: nobody | ||
gid: 65534 | ||
uid: 65534 | ||
http_services_running: | ||
- port: 9093 | ||
response_code: 200 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
tests: | ||
root_user_test: True | ||
default_user: nginx | ||
users_config: | ||
- name: nginx | ||
group: nginx | ||
gid: 101 | ||
uid: 101 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
tests: | ||
root_user_test: True | ||
default_user: nobody | ||
users_config: | ||
- name: nobody | ||
group: nobody |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import os | ||
import subprocess | ||
|
||
import pytest | ||
import testinfra | ||
import yaml | ||
|
||
ASTRO_IMAGE_NAME = os.environ["ASTRO_IMAGE_NAME"] | ||
ASTRO_IMAGE_TEST_CONFIG_PATH = os.environ["ASTRO_IMAGE_TEST_CONFIG_PATH"] | ||
|
||
os.environ["ASTRO_IMAGE_TAG"] = os.environ.get("CIRCLE_SHA1", "latest") | ||
test_config = {} | ||
|
||
# Read the test config | ||
if os.path.exists(ASTRO_IMAGE_TEST_CONFIG_PATH): | ||
with open(ASTRO_IMAGE_TEST_CONFIG_PATH) as file: | ||
config = yaml.safe_load(file) | ||
|
||
# Reading test config | ||
if config is not None and "tests" in config: | ||
test_config = config["tests"] | ||
|
||
|
||
@pytest.fixture(scope="session") | ||
def docker_host(request): | ||
run_command = ["docker-compose", "run", "-d", ASTRO_IMAGE_NAME] | ||
|
||
# run a container | ||
docker_id = subprocess.check_output(run_command).decode().strip() | ||
|
||
# return a testinfra connection to the container | ||
yield testinfra.get_host("docker://" + docker_id) | ||
# cleanup container after test completion | ||
subprocess.check_call(["docker", "rm", "-f", docker_id]) | ||
|
||
|
||
@pytest.mark.skipif( | ||
"root_user_test" not in test_config or test_config["root_user_test"] == False, | ||
reason="Config `root_user_test` is not set in `test.yaml`.", | ||
) | ||
def test_no_root_user(docker_host): | ||
user_info = docker_host.user() | ||
assert user_info.name != "root" | ||
assert user_info.group != "root" | ||
assert user_info.gid != 0 | ||
assert user_info.uid != 0 | ||
|
||
|
||
@pytest.mark.skipif( | ||
"default_user" not in test_config, | ||
reason="Config `default_user` is not set in `test.yaml`.", | ||
) | ||
def test_default_user(docker_host): | ||
if "default_user" in test_config: | ||
"""Ensure default user""" | ||
user = docker_host.check_output("whoami") | ||
assert ( | ||
user == test_config["default_user"] | ||
), f"Expected container to be running as 'nobody', not '{user}'" | ||
|
||
|
||
@pytest.mark.skipif( | ||
"users_config" not in test_config, | ||
reason="Config `users_config` is not set in `test.yaml`.", | ||
) | ||
def test_user_config(docker_host): | ||
if "users_config" in test_config: | ||
|
||
for user_config in test_config["users_config"]: | ||
|
||
user_info = docker_host.user(user_config["name"]) | ||
|
||
if "group" in user_config: | ||
assert user_info.group == user_config["group"] | ||
|
||
if "gid" in user_config: | ||
assert user_info.gid == user_config["gid"] | ||
|
||
if "uid" in user_config: | ||
assert user_info.uid == user_config["uid"] | ||
|
||
|
||
@pytest.mark.skipif( | ||
"http_services_running" not in test_config, | ||
reason="Config `http_services_running` is not set in `test.yaml`.", | ||
) | ||
def test_http_service_running(docker_host): | ||
if "http_services_running" in test_config: | ||
|
||
for service_config in test_config["http_services_running"]: | ||
"""Ensure user is 'nobody'""" | ||
output = docker_host.check_output( | ||
"wget --spider -S http://0.0.0.0:" | ||
+ str(service_config["port"]) | ||
+ " 2>&1 | grep 'HTTP/' | awk '{print $2}'" | ||
) | ||
assert output == str(service_config["response_code"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
tests: | ||
root_user_test: True | ||
default_user: blackbox-exporter | ||
users_config: | ||
- name: blackbox-exporter | ||
group: blackbox-exporter | ||
gid: 1000 | ||
uid: 1000 | ||
http_services_running: | ||
- port: 9115 | ||
response_code: 200 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
tests: | ||
root_user_test: True | ||
default_user: nobody | ||
users_config: | ||
- name: nobody | ||
group: nobody | ||
gid: 65534 | ||
uid: 65534 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
tests: | ||
root_user_test: True | ||
default_user: nobody | ||
users_config: | ||
- name: nobody | ||
group: nobody | ||
gid: 65534 | ||
uid: 65534 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
tests: | ||
root_user_test: False | ||
default_user: root | ||
users_config: | ||
- name: root | ||
group: root | ||
gid: 0 | ||
uid: 0 |
Oops, something went wrong.