tox-dev / tox-docker

A tox plugin to run one or more Docker containers during tests
BSD 3-Clause "New" or "Revised" License
176 stars 40 forks source link

Pass arguments to docker container #159

Open matthbakeredb opened 1 year ago

matthbakeredb commented 1 year ago

The recent addition of Dockerfile support to build and run container is mentioned as a possible fix for #114 and I wish to understand how this can be used in my use case.

There is an existing tox env that runs the test in the host OS

[testenv:pg{12,13,14,15}-docker-behave-{etcd}-{lin,mac}]
description = Run behaviour tests in patroni-dev docker container
setenv =
    etcd: DCS=etcd
    pg11: PG_MAJOR = 11
    pg12: PG_MAJOR = 12
    pg13: PG_MAJOR = 13
    pg14: PG_MAJOR = 14
    pg15: PG_MAJOR = 15
    CONTAINER_NAME = tox-{env_name}-{env:PYTHONHASHSEED}
labels =
    behave
depends =
    pg{11,12,13,14,15}-docker-build

commands =
    docker run \
        -v {tox_root}:/src \
        -e DCS={env:DCS} \
        -e NAME={env:CONTAINER_NAME} \
        --name {env:CONTAINER_NAME} \
        --rm \
        -t \
        {env:PATRONI_DEV_IMAGE:patroni-dev:{env:PG_MAJOR}} \
        run -x 'tox.env_list=py\{36,37,38,39,310,311\}-behave-{env:DCS}-lin' \
        -- --format plain {posargs}

allowlist_externals =
    docker
platform =
    lin: linux
    mac: darwin

I have Dockerfile(s) that contains software/environment setup required to run behaviour tests on different PG versions.

[testenv:pg{12,13,14,15}-docker-build]
description = Build docker containers needed for testing
labels =
    behave
setenv =
    pg11: PG_MAJOR = 11
    pg12: PG_MAJOR = 12
    pg13: PG_MAJOR = 13
    pg14: PG_MAJOR = 14
    pg15: PG_MAJOR = 15
    DOCKER_BUILDKIT = 1
commands =
    docker build . \
        --tag patroni-dev:{env:PG_MAJOR} \
        --build-arg PG_MAJOR \
        --file features/Dockerfile
allowlist_externals = docker

As far as I can see from the new feature addition, I cannot pass arguments to CMD to the container when it runs. Mainly I would like to pass {posargs} but also I would need to pass build args.

I am thinking I would put all of the command line requirements into the entrypoint of the Dockerfile and had something like this:

[docker:patroni-dev]
dockerfile: features/Dockerfile
volumes:
  - bind:rw:{tox_root}:/src

[testenv:pg{12,13,14,15}-docker-behave-{etcd}]
description = Run behaviour tests in patroni-dev docker container
setenv =
    etcd: DCS=etcd
    pg11: PG_MAJOR = 11
    pg12: PG_MAJOR = 12
    pg13: PG_MAJOR = 13
    pg14: PG_MAJOR = 14
    pg15: PG_MAJOR = 15
labels =
    behave
docker = patroni-dev

How do I pass the {posargs} in? Where do I define build_args? As it stands now do I need a separate Dockerfile or dockerfile_target for different build options? Am I missing something? Perhaps there is another way to achieve this?

Thanks!

dcrosta commented 1 year ago

I'm not clear on why you need to pass {posargs} to docker? It looks like you need to pass build args, which are not currently supported (I didn't have a use case, so didn't understand how to design a feature to support build args)

As it stands in 4.1.0, your best bet is to use a multi-stage Dockerfile and use dockerfile_target, if I'm understanding everything here. Is there some reason that wouldn't work?

matthbakeredb commented 1 year ago

From what I can tell, it seems that the current design centers around starting a container that has some application that we want to test, say by hitting an API endpoint listening on a port. In this scenario I wish to create a docker image that has all the required software to run tests as if they were being ran locally. That is done by executing a single command and when it's done the container exits.

So currently the tox.ini has this for the command part (sorry should've added that to the original request), pared down:

[testenv:pg{12,13,14,15}-docker-behave]
description = Run behaviour tests in patroni-dev docker container
setenv =
    pg11: PG_MAJOR = 11
    pg12: PG_MAJOR = 12
    pg13: PG_MAJOR = 13
    pg14: PG_MAJOR = 14
    pg15: PG_MAJOR = 15
    CONTAINER_NAME = tox-{env_name}-{env:PYTHONHASHSEED}
labels =
    behave
depends =
    pg{11,12,13,14,15}-docker-build

commands =
    docker run \
        --volume {tox_root}:/src \
        --hostname {env:CONTAINER_NAME} \
        --name {env:CONTAINER_NAME} \
        --rm \
        --tty \
        {env:PATRONI_DEV_IMAGE:patroni-dev:{env:PG_MAJOR}} \
        tox run -x 'tox.env_list=py\{36,37,38,39,310,311\}-behave' \
        -- --format plain {posargs}

allowlist_externals =
    docker

[testenv:py{36,38,39,310,311}-behave]
description = Run behaviour tests (locally)
deps =
    -r requirements.txt
    behave
setenv =
    DCS = {env:DCS:etcd}
commands =
    python3 -m behave {posargs}

So a user can run tox -m behave to get a full sweep of all behave tests for all versions of PG, or tox -f pg15 docker to get the behave tests just for one version, or tox -f py311 behave to get the behave tests to run on their host machine if they have the required software installed already.

The {posargs} is so they can pass just the test file, feature in this case, or any other command line args to behave.

tox -f pg15 docker -- features/watchdog.feature

At the moment I cannot see how I would do that last part of arbitrarily passing arguments to the CMD of the docker container.