import pytest
import os
import yaml
from enough.common import ansible_utils


from enough.common.dotenough import (
    Hosts,
    DotEnough,
    DotEnoughOpenStack,
    DotEnoughOpenStackUnknownProvider,
)


#
# Hosts
#
def test_hosts_create_delete(tmpdir):
    config_dir = str(tmpdir)
    h = Hosts(config_dir)
    host = 'HOST'
    ip = '1.2.3.4'
    port = '22'
    assert h.create_or_update(host, ip, port) is True
    assert h.create_or_update(host, ip, port) is False
    assert os.path.exists(f'{config_dir}/inventory/hosts.yml')
    h = Hosts(config_dir)
    assert h.create_or_update(host, ip, port) is False
    assert h.hosts[host]['ansible_host'] == ip
    assert h.hosts[host]['ansible_port'] == port

    assert h.missings([host, 'MISSING']) == ['MISSING']

    h.delete(host)
    h = Hosts(config_dir)
    assert h.hosts == {}


def test_hosts_ensure(tmpdir):
    config_dir = str(tmpdir)
    h = Hosts(config_dir)
    host = 'HOST'
    assert h.ensure(host) is True
    assert h.ensure(host) is False
    assert os.path.exists(f'{config_dir}/inventory/hosts.yml')
    h = Hosts(config_dir)
    assert h.ensure(host) is False
    assert h.hosts[host] == {}


#
# DotEnough
#
def test_service_add_to_group(tmpdir):
    d = DotEnough(tmpdir, 'test.com')
    service = 'SERVICE'
    group = DotEnough.service2group(service)
    host = 'HOST'
    expected = {
        group: {
            'hosts': {
                host: None,
            }
        }
    }
    assert d.service_add_to_group(service, host) == expected
    assert d.service_add_to_group(service, host) == expected
    other_host = 'OTHER'
    expected[group]['hosts'][other_host] = None
    assert d.service_add_to_group(service, other_host) == expected
    os.system(f'cat {tmpdir}/services.yml')


#
# DotEnoughOpenStack
#
@pytest.mark.parametrize("clouds,cloud,provider", [
    (
        {
            'clouds': {
                'production': {
                    'auth': {
                        'auth_url': 'https://identity.api.ams.fuga.cloud:443/v3'
                    }
                }
            }
        },
        'production', 'fuga'),
    (
        {
            'clouds': {
                'production': {
                    'auth': {
                        'auth_url': 'https://auth.cloud.ovh.net/v3/'
                    }
                }
            }
        },
        'production', 'ovh'),
])
def test_populate_provider_supported(tmpdir, clouds, cloud, provider):
    d = DotEnoughOpenStack(tmpdir, 'test.com')
    f = f'{d.config_dir}/inventory/group_vars/all/clouds.yml'
    open(f, 'w').write(yaml.dump(clouds))
    a = ansible_utils.Ansible(d.config_dir, d.config_dir,
                              ['tests/enough/common/test_init/provider'])
    f = d.populate_provider(a, 'production')
    v = yaml.safe_load(open(f).read())
    assert v['openstack_provider'] == provider


def test_populate_provider_set(tmpdir):
    d = DotEnoughOpenStack(tmpdir, 'test.com')
    f = f'{d.config_dir}/inventory/group_vars/all/openstack_provider.yml'
    open(f, 'w').write(yaml.dump({'openstack_provider': 'known'}))
    a = ansible_utils.Ansible(d.config_dir, d.config_dir,
                              ['tests/enough/common/test_init/provider'])
    assert d.populate_provider(a, 'production') == 'known'


def test_populate_provider_no_clouds(tmpdir):
    d = DotEnoughOpenStack(tmpdir, 'test.com')
    a = ansible_utils.Ansible(d.config_dir, d.config_dir,
                              ['tests/enough/common/test_init/provider'])
    assert d.populate_provider(a, 'production') is None


def test_populate_provider_unknown(tmpdir):
    d = DotEnoughOpenStack(tmpdir, 'test.com')
    clouds = {
        'clouds': {
            'production': {
                'auth': {
                    'auth_url': 'https://example.com/'
                }
            }
        }
    }
    f = f'{d.config_dir}/inventory/group_vars/all/clouds.yml'
    open(f, 'w').write(yaml.dump(clouds))
    a = ansible_utils.Ansible(d.config_dir, d.config_dir,
                              ['tests/enough/common/test_init/provider'])
    with pytest.raises(DotEnoughOpenStackUnknownProvider) as e:
        assert d.populate_provider(a, 'production') == ''
    assert 'example.com' in str(e)
