Beispiel #1
0
def test_wait_for_service(mocker):
    from derex.runner.docker_utils import wait_for_service

    container = mocker.MagicMock()
    container.exec_run.return_value = mocker.MagicMock(exit_code=0)

    client = mocker.patch("derex.runner.docker_utils.client")
    client.containers.get.return_value = container

    wait_for_service("mysql", 'mysql -psecret -e "SHOW DATABASES"', 1)
    client.containers.get.assert_called_with("mysql")
    container.exec_run.assert_called_with('mysql -psecret -e "SHOW DATABASES"')
Beispiel #2
0
def test_wait_for_service(mocker):
    from derex.runner.docker_utils import wait_for_service

    # Test that a RuntimeError is raised if the container doesn't
    # exists
    with pytest.raises(RuntimeError):
        wait_for_service("service", 1)

    container_info = {
        "State": {
            "Status": "running",
            "Health": {
                "Status": "healthy"
            }
        }
    }
    api_client = mocker.patch("derex.runner.docker_utils.api_client")
    api_client.inspect_container.return_value = container_info

    # Test that the result is successfull when the container
    # is running or restarting and healthy
    result = wait_for_service("service", 1)
    api_client.inspect_container.assert_called_with("service")
    assert result == 0

    container_info["State"]["Status"] = "restarting"
    result = wait_for_service("service", 1)
    assert result == 0

    # Test that a RuntimeError is raised if the container status is
    # exited
    container_info["State"]["Status"] = "exited"
    with pytest.raises(RuntimeError):
        wait_for_service("service", 1)

    # Test that a TimeoutError is raised if the container status is
    # unhealthy
    container_info["State"]["Status"] = "running"
    container_info["State"]["Health"]["Status"] = "unhealthy"
    with pytest.raises(TimeoutError):
        wait_for_service("service", 1)

    # Test that a NotImplementedError is raised if the container doesn't
    # define an healtcheck
    container_info["State"]["Health"] = None
    with pytest.raises(NotImplementedError):
        wait_for_service("service", 1)
Beispiel #3
0
def e2e(project):
    """Run project e2e tests"""
    if not project.e2e_dir:
        click.echo(red(f"No e2e tests directory found in {project.root}"), err=True)
        return 1

    try:
        wait_for_service("httpserver")
    except (TimeoutError, RuntimeError, NotImplementedError) as exc:
        click.echo(click.style(str(exc), fg="red"))
        sys.exit(1)

    click.echo(f"Running e2e Cypress tests from {project.e2e_dir}")
    test_compose_path = generate_ddc_test_compose(project)
    run_docker_compose(
        ["-f", str(test_compose_path), "run", "--rm", "cypress"],
        dry_run=False,
        exit_afterwards=True,
    )
Beispiel #4
0
def minio_update_key(old_key: str):
    """Run minio to re-key data with the new secret"""
    from derex.runner.ddc import run_ddc_services
    from derex.runner.docker_utils import wait_for_service
    from derex.runner.utils import derex_path

    wait_for_service("minio")
    MINIO_SCRIPT_PATH = derex_path(
        "derex/runner/compose_files/minio-update-key.sh")
    click.echo("Updating MinIO secret key...")
    compose_args = [
        "run",
        "--rm",
        "-v",
        f"{MINIO_SCRIPT_PATH}:/minio-update-key.sh",
        "-e",
        f"MINIO_SECRET_KEY_OLD={old_key}",
        "--entrypoint",
        "/bin/sh",
        "-T",
        "minio",
        "/minio-update-key.sh",
    ]
    try:
        run_ddc_services(compose_args)
    except RuntimeError:
        return 1

    # We need to recreate the minio container since we can't set
    # the new key in the running one
    # https://github.com/moby/moby/issues/8838
    # We'll let `docker-compose up` recreate it for us, if needed
    click.echo("\nRecreating MinIO container...")
    compose_args = ["up", "-d", "minio"]
    run_ddc_services(compose_args)

    wait_for_service("minio")
    click.echo("\nMinIO secret key updated successfully!")
    return 0
Beispiel #5
0
def create_index(project):
    """Prime the elasticsearch index for the Forum service"""
    from derex.runner.ddc import run_ddc_project
    from derex.runner.docker_utils import wait_for_service

    try:
        wait_for_service("elasticsearch")
    except (TimeoutError, RuntimeError, NotImplementedError) as exc:
        click.echo(click.style(str(exc), fg="red"))
        sys.exit(1)

    compose_args = [
        "run",
        "--rm",
        "-T",
        "forum",
        "sh",
        "-c",
        """bundle exec rake search:initialize &&
        bundle exec rake search:rebuild_index
        """,
    ]
    run_ddc_project(compose_args, project=project)
    return 0
Beispiel #6
0
def ddc_project():
    """Proxy for docker-compose: writes a docker-compose.yml file with the
    configuration of this project, and then run `docker-compose` on it.

    You probably want do run `ddc-project up -d` and `ddc-project logs -f`.
    """
    check_docker()
    setup_logging()
    try:
        project = Project()
    except ValueError as exc:
        click.echo(str(exc))
        sys.exit(1)
    compose_args, dry_run = ddc_parse_args(sys.argv)
    # If trying to start up containers, first check that needed services are running
    is_start_cmd = any(param in compose_args for param in ["up", "start"])
    if is_start_cmd:
        for service in ["mysql", "mongodb", "rabbitmq"]:
            try:
                wait_for_service(service)
            except (TimeoutError, RuntimeError, NotImplementedError) as exc:
                click.echo(click.style(str(exc), fg="red"))
                sys.exit(1)
    run_ddc_project(list(compose_args), project, dry_run=dry_run, exit_afterwards=True)
Beispiel #7
0
 def inner(*args, **kwargs):
     wait_for_service("mysql")
     return func(*args, **kwargs)
Beispiel #8
0
def wait_for_mysql(max_seconds: int = 20):
    """With a freshly created container mysql might need a bit of time to prime
    its files. This functions waits up to max_seconds seconds.
    """
    return wait_for_service("mysql", 'mysql -psecret -e "SHOW DATABASES"', max_seconds)
Beispiel #9
0
from derex.runner.secrets import DerexSecrets
from derex.runner.secrets import get_secret
from functools import wraps
from pymongo import MongoClient
from typing import cast
from typing import List
from typing import Optional

import logging
import urllib.parse

logger = logging.getLogger(__name__)
MONGODB_ROOT_PASSWORD = get_secret(DerexSecrets.mongodb)

try:
    wait_for_service("mongodb")
    container = docker_client.containers.get("mongodb")
    mongo_address = container.attrs["NetworkSettings"]["Networks"]["derex"][
        "IPAddress"]
    user = urllib.parse.quote_plus(MONGODB_ROOT_USER)
    password = urllib.parse.quote_plus(MONGODB_ROOT_PASSWORD)
    MONGODB_CLIENT = MongoClient(
        f"mongodb://{user}:{password}@{mongo_address}:27017/",
        authSource="admin")
except RuntimeError as e:
    MONGODB_CLIENT = None
    logger.warning(e)


def ensure_mongodb(func):
    """Decorator to raise an exception before running a function in case the mongodb
Beispiel #10
0
def wait_for_mongodb(max_seconds: int = 20):
    """With a freshly created container mongodb might need a bit of time to prime
    its files. This functions waits up to max_seconds seconds.
    """
    return wait_for_service("mongodb", "mongo", max_seconds)