Skip to content

Commit

Permalink
Merge pull request #2366 from craig8/docker-fixture
Browse files Browse the repository at this point in the history
Added prototype docker wrapper and fixture for docker
  • Loading branch information
craig8 authored Jun 17, 2020
2 parents ef2ab01 + 2559ebe commit c92aed3
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 1 deletion.
75 changes: 75 additions & 0 deletions volttrontesting/fixtures/docker_wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
try:
import docker

HAS_DOCKER = True
except ImportError:
HAS_DOCKER = False

import time
import contextlib

# Only allow this function if docker is available from the pip library.
if HAS_DOCKER:

@contextlib.contextmanager
def create_container(image_name: str, ports: dict = None, env: dict = None, command: (list, str) = None,
startup_time_seconds: int = 30) -> \
(docker.models.containers.Container, None):
""" Creates a container instance in a context that will clean up after itself.
This is a wrapper around the docker api documented at https://docker-py.readthedocs.io/en/stable/containers.html.
Some things that this will do automatically for the caller is make the container be ephemeral by removing it
once the context manager is cleaned up.
This function is being used for long running processes. Short processes may not work correctly because
the execution time might be too short for the returning of data from the container.
Usage:
with create_container("mysql", {"3306/tcp": 3306}):
# connect to localhost:3306 with mysql using connector
:param image_name: The image name (from dockerhub) that is to be instantiated
:param ports:
a dictionary following the convention {'portincontainre/protocol': portonhost}
::
# example port exposing mysql's known port.
{'3306/tcp': 3306}
:param env:
:param command: string or list of commands to run during the startup of the container.
:param startup_time_seconds: Allow this many seconds for the startup of the container before raising a
runtime exception (Download of image and instantiation could take a while)
:return:
A container object (https://docker-py.readthedocs.io/en/stable/containers.html.) or None
"""

# Create docker client (Uses localhost as agent connection.
client = docker.from_env()
if ":" in image_name:
client.images.pull(image_name)
else:
# So all tags aren't pulled. According to docs https://docker-py.readthedocs.io/en/stable/images.html.
client.images.pull(image_name + ":latest")
container = client.containers.run(image_name, ports=ports, environment=env, auto_remove=True, detach=True)

if container is None:
raise RuntimeError(f"Unable to run image {image_name}")

error_time = time.time() + startup_time_seconds
invalid = False
while container.status != 'running':
if time.time() > error_time:
invalid = True
break
time.sleep(0.1)
container.reload()

if invalid:
yield None
else:
yield container

container.kill()

19 changes: 18 additions & 1 deletion volttrontesting/testutils/test_fixtures.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@

import pytest
from volttrontesting.fixtures.volttron_platform_fixtures import volttron_instance_web

try:
SKIP_DOCKER = False
from volttrontesting.fixtures.docker_wrapper import create_container
except ImportError:
SKIP_DOCKER = True


def test_web_setup_properly(volttron_instance_web):
instance = volttron_instance_web
Expand All @@ -9,4 +15,15 @@ def test_web_setup_properly(volttron_instance_web):
assert instance.bind_web_address == instance.volttron_central_address


@pytest.mark.skipif(SKIP_DOCKER, reason="No docker available in api (install pip install docker) for availability")
def test_docker_wrapper():
with create_container("mysql") as container:
print(container.status)
print(container.logs())


@pytest.mark.skipif(SKIP_DOCKER, reason="No docker available in api (install pip install docker) for availability")
def test_docker_run_crate_latest():
with create_container("crate", {"4200/tcp": 4200}) as container:
assert container.status == 'running'

0 comments on commit c92aed3

Please sign in to comment.