Browse Source

enough: set openstack_provider from auth_url

When openstack_provider is not a known ansible variable, set it
by guessing from the auth_url value.
keep-around/466a386ec226d0aaa1b93008bef1f91328501227
Loïc Dachary 11 months ago
parent
commit
466a386ec2
Signed by: dachary GPG Key ID: 992D23B392F9E4F2
  1. 10
      enough/common/__init__.py
  2. 6
      enough/common/ansible_utils.py
  3. 35
      enough/common/dotenough.py
  4. 4
      tests/enough/common/test_ansible_utils.py
  5. 85
      tests/enough/common/test_dotenough.py
  6. 4
      tests/enough/common/test_init/provider/hosts.yml

10
enough/common/__init__.py

@ -6,7 +6,7 @@ import shutil
import textwrap
import yaml
from enough.common.dotenough import DotEnough, Hosts
from enough.common.dotenough import DotEnoughOpenStack, DotEnough, Hosts
from enough.common.host import host_factory
from enough.common.service import service_factory
from enough.common.openstack import OpenStack, Heat
@ -28,12 +28,16 @@ class Enough(object):
self.args = self.init_args.copy()
self.args.update(kwargs)
self.dotenough = DotEnough(self.config_dir, self.args['domain'])
self.ansible = ansible_utils.Ansible(self.config_dir, self.share_dir,
self.args.get('inventory'))
if self.args.get('driver') == 'openstack':
self.dotenough = DotEnoughOpenStack(self.config_dir, self.args['domain'])
cloud = self.ansible.get_global_variable('openstack_cloud')
if 'cloud' not in self.args:
self.args['cloud'] = self.ansible.get_global_variable('openstack_cloud')
self.args['cloud'] = cloud
self.dotenough.populate_provider(self.ansible, cloud)
else:
self.dotenough = DotEnough(self.config_dir, self.args['domain'])
self.hosts = Hosts(self.config_dir)
self.host = host_factory(self.config_dir, self.share_dir, **self.args)
self.service = service_factory(self.config_dir, self.share_dir, **self.args)

6
enough/common/ansible_utils.py

@ -10,6 +10,10 @@ import textwrap
log = logging.getLogger(__name__)
class AnsibleVariableNotFound(Exception):
pass
class Ansible(object):
bake_method = sh.ansible
@ -149,7 +153,7 @@ class Ansible(object):
values = {k: v.get(variable) for k, v in out.items()}
for k, v in values.items():
if v == 'VARIABLE IS NOT DEFINED!':
raise KeyError("%r is not defined" % variable)
raise AnsibleVariableNotFound("%r is not defined" % variable)
return values

35
enough/common/dotenough.py

@ -3,6 +3,7 @@ import sh
import shutil
import textwrap
import yaml
from enough.common import ansible_utils
class Hosts(object):
@ -133,6 +134,10 @@ class DotEnough(object):
"""))
class DotEnoughOpenStackUnknownProvider(Exception):
pass
class DotEnoughOpenStack(DotEnough):
def __init__(self, config_dir, domain):
@ -146,6 +151,36 @@ class DotEnoughOpenStack(DotEnough):
super().ensure()
self.populate_config('letsencrypt')
def populate_provider(self, ansible, cloud):
try:
return ansible.get_global_variable('openstack_provider')
except ansible_utils.AnsibleVariableNotFound:
pass
try:
clouds = ansible.get_global_variable('clouds')
except ansible_utils.AnsibleVariableNotFound:
return None
url = clouds[cloud]['auth']['auth_url']
string2provider = (('ovh.net', 'ovh'),
('fuga.cloud', 'fuga'))
provider = None
for (string, found) in string2provider:
if string in url:
provider = found
break
if provider is None:
raise DotEnoughOpenStackUnknownProvider(
f'url {url} does not match any known providers {string2provider}')
f = f'{self.config_dir}/inventory/group_vars/all/openstack-provider.yml'
open(f, 'w').write(textwrap.dedent(f"""\
---
openstack_provider: {provider}
"""))
return f
class DotEnoughDocker(DotEnough):

4
tests/enough/common/test_ansible_utils.py

@ -11,7 +11,7 @@ from enough.common import ansible_utils
def test_get_global_variable():
ansible = ansible_utils.Ansible(settings.CONFIG_DIR, settings.SHARE_DIR)
assert ansible.get_global_variable('openstack_cloud')
with pytest.raises(KeyError):
with pytest.raises(ansible_utils.AnsibleVariableNotFound):
assert ansible.get_global_variable('UNKNOWN')
@ -77,7 +77,7 @@ def test_get_hostvars_unknown_host():
def test_get_hostvars_unknown_variable():
ansible = ansible_utils.Ansible(settings.CONFIG_DIR, settings.SHARE_DIR)
with pytest.raises(KeyError):
with pytest.raises(ansible_utils.AnsibleVariableNotFound):
ansible.get_hostvars('inexistent-variable', 'bind-host')

85
tests/enough/common/test_dotenough.py

@ -1,6 +1,15 @@
import pytest
import os
import yaml
from enough.common import ansible_utils
from enough.common.dotenough import Hosts, DotEnough
from enough.common.dotenough import (
Hosts,
DotEnough,
DotEnoughOpenStack,
DotEnoughOpenStackUnknownProvider,
)
#
@ -60,3 +69,77 @@ def test_service_add_to_group(tmpdir):
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)

4
tests/enough/common/test_init/provider/hosts.yml

@ -0,0 +1,4 @@
---
all:
hosts:
bind-host:
Loading…
Cancel
Save