From 6b5332be476032a637a1d4db1a7d614acbf5b199 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 24 Jul 2023 18:03:13 +0100 Subject: [PATCH 1/5] - Change test dockerfile base to alpine, too (Alpine all the things!) - Tweak build-and-test.sh to allow tests to run against more platforms using buildx - Split GHA out into two seperate files. One for tests on pull requests, another for build and merge on push to `development-v6` (add other branches in later) Signed-off-by: Adam Warner --- ...st-and-build.yml => build-and-publish.yml} | 13 +++----- .github/workflows/build-and-test.yml | 30 +++++++++++++++++++ build-and-test.sh | 3 +- test/Dockerfile | 14 +++------ test/cmd.sh | 4 +-- 5 files changed, 42 insertions(+), 22 deletions(-) rename .github/workflows/{test-and-build.yml => build-and-publish.yml} (92%) create mode 100644 .github/workflows/build-and-test.yml diff --git a/.github/workflows/test-and-build.yml b/.github/workflows/build-and-publish.yml similarity index 92% rename from .github/workflows/test-and-build.yml rename to .github/workflows/build-and-publish.yml index 31ceb26ca..8e6aeb757 100644 --- a/.github/workflows/test-and-build.yml +++ b/.github/workflows/build-and-publish.yml @@ -5,14 +5,13 @@ on: push: branches: - development-v6 - pull_request: env: dockerhub: ${{ secrets.DOCKERHUB_NAMESPACE }}/pihole ghcr: ghcr.io/${{ github.repository_owner }}/pihole jobs: - build-and-test: + build: runs-on: ubuntu-latest strategy: fail-fast: false @@ -30,8 +29,6 @@ jobs: steps: - name: Checkout Repo uses: actions/checkout@v3 - with: - ref: development-v6 - name: Docker meta (Docker Hub and GitHub Container Registry) id: meta @@ -46,7 +43,6 @@ jobs: development-v6 - name: Login to DockerHub and GitHub Container Registry - if: github.event_name != 'pull_request' uses: ./.github/actions/login-repo with: docker_username: ${{ secrets.DOCKERHUB_USER }} @@ -57,7 +53,7 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v2 with: - platforms: all + platforms: ${{ matrix.platform}} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 @@ -72,7 +68,7 @@ jobs: CONTAINER=${{ matrix.container }} labels: ${{ steps.meta.outputs.labels }} outputs: | - type=image,name=${{ env[matrix.registry] }},push-by-digest=${{ github.event_name != 'pull_request' }},name-canonical=true,push=${{ github.event_name != 'pull_request' }} + type=image,name=${{ env[matrix.registry] }},push-by-digest=true,name-canonical=true,push=true - name: Export digests run: | @@ -92,14 +88,13 @@ jobs: # If we would push immediately above, the individual runners would overwrite each other's images # https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners merge-and-deploy: - if: github.event_name != 'pull_request' strategy: fail-fast: false matrix: registry: [dockerhub, ghcr] runs-on: ubuntu-latest needs: - - build-and-test + - build steps: - name: Checkout Repo uses: actions/checkout@v3 diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 000000000..1699d1b41 --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,30 @@ +name: Build and Test (development-v6) +on: + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # Official docker images for docker are only available for amd64 and arm64 + # TODO: Look at: https://github.com/docker-library/official-images#architectures-other-than-amd64 + # Is testing on all platforms really necessary? + platform: [linux/amd64, linux/arm64/v8] + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + with: + platforms: ${{ matrix.platform}} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Run Tests + run: | + echo "Building image to test" + PLATFORM=${{ matrix.platform}} ./build-and-test.sh \ No newline at end of file diff --git a/build-and-test.sh b/build-and-test.sh index b73ed1566..353535ea1 100755 --- a/build-and-test.sh +++ b/build-and-test.sh @@ -8,9 +8,10 @@ fi GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD | sed "s/\//-/g") GIT_TAG=$(git describe --tags --exact-match 2> /dev/null || true) GIT_TAG="${GIT_TAG:-$GIT_BRANCH}" +PLATFORM="${PLATFORM:-linux/amd64}" # generate and build dockerfile -docker build --tag image_pipenv --file test/Dockerfile test/ +docker buildx build --load --platform=${PLATFORM} --tag image_pipenv --file test/Dockerfile test/ docker run --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd):/$(pwd)" \ diff --git a/test/Dockerfile b/test/Dockerfile index 511833ae4..4ac766d06 100644 --- a/test/Dockerfile +++ b/test/Dockerfile @@ -1,18 +1,12 @@ -FROM python:3.10-slim-bullseye +FROM python:3.10-alpine3.18 # Only works for docker CLIENT (bind mounted socket) -COPY --from=docker:20.10.17 /usr/local/bin/docker /usr/local/bin/ +COPY --from=docker:24-cli /usr/local/bin/docker /usr/local/bin/ -ARG packages -RUN apt-get update && \ - apt-get install -y python3-dev curl gcc make \ - libffi-dev libssl-dev ${packages} \ - && rm -rf /var/lib/apt/lists/* \ +RUN apk add --no-cache \ + curl \ && pip3 install --no-cache-dir -U pip pipenv -RUN curl -L https://github.com/docker/compose/releases/download/2.10.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose && \ - chmod +x /usr/local/bin/docker-compose - COPY ./cmd.sh /usr/local/bin/ COPY Pipfile* /root/ WORKDIR /root diff --git a/test/cmd.sh b/test/cmd.sh index 958a8d8ec..e5ee55f40 100755 --- a/test/cmd.sh +++ b/test/cmd.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh set -eux docker build ./src --tag pihole:${GIT_TAG} --no-cache @@ -9,4 +9,4 @@ python -m black ./test/tests/ # TODO: Add junitxml output and have something consume it # 2 parallel max b/c race condition with docker fixture (I think?) -py.test -vv -n 2 ./test/tests/ +py.test -vv -n auto ./test/tests/ From 3208c4042dc48428faa35a9de38357e808ee08ce Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 24 Jul 2023 18:06:43 +0100 Subject: [PATCH 2/5] Strip out no longer relevant tests/test fixtures (persist_docker, for example has not been used in a long time) , begin building test library from ground up. Signed-off-by: Adam Warner --- test/tests/conftest.py | 116 +----------- test/tests/test_bash_functions.py | 288 ++---------------------------- test/tests/test_start.py | 37 ---- 3 files changed, 11 insertions(+), 430 deletions(-) delete mode 100644 test/tests/test_start.py diff --git a/test/tests/conftest.py b/test/tests/conftest.py index 99e080542..1399160f1 100644 --- a/test/tests/conftest.py +++ b/test/tests/conftest.py @@ -42,7 +42,7 @@ def args_volumes(): @pytest.fixture() def args_env(): - return '-e FTLCONF_LOCAL_IPV4="127.0.0.1"' + return '-e TZ="Europe/London"' @pytest.fixture() @@ -87,33 +87,6 @@ def docker(request, test_args, args, image, cmd, entrypoint): return docker_generic(request, test_args, args, image, cmd, entrypoint) -@pytest.fixture(scope="module") -def docker_persist( - request, - persist_test_args, - persist_args, - persist_image, - persist_cmd, - persist_entrypoint, - dig, -): - """ - Persistent Docker container for multiple tests, instead of stopping container after one test - Uses DUP'd module scoped fixtures because smaller scoped fixtures won't mix with module scope - """ - persistent_container = docker_generic( - request, - persist_test_args, - persist_args, - persist_image, - persist_cmd, - persist_entrypoint, - ) - """ attach a dig container for lookups """ - persistent_container.dig = dig(persistent_container.id) - return persistent_container - - @pytest.fixture def entrypoint(): return "" @@ -129,12 +102,6 @@ def tag(version): return "{}".format(version) -@pytest.fixture -def webserver(tag): - """TODO: this is obvious without alpine+nginx as the alternative, remove fixture, hard code lighttpd in tests?""" - return "lighttpd" - - @pytest.fixture() def image(tag): image = "pihole" @@ -146,64 +113,6 @@ def cmd(): return TAIL_DEV_NULL -@pytest.fixture(scope="module") -def persist_version(): - return version - - -@pytest.fixture(scope="module") -def persist_args_dns(): - return "--dns 127.0.0.1 --dns 1.1.1.1" - - -@pytest.fixture(scope="module") -def persist_args_volumes(): - return "-v /dev/null:/etc/pihole/adlists.list" - - -@pytest.fixture(scope="module") -def persist_args_env(): - return '-e ServerIP="127.0.0.1"' - - -@pytest.fixture(scope="module") -def persist_args(persist_args_volumes, persist_args_env): - return "{} {}".format(persist_args_volumes, persist_args_env) - - -@pytest.fixture(scope="module") -def persist_test_args(): - """test override fixture to provide arguments separate from our core args""" - return "" - - -@pytest.fixture(scope="module") -def persist_tag(persist_version): - return "{}".format(persist_version) - - -@pytest.fixture(scope="module") -def persist_webserver(persist_tag): - """TODO: this is obvious without alpine+nginx as the alternative, remove fixture, hard code lighttpd in tests?""" - return "lighttpd" - - -@pytest.fixture(scope="module") -def persist_image(persist_tag): - image = "pihole" - return "{}:{}".format(image, persist_tag) - - -@pytest.fixture(scope="module") -def persist_cmd(): - return TAIL_DEV_NULL - - -@pytest.fixture(scope="module") -def persist_entrypoint(): - return "" - - @pytest.fixture def slow(): """ @@ -225,26 +134,3 @@ def _slow(check, timeout=20): return return _slow - - -@pytest.fixture(scope="module") -def dig(): - """separate container to link to pi-hole and perform lookups""" - """ a docker pull is faster than running an install of dnsutils """ - - def _dig(docker_id): - args = "--link {}:test_pihole".format(docker_id) - image = "azukiapp/dig" - cmd = TAIL_DEV_NULL - dig_container = docker_generic(request, "", args, image, cmd, "") - return dig_container - - return _dig - - -@pytest.fixture -def running_pihole(docker_persist, slow, persist_webserver): - """Persist a fully started docker-pi-hole to help speed up subsequent tests""" - slow(lambda: docker_persist.run("pgrep pihole-FTL").rc == 0) - slow(lambda: docker_persist.run("pgrep lighttpd").rc == 0) - return docker_persist diff --git a/test/tests/test_bash_functions.py b/test/tests/test_bash_functions.py index 64540b9f4..cf31abddb 100644 --- a/test/tests/test_bash_functions.py +++ b/test/tests/test_bash_functions.py @@ -2,289 +2,21 @@ import pytest import re -SETUPVARS_LOC = "/etc/pihole/setupVars.conf" -DNSMASQ_CONFIG_LOC = "/etc/dnsmasq.d/01-pihole.conf" -CMD_SETUP_FTL_CACHESIZE = ". bash_functions.sh ; setup_FTL_CacheSize" -CMD_SETUP_FTL_INTERFACE = ". bash_functions.sh ; setup_FTL_Interface" -CMD_SETUP_WEB_PASSWORD = ". bash_functions.sh ; setup_web_password" +CMD_APPLY_FTL_CONFIG_FROM_ENV = ". bash_functions.sh ; apply_FTL_Configs_From_Env" -def _cat(file): - return "cat {}".format(file) - - -def _grep(string, file): - return "grep -q '{}' {}".format(string, file) +@pytest.mark.parametrize("test_args", ['-e "FTLCONF_webserver_port=999"']) +def test_FTLCONF_webserver_port(docker): + func = docker.run(CMD_APPLY_FTL_CONFIG_FROM_ENV) + assert "Applied pihole-FTL setting webserver.port=999" in func.stdout @pytest.mark.parametrize( - "test_args,expected_ipv6,expected_stdout", - [ - ("", True, "IPv4 and IPv6"), - ('-e "IPv6=True"', True, "IPv4 and IPv6"), - ('-e "IPv6=False"', False, "IPv4"), - ('-e "IPv6=foobar"', False, "IPv4"), - ], + "test_args", ['-e "FTLCONF_dns_upstreams=1.1.1.1;8.8.8.8#1234"'] ) -def test_ipv6_not_true_removes_ipv6( - docker, slow, test_args, expected_ipv6, expected_stdout -): - """When a user overrides IPv6=True they only get IPv4 listening webservers""" - IPV6_LINE = "use-ipv6.pl" - WEB_CONFIG = "/etc/lighttpd/lighttpd.conf" - - function = docker.run(". /usr/local/bin/bash_functions.sh ; setup_ipv4_ipv6") - assert "Using {}".format(expected_stdout) in function.stdout - if expected_stdout == "IPv4": - assert "IPv6" not in function.stdout - # On overlay2(?) docker sometimes writes to disk are slow enough to break some tests... - expected_ipv6_check = ( - lambda: ( - IPV6_LINE in docker.run("grep 'use-ipv6.pl' {}".format(WEB_CONFIG)).stdout - ) - == expected_ipv6 - ) - slow(expected_ipv6_check) - - -@pytest.mark.parametrize("test_args", ['-e "WEB_PORT=999"']) -def test_overrides_default_web_port(docker, slow, test_args): - """When a --net=host user sets WEB_PORT to avoid synology's 80 default IPv4 and or IPv6 ports are updated""" - CONFIG_LINE = r"server.port\s*=\s*999" - WEB_CONFIG = "/etc/lighttpd/lighttpd.conf" - - function = docker.run( - ". /usr/local/bin/bash_functions.sh ; eval `grep setup_web_port /usr/local/bin/_startup.sh`" - ) - assert " [i] Custom WEB_PORT set to 999" in function.stdout +def test_FTLCONF_dns_upstreams(docker): + func = docker.run(CMD_APPLY_FTL_CONFIG_FROM_ENV) assert ( - " [i] Without proper router DNAT forwarding to 127.0.0.1:999, you may not get any blocked websites on ads" - in function.stdout - ) - slow( - lambda: re.search(CONFIG_LINE, docker.run(_cat(WEB_CONFIG)).stdout) is not None - ) - - -@pytest.mark.parametrize( - "test_args,expected_error", - [ - ( - '-e WEB_PORT="LXXX"', - "WARNING: Custom WEB_PORT not used - LXXX is not an integer", - ), - ( - '-e WEB_PORT="1,000"', - "WARNING: Custom WEB_PORT not used - 1,000 is not an integer", - ), - ( - '-e WEB_PORT="99999"', - "WARNING: Custom WEB_PORT not used - 99999 is not within valid port range of 1-65535", - ), - ], -) -def test_bad_input_to_web_port(docker, test_args, expected_error): - function = docker.run( - ". /usr/local/bin/bash_functions.sh ; eval `grep setup_web_port /usr/local/bin/_startup.sh`" - ) - assert expected_error in function.stdout - - -@pytest.mark.parametrize( - "test_args,cache_size", - [('-e CUSTOM_CACHE_SIZE="0"', "0"), ('-e CUSTOM_CACHE_SIZE="20000"', "20000")], -) -def test_overrides_default_custom_cache_size(docker, slow, test_args, cache_size): - """Changes the cache_size setting to increase or decrease the cache size for dnsmasq""" - CONFIG_LINE = r"cache-size\s*=\s*{}".format(cache_size) - - function = docker.run( - "echo ${CUSTOM_CACHE_SIZE};. ./usr/local/bin/bash_functions.sh; echo ${CUSTOM_CACHE_SIZE}; eval `grep setup_FTL_CacheSize /usr/local/bin/_startup.sh`" - ) - assert "Custom CUSTOM_CACHE_SIZE set to {}".format(cache_size) in function.stdout - slow( - lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout) - is not None - ) - - -@pytest.mark.parametrize( - "test_args", - [ - '-e CUSTOM_CACHE_SIZE="-1"', - '-e CUSTOM_CACHE_SIZE="1,000"', - ], -) -def test_bad_input_to_custom_cache_size(docker, slow, test_args): - CONFIG_LINE = r"cache-size\s*=\s*10000" - - docker.run(CMD_SETUP_FTL_CACHESIZE) - slow( - lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout) - is not None - ) - - -@pytest.mark.parametrize( - "test_args", - [ - '-e DNSSEC="true" -e CUSTOM_CACHE_SIZE="0"', - ], -) -def test_dnssec_enabled_with_custom_cache_size(docker, slow, test_args): - CONFIG_LINE = r"cache-size\s*=\s*10000" - - docker.run(CMD_SETUP_FTL_CACHESIZE) - slow( - lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout) - is not None + 'Applied pihole-FTL setting dns.upstreams=["1.1.1.1","8.8.8.8#1234"]' + in func.stdout ) - - -@pytest.mark.parametrize( - "args_env, expected_stdout, expected_config_line", - [ - ("", "binding to default interface: eth0", "PIHOLE_INTERFACE=eth0"), - ( - '-e INTERFACE="br0"', - "binding to custom interface: br0", - "PIHOLE_INTERFACE=br0", - ), - ], -) -def test_dns_interface_override_defaults( - docker, slow, args_env, expected_stdout, expected_config_line -): - """When INTERFACE environment var is passed in, overwrite dnsmasq interface""" - function = docker.run(CMD_SETUP_FTL_INTERFACE) - assert expected_stdout in function.stdout - slow( - lambda: expected_config_line + "\n" - == docker.run('grep "^PIHOLE_INTERFACE" {}'.format(SETUPVARS_LOC)).stdout - ) - - -expected_debian_lines = [ - '"VIRTUAL_HOST" => "127.0.0.1"', - '"PHP_ERROR_LOG" => "/var/log/lighttpd/error-pihole.log"', -] - - -@pytest.mark.parametrize( - "expected_lines,repeat_function", - [(expected_debian_lines, 1), (expected_debian_lines, 2)], -) -def test_debian_setup_php_env(docker, expected_lines, repeat_function): - """confirm all expected output is there and nothing else""" - for _ in range(repeat_function): - docker.run( - ". /usr/local/bin/bash_functions.sh ; eval `grep setup_php_env /usr/local/bin/_startup.sh`" - ) - for expected_line in expected_lines: - search_config_cmd = ( - "grep -c '{}' /etc/lighttpd/conf-enabled/15-pihole-admin.conf".format( - expected_line - ) - ) - search_config_count = docker.run(search_config_cmd) - found_lines = int(search_config_count.stdout.rstrip("\n")) - if found_lines > 1: - assert ( - False - ), f"Found line {expected_line} times (more than once): {found_lines}" - - -def test_webpassword_random_generation(docker): - """When a user sets webPassword env the admin password gets set to that""" - function = docker.run(CMD_SETUP_WEB_PASSWORD) - assert "assigning random password" in function.stdout.lower() - - -@pytest.mark.parametrize("entrypoint,cmd", [("--entrypoint=tail", "-f /dev/null")]) -@pytest.mark.parametrize( - "args_env,secure,setupvars_hash", - [ - ( - "-e WEBPASSWORD=login", - True, - "WEBPASSWORD=6060d59351e8c2f48140f01b2c3f3b61652f396c53a5300ae239ebfbe7d5ff08", - ), - ('-e WEBPASSWORD=""', False, ""), - ], -) -def test_webpassword_env_assigns_password_to_file_or_removes_if_empty( - docker, args_env, secure, setupvars_hash -): - """When a user sets webPassword env the admin password gets set or removed if empty""" - function = docker.run(CMD_SETUP_WEB_PASSWORD) - - if secure: - assert "new password set" in function.stdout.lower() - assert docker.run(_grep(setupvars_hash, SETUPVARS_LOC)).rc == 0 - else: - assert "password removed" in function.stdout.lower() - assert docker.run(_grep("^WEBPASSWORD=$", SETUPVARS_LOC)).rc == 0 - - -@pytest.mark.parametrize("entrypoint,cmd", [("--entrypoint=tail", "-f /dev/null")]) -@pytest.mark.parametrize("test_args", ["-e WEBPASSWORD=login", '-e WEBPASSWORD=""']) -def test_env_always_updates_password(docker, args_env, test_args): - """When a user sets the WEBPASSWORD environment variable, ensure it always sets the password""" - function = docker.run(CMD_SETUP_WEB_PASSWORD) - - assert " [i] Assigning password defined by Environment Variable" in function.stdout - - -@pytest.mark.parametrize("entrypoint,cmd", [("--entrypoint=tail", "-f /dev/null")]) -def test_setupvars_trumps_random_password_if_set(docker, args_env, test_args): - """If a password is already set in setupvars, and no password is set in the environment variable, do not generate a random password""" - docker.run( - ". /opt/pihole/utils.sh ; addOrEditKeyValPair {} WEBPASSWORD volumepass".format( - SETUPVARS_LOC - ) - ) - function = docker.run(CMD_SETUP_WEB_PASSWORD) - - assert "Pre existing WEBPASSWORD found" in function.stdout - assert docker.run(_grep("WEBPASSWORD=volumepass", SETUPVARS_LOC)).rc == 0 - - -@pytest.mark.parametrize( - "args_env,test_args,expected_bind,expect_warning", - [ - ("-e FTLCONF_LOCAL_IPV4=192.0.2.10", "--net=host", "192.0.2.10", True), - ("-e FTLCONF_LOCAL_IPV4=192.0.2.10", "", "0.0.0.0", False), - ( - "-e WEB_BIND_ADDR=192.0.2.20 -e FTLCONF_LOCAL_IPV4=192.0.2.10", - "--net=host", - "192.0.2.20", - False, - ), - ( - "-e WEB_BIND_ADDR=192.0.2.20 -e FTLCONF_LOCAL_IPV4=192.0.2.10", - "", - "192.0.2.20", - False, - ), - ], -) -def test_setup_lighttpd_bind( - docker, args_env, test_args, expected_bind, expect_warning -): - """Lighttpd's bind address is correctly set""" - WEB_CONFIG = "/etc/lighttpd/lighttpd.conf" - WARNING_EXTRACT = "[i] WARNING: running in host network mode forces" - - function = docker.run(". /usr/local/bin/bash_functions.sh ; setup_lighttpd_bind") - - if expect_warning: - assert WARNING_EXTRACT in function.stdout - else: - assert WARNING_EXTRACT not in function.stdout - - config = docker.run(f"cat {WEB_CONFIG} | grep 'server.bind'") - - if expected_bind == "0.0.0.0": - assert "server.bind" not in config.stdout - else: - assert f'server.bind = "{expected_bind}"' in config.stdout diff --git a/test/tests/test_start.py b/test/tests/test_start.py deleted file mode 100644 index 967403b8d..000000000 --- a/test/tests/test_start.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytest -import time - -""" conftest.py provides the defaults through fixtures """ -""" Note, testinfra builtins don't seem fully compatible with - docker containers (esp. musl based OSs) stripped down nature """ - - -# If the test runs /usr/local/bin/_startup.sh, do not let s6 run it too! Kill entrypoint to avoid race condition/duplicated execution -@pytest.mark.parametrize("entrypoint,cmd", [("--entrypoint=tail", "-f /dev/null")]) -@pytest.mark.parametrize( - "args,error_msg,expect_rc", - [ - ( - '-e FTLCONF_LOCAL_IPV4="1.2.3.z"', - "FTLCONF_LOCAL_IPV4 Environment variable (1.2.3.z) doesn't appear to be a valid IPv4 address", - 1, - ), - ( - '-e FTLCONF_LOCAL_IPV4="1.2.3.4" -e FTLCONF_LOCAL_IPV6="1234:1234:1234:ZZZZ"', - "Environment variable (1234:1234:1234:ZZZZ) doesn't appear to be a valid IPv6 address", - 1, - ), - ( - '-e FTLCONF_LOCAL_IPV4="1.2.3.4" -e FTLCONF_LOCAL_IPV6="kernel"', - "ERROR: You passed in IPv6 with a value of 'kernel'", - 1, - ), - ], -) -def test_ftlconf_local_addr_invalid_ips_triggers_exit_error( - docker, error_msg, expect_rc -): - start = docker.run("/usr/local/bin/_startup.sh") - assert start.rc == expect_rc - assert "ERROR" in start.stdout - assert error_msg in start.stdout From 1202dafcbd6d9a5538bc706e891820a57565b6d8 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 24 Jul 2023 18:26:04 +0100 Subject: [PATCH 3/5] Change test dockerfile base to `docker:24.0.4-cli-alpine3.18` rather than copying in, buildx would not work the other way. Signed-off-by: Adam Warner --- test/Dockerfile | 25 ++++++++++++------------- test/cmd.sh | 2 +- test/entrypoint.sh | 1 + 3 files changed, 14 insertions(+), 14 deletions(-) create mode 100644 test/entrypoint.sh diff --git a/test/Dockerfile b/test/Dockerfile index 4ac766d06..676f972e4 100644 --- a/test/Dockerfile +++ b/test/Dockerfile @@ -1,20 +1,19 @@ -FROM python:3.10-alpine3.18 +FROM docker:24.0.4-cli-alpine3.18 -# Only works for docker CLIENT (bind mounted socket) -COPY --from=docker:24-cli /usr/local/bin/docker /usr/local/bin/ - -RUN apk add --no-cache \ - curl \ - && pip3 install --no-cache-dir -U pip pipenv - -COPY ./cmd.sh /usr/local/bin/ +COPY --chmod=0755 ./cmd.sh /usr/local/bin/cmd.sh +COPY --chmod=0755 ./entrypoint.sh /usr/local/bin/entrypoint.sh COPY Pipfile* /root/ WORKDIR /root -RUN pipenv install --system \ - && sed -i 's|/bin/sh|/bin/bash|g' /usr/local/lib/python3.10/site-packages/testinfra/backend/docker.py +RUN apk add --no-cache \ + python3-dev \ + py3-pip \ + curl \ + && pip3 install --no-cache-dir -U pip pipenv \ + && pipenv install --system \ + # Not 100% sure what this line does, but it's always been in the Dockerfile (aside from pointing at a different file) + # Tests fall over without it. Investigate later. + && sed -i 's|/bin/sh|/bin/bash|g' /usr/lib/python3.11/site-packages/testinfra/backend/docker.py -RUN echo "set -ex && cmd.sh && \$@" > /usr/local/bin/entrypoint.sh -RUN chmod +x /usr/local/bin/entrypoint.sh ENTRYPOINT entrypoint.sh CMD cmd.sh diff --git a/test/cmd.sh b/test/cmd.sh index e5ee55f40..2c753d745 100755 --- a/test/cmd.sh +++ b/test/cmd.sh @@ -1,7 +1,7 @@ #!/usr/bin/env sh set -eux -docker build ./src --tag pihole:${GIT_TAG} --no-cache +docker buildx build ./src --tag pihole:${GIT_TAG} --no-cache docker images pihole:${GIT_TAG} # auto-format the pytest code diff --git a/test/entrypoint.sh b/test/entrypoint.sh new file mode 100644 index 000000000..dce4fc190 --- /dev/null +++ b/test/entrypoint.sh @@ -0,0 +1 @@ +set -ex && cmd.sh \ No newline at end of file From 4c8f4613dde880d1bd36eb99dbafb6c492d41750 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 24 Jul 2023 18:29:42 +0100 Subject: [PATCH 4/5] test names should match the regular expression ^[a-z_][a-z0-9_]*$. Apparently Signed-off-by: Adam Warner --- test/tests/test_bash_functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/tests/test_bash_functions.py b/test/tests/test_bash_functions.py index cf31abddb..c9917f5c7 100644 --- a/test/tests/test_bash_functions.py +++ b/test/tests/test_bash_functions.py @@ -6,7 +6,7 @@ @pytest.mark.parametrize("test_args", ['-e "FTLCONF_webserver_port=999"']) -def test_FTLCONF_webserver_port(docker): +def test_ftlconf_webserver_port(docker): func = docker.run(CMD_APPLY_FTL_CONFIG_FROM_ENV) assert "Applied pihole-FTL setting webserver.port=999" in func.stdout @@ -14,7 +14,7 @@ def test_FTLCONF_webserver_port(docker): @pytest.mark.parametrize( "test_args", ['-e "FTLCONF_dns_upstreams=1.1.1.1;8.8.8.8#1234"'] ) -def test_FTLCONF_dns_upstreams(docker): +def test_ftlconf_dns_upstreams(docker): func = docker.run(CMD_APPLY_FTL_CONFIG_FROM_ENV) assert ( 'Applied pihole-FTL setting dns.upstreams=["1.1.1.1","8.8.8.8#1234"]' From fee259597cb924ae9243486aff38a6c03ab9a1f7 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 24 Jul 2023 18:47:47 +0100 Subject: [PATCH 5/5] `./build-and-test.sh enter` was not working because bash not installed, change command to sh instead of bash Signed-off-by: Adam Warner --- build-and-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-and-test.sh b/build-and-test.sh index 353535ea1..0f90186b0 100755 --- a/build-and-test.sh +++ b/build-and-test.sh @@ -2,7 +2,7 @@ set -ex if [[ "$1" == "enter" ]]; then - enter="-it --entrypoint=bash" + enter="-it --entrypoint=sh" fi GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD | sed "s/\//-/g")