2
from __future__ import print_function
4
from argparse import ArgumentParser
5
from contextlib import contextmanager
6
from copy import deepcopy
7
from difflib import ndiff
9
from pprint import pformat
13
from jujupy import client_from_config
20
def remove_display_attributes(cloud):
21
"""Remove the attributes added by display.
23
The 'defined' attribute is asserted to be 'local'.
24
The description attribute is asserted to be appropriate for the cloud type.
27
'openstack': 'Openstack Cloud',
30
'maas': 'Metal As A Service',
32
# The lack of built-in descriptions for vsphere and manual is
33
# bug #1646128. The inability to specify descriptions interactively is
35
defined = cloud.pop('defined')
36
assert_equal(defined, 'local')
37
description = cloud.pop('description')
38
assert_equal(description, type_descriptions[cloud['type']])
41
def get_clouds(client):
42
cloud_list = yaml.safe_load(client.get_juju_output(
43
'clouds', '--format', 'yaml', include_e=False))
44
for cloud_name, cloud in cloud_list.items():
45
if cloud['defined'] == 'built-in':
46
del cloud_list[cloud_name]
48
remove_display_attributes(cloud)
52
def get_home_path(client, subpath):
53
return os.path.join(client.env.juju_home, subpath)
56
def assert_equal(first, second):
57
"""If two values are not the same, raise JujuAssertionError.
59
The text of the error is a diff of the pretty-printed values.
62
diff = ndiff(pformat(first).splitlines(), pformat(second).splitlines())
63
raise JujuAssertionError('\n' + '\n'.join(diff))
66
def assess_clouds(client, expected):
67
"""Assess how clouds behaves when only expected clouds are defined."""
68
cloud_list = get_clouds(client)
69
assert_equal(cloud_list, expected)
72
def assess_show_cloud(client, expected):
73
"""Assess how show-cloud behaves."""
74
for cloud_name, expected_cloud in expected.items():
75
actual_cloud = yaml.safe_load(client.get_juju_output(
76
'show-cloud', cloud_name, '--format', 'yaml', include_e=False))
77
remove_display_attributes(actual_cloud)
78
assert_equal(actual_cloud, expected_cloud)
81
def strip_redundant_endpoints(clouds):
82
no_region_endpoint = deepcopy(clouds)
83
for cloud in no_region_endpoint.values():
84
for region in cloud.get('regions', {}).values():
85
if region['endpoint'] == cloud['endpoint']:
86
region.pop('endpoint')
87
return no_region_endpoint
91
def testing(test_name):
95
print('{}: FAIL'.format(test_name))
98
print('{}: PASS'.format(test_name))
102
parser = ArgumentParser()
103
parser.add_argument('clouds_file')
104
add_arg_juju_bin(parser)
105
args = parser.parse_args()
106
client = client_from_config(None, args.juju_bin)
107
with client.env.make_jes_home(client.env.juju_home, 'mytest',
109
client.env.juju_home = juju_home
110
with open(get_home_path(client, 'public-clouds.yaml'), 'w') as f:
112
with testing('assess_clouds (no_clouds)'):
113
assess_clouds(client, {})
114
with open(args.clouds_file) as f:
115
supplied_clouds = yaml.safe_load(f.read().decode('utf-8'))
116
client.env.write_clouds(client.env.juju_home, supplied_clouds)
117
no_region_endpoint = strip_redundant_endpoints(
118
supplied_clouds['clouds'])
119
with testing('assess_clouds'):
120
assess_clouds(client, no_region_endpoint)
121
with testing('assess_show_cloud'):
122
assess_show_cloud(client, no_region_endpoint)
125
if __name__ == '__main__':