import re
import uuid as py_uuid
from common_fixtures import *  # NOQA
from test_volume import VOLUME_CLEANUP_LABEL

TEST_IMAGE = 'ibuildthecloud/helloworld'
TEST_IMAGE_LATEST = TEST_IMAGE + ':latest'
TEST_IMAGE_UUID = 'docker:' + TEST_IMAGE

if_docker = pytest.mark.skipif("os.environ.get('DOCKER_TEST') == 'false'",
                               reason='DOCKER_TEST is not set')

os_environ = "os.environ.get('DOCKER_VERSION') != '1.12.1'"
if_docker_1_12 = pytest.mark.skipif(os_environ,
                                    reason='Doc
ker version is not 1.12.1')

sched_environ = "os.environ.get('CATTLE_TEST_RESOURCE_SCHEDULER') != 'true'"
if_resource_scheduler = pytest.mark.skipif(sched_environ)


@pytest.fixture(scope='session')
def docker_client(super_client):
    for host in super_client.list_host(state='active', remove_null=True,
                     
                  kind='docker'):
        key = super_client.create_api_key(accountId=host.accountId)
        super_client.wait_success(key)

        wait_for(lambda: host.agent().state == 'active')
        wait_for(lambda: len(host.storagePools()) > 0 and
                 host.storagePools()[0].state == 'active')
        return api_client(key.publicValue, key.secretValue)

    raise Exception('Failed to find docker host, please register one')


@if_docker
def test_docker_create_only(docker_client, super_client):
    uuid = TEST_IMAGE_UUID
    container = docker_client.create_container(imageUuid=uuid,
                                               networkMode='bridge',
                                               startOnCreate=False)
    try:
        container = docker_client.wait_success(container)

        assert container is not None
        assert 'container' == container.type
    finally:
        if container is not None:
            docker_client.delete(container)


@if_docker
def test_docker_create_only_from_sha(docker_client, super_client):
    image_name = 'tianon/true@sha256:662fc60808e6d5628a090e39' \
                 'b4bcae694add28a626031cc889109c2cf2af5d73'
    uuid = 'docker:' + image_name
    container = docker_client.create_container(name='test-sha256',
                                               imageUuid=uuid,
                                               networkMode='bridge',
                                               startOnCreate=False)
    try:
        container = docker_client.wait_success(container)

        assert container is not None
        assert 'container' == container.type
    finally:
        if container is not None:
            docker_client.delete(container)


@if_docker
def test_docker_create_with_start(docker_client, super_client):
    uuid = TEST_IMAGE_UUID
    container = docker_client.create_container(imageUuid=uuid,
                                               networkMode='bridge')

    try:
        assert container.state == 'creating'

        container = super_client.wait_success(container)

        assert container.state == 'running'

        assert container.data.dockerContainer.Image == TEST_IMAGE
    finally:
        if container is not None:
            docker_client.delete(container)


@if_docker
def test_docker_build(docker_client, super_client):
    uuid = 'image-' + random_str()
    url = 'https://github.com/rancherio/tiny-build/raw/master/build.tar'
    container = docker_client.create_container(imageUuid='docker:' + uuid,
                                               networkMode='bridge',
                                               build={
                                                   'context': url,
                                               })

    try:
        assert container.state == 'creating'
        container = super_client.wait_success(container)

        # This builds tianon/true which just dies
        assert container.state == 'running' or container.state == 'stopped'
        assert container.transitioning == 'no'
        assert container.data.dockerContainer.Image == uuid
    finally:
        if container is not None:
            docker_client.delete(container)


@if_docker
def test_docker_create_with_start_using_docker_io(docker_client, super_client):
    image = 'docker.io/' + TEST_IMAGE
    uuid = 'docker:' + image
    container = docker_client.create_container(imageUuid=uuid,
                                               networkMode='bridge')
    container = super_client.wait_success(container)
    assert container.state == 'running'
    assert container.data.dockerContainer.Image == image
    if container is not None:
        docker_client.delete(container)


@if_docker
def test_docker_command(docker_client, super_client):
    uuid = TEST_IMAGE_UUID
    container = docker_client.create_container(imageUuid=uuid,
                                               networkMode='bridge',
                                               command=['sleep', '42'])

    try:
        container = super_client.wait_success(container)
        assert container.data.dockerInspect.Config.Cmd == ['sleep', '42']
    finally:
        if container is not None:
            docker_client.delete(container)


@if_docker
def test_docker_command_args(docker_client, super_client):
    uuid = TEST_IMAGE_UUID
    container = docker_client.create_container(imageUuid=uuid,
                                               networkMode='bridge',
                                               command=['sleep', '1', '2',
                                                        '3'])

    try:
        container = super_client.wait_success(container)
        assert container.data.dockerInspect.Config.Cmd == ['sleep', '1', '2',
                                                           '3']
    finally:
        if container is not None:
            docker_client.delete(container)


@if_docker
def test_short_lived_container(docker_client, super_client):
    container = docker_client.create_container(imageUuid="docker:tianon/true",
                                               networkMode='bridge')
    container = wait_for_condition(
        docker_client, container,
        lambda x: x.state == 'stopped',
        lambda x: 'State is: ' + x.state)

    assert container.state == 'stopped'
    assert container.transitioning == 'no'


@if_docker
def test_docker_stop(docker_client):
    uuid = TEST_IMAGE_UUID
    container = docker_client.create_container(imageUuid=uuid,
                                               networkMode='bridge')

    assert container.state == 'creating'

    container = docker_client.wait_success(container)

    assert container.state == 'running'

    start = time.time()
    container = container.stop(timeout=0)
    assert container.state == 'stopping'

    container = docker_client.wait_success(container)
    delta = time.time() - start
    assert container.state == 'stopped'
    assert delta < 10


@if_docker
def test_docker_purge(docker_client):
    uuid = TEST_IMAGE_UUID
    container = docker_client.create_container(imageUuid=uuid,
                                               networkMode='bridge')

    assert container.state == 'creating'

    container = docker_client.wait_success(container)

    assert container.state == 'running'

    container = container.stop(timeout=0)
    assert container.state == 'stopping'

    container = docker_client.wait_success(container)
    assert container.state == 'stopped'

    docker_client.delete(container)

    container = docker_client.wait_success(container)
    assert container.removed is not None


@if_docker
def test_docker_ports_from_container_publish_all(docker_client):
    uuid = TEST_IMAGE_UUID
    c = docker_client.create_container(networkMode='bridge',
                                       publishAllPorts=True,
                                       imageUuid=uuid)

    c = docker_client.wait_success(c)

    assert c.state == 'running'

    ports = c.ports_link()
    assert len(ports) == 1
    port = ports[0]

    assert port.publicPort is not None
    assert port.privatePort == 8080
    assert port.publicIpAddressId is not None
    assert port.kind == 'imagePort'

    docker_client.delete(c)


@if_docker
def test_docker_ports_from_container_no_pub