Blackify everything else
Black used with the '-l 79 -S' flags. A future change will ignore this commit in git-blame history by adding a 'git-blame-ignore-revs' file. Change-Id: Ie106a5cec8831e113a2b764b62b712a205e3153b Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
parent
004c7352d0
commit
a36f514295
@ -77,10 +77,13 @@ htmlhelp_basename = 'openstacksdkdoc'
|
|||||||
# (source start file, target name, title, author, documentclass
|
# (source start file, target name, title, author, documentclass
|
||||||
# [howto/manual]).
|
# [howto/manual]).
|
||||||
latex_documents = [
|
latex_documents = [
|
||||||
('index',
|
(
|
||||||
'doc-openstacksdk.tex',
|
'index',
|
||||||
'OpenStackSDK Documentation',
|
'doc-openstacksdk.tex',
|
||||||
'OpenStack Foundation', 'manual'),
|
'OpenStackSDK Documentation',
|
||||||
|
'OpenStack Foundation',
|
||||||
|
'manual',
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Allow deeper levels of nesting for \begin...\end stanzas
|
# Allow deeper levels of nesting for \begin...\end stanzas
|
||||||
|
@ -16,11 +16,11 @@ from openstack import cloud as openstack
|
|||||||
openstack.enable_logging(debug=True)
|
openstack.enable_logging(debug=True)
|
||||||
|
|
||||||
for cloud_name, region_name in [
|
for cloud_name, region_name in [
|
||||||
('my-vexxhost', 'ca-ymq-1'),
|
('my-vexxhost', 'ca-ymq-1'),
|
||||||
('my-citycloud', 'Buf1'),
|
('my-citycloud', 'Buf1'),
|
||||||
('my-internap', 'ams01')]:
|
('my-internap', 'ams01'),
|
||||||
|
]:
|
||||||
# Initialize cloud
|
# Initialize cloud
|
||||||
cloud = openstack.connect(
|
cloud = openstack.connect(cloud=cloud_name, region_name=region_name)
|
||||||
cloud=cloud_name, region_name=region_name)
|
|
||||||
for server in cloud.search_servers('my-server'):
|
for server in cloud.search_servers('my-server'):
|
||||||
cloud.delete_server(server, wait=True, delete_ips=True)
|
cloud.delete_server(server, wait=True, delete_ips=True)
|
||||||
|
@ -16,20 +16,31 @@ from openstack import cloud as openstack
|
|||||||
openstack.enable_logging(debug=True)
|
openstack.enable_logging(debug=True)
|
||||||
|
|
||||||
for cloud_name, region_name, image, flavor_id in [
|
for cloud_name, region_name, image, flavor_id in [
|
||||||
('my-vexxhost', 'ca-ymq-1', 'Ubuntu 16.04.1 LTS [2017-03-03]',
|
(
|
||||||
'5cf64088-893b-46b5-9bb1-ee020277635d'),
|
'my-vexxhost',
|
||||||
('my-citycloud', 'Buf1', 'Ubuntu 16.04 Xenial Xerus',
|
'ca-ymq-1',
|
||||||
'0dab10b5-42a2-438e-be7b-505741a7ffcc'),
|
'Ubuntu 16.04.1 LTS [2017-03-03]',
|
||||||
('my-internap', 'ams01', 'Ubuntu 16.04 LTS (Xenial Xerus)',
|
'5cf64088-893b-46b5-9bb1-ee020277635d',
|
||||||
'A1.4')]:
|
),
|
||||||
|
(
|
||||||
|
'my-citycloud',
|
||||||
|
'Buf1',
|
||||||
|
'Ubuntu 16.04 Xenial Xerus',
|
||||||
|
'0dab10b5-42a2-438e-be7b-505741a7ffcc',
|
||||||
|
),
|
||||||
|
('my-internap', 'ams01', 'Ubuntu 16.04 LTS (Xenial Xerus)', 'A1.4'),
|
||||||
|
]:
|
||||||
# Initialize cloud
|
# Initialize cloud
|
||||||
cloud = openstack.connect(
|
cloud = openstack.connect(cloud=cloud_name, region_name=region_name)
|
||||||
cloud=cloud_name, region_name=region_name)
|
|
||||||
|
|
||||||
# Boot a server, wait for it to boot, and then do whatever is needed
|
# Boot a server, wait for it to boot, and then do whatever is needed
|
||||||
# to get a public ip for it.
|
# to get a public ip for it.
|
||||||
server = cloud.create_server(
|
server = cloud.create_server(
|
||||||
'my-server', image=image, flavor=dict(id=flavor_id),
|
'my-server',
|
||||||
wait=True, auto_ip=True)
|
image=image,
|
||||||
|
flavor=dict(id=flavor_id),
|
||||||
|
wait=True,
|
||||||
|
auto_ip=True,
|
||||||
|
)
|
||||||
# Delete it - this is a demo
|
# Delete it - this is a demo
|
||||||
cloud.delete_server(server, wait=True, delete_ips=True)
|
cloud.delete_server(server, wait=True, delete_ips=True)
|
||||||
|
@ -16,21 +16,24 @@ from openstack import cloud as openstack
|
|||||||
openstack.enable_logging(debug=True)
|
openstack.enable_logging(debug=True)
|
||||||
|
|
||||||
for cloud_name, region_name, image, flavor in [
|
for cloud_name, region_name, image, flavor in [
|
||||||
('my-vexxhost', 'ca-ymq-1',
|
(
|
||||||
'Ubuntu 16.04.1 LTS [2017-03-03]', 'v1-standard-4'),
|
'my-vexxhost',
|
||||||
('my-citycloud', 'Buf1',
|
'ca-ymq-1',
|
||||||
'Ubuntu 16.04 Xenial Xerus', '4C-4GB-100GB'),
|
'Ubuntu 16.04.1 LTS [2017-03-03]',
|
||||||
('my-internap', 'ams01',
|
'v1-standard-4',
|
||||||
'Ubuntu 16.04 LTS (Xenial Xerus)', 'A1.4')]:
|
),
|
||||||
|
('my-citycloud', 'Buf1', 'Ubuntu 16.04 Xenial Xerus', '4C-4GB-100GB'),
|
||||||
|
('my-internap', 'ams01', 'Ubuntu 16.04 LTS (Xenial Xerus)', 'A1.4'),
|
||||||
|
]:
|
||||||
# Initialize cloud
|
# Initialize cloud
|
||||||
cloud = openstack.connect(
|
cloud = openstack.connect(cloud=cloud_name, region_name=region_name)
|
||||||
cloud=cloud_name, region_name=region_name)
|
|
||||||
cloud.delete_server('my-server', wait=True, delete_ips=True)
|
cloud.delete_server('my-server', wait=True, delete_ips=True)
|
||||||
|
|
||||||
# Boot a server, wait for it to boot, and then do whatever is needed
|
# Boot a server, wait for it to boot, and then do whatever is needed
|
||||||
# to get a public ip for it.
|
# to get a public ip for it.
|
||||||
server = cloud.create_server(
|
server = cloud.create_server(
|
||||||
'my-server', image=image, flavor=flavor, wait=True, auto_ip=True)
|
'my-server', image=image, flavor=flavor, wait=True, auto_ip=True
|
||||||
|
)
|
||||||
print(server.name)
|
print(server.name)
|
||||||
print(server['name'])
|
print(server['name'])
|
||||||
cloud.pprint(server)
|
cloud.pprint(server)
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from openstack import cloud as openstack
|
from openstack import cloud as openstack
|
||||||
|
|
||||||
openstack.enable_logging(debug=True)
|
openstack.enable_logging(debug=True)
|
||||||
|
|
||||||
cloud = openstack.connect(
|
cloud = openstack.connect(cloud='my-vexxhost', region_name='ca-ymq-1')
|
||||||
cloud='my-vexxhost', region_name='ca-ymq-1')
|
|
||||||
cloud.get_image('Ubuntu 16.04.1 LTS [2017-03-03]')
|
cloud.get_image('Ubuntu 16.04.1 LTS [2017-03-03]')
|
||||||
|
@ -11,9 +11,10 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from openstack import cloud as openstack
|
from openstack import cloud as openstack
|
||||||
|
|
||||||
openstack.enable_logging()
|
openstack.enable_logging()
|
||||||
|
|
||||||
cloud = openstack.connect(cloud='fuga', region_name='cystack')
|
cloud = openstack.connect(cloud='fuga', region_name='cystack')
|
||||||
cloud.pprint([
|
cloud.pprint(
|
||||||
image for image in cloud.list_images()
|
[image for image in cloud.list_images() if 'ubuntu' in image.name.lower()]
|
||||||
if 'ubuntu' in image.name.lower()])
|
)
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from openstack import cloud as openstack
|
from openstack import cloud as openstack
|
||||||
|
|
||||||
openstack.enable_logging(http_debug=True)
|
openstack.enable_logging(http_debug=True)
|
||||||
|
|
||||||
cloud = openstack.connect(
|
cloud = openstack.connect(cloud='my-vexxhost', region_name='ca-ymq-1')
|
||||||
cloud='my-vexxhost', region_name='ca-ymq-1')
|
|
||||||
cloud.get_image('Ubuntu 16.04.1 LTS [2017-03-03]')
|
cloud.get_image('Ubuntu 16.04.1 LTS [2017-03-03]')
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from openstack import cloud as openstack
|
from openstack import cloud as openstack
|
||||||
|
|
||||||
openstack.enable_logging(debug=True)
|
openstack.enable_logging(debug=True)
|
||||||
|
|
||||||
cloud = openstack.connect(cloud='ovh', region_name='SBG1')
|
cloud = openstack.connect(cloud='ovh', region_name='SBG1')
|
||||||
|
@ -11,9 +11,11 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from openstack import cloud as openstack
|
from openstack import cloud as openstack
|
||||||
|
|
||||||
openstack.enable_logging()
|
openstack.enable_logging()
|
||||||
|
|
||||||
cloud = openstack.connect(cloud='fuga', region_name='cystack')
|
cloud = openstack.connect(cloud='fuga', region_name='cystack')
|
||||||
image = cloud.get_image(
|
image = cloud.get_image(
|
||||||
'Ubuntu 16.04 LTS - Xenial Xerus - 64-bit - Fuga Cloud Based Image')
|
'Ubuntu 16.04 LTS - Xenial Xerus - 64-bit - Fuga Cloud Based Image'
|
||||||
|
)
|
||||||
cloud.pprint(image)
|
cloud.pprint(image)
|
||||||
|
@ -11,14 +11,18 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import openstack
|
import openstack
|
||||||
|
|
||||||
openstack.enable_logging(debug=True)
|
openstack.enable_logging(debug=True)
|
||||||
|
|
||||||
cloud = openstack.connect(cloud='my-citycloud', region_name='Buf1')
|
cloud = openstack.connect(cloud='my-citycloud', region_name='Buf1')
|
||||||
try:
|
try:
|
||||||
server = cloud.create_server(
|
server = cloud.create_server(
|
||||||
'my-server', image='Ubuntu 16.04 Xenial Xerus',
|
'my-server',
|
||||||
|
image='Ubuntu 16.04 Xenial Xerus',
|
||||||
flavor=dict(id='0dab10b5-42a2-438e-be7b-505741a7ffcc'),
|
flavor=dict(id='0dab10b5-42a2-438e-be7b-505741a7ffcc'),
|
||||||
wait=True, auto_ip=True)
|
wait=True,
|
||||||
|
auto_ip=True,
|
||||||
|
)
|
||||||
|
|
||||||
print("\n\nFull Server\n\n")
|
print("\n\nFull Server\n\n")
|
||||||
cloud.pprint(server)
|
cloud.pprint(server)
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import openstack
|
import openstack
|
||||||
|
|
||||||
openstack.enable_logging(debug=True)
|
openstack.enable_logging(debug=True)
|
||||||
|
|
||||||
cloud = openstack.connect(cloud='rax', region_name='DFW')
|
cloud = openstack.connect(cloud='rax', region_name='DFW')
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import openstack
|
import openstack
|
||||||
|
|
||||||
openstack.enable_logging(debug=True)
|
openstack.enable_logging(debug=True)
|
||||||
|
|
||||||
cloud = openstack.connect(cloud='kiss', region_name='region1')
|
cloud = openstack.connect(cloud='kiss', region_name='region1')
|
||||||
|
@ -11,10 +11,11 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import openstack
|
import openstack
|
||||||
|
|
||||||
openstack.enable_logging()
|
openstack.enable_logging()
|
||||||
|
|
||||||
cloud = openstack.connect(
|
cloud = openstack.connect(cloud='fuga', region_name='cystack', strict=True)
|
||||||
cloud='fuga', region_name='cystack', strict=True)
|
|
||||||
image = cloud.get_image(
|
image = cloud.get_image(
|
||||||
'Ubuntu 16.04 LTS - Xenial Xerus - 64-bit - Fuga Cloud Based Image')
|
'Ubuntu 16.04 LTS - Xenial Xerus - 64-bit - Fuga Cloud Based Image'
|
||||||
|
)
|
||||||
cloud.pprint(image)
|
cloud.pprint(image)
|
||||||
|
@ -11,12 +11,15 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import openstack
|
import openstack
|
||||||
|
|
||||||
openstack.enable_logging(debug=True)
|
openstack.enable_logging(debug=True)
|
||||||
|
|
||||||
cloud = openstack.connect(cloud='ovh', region_name='SBG1')
|
cloud = openstack.connect(cloud='ovh', region_name='SBG1')
|
||||||
cloud.create_object(
|
cloud.create_object(
|
||||||
container='my-container', name='my-object',
|
container='my-container',
|
||||||
|
name='my-object',
|
||||||
filename='/home/mordred/briarcliff.sh3d',
|
filename='/home/mordred/briarcliff.sh3d',
|
||||||
segment_size=1000000)
|
segment_size=1000000,
|
||||||
|
)
|
||||||
cloud.delete_object('my-container', 'my-object')
|
cloud.delete_object('my-container', 'my-object')
|
||||||
cloud.delete_container('my-container')
|
cloud.delete_container('my-container')
|
||||||
|
@ -11,12 +11,15 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import openstack
|
import openstack
|
||||||
|
|
||||||
openstack.enable_logging(debug=True)
|
openstack.enable_logging(debug=True)
|
||||||
|
|
||||||
cloud = openstack.connect(cloud='ovh', region_name='SBG1')
|
cloud = openstack.connect(cloud='ovh', region_name='SBG1')
|
||||||
cloud.create_object(
|
cloud.create_object(
|
||||||
container='my-container', name='my-object',
|
container='my-container',
|
||||||
|
name='my-object',
|
||||||
filename='/home/mordred/briarcliff.sh3d',
|
filename='/home/mordred/briarcliff.sh3d',
|
||||||
segment_size=1000000)
|
segment_size=1000000,
|
||||||
|
)
|
||||||
cloud.delete_object('my-container', 'my-object')
|
cloud.delete_object('my-container', 'my-object')
|
||||||
cloud.delete_container('my-container')
|
cloud.delete_container('my-container')
|
||||||
|
@ -11,8 +11,10 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import openstack
|
import openstack
|
||||||
|
|
||||||
openstack.enable_logging(http_debug=True)
|
openstack.enable_logging(http_debug=True)
|
||||||
|
|
||||||
cloud = openstack.connect(
|
cloud = openstack.connect(
|
||||||
cloud='datacentred', app_name='AmazingApp', app_version='1.0')
|
cloud='datacentred', app_name='AmazingApp', app_version='1.0'
|
||||||
|
)
|
||||||
cloud.list_networks()
|
cloud.list_networks()
|
||||||
|
@ -107,9 +107,7 @@ def replace_nodes_in_cluster(conn):
|
|||||||
|
|
||||||
old_node = NODE_ID
|
old_node = NODE_ID
|
||||||
new_node = "cd803d4a-015d-4223-b15f-db29bad3146c"
|
new_node = "cd803d4a-015d-4223-b15f-db29bad3146c"
|
||||||
spec = {
|
spec = {old_node: new_node}
|
||||||
old_node: new_node
|
|
||||||
}
|
|
||||||
res = conn.clustering.replace_nodes_in_cluster(CLUSTER_ID, **spec)
|
res = conn.clustering.replace_nodes_in_cluster(CLUSTER_ID, **spec)
|
||||||
print(res)
|
print(res)
|
||||||
|
|
||||||
@ -135,7 +133,7 @@ def resize_cluster(conn):
|
|||||||
'min_size': 1,
|
'min_size': 1,
|
||||||
'max_size': 6,
|
'max_size': 6,
|
||||||
'adjustment_type': 'EXACT_CAPACITY',
|
'adjustment_type': 'EXACT_CAPACITY',
|
||||||
'number': 2
|
'number': 2,
|
||||||
}
|
}
|
||||||
res = conn.clustering.resize_cluster(CLUSTER_ID, **spec)
|
res = conn.clustering.resize_cluster(CLUSTER_ID, **spec)
|
||||||
print(res)
|
print(res)
|
||||||
@ -146,7 +144,8 @@ def attach_policy_to_cluster(conn):
|
|||||||
|
|
||||||
spec = {'enabled': True}
|
spec = {'enabled': True}
|
||||||
res = conn.clustering.attach_policy_to_cluster(
|
res = conn.clustering.attach_policy_to_cluster(
|
||||||
CLUSTER_ID, POLICY_ID, **spec)
|
CLUSTER_ID, POLICY_ID, **spec
|
||||||
|
)
|
||||||
print(res)
|
print(res)
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ def create_policy(conn):
|
|||||||
'properties': {
|
'properties': {
|
||||||
'criteria': 'oldest_first',
|
'criteria': 'oldest_first',
|
||||||
'destroy_after_deletion': True,
|
'destroy_after_deletion': True,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
policy = conn.clustering.create_policy(attrs)
|
policy = conn.clustering.create_policy(attrs)
|
||||||
|
@ -44,10 +44,8 @@ def create_profile(conn):
|
|||||||
'name': SERVER_NAME,
|
'name': SERVER_NAME,
|
||||||
'flavor': FLAVOR_NAME,
|
'flavor': FLAVOR_NAME,
|
||||||
'image': IMAGE_NAME,
|
'image': IMAGE_NAME,
|
||||||
'networks': {
|
'networks': {'network': NETWORK_NAME},
|
||||||
'network': NETWORK_NAME
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
profile = conn.clustering.create_profile(spec)
|
profile = conn.clustering.create_profile(spec)
|
||||||
|
@ -39,10 +39,8 @@ def create_receiver(conn):
|
|||||||
"action": "CLUSTER_SCALE_OUT",
|
"action": "CLUSTER_SCALE_OUT",
|
||||||
"cluster_id": CLUSTER_ID,
|
"cluster_id": CLUSTER_ID,
|
||||||
"name": FAKE_NAME,
|
"name": FAKE_NAME,
|
||||||
"params": {
|
"params": {"count": "1"},
|
||||||
"count": "1"
|
"type": "webhook",
|
||||||
},
|
|
||||||
"type": "webhook"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
receiver = conn.clustering.create_receiver(**spec)
|
receiver = conn.clustering.create_receiver(**spec)
|
||||||
@ -66,12 +64,7 @@ def find_receiver(conn):
|
|||||||
def update_receiver(conn):
|
def update_receiver(conn):
|
||||||
print("Update Receiver:")
|
print("Update Receiver:")
|
||||||
|
|
||||||
spec = {
|
spec = {"name": "test_receiver2", "params": {"count": "2"}}
|
||||||
"name": "test_receiver2",
|
|
||||||
"params": {
|
|
||||||
"count": "2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
receiver = conn.clustering.update_receiver(FAKE_NAME, **spec)
|
receiver = conn.clustering.update_receiver(FAKE_NAME, **spec)
|
||||||
print(receiver.to_dict())
|
print(receiver.to_dict())
|
||||||
|
|
||||||
|
@ -62,11 +62,17 @@ def create_server(conn):
|
|||||||
keypair = create_keypair(conn)
|
keypair = create_keypair(conn)
|
||||||
|
|
||||||
server = conn.compute.create_server(
|
server = conn.compute.create_server(
|
||||||
name=SERVER_NAME, image_id=image.id, flavor_id=flavor.id,
|
name=SERVER_NAME,
|
||||||
networks=[{"uuid": network.id}], key_name=keypair.name)
|
image_id=image.id,
|
||||||
|
flavor_id=flavor.id,
|
||||||
|
networks=[{"uuid": network.id}],
|
||||||
|
key_name=keypair.name,
|
||||||
|
)
|
||||||
|
|
||||||
server = conn.compute.wait_for_server(server)
|
server = conn.compute.wait_for_server(server)
|
||||||
|
|
||||||
print("ssh -i {key} root@{ip}".format(
|
print(
|
||||||
key=PRIVATE_KEYPAIR_FILE,
|
"ssh -i {key} root@{ip}".format(
|
||||||
ip=server.access_ipv4))
|
key=PRIVATE_KEYPAIR_FILE, ip=server.access_ipv4
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@ -45,8 +45,9 @@ class Opts:
|
|||||||
|
|
||||||
|
|
||||||
def _get_resource_value(resource_key, default):
|
def _get_resource_value(resource_key, default):
|
||||||
return config.get_extra_config(
|
return config.get_extra_config(EXAMPLE_CONFIG_KEY).get(
|
||||||
EXAMPLE_CONFIG_KEY).get(resource_key, default)
|
resource_key, default
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
SERVER_NAME = 'openstacksdk-example'
|
SERVER_NAME = 'openstacksdk-example'
|
||||||
@ -55,10 +56,12 @@ FLAVOR_NAME = _get_resource_value('flavor_name', 'm1.small')
|
|||||||
NETWORK_NAME = _get_resource_value('network_name', 'private')
|
NETWORK_NAME = _get_resource_value('network_name', 'private')
|
||||||
KEYPAIR_NAME = _get_resource_value('keypair_name', 'openstacksdk-example')
|
KEYPAIR_NAME = _get_resource_value('keypair_name', 'openstacksdk-example')
|
||||||
SSH_DIR = _get_resource_value(
|
SSH_DIR = _get_resource_value(
|
||||||
'ssh_dir', '{home}/.ssh'.format(home=os.path.expanduser("~")))
|
'ssh_dir', '{home}/.ssh'.format(home=os.path.expanduser("~"))
|
||||||
|
)
|
||||||
PRIVATE_KEYPAIR_FILE = _get_resource_value(
|
PRIVATE_KEYPAIR_FILE = _get_resource_value(
|
||||||
'private_keypair_file', '{ssh_dir}/id_rsa.{key}'.format(
|
'private_keypair_file',
|
||||||
ssh_dir=SSH_DIR, key=KEYPAIR_NAME))
|
'{ssh_dir}/id_rsa.{key}'.format(ssh_dir=SSH_DIR, key=KEYPAIR_NAME),
|
||||||
|
)
|
||||||
|
|
||||||
EXAMPLE_IMAGE_NAME = 'openstacksdk-example-public-image'
|
EXAMPLE_IMAGE_NAME = 'openstacksdk-example-public-image'
|
||||||
|
|
||||||
@ -72,8 +75,15 @@ def create_connection_from_args():
|
|||||||
return openstack.connect(options=parser)
|
return openstack.connect(options=parser)
|
||||||
|
|
||||||
|
|
||||||
def create_connection(auth_url, region, project_name, username, password,
|
def create_connection(
|
||||||
user_domain, project_domain):
|
auth_url,
|
||||||
|
region,
|
||||||
|
project_name,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
user_domain,
|
||||||
|
project_domain,
|
||||||
|
):
|
||||||
return openstack.connect(
|
return openstack.connect(
|
||||||
auth_url=auth_url,
|
auth_url=auth_url,
|
||||||
project_name=project_name,
|
project_name=project_name,
|
||||||
|
@ -24,8 +24,10 @@ def import_image(conn):
|
|||||||
print("Import Image:")
|
print("Import Image:")
|
||||||
|
|
||||||
# Url where glance can download the image
|
# Url where glance can download the image
|
||||||
uri = 'https://download.cirros-cloud.net/0.4.0/' \
|
uri = (
|
||||||
'cirros-0.4.0-x86_64-disk.img'
|
'https://download.cirros-cloud.net/0.4.0/'
|
||||||
|
'cirros-0.4.0-x86_64-disk.img'
|
||||||
|
)
|
||||||
|
|
||||||
# Build the image attributes and import the image.
|
# Build the image attributes and import the image.
|
||||||
image_attrs = {
|
image_attrs = {
|
||||||
|
@ -18,8 +18,10 @@ List resources from the Key Manager service.
|
|||||||
def create_secret(conn):
|
def create_secret(conn):
|
||||||
print("Create a secret:")
|
print("Create a secret:")
|
||||||
|
|
||||||
conn.key_manager.create_secret(name="My public key",
|
conn.key_manager.create_secret(
|
||||||
secret_type="public",
|
name="My public key",
|
||||||
expiration="2020-02-28T23:59:59",
|
secret_type="public",
|
||||||
payload="ssh rsa...",
|
expiration="2020-02-28T23:59:59",
|
||||||
payload_content_type="text/plain")
|
payload="ssh rsa...",
|
||||||
|
payload_content_type="text/plain",
|
||||||
|
)
|
||||||
|
@ -26,6 +26,6 @@ def list_secrets_query(conn):
|
|||||||
print("List Secrets:")
|
print("List Secrets:")
|
||||||
|
|
||||||
for secret in conn.key_manager.secrets(
|
for secret in conn.key_manager.secrets(
|
||||||
secret_type="symmetric",
|
secret_type="symmetric", expiration="gte:2020-01-01T00:00:00"
|
||||||
expiration="gte:2020-01-01T00:00:00"):
|
):
|
||||||
print(secret)
|
print(secret)
|
||||||
|
@ -22,7 +22,8 @@ def create_network(conn):
|
|||||||
print("Create Network:")
|
print("Create Network:")
|
||||||
|
|
||||||
example_network = conn.network.create_network(
|
example_network = conn.network.create_network(
|
||||||
name='openstacksdk-example-project-network')
|
name='openstacksdk-example-project-network'
|
||||||
|
)
|
||||||
|
|
||||||
print(example_network)
|
print(example_network)
|
||||||
|
|
||||||
@ -31,6 +32,7 @@ def create_network(conn):
|
|||||||
network_id=example_network.id,
|
network_id=example_network.id,
|
||||||
ip_version='4',
|
ip_version='4',
|
||||||
cidr='10.0.2.0/24',
|
cidr='10.0.2.0/24',
|
||||||
gateway_ip='10.0.2.1')
|
gateway_ip='10.0.2.1',
|
||||||
|
)
|
||||||
|
|
||||||
print(example_subnet)
|
print(example_subnet)
|
||||||
|
@ -22,7 +22,8 @@ def delete_network(conn):
|
|||||||
print("Delete Network:")
|
print("Delete Network:")
|
||||||
|
|
||||||
example_network = conn.network.find_network(
|
example_network = conn.network.find_network(
|
||||||
'openstacksdk-example-project-network')
|
'openstacksdk-example-project-network'
|
||||||
|
)
|
||||||
|
|
||||||
for example_subnet in example_network.subnet_ids:
|
for example_subnet in example_network.subnet_ids:
|
||||||
conn.network.delete_subnet(example_subnet, ignore_missing=False)
|
conn.network.delete_subnet(example_subnet, ignore_missing=False)
|
||||||
|
@ -22,7 +22,8 @@ def open_port(conn):
|
|||||||
print("Open a port:")
|
print("Open a port:")
|
||||||
|
|
||||||
example_sec_group = conn.network.create_security_group(
|
example_sec_group = conn.network.create_security_group(
|
||||||
name='openstacksdk-example-security-group')
|
name='openstacksdk-example-security-group'
|
||||||
|
)
|
||||||
|
|
||||||
print(example_sec_group)
|
print(example_sec_group)
|
||||||
|
|
||||||
@ -33,7 +34,8 @@ def open_port(conn):
|
|||||||
protocol='HTTPS',
|
protocol='HTTPS',
|
||||||
port_range_max='443',
|
port_range_max='443',
|
||||||
port_range_min='443',
|
port_range_min='443',
|
||||||
ethertype='IPv4')
|
ethertype='IPv4',
|
||||||
|
)
|
||||||
|
|
||||||
print(example_rule)
|
print(example_rule)
|
||||||
|
|
||||||
@ -42,7 +44,8 @@ def allow_ping(conn):
|
|||||||
print("Allow pings:")
|
print("Allow pings:")
|
||||||
|
|
||||||
example_sec_group = conn.network.create_security_group(
|
example_sec_group = conn.network.create_security_group(
|
||||||
name='openstacksdk-example-security-group2')
|
name='openstacksdk-example-security-group2'
|
||||||
|
)
|
||||||
|
|
||||||
print(example_sec_group)
|
print(example_sec_group)
|
||||||
|
|
||||||
@ -53,6 +56,7 @@ def allow_ping(conn):
|
|||||||
protocol='icmp',
|
protocol='icmp',
|
||||||
port_range_max=None,
|
port_range_max=None,
|
||||||
port_range_min=None,
|
port_range_min=None,
|
||||||
ethertype='IPv4')
|
ethertype='IPv4',
|
||||||
|
)
|
||||||
|
|
||||||
print(example_rule)
|
print(example_rule)
|
||||||
|
@ -31,8 +31,10 @@ def get_share_instance(conn, share_instance_id):
|
|||||||
|
|
||||||
|
|
||||||
def reset_share_instance_status(conn, share_instance_id, status):
|
def reset_share_instance_status(conn, share_instance_id, status):
|
||||||
print('Reset the status of the share instance with the given '
|
print(
|
||||||
'share_instance_id to the given status')
|
'Reset the status of the share instance with the given '
|
||||||
|
'share_instance_id to the given status'
|
||||||
|
)
|
||||||
conn.share.reset_share_instance_status(share_instance_id, status)
|
conn.share.reset_share_instance_status(share_instance_id, status)
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,16 +19,18 @@ import pbr.version
|
|||||||
|
|
||||||
|
|
||||||
def show_version(args):
|
def show_version(args):
|
||||||
print("OpenstackSDK Version %s" %
|
print(
|
||||||
pbr.version.VersionInfo('openstacksdk').version_string_with_vcs())
|
"OpenstackSDK Version %s"
|
||||||
|
% pbr.version.VersionInfo('openstacksdk').version_string_with_vcs()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Openstack SDK")
|
parser = argparse.ArgumentParser(description="Openstack SDK")
|
||||||
subparsers = parser.add_subparsers(title='commands',
|
subparsers = parser.add_subparsers(title='commands', dest='command')
|
||||||
dest='command')
|
|
||||||
|
|
||||||
cmd_version = subparsers.add_parser('version',
|
cmd_version = subparsers.add_parser(
|
||||||
help='show Openstack SDK version')
|
'version', help='show Openstack SDK version'
|
||||||
|
)
|
||||||
cmd_version.set_defaults(func=show_version)
|
cmd_version.set_defaults(func=show_version)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
@ -44,7 +44,10 @@ def setup_logging(name, handlers=None, level=None):
|
|||||||
|
|
||||||
|
|
||||||
def enable_logging(
|
def enable_logging(
|
||||||
debug=False, http_debug=False, path=None, stream=None,
|
debug=False,
|
||||||
|
http_debug=False,
|
||||||
|
path=None,
|
||||||
|
stream=None,
|
||||||
format_stream=False,
|
format_stream=False,
|
||||||
format_template='%(asctime)s %(levelname)s: %(name)s %(message)s',
|
format_template='%(asctime)s %(levelname)s: %(name)s %(message)s',
|
||||||
handlers=None,
|
handlers=None,
|
||||||
@ -121,9 +124,11 @@ def enable_logging(
|
|||||||
# enable_logging should not be used and instead python logging should
|
# enable_logging should not be used and instead python logging should
|
||||||
# be configured directly.
|
# be configured directly.
|
||||||
setup_logging(
|
setup_logging(
|
||||||
'urllib3', handlers=[logging.NullHandler()], level=logging.INFO)
|
'urllib3', handlers=[logging.NullHandler()], level=logging.INFO
|
||||||
|
)
|
||||||
setup_logging(
|
setup_logging(
|
||||||
'stevedore', handlers=[logging.NullHandler()], level=logging.INFO)
|
'stevedore', handlers=[logging.NullHandler()], level=logging.INFO
|
||||||
|
)
|
||||||
# Suppress warning about keystoneauth loggers
|
# Suppress warning about keystoneauth loggers
|
||||||
setup_logging('keystoneauth.discovery')
|
setup_logging('keystoneauth.discovery')
|
||||||
setup_logging('keystoneauth.identity.base')
|
setup_logging('keystoneauth.identity.base')
|
||||||
|
@ -6,7 +6,9 @@ from openstack.baremetal_introspection import baremetal_introspection_service
|
|||||||
from openstack.block_storage import block_storage_service
|
from openstack.block_storage import block_storage_service
|
||||||
from openstack.clustering import clustering_service
|
from openstack.clustering import clustering_service
|
||||||
from openstack.compute import compute_service
|
from openstack.compute import compute_service
|
||||||
from openstack.container_infrastructure_management import container_infrastructure_management_service
|
from openstack.container_infrastructure_management import (
|
||||||
|
container_infrastructure_management_service,
|
||||||
|
)
|
||||||
from openstack.database import database_service
|
from openstack.database import database_service
|
||||||
from openstack.dns import dns_service
|
from openstack.dns import dns_service
|
||||||
from openstack.identity import identity_service
|
from openstack.identity import identity_service
|
||||||
@ -31,32 +33,52 @@ class ServicesMixin:
|
|||||||
|
|
||||||
image = image_service.ImageService(service_type='image')
|
image = image_service.ImageService(service_type='image')
|
||||||
|
|
||||||
load_balancer = load_balancer_service.LoadBalancerService(service_type='load-balancer')
|
load_balancer = load_balancer_service.LoadBalancerService(
|
||||||
|
service_type='load-balancer'
|
||||||
|
)
|
||||||
|
|
||||||
object_store = object_store_service.ObjectStoreService(service_type='object-store')
|
object_store = object_store_service.ObjectStoreService(
|
||||||
|
service_type='object-store'
|
||||||
|
)
|
||||||
|
|
||||||
clustering = clustering_service.ClusteringService(service_type='clustering')
|
clustering = clustering_service.ClusteringService(
|
||||||
|
service_type='clustering'
|
||||||
|
)
|
||||||
resource_cluster = clustering
|
resource_cluster = clustering
|
||||||
cluster = clustering
|
cluster = clustering
|
||||||
|
|
||||||
data_processing = service_description.ServiceDescription(service_type='data-processing')
|
data_processing = service_description.ServiceDescription(
|
||||||
|
service_type='data-processing'
|
||||||
|
)
|
||||||
|
|
||||||
baremetal = baremetal_service.BaremetalService(service_type='baremetal')
|
baremetal = baremetal_service.BaremetalService(service_type='baremetal')
|
||||||
bare_metal = baremetal
|
bare_metal = baremetal
|
||||||
|
|
||||||
baremetal_introspection = baremetal_introspection_service.BaremetalIntrospectionService(service_type='baremetal-introspection')
|
baremetal_introspection = (
|
||||||
|
baremetal_introspection_service.BaremetalIntrospectionService(
|
||||||
|
service_type='baremetal-introspection'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
key_manager = key_manager_service.KeyManagerService(service_type='key-manager')
|
key_manager = key_manager_service.KeyManagerService(
|
||||||
|
service_type='key-manager'
|
||||||
|
)
|
||||||
|
|
||||||
resource_optimization = service_description.ServiceDescription(service_type='resource-optimization')
|
resource_optimization = service_description.ServiceDescription(
|
||||||
|
service_type='resource-optimization'
|
||||||
|
)
|
||||||
infra_optim = resource_optimization
|
infra_optim = resource_optimization
|
||||||
|
|
||||||
message = message_service.MessageService(service_type='message')
|
message = message_service.MessageService(service_type='message')
|
||||||
messaging = message
|
messaging = message
|
||||||
|
|
||||||
application_catalog = service_description.ServiceDescription(service_type='application-catalog')
|
application_catalog = service_description.ServiceDescription(
|
||||||
|
service_type='application-catalog'
|
||||||
|
)
|
||||||
|
|
||||||
container_infrastructure_management = container_infrastructure_management_service.ContainerInfrastructureManagementService(service_type='container-infrastructure-management')
|
container_infrastructure_management = container_infrastructure_management_service.ContainerInfrastructureManagementService(
|
||||||
|
service_type='container-infrastructure-management'
|
||||||
|
)
|
||||||
container_infra = container_infrastructure_management
|
container_infra = container_infrastructure_management
|
||||||
container_infrastructure = container_infrastructure_management
|
container_infrastructure = container_infrastructure_management
|
||||||
|
|
||||||
@ -68,17 +90,27 @@ class ServicesMixin:
|
|||||||
|
|
||||||
rating = service_description.ServiceDescription(service_type='rating')
|
rating = service_description.ServiceDescription(service_type='rating')
|
||||||
|
|
||||||
operator_policy = service_description.ServiceDescription(service_type='operator-policy')
|
operator_policy = service_description.ServiceDescription(
|
||||||
|
service_type='operator-policy'
|
||||||
|
)
|
||||||
policy = operator_policy
|
policy = operator_policy
|
||||||
|
|
||||||
shared_file_system = shared_file_system_service.SharedFilesystemService(service_type='shared-file-system')
|
shared_file_system = shared_file_system_service.SharedFilesystemService(
|
||||||
|
service_type='shared-file-system'
|
||||||
|
)
|
||||||
share = shared_file_system
|
share = shared_file_system
|
||||||
|
|
||||||
data_protection_orchestration = service_description.ServiceDescription(service_type='data-protection-orchestration')
|
data_protection_orchestration = service_description.ServiceDescription(
|
||||||
|
service_type='data-protection-orchestration'
|
||||||
|
)
|
||||||
|
|
||||||
orchestration = orchestration_service.OrchestrationService(service_type='orchestration')
|
orchestration = orchestration_service.OrchestrationService(
|
||||||
|
service_type='orchestration'
|
||||||
|
)
|
||||||
|
|
||||||
block_storage = block_storage_service.BlockStorageService(service_type='block-storage')
|
block_storage = block_storage_service.BlockStorageService(
|
||||||
|
service_type='block-storage'
|
||||||
|
)
|
||||||
block_store = block_storage
|
block_store = block_storage
|
||||||
volume = block_storage
|
volume = block_storage
|
||||||
|
|
||||||
@ -92,44 +124,69 @@ class ServicesMixin:
|
|||||||
event = service_description.ServiceDescription(service_type='event')
|
event = service_description.ServiceDescription(service_type='event')
|
||||||
events = event
|
events = event
|
||||||
|
|
||||||
application_deployment = service_description.ServiceDescription(service_type='application-deployment')
|
application_deployment = service_description.ServiceDescription(
|
||||||
|
service_type='application-deployment'
|
||||||
|
)
|
||||||
application_deployment = application_deployment
|
application_deployment = application_deployment
|
||||||
|
|
||||||
multi_region_network_automation = service_description.ServiceDescription(service_type='multi-region-network-automation')
|
multi_region_network_automation = service_description.ServiceDescription(
|
||||||
|
service_type='multi-region-network-automation'
|
||||||
|
)
|
||||||
tricircle = multi_region_network_automation
|
tricircle = multi_region_network_automation
|
||||||
|
|
||||||
database = database_service.DatabaseService(service_type='database')
|
database = database_service.DatabaseService(service_type='database')
|
||||||
|
|
||||||
application_container = service_description.ServiceDescription(service_type='application-container')
|
application_container = service_description.ServiceDescription(
|
||||||
|
service_type='application-container'
|
||||||
|
)
|
||||||
container = application_container
|
container = application_container
|
||||||
|
|
||||||
root_cause_analysis = service_description.ServiceDescription(service_type='root-cause-analysis')
|
root_cause_analysis = service_description.ServiceDescription(
|
||||||
|
service_type='root-cause-analysis'
|
||||||
|
)
|
||||||
rca = root_cause_analysis
|
rca = root_cause_analysis
|
||||||
|
|
||||||
nfv_orchestration = service_description.ServiceDescription(service_type='nfv-orchestration')
|
nfv_orchestration = service_description.ServiceDescription(
|
||||||
|
service_type='nfv-orchestration'
|
||||||
|
)
|
||||||
|
|
||||||
network = network_service.NetworkService(service_type='network')
|
network = network_service.NetworkService(service_type='network')
|
||||||
|
|
||||||
backup = service_description.ServiceDescription(service_type='backup')
|
backup = service_description.ServiceDescription(service_type='backup')
|
||||||
|
|
||||||
monitoring_logging = service_description.ServiceDescription(service_type='monitoring-logging')
|
monitoring_logging = service_description.ServiceDescription(
|
||||||
|
service_type='monitoring-logging'
|
||||||
|
)
|
||||||
monitoring_log_api = monitoring_logging
|
monitoring_log_api = monitoring_logging
|
||||||
|
|
||||||
monitoring = service_description.ServiceDescription(service_type='monitoring')
|
monitoring = service_description.ServiceDescription(
|
||||||
|
service_type='monitoring'
|
||||||
|
)
|
||||||
|
|
||||||
monitoring_events = service_description.ServiceDescription(service_type='monitoring-events')
|
monitoring_events = service_description.ServiceDescription(
|
||||||
|
service_type='monitoring-events'
|
||||||
|
)
|
||||||
|
|
||||||
placement = placement_service.PlacementService(service_type='placement')
|
placement = placement_service.PlacementService(service_type='placement')
|
||||||
|
|
||||||
instance_ha = instance_ha_service.InstanceHaService(service_type='instance-ha')
|
instance_ha = instance_ha_service.InstanceHaService(
|
||||||
|
service_type='instance-ha'
|
||||||
|
)
|
||||||
ha = instance_ha
|
ha = instance_ha
|
||||||
|
|
||||||
reservation = service_description.ServiceDescription(service_type='reservation')
|
reservation = service_description.ServiceDescription(
|
||||||
|
service_type='reservation'
|
||||||
|
)
|
||||||
|
|
||||||
function_engine = service_description.ServiceDescription(service_type='function-engine')
|
function_engine = service_description.ServiceDescription(
|
||||||
|
service_type='function-engine'
|
||||||
|
)
|
||||||
|
|
||||||
accelerator = accelerator_service.AcceleratorService(service_type='accelerator')
|
accelerator = accelerator_service.AcceleratorService(
|
||||||
|
service_type='accelerator'
|
||||||
|
)
|
||||||
|
|
||||||
admin_logic = service_description.ServiceDescription(service_type='admin-logic')
|
admin_logic = service_description.ServiceDescription(
|
||||||
|
service_type='admin-logic'
|
||||||
|
)
|
||||||
registration = admin_logic
|
registration = admin_logic
|
||||||
|
|
||||||
|
@ -82,14 +82,13 @@ class MetadataMixin:
|
|||||||
url = utils.urljoin(self.base_path, self.id, 'metadata', key)
|
url = utils.urljoin(self.base_path, self.id, 'metadata', key)
|
||||||
response = session.get(url)
|
response = session.get(url)
|
||||||
exceptions.raise_from_response(
|
exceptions.raise_from_response(
|
||||||
response, error_message='Metadata item does not exist')
|
response, error_message='Metadata item does not exist'
|
||||||
|
)
|
||||||
meta = response.json().get('meta', {})
|
meta = response.json().get('meta', {})
|
||||||
# Here we need to potentially init metadata
|
# Here we need to potentially init metadata
|
||||||
metadata = self.metadata or {}
|
metadata = self.metadata or {}
|
||||||
metadata[key] = meta.get(key)
|
metadata[key] = meta.get(key)
|
||||||
self._body.attributes.update({
|
self._body.attributes.update({'metadata': metadata})
|
||||||
'metadata': metadata
|
|
||||||
})
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -101,17 +100,12 @@ class MetadataMixin:
|
|||||||
:param str value: The value.
|
:param str value: The value.
|
||||||
"""
|
"""
|
||||||
url = utils.urljoin(self.base_path, self.id, 'metadata', key)
|
url = utils.urljoin(self.base_path, self.id, 'metadata', key)
|
||||||
response = session.put(
|
response = session.put(url, json={'meta': {key: value}})
|
||||||
url,
|
|
||||||
json={'meta': {key: value}}
|
|
||||||
)
|
|
||||||
exceptions.raise_from_response(response)
|
exceptions.raise_from_response(response)
|
||||||
# we do not want to update tags directly
|
# we do not want to update tags directly
|
||||||
metadata = self.metadata
|
metadata = self.metadata
|
||||||
metadata[key] = value
|
metadata[key] = value
|
||||||
self._body.attributes.update({
|
self._body.attributes.update({'metadata': metadata})
|
||||||
'metadata': metadata
|
|
||||||
})
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def delete_metadata_item(self, session, key):
|
def delete_metadata_item(self, session, key):
|
||||||
@ -132,7 +126,5 @@ class MetadataMixin:
|
|||||||
metadata = {}
|
metadata = {}
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass # do nothing!
|
pass # do nothing!
|
||||||
self._body.attributes.update({
|
self._body.attributes.update({'metadata': metadata})
|
||||||
'metadata': metadata
|
|
||||||
})
|
|
||||||
return self
|
return self
|
||||||
|
@ -26,8 +26,7 @@ class QuotaSet(resource.Resource):
|
|||||||
allow_delete = True
|
allow_delete = True
|
||||||
allow_commit = True
|
allow_commit = True
|
||||||
|
|
||||||
_query_mapping = resource.QueryParameters(
|
_query_mapping = resource.QueryParameters("usage")
|
||||||
"usage")
|
|
||||||
|
|
||||||
# NOTE(gtema) Sadly this attribute is useless in all the methods, but keep
|
# NOTE(gtema) Sadly this attribute is useless in all the methods, but keep
|
||||||
# it here extra as a reminder
|
# it here extra as a reminder
|
||||||
@ -47,8 +46,14 @@ class QuotaSet(resource.Resource):
|
|||||||
|
|
||||||
project_id = resource.URI('project_id')
|
project_id = resource.URI('project_id')
|
||||||
|
|
||||||
def fetch(self, session, requires_id=False,
|
def fetch(
|
||||||
base_path=None, error_message=None, **params):
|
self,
|
||||||
|
session,
|
||||||
|
requires_id=False,
|
||||||
|
base_path=None,
|
||||||
|
error_message=None,
|
||||||
|
**params
|
||||||
|
):
|
||||||
return super(QuotaSet, self).fetch(
|
return super(QuotaSet, self).fetch(
|
||||||
session,
|
session,
|
||||||
requires_id=False,
|
requires_id=False,
|
||||||
@ -93,8 +98,9 @@ class QuotaSet(resource.Resource):
|
|||||||
if 'in_use' in val:
|
if 'in_use' in val:
|
||||||
normalized_attrs['usage'][key] = val['in_use']
|
normalized_attrs['usage'][key] = val['in_use']
|
||||||
if 'reserved' in val:
|
if 'reserved' in val:
|
||||||
normalized_attrs['reservation'][key] = \
|
normalized_attrs['reservation'][key] = val[
|
||||||
val['reserved']
|
'reserved'
|
||||||
|
]
|
||||||
if 'limit' in val:
|
if 'limit' in val:
|
||||||
normalized_attrs[key] = val['limit']
|
normalized_attrs[key] = val['limit']
|
||||||
else:
|
else:
|
||||||
|
@ -81,8 +81,9 @@ class TagMixin:
|
|||||||
url = utils.urljoin(self.base_path, self.id, 'tags', tag)
|
url = utils.urljoin(self.base_path, self.id, 'tags', tag)
|
||||||
session = self._get_session(session)
|
session = self._get_session(session)
|
||||||
response = session.get(url)
|
response = session.get(url)
|
||||||
exceptions.raise_from_response(response,
|
exceptions.raise_from_response(
|
||||||
error_message='Tag does not exist')
|
response, error_message='Tag does not exist'
|
||||||
|
)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def add_tag(self, session, tag):
|
def add_tag(self, session, tag):
|
||||||
@ -98,9 +99,7 @@ class TagMixin:
|
|||||||
# we do not want to update tags directly
|
# we do not want to update tags directly
|
||||||
tags = self.tags
|
tags = self.tags
|
||||||
tags.append(tag)
|
tags.append(tag)
|
||||||
self._body.attributes.update({
|
self._body.attributes.update({'tags': tags})
|
||||||
'tags': tags
|
|
||||||
})
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def remove_tag(self, session, tag):
|
def remove_tag(self, session, tag):
|
||||||
@ -121,7 +120,5 @@ class TagMixin:
|
|||||||
tags.remove(tag)
|
tags.remove(tag)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass # do nothing!
|
pass # do nothing!
|
||||||
self._body.attributes.update({
|
self._body.attributes.update({'tags': tags})
|
||||||
'tags': tags
|
|
||||||
})
|
|
||||||
return self
|
return self
|
||||||
|
@ -18,15 +18,20 @@ from openstack.config.loader import OpenStackConfig # noqa
|
|||||||
|
|
||||||
|
|
||||||
def get_cloud_region(
|
def get_cloud_region(
|
||||||
service_key=None, options=None,
|
service_key=None,
|
||||||
app_name=None, app_version=None,
|
options=None,
|
||||||
load_yaml_config=True,
|
app_name=None,
|
||||||
load_envvars=True,
|
app_version=None,
|
||||||
**kwargs):
|
load_yaml_config=True,
|
||||||
|
load_envvars=True,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
config = OpenStackConfig(
|
config = OpenStackConfig(
|
||||||
load_yaml_config=load_yaml_config,
|
load_yaml_config=load_yaml_config,
|
||||||
load_envvars=load_envvars,
|
load_envvars=load_envvars,
|
||||||
app_name=app_name, app_version=app_version)
|
app_name=app_name,
|
||||||
|
app_version=app_version,
|
||||||
|
)
|
||||||
if options:
|
if options:
|
||||||
config.register_argparse_arguments(options, sys.argv, service_key)
|
config.register_argparse_arguments(options, sys.argv, service_key)
|
||||||
parsed_options = options.parse_known_args(sys.argv)
|
parsed_options = options.parse_known_args(sys.argv)
|
||||||
|
@ -22,7 +22,9 @@ def normalize_keys(config):
|
|||||||
elif isinstance(value, bool):
|
elif isinstance(value, bool):
|
||||||
new_config[key] = value
|
new_config[key] = value
|
||||||
elif isinstance(value, int) and key not in (
|
elif isinstance(value, int) and key not in (
|
||||||
'verbose_level', 'api_timeout'):
|
'verbose_level',
|
||||||
|
'api_timeout',
|
||||||
|
):
|
||||||
new_config[key] = str(value)
|
new_config[key] = str(value)
|
||||||
elif isinstance(value, float):
|
elif isinstance(value, float):
|
||||||
new_config[key] = str(value)
|
new_config[key] = str(value)
|
||||||
|
@ -18,7 +18,6 @@ from openstack.config import cloud_region
|
|||||||
|
|
||||||
|
|
||||||
class CloudConfig(cloud_region.CloudRegion):
|
class CloudConfig(cloud_region.CloudRegion):
|
||||||
|
|
||||||
def __init__(self, name, region, config, **kwargs):
|
def __init__(self, name, region, config, **kwargs):
|
||||||
super(CloudConfig, self).__init__(name, region, config, **kwargs)
|
super(CloudConfig, self).__init__(name, region, config, **kwargs)
|
||||||
self.region = region
|
self.region = region
|
||||||
|
@ -28,6 +28,7 @@ from keystoneauth1.loading import adapter as ks_load_adap
|
|||||||
from keystoneauth1 import session as ks_session
|
from keystoneauth1 import session as ks_session
|
||||||
import os_service_types
|
import os_service_types
|
||||||
import requestsexceptions
|
import requestsexceptions
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import statsd
|
import statsd
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -52,9 +53,11 @@ from openstack import version as openstack_version
|
|||||||
_logger = _log.setup_logging('openstack')
|
_logger = _log.setup_logging('openstack')
|
||||||
|
|
||||||
SCOPE_KEYS = {
|
SCOPE_KEYS = {
|
||||||
'domain_id', 'domain_name',
|
'domain_id',
|
||||||
'project_id', 'project_name',
|
'domain_name',
|
||||||
'system_scope'
|
'project_id',
|
||||||
|
'project_name',
|
||||||
|
'system_scope',
|
||||||
}
|
}
|
||||||
|
|
||||||
# Sentinel for nonexistence
|
# Sentinel for nonexistence
|
||||||
@ -90,9 +93,15 @@ def _get_implied_microversion(version):
|
|||||||
return version
|
return version
|
||||||
|
|
||||||
|
|
||||||
def from_session(session, name=None, region_name=None,
|
def from_session(
|
||||||
force_ipv4=False,
|
session,
|
||||||
app_name=None, app_version=None, **kwargs):
|
name=None,
|
||||||
|
region_name=None,
|
||||||
|
force_ipv4=False,
|
||||||
|
app_name=None,
|
||||||
|
app_version=None,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
"""Construct a CloudRegion from an existing `keystoneauth1.session.Session`
|
"""Construct a CloudRegion from an existing `keystoneauth1.session.Session`
|
||||||
|
|
||||||
When a Session already exists, we don't actually even need to go through
|
When a Session already exists, we don't actually even need to go through
|
||||||
@ -118,9 +127,14 @@ def from_session(session, name=None, region_name=None,
|
|||||||
config_dict = config_defaults.get_defaults()
|
config_dict = config_defaults.get_defaults()
|
||||||
config_dict.update(**kwargs)
|
config_dict.update(**kwargs)
|
||||||
return CloudRegion(
|
return CloudRegion(
|
||||||
name=name, session=session, config=config_dict,
|
name=name,
|
||||||
region_name=region_name, force_ipv4=force_ipv4,
|
session=session,
|
||||||
app_name=app_name, app_version=app_version)
|
config=config_dict,
|
||||||
|
region_name=region_name,
|
||||||
|
force_ipv4=force_ipv4,
|
||||||
|
app_name=app_name,
|
||||||
|
app_version=app_version,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def from_conf(conf, session=None, service_types=None, **kwargs):
|
def from_conf(conf, session=None, service_types=None, **kwargs):
|
||||||
@ -160,8 +174,10 @@ def from_conf(conf, session=None, service_types=None, **kwargs):
|
|||||||
for st in stm.all_types_by_service_type:
|
for st in stm.all_types_by_service_type:
|
||||||
if service_types is not None and st not in service_types:
|
if service_types is not None and st not in service_types:
|
||||||
_disable_service(
|
_disable_service(
|
||||||
config_dict, st,
|
config_dict,
|
||||||
reason="Not in the list of requested service_types.")
|
st,
|
||||||
|
reason="Not in the list of requested service_types.",
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
project_name = stm.get_project_name(st)
|
project_name = stm.get_project_name(st)
|
||||||
if project_name not in conf:
|
if project_name not in conf:
|
||||||
@ -170,10 +186,13 @@ def from_conf(conf, session=None, service_types=None, **kwargs):
|
|||||||
|
|
||||||
if project_name not in conf:
|
if project_name not in conf:
|
||||||
_disable_service(
|
_disable_service(
|
||||||
config_dict, st,
|
config_dict,
|
||||||
|
st,
|
||||||
reason="No section for project '{project}' (service type "
|
reason="No section for project '{project}' (service type "
|
||||||
"'{service_type}') was present in the config."
|
"'{service_type}') was present in the config.".format(
|
||||||
.format(project=project_name, service_type=st))
|
project=project_name, service_type=st
|
||||||
|
),
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
opt_dict = {}
|
opt_dict = {}
|
||||||
# Populate opt_dict with (appropriately processed) Adapter conf opts
|
# Populate opt_dict with (appropriately processed) Adapter conf opts
|
||||||
@ -189,20 +208,24 @@ def from_conf(conf, session=None, service_types=None, **kwargs):
|
|||||||
# option of) blowing up right away for (2) rather than letting them
|
# option of) blowing up right away for (2) rather than letting them
|
||||||
# get all the way to the point of trying the service and having
|
# get all the way to the point of trying the service and having
|
||||||
# *that* blow up.
|
# *that* blow up.
|
||||||
reason = ("Encountered an exception attempting to process config "
|
reason = (
|
||||||
"for project '{project}' (service type "
|
"Encountered an exception attempting to process config "
|
||||||
"'{service_type}'): {exception}".format(
|
"for project '{project}' (service type "
|
||||||
project=project_name, service_type=st, exception=e))
|
"'{service_type}'): {exception}".format(
|
||||||
_logger.warning("Disabling service '{service_type}': "
|
project=project_name, service_type=st, exception=e
|
||||||
"{reason}".format(service_type=st, reason=reason))
|
)
|
||||||
|
)
|
||||||
|
_logger.warning(
|
||||||
|
"Disabling service '{service_type}': "
|
||||||
|
"{reason}".format(service_type=st, reason=reason)
|
||||||
|
)
|
||||||
_disable_service(config_dict, st, reason=reason)
|
_disable_service(config_dict, st, reason=reason)
|
||||||
continue
|
continue
|
||||||
# Load them into config_dict under keys prefixed by ${service_type}_
|
# Load them into config_dict under keys prefixed by ${service_type}_
|
||||||
for raw_name, opt_val in opt_dict.items():
|
for raw_name, opt_val in opt_dict.items():
|
||||||
config_name = _make_key(raw_name, st)
|
config_name = _make_key(raw_name, st)
|
||||||
config_dict[config_name] = opt_val
|
config_dict[config_name] = opt_val
|
||||||
return CloudRegion(
|
return CloudRegion(session=session, config=config_dict, **kwargs)
|
||||||
session=session, config=config_dict, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class CloudRegion:
|
class CloudRegion:
|
||||||
@ -232,18 +255,34 @@ class CloudRegion:
|
|||||||
|
|
||||||
'interface': 'public'
|
'interface': 'public'
|
||||||
"""
|
"""
|
||||||
def __init__(self, name=None, region_name=None, config=None,
|
|
||||||
force_ipv4=False, auth_plugin=None,
|
def __init__(
|
||||||
openstack_config=None, session_constructor=None,
|
self,
|
||||||
app_name=None, app_version=None, session=None,
|
name=None,
|
||||||
discovery_cache=None, extra_config=None,
|
region_name=None,
|
||||||
cache_expiration_time=0, cache_expirations=None,
|
config=None,
|
||||||
cache_path=None, cache_class='dogpile.cache.null',
|
force_ipv4=False,
|
||||||
cache_arguments=None, password_callback=None,
|
auth_plugin=None,
|
||||||
statsd_host=None, statsd_port=None, statsd_prefix=None,
|
openstack_config=None,
|
||||||
influxdb_config=None,
|
session_constructor=None,
|
||||||
collector_registry=None,
|
app_name=None,
|
||||||
cache_auth=False):
|
app_version=None,
|
||||||
|
session=None,
|
||||||
|
discovery_cache=None,
|
||||||
|
extra_config=None,
|
||||||
|
cache_expiration_time=0,
|
||||||
|
cache_expirations=None,
|
||||||
|
cache_path=None,
|
||||||
|
cache_class='dogpile.cache.null',
|
||||||
|
cache_arguments=None,
|
||||||
|
password_callback=None,
|
||||||
|
statsd_host=None,
|
||||||
|
statsd_port=None,
|
||||||
|
statsd_prefix=None,
|
||||||
|
influxdb_config=None,
|
||||||
|
collector_registry=None,
|
||||||
|
cache_auth=False,
|
||||||
|
):
|
||||||
self._name = name
|
self._name = name
|
||||||
self.config = _util.normalize_keys(config)
|
self.config = _util.normalize_keys(config)
|
||||||
# NOTE(efried): For backward compatibility: a) continue to accept the
|
# NOTE(efried): For backward compatibility: a) continue to accept the
|
||||||
@ -294,9 +333,7 @@ class CloudRegion:
|
|||||||
return self.config.__iter__()
|
return self.config.__iter__()
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return (
|
return self.name == other.name and self.config == other.config
|
||||||
self.name == other.name
|
|
||||||
and self.config == other.config)
|
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not self == other
|
return not self == other
|
||||||
@ -306,7 +343,8 @@ class CloudRegion:
|
|||||||
if self._name is None:
|
if self._name is None:
|
||||||
try:
|
try:
|
||||||
self._name = urllib.parse.urlparse(
|
self._name = urllib.parse.urlparse(
|
||||||
self.get_session().auth.auth_url).hostname
|
self.get_session().auth.auth_url
|
||||||
|
).hostname
|
||||||
except Exception:
|
except Exception:
|
||||||
self._name = self._app_name or ''
|
self._name = self._app_name or ''
|
||||||
return self._name
|
return self._name
|
||||||
@ -352,7 +390,9 @@ class CloudRegion:
|
|||||||
"You are specifying a cacert for the cloud {full_name}"
|
"You are specifying a cacert for the cloud {full_name}"
|
||||||
" but also to ignore the host verification. The host SSL"
|
" but also to ignore the host verification. The host SSL"
|
||||||
" cert will not be verified.".format(
|
" cert will not be verified.".format(
|
||||||
full_name=self.full_name))
|
full_name=self.full_name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
cert = self.config.get('cert')
|
cert = self.config.get('cert')
|
||||||
if cert:
|
if cert:
|
||||||
@ -365,19 +405,23 @@ class CloudRegion:
|
|||||||
"""Return a list of service types we know something about."""
|
"""Return a list of service types we know something about."""
|
||||||
services = []
|
services = []
|
||||||
for key, val in self.config.items():
|
for key, val in self.config.items():
|
||||||
if (key.endswith('api_version')
|
if (
|
||||||
or key.endswith('service_type')
|
key.endswith('api_version')
|
||||||
or key.endswith('service_name')):
|
or key.endswith('service_type')
|
||||||
|
or key.endswith('service_name')
|
||||||
|
):
|
||||||
services.append("_".join(key.split('_')[:-2]))
|
services.append("_".join(key.split('_')[:-2]))
|
||||||
return list(set(services))
|
return list(set(services))
|
||||||
|
|
||||||
def get_enabled_services(self):
|
def get_enabled_services(self):
|
||||||
services = set()
|
services = set()
|
||||||
|
|
||||||
all_services = [k['service_type'] for k in
|
all_services = [
|
||||||
self._service_type_manager.services]
|
k['service_type'] for k in self._service_type_manager.services
|
||||||
all_services.extend(k[4:] for k in
|
]
|
||||||
self.config.keys() if k.startswith('has_'))
|
all_services.extend(
|
||||||
|
k[4:] for k in self.config.keys() if k.startswith('has_')
|
||||||
|
)
|
||||||
|
|
||||||
for srv in all_services:
|
for srv in all_services:
|
||||||
ep = self.get_endpoint_from_catalog(srv)
|
ep = self.get_endpoint_from_catalog(srv)
|
||||||
@ -390,10 +434,13 @@ class CloudRegion:
|
|||||||
return self.config.get('auth', {})
|
return self.config.get('auth', {})
|
||||||
|
|
||||||
def _get_config(
|
def _get_config(
|
||||||
self, key, service_type,
|
self,
|
||||||
default=None,
|
key,
|
||||||
fallback_to_unprefixed=False,
|
service_type,
|
||||||
converter=None):
|
default=None,
|
||||||
|
fallback_to_unprefixed=False,
|
||||||
|
converter=None,
|
||||||
|
):
|
||||||
'''Get a config value for a service_type.
|
'''Get a config value for a service_type.
|
||||||
|
|
||||||
Finds the config value for a key, looking first for it prefixed by
|
Finds the config value for a key, looking first for it prefixed by
|
||||||
@ -442,11 +489,13 @@ class CloudRegion:
|
|||||||
# If a region_name for the specific service_type is configured, use it;
|
# If a region_name for the specific service_type is configured, use it;
|
||||||
# else use the one configured for the CloudRegion as a whole.
|
# else use the one configured for the CloudRegion as a whole.
|
||||||
return self._get_config(
|
return self._get_config(
|
||||||
'region_name', service_type, fallback_to_unprefixed=True)
|
'region_name', service_type, fallback_to_unprefixed=True
|
||||||
|
)
|
||||||
|
|
||||||
def get_interface(self, service_type=None):
|
def get_interface(self, service_type=None):
|
||||||
return self._get_config(
|
return self._get_config(
|
||||||
'interface', service_type, fallback_to_unprefixed=True)
|
'interface', service_type, fallback_to_unprefixed=True
|
||||||
|
)
|
||||||
|
|
||||||
def get_api_version(self, service_type):
|
def get_api_version(self, service_type):
|
||||||
version = self._get_config('api_version', service_type)
|
version = self._get_config('api_version', service_type)
|
||||||
@ -458,7 +507,8 @@ class CloudRegion:
|
|||||||
warnings.warn(
|
warnings.warn(
|
||||||
"You have a configured API_VERSION with 'latest' in"
|
"You have a configured API_VERSION with 'latest' in"
|
||||||
" it. In the context of openstacksdk this doesn't make"
|
" it. In the context of openstacksdk this doesn't make"
|
||||||
" any sense.")
|
" any sense."
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
return version
|
return version
|
||||||
|
|
||||||
@ -475,9 +525,11 @@ class CloudRegion:
|
|||||||
# type will get us things in the right order.
|
# type will get us things in the right order.
|
||||||
if self._service_type_manager.is_known(service_type):
|
if self._service_type_manager.is_known(service_type):
|
||||||
service_type = self._service_type_manager.get_service_type(
|
service_type = self._service_type_manager.get_service_type(
|
||||||
service_type)
|
service_type
|
||||||
|
)
|
||||||
return self._get_config(
|
return self._get_config(
|
||||||
'service_type', service_type, default=service_type)
|
'service_type', service_type, default=service_type
|
||||||
|
)
|
||||||
|
|
||||||
def get_service_name(self, service_type):
|
def get_service_name(self, service_type):
|
||||||
return self._get_config('service_name', service_type)
|
return self._get_config('service_name', service_type)
|
||||||
@ -492,8 +544,11 @@ class CloudRegion:
|
|||||||
# then the endpoint value is the endpoint_override for every
|
# then the endpoint value is the endpoint_override for every
|
||||||
# service.
|
# service.
|
||||||
value = auth.get('endpoint')
|
value = auth.get('endpoint')
|
||||||
if (not value and service_type == 'identity'
|
if (
|
||||||
and SCOPE_KEYS.isdisjoint(set(auth.keys()))):
|
not value
|
||||||
|
and service_type == 'identity'
|
||||||
|
and SCOPE_KEYS.isdisjoint(set(auth.keys()))
|
||||||
|
):
|
||||||
# There are a small number of unscoped identity operations.
|
# There are a small number of unscoped identity operations.
|
||||||
# Specifically, looking up a list of projects/domains/system to
|
# Specifically, looking up a list of projects/domains/system to
|
||||||
# scope to.
|
# scope to.
|
||||||
@ -503,7 +558,8 @@ class CloudRegion:
|
|||||||
# only v1 is in the catalog but the service actually does support
|
# only v1 is in the catalog but the service actually does support
|
||||||
# v2. But the endpoint needs the project_id.
|
# v2. But the endpoint needs the project_id.
|
||||||
service_type = self._service_type_manager.get_service_type(
|
service_type = self._service_type_manager.get_service_type(
|
||||||
service_type)
|
service_type
|
||||||
|
)
|
||||||
if (
|
if (
|
||||||
value
|
value
|
||||||
and self.config.get('profile') == 'rackspace'
|
and self.config.get('profile') == 'rackspace'
|
||||||
@ -513,7 +569,8 @@ class CloudRegion:
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
def get_endpoint_from_catalog(
|
def get_endpoint_from_catalog(
|
||||||
self, service_type, interface=None, region_name=None):
|
self, service_type, interface=None, region_name=None
|
||||||
|
):
|
||||||
"""Return the endpoint for a given service as found in the catalog.
|
"""Return the endpoint for a given service as found in the catalog.
|
||||||
|
|
||||||
For values respecting endpoint overrides, see
|
For values respecting endpoint overrides, see
|
||||||
@ -537,19 +594,26 @@ class CloudRegion:
|
|||||||
return catalog.url_for(
|
return catalog.url_for(
|
||||||
service_type=service_type,
|
service_type=service_type,
|
||||||
interface=interface,
|
interface=interface,
|
||||||
region_name=region_name)
|
region_name=region_name,
|
||||||
|
)
|
||||||
except keystoneauth1.exceptions.catalog.EndpointNotFound:
|
except keystoneauth1.exceptions.catalog.EndpointNotFound:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_connect_retries(self, service_type):
|
def get_connect_retries(self, service_type):
|
||||||
return self._get_config('connect_retries', service_type,
|
return self._get_config(
|
||||||
fallback_to_unprefixed=True,
|
'connect_retries',
|
||||||
converter=int)
|
service_type,
|
||||||
|
fallback_to_unprefixed=True,
|
||||||
|
converter=int,
|
||||||
|
)
|
||||||
|
|
||||||
def get_status_code_retries(self, service_type):
|
def get_status_code_retries(self, service_type):
|
||||||
return self._get_config('status_code_retries', service_type,
|
return self._get_config(
|
||||||
fallback_to_unprefixed=True,
|
'status_code_retries',
|
||||||
converter=int)
|
service_type,
|
||||||
|
fallback_to_unprefixed=True,
|
||||||
|
converter=int,
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def prefer_ipv6(self):
|
def prefer_ipv6(self):
|
||||||
@ -612,14 +676,16 @@ class CloudRegion:
|
|||||||
desirable.
|
desirable.
|
||||||
"""
|
"""
|
||||||
self._keystone_session.additional_user_agent.append(
|
self._keystone_session.additional_user_agent.append(
|
||||||
('openstacksdk', openstack_version.__version__))
|
('openstacksdk', openstack_version.__version__)
|
||||||
|
)
|
||||||
|
|
||||||
def get_session(self):
|
def get_session(self):
|
||||||
"""Return a keystoneauth session based on the auth credentials."""
|
"""Return a keystoneauth session based on the auth credentials."""
|
||||||
if self._keystone_session is None:
|
if self._keystone_session is None:
|
||||||
if not self._auth:
|
if not self._auth:
|
||||||
raise exceptions.ConfigException(
|
raise exceptions.ConfigException(
|
||||||
"Problem with auth parameters")
|
"Problem with auth parameters"
|
||||||
|
)
|
||||||
(verify, cert) = self.get_requests_verify_args()
|
(verify, cert) = self.get_requests_verify_args()
|
||||||
# Turn off urllib3 warnings about insecure certs if we have
|
# Turn off urllib3 warnings about insecure certs if we have
|
||||||
# explicitly configured requests to tell it we do not want
|
# explicitly configured requests to tell it we do not want
|
||||||
@ -627,7 +693,8 @@ class CloudRegion:
|
|||||||
if not verify:
|
if not verify:
|
||||||
self.log.debug(
|
self.log.debug(
|
||||||
"Turning off SSL warnings for {full_name}"
|
"Turning off SSL warnings for {full_name}"
|
||||||
" since verify=False".format(full_name=self.full_name))
|
" since verify=False".format(full_name=self.full_name)
|
||||||
|
)
|
||||||
requestsexceptions.squelch_warnings(insecure_requests=not verify)
|
requestsexceptions.squelch_warnings(insecure_requests=not verify)
|
||||||
self._keystone_session = self._session_constructor(
|
self._keystone_session = self._session_constructor(
|
||||||
auth=self._auth,
|
auth=self._auth,
|
||||||
@ -635,7 +702,8 @@ class CloudRegion:
|
|||||||
cert=cert,
|
cert=cert,
|
||||||
timeout=self.config.get('api_timeout'),
|
timeout=self.config.get('api_timeout'),
|
||||||
collect_timing=self.config.get('timing'),
|
collect_timing=self.config.get('timing'),
|
||||||
discovery_cache=self._discovery_cache)
|
discovery_cache=self._discovery_cache,
|
||||||
|
)
|
||||||
self.insert_user_agent()
|
self.insert_user_agent()
|
||||||
# Using old keystoneauth with new os-client-config fails if
|
# Using old keystoneauth with new os-client-config fails if
|
||||||
# we pass in app_name and app_version. Those are not essential,
|
# we pass in app_name and app_version. Those are not essential,
|
||||||
@ -683,15 +751,20 @@ class CloudRegion:
|
|||||||
|
|
||||||
default_microversion = self.get_default_microversion(service_type)
|
default_microversion = self.get_default_microversion(service_type)
|
||||||
implied_microversion = _get_implied_microversion(version)
|
implied_microversion = _get_implied_microversion(version)
|
||||||
if (implied_microversion and default_microversion
|
if (
|
||||||
and implied_microversion != default_microversion):
|
implied_microversion
|
||||||
|
and default_microversion
|
||||||
|
and implied_microversion != default_microversion
|
||||||
|
):
|
||||||
raise exceptions.ConfigException(
|
raise exceptions.ConfigException(
|
||||||
"default_microversion of {default_microversion} was given"
|
"default_microversion of {default_microversion} was given"
|
||||||
" for {service_type}, but api_version looks like a"
|
" for {service_type}, but api_version looks like a"
|
||||||
" microversion as well. Please set api_version to just the"
|
" microversion as well. Please set api_version to just the"
|
||||||
" desired major version, or omit default_microversion".format(
|
" desired major version, or omit default_microversion".format(
|
||||||
default_microversion=default_microversion,
|
default_microversion=default_microversion,
|
||||||
service_type=service_type))
|
service_type=service_type,
|
||||||
|
)
|
||||||
|
)
|
||||||
if implied_microversion:
|
if implied_microversion:
|
||||||
default_microversion = implied_microversion
|
default_microversion = implied_microversion
|
||||||
# If we're inferring a microversion, don't pass the whole
|
# If we're inferring a microversion, don't pass the whole
|
||||||
@ -715,7 +788,8 @@ class CloudRegion:
|
|||||||
)
|
)
|
||||||
region_versions = versions.get(region_name, {})
|
region_versions = versions.get(region_name, {})
|
||||||
interface_versions = region_versions.get(
|
interface_versions = region_versions.get(
|
||||||
self.get_interface(service_type), {})
|
self.get_interface(service_type), {}
|
||||||
|
)
|
||||||
return interface_versions.get(service_type, [])
|
return interface_versions.get(service_type, [])
|
||||||
|
|
||||||
def _get_endpoint_from_catalog(self, service_type, constructor):
|
def _get_endpoint_from_catalog(self, service_type, constructor):
|
||||||
@ -729,8 +803,7 @@ class CloudRegion:
|
|||||||
return adapter.get_endpoint()
|
return adapter.get_endpoint()
|
||||||
|
|
||||||
def _get_hardcoded_endpoint(self, service_type, constructor):
|
def _get_hardcoded_endpoint(self, service_type, constructor):
|
||||||
endpoint = self._get_endpoint_from_catalog(
|
endpoint = self._get_endpoint_from_catalog(service_type, constructor)
|
||||||
service_type, constructor)
|
|
||||||
if not endpoint.rstrip().rsplit('/')[-1] == 'v2.0':
|
if not endpoint.rstrip().rsplit('/')[-1] == 'v2.0':
|
||||||
if not endpoint.endswith('/'):
|
if not endpoint.endswith('/'):
|
||||||
endpoint += '/'
|
endpoint += '/'
|
||||||
@ -738,9 +811,8 @@ class CloudRegion:
|
|||||||
return endpoint
|
return endpoint
|
||||||
|
|
||||||
def get_session_client(
|
def get_session_client(
|
||||||
self, service_type, version=None,
|
self, service_type, version=None, constructor=proxy.Proxy, **kwargs
|
||||||
constructor=proxy.Proxy,
|
):
|
||||||
**kwargs):
|
|
||||||
"""Return a prepped keystoneauth Adapter for a given service.
|
"""Return a prepped keystoneauth Adapter for a given service.
|
||||||
|
|
||||||
This is useful for making direct requests calls against a
|
This is useful for making direct requests calls against a
|
||||||
@ -757,23 +829,28 @@ class CloudRegion:
|
|||||||
version_request = self._get_version_request(service_type, version)
|
version_request = self._get_version_request(service_type, version)
|
||||||
|
|
||||||
kwargs.setdefault('region_name', self.get_region_name(service_type))
|
kwargs.setdefault('region_name', self.get_region_name(service_type))
|
||||||
kwargs.setdefault('connect_retries',
|
kwargs.setdefault(
|
||||||
self.get_connect_retries(service_type))
|
'connect_retries', self.get_connect_retries(service_type)
|
||||||
kwargs.setdefault('status_code_retries',
|
)
|
||||||
self.get_status_code_retries(service_type))
|
kwargs.setdefault(
|
||||||
|
'status_code_retries', self.get_status_code_retries(service_type)
|
||||||
|
)
|
||||||
kwargs.setdefault('statsd_prefix', self.get_statsd_prefix())
|
kwargs.setdefault('statsd_prefix', self.get_statsd_prefix())
|
||||||
kwargs.setdefault('statsd_client', self.get_statsd_client())
|
kwargs.setdefault('statsd_client', self.get_statsd_client())
|
||||||
kwargs.setdefault('prometheus_counter', self.get_prometheus_counter())
|
kwargs.setdefault('prometheus_counter', self.get_prometheus_counter())
|
||||||
kwargs.setdefault(
|
kwargs.setdefault(
|
||||||
'prometheus_histogram', self.get_prometheus_histogram())
|
'prometheus_histogram', self.get_prometheus_histogram()
|
||||||
|
)
|
||||||
kwargs.setdefault('influxdb_config', self._influxdb_config)
|
kwargs.setdefault('influxdb_config', self._influxdb_config)
|
||||||
kwargs.setdefault('influxdb_client', self.get_influxdb_client())
|
kwargs.setdefault('influxdb_client', self.get_influxdb_client())
|
||||||
endpoint_override = self.get_endpoint(service_type)
|
endpoint_override = self.get_endpoint(service_type)
|
||||||
version = version_request.version
|
version = version_request.version
|
||||||
min_api_version = (
|
min_api_version = (
|
||||||
kwargs.pop('min_version', None) or version_request.min_api_version)
|
kwargs.pop('min_version', None) or version_request.min_api_version
|
||||||
|
)
|
||||||
max_api_version = (
|
max_api_version = (
|
||||||
kwargs.pop('max_version', None) or version_request.max_api_version)
|
kwargs.pop('max_version', None) or version_request.max_api_version
|
||||||
|
)
|
||||||
|
|
||||||
# Older neutron has inaccessible discovery document. Nobody noticed
|
# Older neutron has inaccessible discovery document. Nobody noticed
|
||||||
# because neutronclient hard-codes an append of v2.0. YAY!
|
# because neutronclient hard-codes an append of v2.0. YAY!
|
||||||
@ -784,7 +861,8 @@ class CloudRegion:
|
|||||||
max_api_version = None
|
max_api_version = None
|
||||||
if endpoint_override is None:
|
if endpoint_override is None:
|
||||||
endpoint_override = self._get_hardcoded_endpoint(
|
endpoint_override = self._get_hardcoded_endpoint(
|
||||||
service_type, constructor)
|
service_type, constructor
|
||||||
|
)
|
||||||
|
|
||||||
client = constructor(
|
client = constructor(
|
||||||
session=self.get_session(),
|
session=self.get_session(),
|
||||||
@ -798,14 +876,15 @@ class CloudRegion:
|
|||||||
default_microversion=version_request.default_microversion,
|
default_microversion=version_request.default_microversion,
|
||||||
rate_limit=self.get_rate_limit(service_type),
|
rate_limit=self.get_rate_limit(service_type),
|
||||||
concurrency=self.get_concurrency(service_type),
|
concurrency=self.get_concurrency(service_type),
|
||||||
**kwargs)
|
**kwargs
|
||||||
|
)
|
||||||
if version_request.default_microversion:
|
if version_request.default_microversion:
|
||||||
default_microversion = version_request.default_microversion
|
default_microversion = version_request.default_microversion
|
||||||
info = client.get_endpoint_data()
|
info = client.get_endpoint_data()
|
||||||
if not discover.version_between(
|
if not discover.version_between(
|
||||||
info.min_microversion,
|
info.min_microversion,
|
||||||
info.max_microversion,
|
info.max_microversion,
|
||||||
default_microversion
|
default_microversion,
|
||||||
):
|
):
|
||||||
if self.get_default_microversion(service_type):
|
if self.get_default_microversion(service_type):
|
||||||
raise exceptions.ConfigException(
|
raise exceptions.ConfigException(
|
||||||
@ -816,9 +895,13 @@ class CloudRegion:
|
|||||||
service_type=service_type,
|
service_type=service_type,
|
||||||
default_microversion=default_microversion,
|
default_microversion=default_microversion,
|
||||||
min_microversion=discover.version_to_string(
|
min_microversion=discover.version_to_string(
|
||||||
info.min_microversion),
|
info.min_microversion
|
||||||
|
),
|
||||||
max_microversion=discover.version_to_string(
|
max_microversion=discover.version_to_string(
|
||||||
info.max_microversion)))
|
info.max_microversion
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise exceptions.ConfigException(
|
raise exceptions.ConfigException(
|
||||||
"A default microversion for service {service_type} of"
|
"A default microversion for service {service_type} of"
|
||||||
@ -836,13 +919,18 @@ class CloudRegion:
|
|||||||
api_version=self.get_api_version(service_type),
|
api_version=self.get_api_version(service_type),
|
||||||
default_microversion=default_microversion,
|
default_microversion=default_microversion,
|
||||||
min_microversion=discover.version_to_string(
|
min_microversion=discover.version_to_string(
|
||||||
info.min_microversion),
|
info.min_microversion
|
||||||
|
),
|
||||||
max_microversion=discover.version_to_string(
|
max_microversion=discover.version_to_string(
|
||||||
info.max_microversion)))
|
info.max_microversion
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
return client
|
return client
|
||||||
|
|
||||||
def get_session_endpoint(
|
def get_session_endpoint(
|
||||||
self, service_type, min_version=None, max_version=None):
|
self, service_type, min_version=None, max_version=None
|
||||||
|
):
|
||||||
"""Return the endpoint from config or the catalog.
|
"""Return the endpoint from config or the catalog.
|
||||||
|
|
||||||
If a configuration lists an explicit endpoint for a service,
|
If a configuration lists an explicit endpoint for a service,
|
||||||
@ -934,38 +1022,50 @@ class CloudRegion:
|
|||||||
def get_external_networks(self):
|
def get_external_networks(self):
|
||||||
"""Get list of network names for external networks."""
|
"""Get list of network names for external networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config.get('networks', [])
|
net['name']
|
||||||
if net['routes_externally']]
|
for net in self.config.get('networks', [])
|
||||||
|
if net['routes_externally']
|
||||||
|
]
|
||||||
|
|
||||||
def get_external_ipv4_networks(self):
|
def get_external_ipv4_networks(self):
|
||||||
"""Get list of network names for external IPv4 networks."""
|
"""Get list of network names for external IPv4 networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config.get('networks', [])
|
net['name']
|
||||||
if net['routes_ipv4_externally']]
|
for net in self.config.get('networks', [])
|
||||||
|
if net['routes_ipv4_externally']
|
||||||
|
]
|
||||||
|
|
||||||
def get_external_ipv6_networks(self):
|
def get_external_ipv6_networks(self):
|
||||||
"""Get list of network names for external IPv6 networks."""
|
"""Get list of network names for external IPv6 networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config.get('networks', [])
|
net['name']
|
||||||
if net['routes_ipv6_externally']]
|
for net in self.config.get('networks', [])
|
||||||
|
if net['routes_ipv6_externally']
|
||||||
|
]
|
||||||
|
|
||||||
def get_internal_networks(self):
|
def get_internal_networks(self):
|
||||||
"""Get list of network names for internal networks."""
|
"""Get list of network names for internal networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config.get('networks', [])
|
net['name']
|
||||||
if not net['routes_externally']]
|
for net in self.config.get('networks', [])
|
||||||
|
if not net['routes_externally']
|
||||||
|
]
|
||||||
|
|
||||||
def get_internal_ipv4_networks(self):
|
def get_internal_ipv4_networks(self):
|
||||||
"""Get list of network names for internal IPv4 networks."""
|
"""Get list of network names for internal IPv4 networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config.get('networks', [])
|
net['name']
|
||||||
if not net['routes_ipv4_externally']]
|
for net in self.config.get('networks', [])
|
||||||
|
if not net['routes_ipv4_externally']
|
||||||
|
]
|
||||||
|
|
||||||
def get_internal_ipv6_networks(self):
|
def get_internal_ipv6_networks(self):
|
||||||
"""Get list of network names for internal IPv6 networks."""
|
"""Get list of network names for internal IPv6 networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config.get('networks', [])
|
net['name']
|
||||||
if not net['routes_ipv6_externally']]
|
for net in self.config.get('networks', [])
|
||||||
|
if not net['routes_ipv6_externally']
|
||||||
|
]
|
||||||
|
|
||||||
def get_default_network(self):
|
def get_default_network(self):
|
||||||
"""Get network used for default interactions."""
|
"""Get network used for default interactions."""
|
||||||
@ -999,8 +1099,8 @@ class CloudRegion:
|
|||||||
if not key:
|
if not key:
|
||||||
return defaults
|
return defaults
|
||||||
return _util.merge_clouds(
|
return _util.merge_clouds(
|
||||||
defaults,
|
defaults, _util.normalize_keys(self._extra_config.get(key, {}))
|
||||||
_util.normalize_keys(self._extra_config.get(key, {})))
|
)
|
||||||
|
|
||||||
def get_client_config(self, name=None, defaults=None):
|
def get_client_config(self, name=None, defaults=None):
|
||||||
"""Get config settings for a named client.
|
"""Get config settings for a named client.
|
||||||
@ -1020,25 +1120,29 @@ class CloudRegion:
|
|||||||
client section and the defaults.
|
client section and the defaults.
|
||||||
"""
|
"""
|
||||||
return self._get_extra_config(
|
return self._get_extra_config(
|
||||||
name, self._get_extra_config('client', defaults))
|
name, self._get_extra_config('client', defaults)
|
||||||
|
)
|
||||||
|
|
||||||
def get_password_callback(self):
|
def get_password_callback(self):
|
||||||
return self._password_callback
|
return self._password_callback
|
||||||
|
|
||||||
def get_rate_limit(self, service_type=None):
|
def get_rate_limit(self, service_type=None):
|
||||||
return self._get_service_config(
|
return self._get_service_config(
|
||||||
'rate_limit', service_type=service_type)
|
'rate_limit', service_type=service_type
|
||||||
|
)
|
||||||
|
|
||||||
def get_concurrency(self, service_type=None):
|
def get_concurrency(self, service_type=None):
|
||||||
return self._get_service_config(
|
return self._get_service_config(
|
||||||
'concurrency', service_type=service_type)
|
'concurrency', service_type=service_type
|
||||||
|
)
|
||||||
|
|
||||||
def get_statsd_client(self):
|
def get_statsd_client(self):
|
||||||
if not statsd:
|
if not statsd:
|
||||||
if self._statsd_host:
|
if self._statsd_host:
|
||||||
self.log.warning(
|
self.log.warning(
|
||||||
'StatsD python library is not available. '
|
'StatsD python library is not available. '
|
||||||
'Reporting disabled')
|
'Reporting disabled'
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
statsd_args = {}
|
statsd_args = {}
|
||||||
if self._statsd_host:
|
if self._statsd_host:
|
||||||
@ -1075,7 +1179,10 @@ class CloudRegion:
|
|||||||
'openstack_http_response_time',
|
'openstack_http_response_time',
|
||||||
'Time taken for an http response to an OpenStack service',
|
'Time taken for an http response to an OpenStack service',
|
||||||
labelnames=[
|
labelnames=[
|
||||||
'method', 'endpoint', 'service_type', 'status_code'
|
'method',
|
||||||
|
'endpoint',
|
||||||
|
'service_type',
|
||||||
|
'status_code',
|
||||||
],
|
],
|
||||||
registry=registry,
|
registry=registry,
|
||||||
)
|
)
|
||||||
@ -1092,7 +1199,10 @@ class CloudRegion:
|
|||||||
'openstack_http_requests',
|
'openstack_http_requests',
|
||||||
'Number of HTTP requests made to an OpenStack service',
|
'Number of HTTP requests made to an OpenStack service',
|
||||||
labelnames=[
|
labelnames=[
|
||||||
'method', 'endpoint', 'service_type', 'status_code'
|
'method',
|
||||||
|
'endpoint',
|
||||||
|
'service_type',
|
||||||
|
'status_code',
|
||||||
],
|
],
|
||||||
registry=registry,
|
registry=registry,
|
||||||
)
|
)
|
||||||
@ -1103,7 +1213,8 @@ class CloudRegion:
|
|||||||
service_type = service_type.lower().replace('-', '_')
|
service_type = service_type.lower().replace('-', '_')
|
||||||
key = 'has_{service_type}'.format(service_type=service_type)
|
key = 'has_{service_type}'.format(service_type=service_type)
|
||||||
return self.config.get(
|
return self.config.get(
|
||||||
key, self._service_type_manager.is_official(service_type))
|
key, self._service_type_manager.is_official(service_type)
|
||||||
|
)
|
||||||
|
|
||||||
def disable_service(self, service_type, reason=None):
|
def disable_service(self, service_type, reason=None):
|
||||||
_disable_service(self.config, service_type, reason=reason)
|
_disable_service(self.config, service_type, reason=reason)
|
||||||
@ -1140,6 +1251,8 @@ class CloudRegion:
|
|||||||
except Exception:
|
except Exception:
|
||||||
self.log.warning('Cannot establish connection to InfluxDB')
|
self.log.warning('Cannot establish connection to InfluxDB')
|
||||||
else:
|
else:
|
||||||
self.log.warning('InfluxDB configuration is present, '
|
self.log.warning(
|
||||||
'but no client library is found.')
|
'InfluxDB configuration is present, '
|
||||||
|
'but no client library is found.'
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
@ -17,7 +17,8 @@ import os
|
|||||||
import threading
|
import threading
|
||||||
|
|
||||||
_json_path = os.path.join(
|
_json_path = os.path.join(
|
||||||
os.path.dirname(os.path.realpath(__file__)), 'defaults.json')
|
os.path.dirname(os.path.realpath(__file__)), 'defaults.json'
|
||||||
|
)
|
||||||
_defaults = None
|
_defaults = None
|
||||||
_defaults_lock = threading.Lock()
|
_defaults_lock = threading.Lock()
|
||||||
|
|
||||||
|
@ -46,19 +46,23 @@ CACHE_PATH = APPDIRS.user_cache_dir
|
|||||||
# see https://snapcraft.io/docs/environment-variables
|
# see https://snapcraft.io/docs/environment-variables
|
||||||
SNAP_REAL_HOME = os.getenv('SNAP_REAL_HOME')
|
SNAP_REAL_HOME = os.getenv('SNAP_REAL_HOME')
|
||||||
if SNAP_REAL_HOME:
|
if SNAP_REAL_HOME:
|
||||||
UNIX_CONFIG_HOME = os.path.join(os.path.join(SNAP_REAL_HOME, '.config'),
|
UNIX_CONFIG_HOME = os.path.join(
|
||||||
'openstack')
|
os.path.join(SNAP_REAL_HOME, '.config'), 'openstack'
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
UNIX_CONFIG_HOME = os.path.join(
|
UNIX_CONFIG_HOME = os.path.join(
|
||||||
os.path.expanduser(os.path.join('~', '.config')), 'openstack')
|
os.path.expanduser(os.path.join('~', '.config')), 'openstack'
|
||||||
|
)
|
||||||
UNIX_SITE_CONFIG_HOME = '/etc/openstack'
|
UNIX_SITE_CONFIG_HOME = '/etc/openstack'
|
||||||
|
|
||||||
SITE_CONFIG_HOME = APPDIRS.site_config_dir
|
SITE_CONFIG_HOME = APPDIRS.site_config_dir
|
||||||
|
|
||||||
CONFIG_SEARCH_PATH = [
|
CONFIG_SEARCH_PATH = [
|
||||||
os.getcwd(),
|
os.getcwd(),
|
||||||
CONFIG_HOME, UNIX_CONFIG_HOME,
|
CONFIG_HOME,
|
||||||
SITE_CONFIG_HOME, UNIX_SITE_CONFIG_HOME
|
UNIX_CONFIG_HOME,
|
||||||
|
SITE_CONFIG_HOME,
|
||||||
|
UNIX_SITE_CONFIG_HOME,
|
||||||
]
|
]
|
||||||
YAML_SUFFIXES = ('.yaml', '.yml')
|
YAML_SUFFIXES = ('.yaml', '.yml')
|
||||||
JSON_SUFFIXES = ('.json',)
|
JSON_SUFFIXES = ('.json',)
|
||||||
@ -134,8 +138,8 @@ def _fix_argv(argv):
|
|||||||
"The following options were given: '{options}' which contain"
|
"The following options were given: '{options}' which contain"
|
||||||
" duplicates except that one has _ and one has -. There is"
|
" duplicates except that one has _ and one has -. There is"
|
||||||
" no sane way for us to know what you're doing. Remove the"
|
" no sane way for us to know what you're doing. Remove the"
|
||||||
" duplicate option and try again".format(
|
" duplicate option and try again".format(options=','.join(overlap))
|
||||||
options=','.join(overlap)))
|
)
|
||||||
|
|
||||||
|
|
||||||
class OpenStackConfig:
|
class OpenStackConfig:
|
||||||
@ -146,14 +150,25 @@ class OpenStackConfig:
|
|||||||
_cloud_region_class = cloud_region.CloudRegion
|
_cloud_region_class = cloud_region.CloudRegion
|
||||||
_defaults_module = defaults
|
_defaults_module = defaults
|
||||||
|
|
||||||
def __init__(self, config_files=None, vendor_files=None,
|
def __init__(
|
||||||
override_defaults=None, force_ipv4=None,
|
self,
|
||||||
envvar_prefix=None, secure_files=None,
|
config_files=None,
|
||||||
pw_func=None, session_constructor=None,
|
vendor_files=None,
|
||||||
app_name=None, app_version=None,
|
override_defaults=None,
|
||||||
load_yaml_config=True, load_envvars=True,
|
force_ipv4=None,
|
||||||
statsd_host=None, statsd_port=None,
|
envvar_prefix=None,
|
||||||
statsd_prefix=None, influxdb_config=None):
|
secure_files=None,
|
||||||
|
pw_func=None,
|
||||||
|
session_constructor=None,
|
||||||
|
app_name=None,
|
||||||
|
app_version=None,
|
||||||
|
load_yaml_config=True,
|
||||||
|
load_envvars=True,
|
||||||
|
statsd_host=None,
|
||||||
|
statsd_port=None,
|
||||||
|
statsd_prefix=None,
|
||||||
|
influxdb_config=None,
|
||||||
|
):
|
||||||
self.log = _log.setup_logging('openstack.config')
|
self.log = _log.setup_logging('openstack.config')
|
||||||
self._session_constructor = session_constructor
|
self._session_constructor = session_constructor
|
||||||
self._app_name = app_name
|
self._app_name = app_name
|
||||||
@ -196,7 +211,8 @@ class OpenStackConfig:
|
|||||||
_, secure_config = self._load_secure_file()
|
_, secure_config = self._load_secure_file()
|
||||||
if secure_config:
|
if secure_config:
|
||||||
self.cloud_config = _util.merge_clouds(
|
self.cloud_config = _util.merge_clouds(
|
||||||
self.cloud_config, secure_config)
|
self.cloud_config, secure_config
|
||||||
|
)
|
||||||
|
|
||||||
if not self.cloud_config:
|
if not self.cloud_config:
|
||||||
self.cloud_config = {'clouds': {}}
|
self.cloud_config = {'clouds': {}}
|
||||||
@ -217,14 +233,20 @@ class OpenStackConfig:
|
|||||||
# Get the backwards compat value
|
# Get the backwards compat value
|
||||||
prefer_ipv6 = get_boolean(
|
prefer_ipv6 = get_boolean(
|
||||||
self._get_envvar(
|
self._get_envvar(
|
||||||
'OS_PREFER_IPV6', client_config.get(
|
'OS_PREFER_IPV6',
|
||||||
'prefer_ipv6', client_config.get(
|
client_config.get(
|
||||||
'prefer-ipv6', True))))
|
'prefer_ipv6', client_config.get('prefer-ipv6', True)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
force_ipv4 = get_boolean(
|
force_ipv4 = get_boolean(
|
||||||
self._get_envvar(
|
self._get_envvar(
|
||||||
'OS_FORCE_IPV4', client_config.get(
|
'OS_FORCE_IPV4',
|
||||||
'force_ipv4', client_config.get(
|
client_config.get(
|
||||||
'broken-ipv6', False))))
|
'force_ipv4', client_config.get('broken-ipv6', False)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.force_ipv4 = force_ipv4
|
self.force_ipv4 = force_ipv4
|
||||||
if not prefer_ipv6:
|
if not prefer_ipv6:
|
||||||
@ -239,8 +261,10 @@ class OpenStackConfig:
|
|||||||
'"{0}" defines a cloud named "{1}", but'
|
'"{0}" defines a cloud named "{1}", but'
|
||||||
' OS_CLOUD_NAME is also set to "{1}". Please rename'
|
' OS_CLOUD_NAME is also set to "{1}". Please rename'
|
||||||
' either your environment based cloud, or one of your'
|
' either your environment based cloud, or one of your'
|
||||||
' file-based clouds.'.format(self.config_filename,
|
' file-based clouds.'.format(
|
||||||
self.envvar_key))
|
self.config_filename, self.envvar_key
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.default_cloud = self._get_envvar('OS_CLOUD')
|
self.default_cloud = self._get_envvar('OS_CLOUD')
|
||||||
|
|
||||||
@ -259,15 +283,15 @@ class OpenStackConfig:
|
|||||||
# clouds.yaml.
|
# clouds.yaml.
|
||||||
# The next/iter thing is for python3 compat where dict.keys
|
# The next/iter thing is for python3 compat where dict.keys
|
||||||
# returns an iterator but in python2 it's a list.
|
# returns an iterator but in python2 it's a list.
|
||||||
self.default_cloud = next(iter(
|
self.default_cloud = next(
|
||||||
self.cloud_config['clouds'].keys()))
|
iter(self.cloud_config['clouds'].keys())
|
||||||
|
)
|
||||||
|
|
||||||
# Finally, fall through and make a cloud that starts with defaults
|
# Finally, fall through and make a cloud that starts with defaults
|
||||||
# because we need somewhere to put arguments, and there are neither
|
# because we need somewhere to put arguments, and there are neither
|
||||||
# config files or env vars
|
# config files or env vars
|
||||||
if not self.cloud_config['clouds']:
|
if not self.cloud_config['clouds']:
|
||||||
self.cloud_config = dict(
|
self.cloud_config = dict(clouds=dict(defaults=dict(self.defaults)))
|
||||||
clouds=dict(defaults=dict(self.defaults)))
|
|
||||||
self.default_cloud = 'defaults'
|
self.default_cloud = 'defaults'
|
||||||
|
|
||||||
self._cache_auth = False
|
self._cache_auth = False
|
||||||
@ -281,13 +305,15 @@ class OpenStackConfig:
|
|||||||
cache_settings = _util.normalize_keys(self.cloud_config['cache'])
|
cache_settings = _util.normalize_keys(self.cloud_config['cache'])
|
||||||
|
|
||||||
self._cache_auth = get_boolean(
|
self._cache_auth = get_boolean(
|
||||||
cache_settings.get('auth', self._cache_auth))
|
cache_settings.get('auth', self._cache_auth)
|
||||||
|
)
|
||||||
|
|
||||||
# expiration_time used to be 'max_age' but the dogpile setting
|
# expiration_time used to be 'max_age' but the dogpile setting
|
||||||
# is expiration_time. Support max_age for backwards compat.
|
# is expiration_time. Support max_age for backwards compat.
|
||||||
self._cache_expiration_time = cache_settings.get(
|
self._cache_expiration_time = cache_settings.get(
|
||||||
'expiration_time', cache_settings.get(
|
'expiration_time',
|
||||||
'max_age', self._cache_expiration_time))
|
cache_settings.get('max_age', self._cache_expiration_time),
|
||||||
|
)
|
||||||
|
|
||||||
# If cache class is given, use that. If not, but if cache time
|
# If cache class is given, use that. If not, but if cache time
|
||||||
# is given, default to memory. Otherwise, default to nothing.
|
# is given, default to memory. Otherwise, default to nothing.
|
||||||
@ -295,14 +321,18 @@ class OpenStackConfig:
|
|||||||
if self._cache_expiration_time:
|
if self._cache_expiration_time:
|
||||||
self._cache_class = 'dogpile.cache.memory'
|
self._cache_class = 'dogpile.cache.memory'
|
||||||
self._cache_class = self.cloud_config['cache'].get(
|
self._cache_class = self.cloud_config['cache'].get(
|
||||||
'class', self._cache_class)
|
'class', self._cache_class
|
||||||
|
)
|
||||||
|
|
||||||
self._cache_path = os.path.expanduser(
|
self._cache_path = os.path.expanduser(
|
||||||
cache_settings.get('path', self._cache_path))
|
cache_settings.get('path', self._cache_path)
|
||||||
|
)
|
||||||
self._cache_arguments = cache_settings.get(
|
self._cache_arguments = cache_settings.get(
|
||||||
'arguments', self._cache_arguments)
|
'arguments', self._cache_arguments
|
||||||
|
)
|
||||||
self._cache_expirations = cache_settings.get(
|
self._cache_expirations = cache_settings.get(
|
||||||
'expiration', self._cache_expirations)
|
'expiration', self._cache_expirations
|
||||||
|
)
|
||||||
|
|
||||||
if load_yaml_config:
|
if load_yaml_config:
|
||||||
metrics_config = self.cloud_config.get('metrics', {})
|
metrics_config = self.cloud_config.get('metrics', {})
|
||||||
@ -326,12 +356,21 @@ class OpenStackConfig:
|
|||||||
use_udp = use_udp.lower() in ('true', 'yes', '1')
|
use_udp = use_udp.lower() in ('true', 'yes', '1')
|
||||||
elif not isinstance(use_udp, bool):
|
elif not isinstance(use_udp, bool):
|
||||||
use_udp = False
|
use_udp = False
|
||||||
self.log.warning('InfluxDB.use_udp value type is not '
|
self.log.warning(
|
||||||
'supported. Use one of '
|
'InfluxDB.use_udp value type is not '
|
||||||
'[true|false|yes|no|1|0]')
|
'supported. Use one of '
|
||||||
|
'[true|false|yes|no|1|0]'
|
||||||
|
)
|
||||||
config['use_udp'] = use_udp
|
config['use_udp'] = use_udp
|
||||||
for key in ['host', 'port', 'username', 'password', 'database',
|
for key in [
|
||||||
'measurement', 'timeout']:
|
'host',
|
||||||
|
'port',
|
||||||
|
'username',
|
||||||
|
'password',
|
||||||
|
'database',
|
||||||
|
'measurement',
|
||||||
|
'timeout',
|
||||||
|
]:
|
||||||
if key in influxdb_config:
|
if key in influxdb_config:
|
||||||
config[key] = influxdb_config[key]
|
config[key] = influxdb_config[key]
|
||||||
self._influxdb_config = config
|
self._influxdb_config = config
|
||||||
@ -357,20 +396,28 @@ class OpenStackConfig:
|
|||||||
if not envvar_prefix:
|
if not envvar_prefix:
|
||||||
# This makes the or below be OS_ or OS_ which is a no-op
|
# This makes the or below be OS_ or OS_ which is a no-op
|
||||||
envvar_prefix = 'OS_'
|
envvar_prefix = 'OS_'
|
||||||
environkeys = [k for k in os.environ.keys()
|
environkeys = [
|
||||||
if (k.startswith('OS_') or k.startswith(envvar_prefix))
|
k
|
||||||
and not k.startswith('OS_TEST') # infra CI var
|
for k in os.environ.keys()
|
||||||
and not k.startswith('OS_STD') # oslotest var
|
if (k.startswith('OS_') or k.startswith(envvar_prefix))
|
||||||
and not k.startswith('OS_LOG') # oslotest var
|
and not k.startswith('OS_TEST') # infra CI var
|
||||||
]
|
and not k.startswith('OS_STD') # oslotest var
|
||||||
|
and not k.startswith('OS_LOG') # oslotest var
|
||||||
|
]
|
||||||
for k in environkeys:
|
for k in environkeys:
|
||||||
newkey = k.split('_', 1)[-1].lower()
|
newkey = k.split('_', 1)[-1].lower()
|
||||||
ret[newkey] = os.environ[k]
|
ret[newkey] = os.environ[k]
|
||||||
# If the only environ keys are selectors or behavior modification,
|
# If the only environ keys are selectors or behavior modification,
|
||||||
# don't return anything
|
# don't return anything
|
||||||
selectors = set([
|
selectors = set(
|
||||||
'OS_CLOUD', 'OS_REGION_NAME',
|
[
|
||||||
'OS_CLIENT_CONFIG_FILE', 'OS_CLIENT_SECURE_FILE', 'OS_CLOUD_NAME'])
|
'OS_CLOUD',
|
||||||
|
'OS_REGION_NAME',
|
||||||
|
'OS_CLIENT_CONFIG_FILE',
|
||||||
|
'OS_CLIENT_SECURE_FILE',
|
||||||
|
'OS_CLOUD_NAME',
|
||||||
|
]
|
||||||
|
)
|
||||||
if set(environkeys) - selectors:
|
if set(environkeys) - selectors:
|
||||||
return ret
|
return ret
|
||||||
return None
|
return None
|
||||||
@ -391,8 +438,8 @@ class OpenStackConfig:
|
|||||||
if not key:
|
if not key:
|
||||||
return defaults
|
return defaults
|
||||||
return _util.merge_clouds(
|
return _util.merge_clouds(
|
||||||
defaults,
|
defaults, _util.normalize_keys(self.cloud_config.get(key, {}))
|
||||||
_util.normalize_keys(self.cloud_config.get(key, {})))
|
)
|
||||||
|
|
||||||
def _load_config_file(self):
|
def _load_config_file(self):
|
||||||
return self._load_yaml_json_file(self._config_files)
|
return self._load_yaml_json_file(self._config_files)
|
||||||
@ -427,10 +474,12 @@ class OpenStackConfig:
|
|||||||
for region in regions:
|
for region in regions:
|
||||||
if isinstance(region, dict):
|
if isinstance(region, dict):
|
||||||
# i.e. must have name key, and only name,values keys
|
# i.e. must have name key, and only name,values keys
|
||||||
if 'name' not in region or \
|
if 'name' not in region or not {'name', 'values'} >= set(
|
||||||
not {'name', 'values'} >= set(region):
|
region
|
||||||
|
):
|
||||||
raise exceptions.ConfigException(
|
raise exceptions.ConfigException(
|
||||||
'Invalid region entry at: %s' % region)
|
'Invalid region entry at: %s' % region
|
||||||
|
)
|
||||||
if 'values' not in region:
|
if 'values' not in region:
|
||||||
region['values'] = {}
|
region['values'] = {}
|
||||||
ret.append(copy.deepcopy(region))
|
ret.append(copy.deepcopy(region))
|
||||||
@ -460,7 +509,8 @@ class OpenStackConfig:
|
|||||||
warnings.warn(
|
warnings.warn(
|
||||||
"Comma separated lists in region_name are deprecated."
|
"Comma separated lists in region_name are deprecated."
|
||||||
" Please use a yaml list in the regions"
|
" Please use a yaml list in the regions"
|
||||||
" parameter in {0} instead.".format(self.config_filename))
|
" parameter in {0} instead.".format(self.config_filename)
|
||||||
|
)
|
||||||
return self._expand_regions(regions)
|
return self._expand_regions(regions)
|
||||||
else:
|
else:
|
||||||
# crappit. we don't have a region defined.
|
# crappit. we don't have a region defined.
|
||||||
@ -495,7 +545,9 @@ class OpenStackConfig:
|
|||||||
' region names are case sensitive.'.format(
|
' region names are case sensitive.'.format(
|
||||||
region_name=region_name,
|
region_name=region_name,
|
||||||
region_list=','.join([r['name'] for r in regions]),
|
region_list=','.join([r['name'] for r in regions]),
|
||||||
cloud=cloud))
|
cloud=cloud,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def get_cloud_names(self):
|
def get_cloud_names(self):
|
||||||
return self.cloud_config['clouds'].keys()
|
return self.cloud_config['clouds'].keys()
|
||||||
@ -506,8 +558,8 @@ class OpenStackConfig:
|
|||||||
# Only validate cloud name if one was given
|
# Only validate cloud name if one was given
|
||||||
if name and name not in self.cloud_config['clouds']:
|
if name and name not in self.cloud_config['clouds']:
|
||||||
raise exceptions.ConfigException(
|
raise exceptions.ConfigException(
|
||||||
"Cloud {name} was not found.".format(
|
"Cloud {name} was not found.".format(name=name)
|
||||||
name=name))
|
)
|
||||||
|
|
||||||
our_cloud = self.cloud_config['clouds'].get(name, dict())
|
our_cloud = self.cloud_config['clouds'].get(name, dict())
|
||||||
if profile:
|
if profile:
|
||||||
@ -536,11 +588,15 @@ class OpenStackConfig:
|
|||||||
warnings.warn(
|
warnings.warn(
|
||||||
"{0} uses the keyword 'cloud' to reference a known "
|
"{0} uses the keyword 'cloud' to reference a known "
|
||||||
"vendor profile. This has been deprecated in favor of the "
|
"vendor profile. This has been deprecated in favor of the "
|
||||||
"'profile' keyword.".format(self.config_filename))
|
"'profile' keyword.".format(self.config_filename)
|
||||||
|
)
|
||||||
|
|
||||||
vendor_filename, vendor_file = self._load_vendor_file()
|
vendor_filename, vendor_file = self._load_vendor_file()
|
||||||
if (vendor_file and 'public-clouds' in vendor_file
|
if (
|
||||||
and profile_name in vendor_file['public-clouds']):
|
vendor_file
|
||||||
|
and 'public-clouds' in vendor_file
|
||||||
|
and profile_name in vendor_file['public-clouds']
|
||||||
|
):
|
||||||
_auth_update(cloud, vendor_file['public-clouds'][profile_name])
|
_auth_update(cloud, vendor_file['public-clouds'][profile_name])
|
||||||
else:
|
else:
|
||||||
profile_data = vendors.get_profile(profile_name)
|
profile_data = vendors.get_profile(profile_name)
|
||||||
@ -555,23 +611,31 @@ class OpenStackConfig:
|
|||||||
if status == 'deprecated':
|
if status == 'deprecated':
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"{profile_name} is deprecated: {message}".format(
|
"{profile_name} is deprecated: {message}".format(
|
||||||
profile_name=profile_name, message=message))
|
profile_name=profile_name, message=message
|
||||||
|
)
|
||||||
|
)
|
||||||
elif status == 'shutdown':
|
elif status == 'shutdown':
|
||||||
raise exceptions.ConfigException(
|
raise exceptions.ConfigException(
|
||||||
"{profile_name} references a cloud that no longer"
|
"{profile_name} references a cloud that no longer"
|
||||||
" exists: {message}".format(
|
" exists: {message}".format(
|
||||||
profile_name=profile_name, message=message))
|
profile_name=profile_name, message=message
|
||||||
|
)
|
||||||
|
)
|
||||||
_auth_update(cloud, profile_data)
|
_auth_update(cloud, profile_data)
|
||||||
else:
|
else:
|
||||||
# Can't find the requested vendor config, go about business
|
# Can't find the requested vendor config, go about business
|
||||||
warnings.warn("Couldn't find the vendor profile '{0}', for"
|
warnings.warn(
|
||||||
" the cloud '{1}'".format(profile_name,
|
"Couldn't find the vendor profile '{0}', for"
|
||||||
name))
|
" the cloud '{1}'".format(profile_name, name)
|
||||||
|
)
|
||||||
|
|
||||||
def _project_scoped(self, cloud):
|
def _project_scoped(self, cloud):
|
||||||
return ('project_id' in cloud or 'project_name' in cloud
|
return (
|
||||||
or 'project_id' in cloud['auth']
|
'project_id' in cloud
|
||||||
or 'project_name' in cloud['auth'])
|
or 'project_name' in cloud
|
||||||
|
or 'project_id' in cloud['auth']
|
||||||
|
or 'project_name' in cloud['auth']
|
||||||
|
)
|
||||||
|
|
||||||
def _validate_networks(self, networks, key):
|
def _validate_networks(self, networks, key):
|
||||||
value = None
|
value = None
|
||||||
@ -580,9 +644,9 @@ class OpenStackConfig:
|
|||||||
raise exceptions.ConfigException(
|
raise exceptions.ConfigException(
|
||||||
"Duplicate network entries for {key}: {net1} and {net2}."
|
"Duplicate network entries for {key}: {net1} and {net2}."
|
||||||
" Only one network can be flagged with {key}".format(
|
" Only one network can be flagged with {key}".format(
|
||||||
key=key,
|
key=key, net1=value['name'], net2=net['name']
|
||||||
net1=value['name'],
|
)
|
||||||
net2=net['name']))
|
)
|
||||||
if not value and net[key]:
|
if not value and net[key]:
|
||||||
value = net
|
value = net
|
||||||
|
|
||||||
@ -595,7 +659,8 @@ class OpenStackConfig:
|
|||||||
name = net.get('name')
|
name = net.get('name')
|
||||||
if not name:
|
if not name:
|
||||||
raise exceptions.ConfigException(
|
raise exceptions.ConfigException(
|
||||||
'Entry in network list is missing required field "name".')
|
'Entry in network list is missing required field "name".'
|
||||||
|
)
|
||||||
network = dict(
|
network = dict(
|
||||||
name=name,
|
name=name,
|
||||||
routes_externally=get_boolean(net.get('routes_externally')),
|
routes_externally=get_boolean(net.get('routes_externally')),
|
||||||
@ -605,12 +670,12 @@ class OpenStackConfig:
|
|||||||
)
|
)
|
||||||
# routes_ipv4_externally defaults to the value of routes_externally
|
# routes_ipv4_externally defaults to the value of routes_externally
|
||||||
network['routes_ipv4_externally'] = get_boolean(
|
network['routes_ipv4_externally'] = get_boolean(
|
||||||
net.get(
|
net.get('routes_ipv4_externally', network['routes_externally'])
|
||||||
'routes_ipv4_externally', network['routes_externally']))
|
)
|
||||||
# routes_ipv6_externally defaults to the value of routes_externally
|
# routes_ipv6_externally defaults to the value of routes_externally
|
||||||
network['routes_ipv6_externally'] = get_boolean(
|
network['routes_ipv6_externally'] = get_boolean(
|
||||||
net.get(
|
net.get('routes_ipv6_externally', network['routes_externally'])
|
||||||
'routes_ipv6_externally', network['routes_externally']))
|
)
|
||||||
networks.append(network)
|
networks.append(network)
|
||||||
|
|
||||||
for key in ('external_network', 'internal_network'):
|
for key in ('external_network', 'internal_network'):
|
||||||
@ -619,18 +684,24 @@ class OpenStackConfig:
|
|||||||
raise exceptions.ConfigException(
|
raise exceptions.ConfigException(
|
||||||
"Both {key} and networks were specified in the config."
|
"Both {key} and networks were specified in the config."
|
||||||
" Please remove {key} from the config and use the network"
|
" Please remove {key} from the config and use the network"
|
||||||
" list to configure network behavior.".format(key=key))
|
" list to configure network behavior.".format(key=key)
|
||||||
|
)
|
||||||
if key in cloud:
|
if key in cloud:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"{key} is deprecated. Please replace with an entry in"
|
"{key} is deprecated. Please replace with an entry in"
|
||||||
" a dict inside of the networks list with name: {name}"
|
" a dict inside of the networks list with name: {name}"
|
||||||
" and routes_externally: {external}".format(
|
" and routes_externally: {external}".format(
|
||||||
key=key, name=cloud[key], external=external))
|
key=key, name=cloud[key], external=external
|
||||||
networks.append(dict(
|
)
|
||||||
name=cloud[key],
|
)
|
||||||
routes_externally=external,
|
networks.append(
|
||||||
nat_destination=not external,
|
dict(
|
||||||
default_interface=external))
|
name=cloud[key],
|
||||||
|
routes_externally=external,
|
||||||
|
nat_destination=not external,
|
||||||
|
default_interface=external,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Validate that we don't have duplicates
|
# Validate that we don't have duplicates
|
||||||
self._validate_networks(networks, 'nat_destination')
|
self._validate_networks(networks, 'nat_destination')
|
||||||
@ -668,7 +739,9 @@ class OpenStackConfig:
|
|||||||
'user_domain_name': ('user_domain_name', 'user-domain-name'),
|
'user_domain_name': ('user_domain_name', 'user-domain-name'),
|
||||||
'project_domain_id': ('project_domain_id', 'project-domain-id'),
|
'project_domain_id': ('project_domain_id', 'project-domain-id'),
|
||||||
'project_domain_name': (
|
'project_domain_name': (
|
||||||
'project_domain_name', 'project-domain-name'),
|
'project_domain_name',
|
||||||
|
'project-domain-name',
|
||||||
|
),
|
||||||
'token': ('auth-token', 'auth_token', 'token'),
|
'token': ('auth-token', 'auth_token', 'token'),
|
||||||
}
|
}
|
||||||
if cloud.get('auth_type', None) == 'v2password':
|
if cloud.get('auth_type', None) == 'v2password':
|
||||||
@ -676,14 +749,30 @@ class OpenStackConfig:
|
|||||||
# clouds. That's fine - we need to map settings in the opposite
|
# clouds. That's fine - we need to map settings in the opposite
|
||||||
# direction
|
# direction
|
||||||
mappings['tenant_id'] = (
|
mappings['tenant_id'] = (
|
||||||
'project_id', 'project-id', 'tenant_id', 'tenant-id')
|
'project_id',
|
||||||
|
'project-id',
|
||||||
|
'tenant_id',
|
||||||
|
'tenant-id',
|
||||||
|
)
|
||||||
mappings['tenant_name'] = (
|
mappings['tenant_name'] = (
|
||||||
'project_name', 'project-name', 'tenant_name', 'tenant-name')
|
'project_name',
|
||||||
|
'project-name',
|
||||||
|
'tenant_name',
|
||||||
|
'tenant-name',
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
mappings['project_id'] = (
|
mappings['project_id'] = (
|
||||||
'tenant_id', 'tenant-id', 'project_id', 'project-id')
|
'tenant_id',
|
||||||
|
'tenant-id',
|
||||||
|
'project_id',
|
||||||
|
'project-id',
|
||||||
|
)
|
||||||
mappings['project_name'] = (
|
mappings['project_name'] = (
|
||||||
'tenant_name', 'tenant-name', 'project_name', 'project-name')
|
'tenant_name',
|
||||||
|
'tenant-name',
|
||||||
|
'project_name',
|
||||||
|
'project-name',
|
||||||
|
)
|
||||||
for target_key, possible_values in mappings.items():
|
for target_key, possible_values in mappings.items():
|
||||||
target = None
|
target = None
|
||||||
for key in possible_values:
|
for key in possible_values:
|
||||||
@ -747,7 +836,8 @@ class OpenStackConfig:
|
|||||||
'--os-cloud',
|
'--os-cloud',
|
||||||
metavar='<name>',
|
metavar='<name>',
|
||||||
default=self._get_envvar('OS_CLOUD', None),
|
default=self._get_envvar('OS_CLOUD', None),
|
||||||
help='Named cloud to connect to')
|
help='Named cloud to connect to',
|
||||||
|
)
|
||||||
|
|
||||||
# we need to peek to see if timeout was actually passed, since
|
# we need to peek to see if timeout was actually passed, since
|
||||||
# the keystoneauth declaration of it has a default, which means
|
# the keystoneauth declaration of it has a default, which means
|
||||||
@ -782,7 +872,8 @@ class OpenStackConfig:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
loading.register_auth_argparse_arguments(
|
loading.register_auth_argparse_arguments(
|
||||||
parser, argv, default=default_auth_type)
|
parser, argv, default=default_auth_type
|
||||||
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
# Hidiing the keystoneauth exception because we're not actually
|
# Hidiing the keystoneauth exception because we're not actually
|
||||||
# loading the auth plugin at this point, so the error message
|
# loading the auth plugin at this point, so the error message
|
||||||
@ -793,7 +884,9 @@ class OpenStackConfig:
|
|||||||
"An invalid auth-type was specified: {auth_type}."
|
"An invalid auth-type was specified: {auth_type}."
|
||||||
" Valid choices are: {plugin_names}.".format(
|
" Valid choices are: {plugin_names}.".format(
|
||||||
auth_type=options.os_auth_type,
|
auth_type=options.os_auth_type,
|
||||||
plugin_names=",".join(plugin_names)))
|
plugin_names=",".join(plugin_names),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if service_keys:
|
if service_keys:
|
||||||
primary_service = service_keys[0]
|
primary_service = service_keys[0]
|
||||||
@ -801,15 +894,19 @@ class OpenStackConfig:
|
|||||||
primary_service = None
|
primary_service = None
|
||||||
loading.register_session_argparse_arguments(parser)
|
loading.register_session_argparse_arguments(parser)
|
||||||
adapter.register_adapter_argparse_arguments(
|
adapter.register_adapter_argparse_arguments(
|
||||||
parser, service_type=primary_service)
|
parser, service_type=primary_service
|
||||||
|
)
|
||||||
for service_key in service_keys:
|
for service_key in service_keys:
|
||||||
# legacy clients have un-prefixed api-version options
|
# legacy clients have un-prefixed api-version options
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--{service_key}-api-version'.format(
|
'--{service_key}-api-version'.format(
|
||||||
service_key=service_key.replace('_', '-')),
|
service_key=service_key.replace('_', '-')
|
||||||
help=argparse_mod.SUPPRESS)
|
),
|
||||||
|
help=argparse_mod.SUPPRESS,
|
||||||
|
)
|
||||||
adapter.register_service_adapter_argparse_arguments(
|
adapter.register_service_adapter_argparse_arguments(
|
||||||
parser, service_type=service_key)
|
parser, service_type=service_key
|
||||||
|
)
|
||||||
|
|
||||||
# Backwards compat options for legacy clients
|
# Backwards compat options for legacy clients
|
||||||
parser.add_argument('--http-timeout', help=argparse_mod.SUPPRESS)
|
parser.add_argument('--http-timeout', help=argparse_mod.SUPPRESS)
|
||||||
@ -837,7 +934,8 @@ class OpenStackConfig:
|
|||||||
service_timeout = None
|
service_timeout = None
|
||||||
for key in cloud.keys():
|
for key in cloud.keys():
|
||||||
if key.endswith('timeout') and not (
|
if key.endswith('timeout') and not (
|
||||||
key == 'timeout' or key == 'api_timeout'):
|
key == 'timeout' or key == 'api_timeout'
|
||||||
|
):
|
||||||
service_timeout = cloud[key]
|
service_timeout = cloud[key]
|
||||||
else:
|
else:
|
||||||
new_cloud[key] = cloud[key]
|
new_cloud[key] = cloud[key]
|
||||||
@ -857,9 +955,11 @@ class OpenStackConfig:
|
|||||||
for cloud in self.get_cloud_names():
|
for cloud in self.get_cloud_names():
|
||||||
for region in self._get_regions(cloud):
|
for region in self._get_regions(cloud):
|
||||||
if region:
|
if region:
|
||||||
clouds.append(self.get_one(
|
clouds.append(
|
||||||
cloud, region_name=region['name']))
|
self.get_one(cloud, region_name=region['name'])
|
||||||
|
)
|
||||||
return clouds
|
return clouds
|
||||||
|
|
||||||
# TODO(mordred) Backwards compat for OSC transition
|
# TODO(mordred) Backwards compat for OSC transition
|
||||||
get_all_clouds = get_all
|
get_all_clouds = get_all
|
||||||
|
|
||||||
@ -904,8 +1004,9 @@ class OpenStackConfig:
|
|||||||
if opt_name in config:
|
if opt_name in config:
|
||||||
return config[opt_name]
|
return config[opt_name]
|
||||||
else:
|
else:
|
||||||
deprecated = getattr(opt, 'deprecated', getattr(
|
deprecated = getattr(
|
||||||
opt, 'deprecated_opts', []))
|
opt, 'deprecated', getattr(opt, 'deprecated_opts', [])
|
||||||
|
)
|
||||||
for d_opt in deprecated:
|
for d_opt in deprecated:
|
||||||
d_opt_name = d_opt.name.replace('-', '_')
|
d_opt_name = d_opt.name.replace('-', '_')
|
||||||
if d_opt_name in config:
|
if d_opt_name in config:
|
||||||
@ -1027,9 +1128,9 @@ class OpenStackConfig:
|
|||||||
def option_prompt(self, config, p_opt):
|
def option_prompt(self, config, p_opt):
|
||||||
"""Prompt user for option that requires a value"""
|
"""Prompt user for option that requires a value"""
|
||||||
if (
|
if (
|
||||||
getattr(p_opt, 'prompt', None) is not None
|
getattr(p_opt, 'prompt', None) is not None
|
||||||
and p_opt.dest not in config['auth']
|
and p_opt.dest not in config['auth']
|
||||||
and self._pw_callback is not None
|
and self._pw_callback is not None
|
||||||
):
|
):
|
||||||
config['auth'][p_opt.dest] = self._pw_callback(p_opt.prompt)
|
config['auth'][p_opt.dest] = self._pw_callback(p_opt.prompt)
|
||||||
return config
|
return config
|
||||||
@ -1046,8 +1147,7 @@ class OpenStackConfig:
|
|||||||
# Prefer the plugin configuration dest value if the value's key
|
# Prefer the plugin configuration dest value if the value's key
|
||||||
# is marked as depreciated.
|
# is marked as depreciated.
|
||||||
if p_opt.dest is None:
|
if p_opt.dest is None:
|
||||||
config['auth'][p_opt.name.replace('-', '_')] = (
|
config['auth'][p_opt.name.replace('-', '_')] = winning_value
|
||||||
winning_value)
|
|
||||||
else:
|
else:
|
||||||
config['auth'][p_opt.dest] = winning_value
|
config['auth'][p_opt.dest] = winning_value
|
||||||
return config
|
return config
|
||||||
@ -1056,9 +1156,11 @@ class OpenStackConfig:
|
|||||||
"""Perform the set of magic argument fixups"""
|
"""Perform the set of magic argument fixups"""
|
||||||
|
|
||||||
# Infer token plugin if a token was given
|
# Infer token plugin if a token was given
|
||||||
if (('auth' in config and 'token' in config['auth'])
|
if (
|
||||||
or ('auth_token' in config and config['auth_token'])
|
('auth' in config and 'token' in config['auth'])
|
||||||
or ('token' in config and config['token'])):
|
or ('auth_token' in config and config['auth_token'])
|
||||||
|
or ('token' in config and config['token'])
|
||||||
|
):
|
||||||
config.setdefault('token', config.pop('auth_token', None))
|
config.setdefault('token', config.pop('auth_token', None))
|
||||||
|
|
||||||
# Infer passcode if it was given separately
|
# Infer passcode if it was given separately
|
||||||
@ -1094,12 +1196,12 @@ class OpenStackConfig:
|
|||||||
# more generalized
|
# more generalized
|
||||||
if 'auth' in config and 'auth_url' in config['auth']:
|
if 'auth' in config and 'auth_url' in config['auth']:
|
||||||
config['auth']['auth_url'] = config['auth']['auth_url'].format(
|
config['auth']['auth_url'] = config['auth']['auth_url'].format(
|
||||||
**config)
|
**config
|
||||||
|
)
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def get_one(
|
def get_one(self, cloud=None, validate=True, argparse=None, **kwargs):
|
||||||
self, cloud=None, validate=True, argparse=None, **kwargs):
|
|
||||||
"""Retrieve a single CloudRegion and merge additional options
|
"""Retrieve a single CloudRegion and merge additional options
|
||||||
|
|
||||||
:param string cloud:
|
:param string cloud:
|
||||||
@ -1217,15 +1319,12 @@ class OpenStackConfig:
|
|||||||
statsd_prefix=statsd_prefix,
|
statsd_prefix=statsd_prefix,
|
||||||
influxdb_config=influxdb_config,
|
influxdb_config=influxdb_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO(mordred) Backwards compat for OSC transition
|
# TODO(mordred) Backwards compat for OSC transition
|
||||||
get_one_cloud = get_one
|
get_one_cloud = get_one
|
||||||
|
|
||||||
def get_one_cloud_osc(
|
def get_one_cloud_osc(
|
||||||
self,
|
self, cloud=None, validate=True, argparse=None, **kwargs
|
||||||
cloud=None,
|
|
||||||
validate=True,
|
|
||||||
argparse=None,
|
|
||||||
**kwargs
|
|
||||||
):
|
):
|
||||||
"""Retrieve a single CloudRegion and merge additional options
|
"""Retrieve a single CloudRegion and merge additional options
|
||||||
|
|
||||||
@ -1359,10 +1458,10 @@ if __name__ == '__main__':
|
|||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
print_cloud = True
|
print_cloud = True
|
||||||
elif len(sys.argv) == 3 and (
|
elif len(sys.argv) == 3 and (
|
||||||
sys.argv[1] == cloud.name and sys.argv[2] == cloud.region):
|
sys.argv[1] == cloud.name and sys.argv[2] == cloud.region
|
||||||
|
):
|
||||||
print_cloud = True
|
print_cloud = True
|
||||||
elif len(sys.argv) == 2 and (
|
elif len(sys.argv) == 2 and (sys.argv[1] == cloud.name):
|
||||||
sys.argv[1] == cloud.name):
|
|
||||||
print_cloud = True
|
print_cloud = True
|
||||||
|
|
||||||
if print_cloud:
|
if print_cloud:
|
||||||
|
8
openstack/config/vendors/__init__.py
vendored
8
openstack/config/vendors/__init__.py
vendored
@ -61,7 +61,9 @@ def get_profile(profile_name):
|
|||||||
" {status_code} {reason}".format(
|
" {status_code} {reason}".format(
|
||||||
profile_name=profile_name,
|
profile_name=profile_name,
|
||||||
status_code=response.status_code,
|
status_code=response.status_code,
|
||||||
reason=response.reason))
|
reason=response.reason,
|
||||||
|
)
|
||||||
|
)
|
||||||
vendor_defaults[profile_name] = None
|
vendor_defaults[profile_name] = None
|
||||||
return
|
return
|
||||||
vendor_data = response.json()
|
vendor_data = response.json()
|
||||||
@ -69,8 +71,8 @@ def get_profile(profile_name):
|
|||||||
# Merge named and url cloud config, but make named config override the
|
# Merge named and url cloud config, but make named config override the
|
||||||
# config from the cloud so that we can supply local overrides if needed.
|
# config from the cloud so that we can supply local overrides if needed.
|
||||||
profile = _util.merge_clouds(
|
profile = _util.merge_clouds(
|
||||||
vendor_data['profile'],
|
vendor_data['profile'], vendor_defaults.get(name, {})
|
||||||
vendor_defaults.get(name, {}))
|
)
|
||||||
# If there is (or was) a profile listed in a named config profile, it
|
# If there is (or was) a profile listed in a named config profile, it
|
||||||
# might still be here. We just merged in content from a URL though, so
|
# might still be here. We just merged in content from a URL though, so
|
||||||
# pop the key to prevent doing it again in the future.
|
# pop the key to prevent doing it again in the future.
|
||||||
|
@ -220,7 +220,8 @@ __all__ = [
|
|||||||
|
|
||||||
if requestsexceptions.SubjectAltNameWarning:
|
if requestsexceptions.SubjectAltNameWarning:
|
||||||
warnings.filterwarnings(
|
warnings.filterwarnings(
|
||||||
'ignore', category=requestsexceptions.SubjectAltNameWarning)
|
'ignore', category=requestsexceptions.SubjectAltNameWarning
|
||||||
|
)
|
||||||
|
|
||||||
_logger = _log.setup_logging('openstack')
|
_logger = _log.setup_logging('openstack')
|
||||||
|
|
||||||
@ -249,7 +250,8 @@ def from_config(cloud=None, config=None, options=None, **kwargs):
|
|||||||
config = kwargs.pop('cloud_config', config)
|
config = kwargs.pop('cloud_config', config)
|
||||||
if config is None:
|
if config is None:
|
||||||
config = _config.OpenStackConfig().get_one(
|
config = _config.OpenStackConfig().get_one(
|
||||||
cloud=cloud, argparse=options, **kwargs)
|
cloud=cloud, argparse=options, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
return Connection(config=config)
|
return Connection(config=config)
|
||||||
|
|
||||||
@ -274,20 +276,25 @@ class Connection(
|
|||||||
_security_group.SecurityGroupCloudMixin,
|
_security_group.SecurityGroupCloudMixin,
|
||||||
_shared_file_system.SharedFileSystemCloudMixin,
|
_shared_file_system.SharedFileSystemCloudMixin,
|
||||||
):
|
):
|
||||||
|
def __init__(
|
||||||
def __init__(self, cloud=None, config=None, session=None,
|
self,
|
||||||
app_name=None, app_version=None,
|
cloud=None,
|
||||||
extra_services=None,
|
config=None,
|
||||||
strict=False,
|
session=None,
|
||||||
use_direct_get=False,
|
app_name=None,
|
||||||
task_manager=None,
|
app_version=None,
|
||||||
rate_limit=None,
|
extra_services=None,
|
||||||
oslo_conf=None,
|
strict=False,
|
||||||
service_types=None,
|
use_direct_get=False,
|
||||||
global_request_id=None,
|
task_manager=None,
|
||||||
strict_proxies=False,
|
rate_limit=None,
|
||||||
pool_executor=None,
|
oslo_conf=None,
|
||||||
**kwargs):
|
service_types=None,
|
||||||
|
global_request_id=None,
|
||||||
|
strict_proxies=False,
|
||||||
|
pool_executor=None,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
"""Create a connection to a cloud.
|
"""Create a connection to a cloud.
|
||||||
|
|
||||||
A connection needs information about how to connect, how to
|
A connection needs information about how to connect, how to
|
||||||
@ -373,24 +380,32 @@ class Connection(
|
|||||||
if not self.config:
|
if not self.config:
|
||||||
if oslo_conf:
|
if oslo_conf:
|
||||||
self.config = cloud_region.from_conf(
|
self.config = cloud_region.from_conf(
|
||||||
oslo_conf, session=session, app_name=app_name,
|
oslo_conf,
|
||||||
app_version=app_version, service_types=service_types)
|
session=session,
|
||||||
|
app_name=app_name,
|
||||||
|
app_version=app_version,
|
||||||
|
service_types=service_types,
|
||||||
|
)
|
||||||
elif session:
|
elif session:
|
||||||
self.config = cloud_region.from_session(
|
self.config = cloud_region.from_session(
|
||||||
session=session,
|
session=session,
|
||||||
app_name=app_name, app_version=app_version,
|
app_name=app_name,
|
||||||
|
app_version=app_version,
|
||||||
load_yaml_config=False,
|
load_yaml_config=False,
|
||||||
load_envvars=False,
|
load_envvars=False,
|
||||||
rate_limit=rate_limit,
|
rate_limit=rate_limit,
|
||||||
**kwargs)
|
**kwargs
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.config = _config.get_cloud_region(
|
self.config = _config.get_cloud_region(
|
||||||
cloud=cloud,
|
cloud=cloud,
|
||||||
app_name=app_name, app_version=app_version,
|
app_name=app_name,
|
||||||
|
app_version=app_version,
|
||||||
load_yaml_config=cloud is not None,
|
load_yaml_config=cloud is not None,
|
||||||
load_envvars=cloud is not None,
|
load_envvars=cloud is not None,
|
||||||
rate_limit=rate_limit,
|
rate_limit=rate_limit,
|
||||||
**kwargs)
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
self._session = None
|
self._session = None
|
||||||
self._proxies = {}
|
self._proxies = {}
|
||||||
@ -440,19 +455,25 @@ class Connection(
|
|||||||
hook = ep.load()
|
hook = ep.load()
|
||||||
hook(self)
|
hook(self)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.log.warning('Hook should be in the entrypoint '
|
self.log.warning(
|
||||||
'module:attribute format')
|
'Hook should be in the entrypoint '
|
||||||
|
'module:attribute format'
|
||||||
|
)
|
||||||
except (ImportError, TypeError, AttributeError) as e:
|
except (ImportError, TypeError, AttributeError) as e:
|
||||||
self.log.warning('Configured hook %s cannot be executed: %s',
|
self.log.warning(
|
||||||
vendor_hook, e)
|
'Configured hook %s cannot be executed: %s', vendor_hook, e
|
||||||
|
)
|
||||||
|
|
||||||
# Add additional metrics into the configuration according to the
|
# Add additional metrics into the configuration according to the
|
||||||
# selected connection. We don't want to deal with overall config in the
|
# selected connection. We don't want to deal with overall config in the
|
||||||
# proxy, just pass required part.
|
# proxy, just pass required part.
|
||||||
if (self.config._influxdb_config
|
if (
|
||||||
and 'additional_metric_tags' in self.config.config):
|
self.config._influxdb_config
|
||||||
self.config._influxdb_config['additional_metric_tags'] = \
|
and 'additional_metric_tags' in self.config.config
|
||||||
self.config.config['additional_metric_tags']
|
):
|
||||||
|
self.config._influxdb_config[
|
||||||
|
'additional_metric_tags'
|
||||||
|
] = self.config.config['additional_metric_tags']
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
# try to force release of resources and save authorization
|
# try to force release of resources and save authorization
|
||||||
@ -500,7 +521,7 @@ class Connection(
|
|||||||
setattr(
|
setattr(
|
||||||
self.__class__,
|
self.__class__,
|
||||||
attr_name.replace('-', '_'),
|
attr_name.replace('-', '_'),
|
||||||
property(fget=getter)
|
property(fget=getter),
|
||||||
)
|
)
|
||||||
self.config.enable_service(service.service_type)
|
self.config.enable_service(service.service_type)
|
||||||
|
|
||||||
@ -527,7 +548,8 @@ class Connection(
|
|||||||
def _pool_executor(self):
|
def _pool_executor(self):
|
||||||
if not self.__pool_executor:
|
if not self.__pool_executor:
|
||||||
self.__pool_executor = concurrent.futures.ThreadPoolExecutor(
|
self.__pool_executor = concurrent.futures.ThreadPoolExecutor(
|
||||||
max_workers=5)
|
max_workers=5
|
||||||
|
)
|
||||||
return self.__pool_executor
|
return self.__pool_executor
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
@ -24,6 +24,7 @@ from requests import exceptions as _rex
|
|||||||
|
|
||||||
class SDKException(Exception):
|
class SDKException(Exception):
|
||||||
"""The base exception class for all exceptions this library raises."""
|
"""The base exception class for all exceptions this library raises."""
|
||||||
|
|
||||||
def __init__(self, message=None, extra_data=None):
|
def __init__(self, message=None, extra_data=None):
|
||||||
self.message = self.__class__.__name__ if message is None else message
|
self.message = self.__class__.__name__ if message is None else message
|
||||||
self.extra_data = extra_data
|
self.extra_data = extra_data
|
||||||
@ -35,6 +36,7 @@ OpenStackCloudException = SDKException
|
|||||||
|
|
||||||
class EndpointNotFound(SDKException):
|
class EndpointNotFound(SDKException):
|
||||||
"""A mismatch occurred between what the client and server expect."""
|
"""A mismatch occurred between what the client and server expect."""
|
||||||
|
|
||||||
def __init__(self, message=None):
|
def __init__(self, message=None):
|
||||||
super(EndpointNotFound, self).__init__(message)
|
super(EndpointNotFound, self).__init__(message)
|
||||||
|
|
||||||
@ -55,20 +57,25 @@ class InvalidRequest(SDKException):
|
|||||||
|
|
||||||
|
|
||||||
class HttpException(SDKException, _rex.HTTPError):
|
class HttpException(SDKException, _rex.HTTPError):
|
||||||
|
def __init__(
|
||||||
def __init__(self, message='Error', response=None,
|
self,
|
||||||
http_status=None,
|
message='Error',
|
||||||
details=None, request_id=None):
|
response=None,
|
||||||
|
http_status=None,
|
||||||
|
details=None,
|
||||||
|
request_id=None,
|
||||||
|
):
|
||||||
# TODO(shade) Remove http_status parameter and the ability for response
|
# TODO(shade) Remove http_status parameter and the ability for response
|
||||||
# to be None once we're not mocking Session everywhere.
|
# to be None once we're not mocking Session everywhere.
|
||||||
if not message:
|
if not message:
|
||||||
if response is not None:
|
if response is not None:
|
||||||
message = "{name}: {code}".format(
|
message = "{name}: {code}".format(
|
||||||
name=self.__class__.__name__,
|
name=self.__class__.__name__, code=response.status_code
|
||||||
code=response.status_code)
|
)
|
||||||
else:
|
else:
|
||||||
message = "{name}: Unknown error".format(
|
message = "{name}: Unknown error".format(
|
||||||
name=self.__class__.__name__)
|
name=self.__class__.__name__
|
||||||
|
)
|
||||||
|
|
||||||
# Call directly rather than via super to control parameters
|
# Call directly rather than via super to control parameters
|
||||||
SDKException.__init__(self, message=message)
|
SDKException.__init__(self, message=message)
|
||||||
@ -96,7 +103,8 @@ class HttpException(SDKException, _rex.HTTPError):
|
|||||||
return self.message
|
return self.message
|
||||||
if self.url:
|
if self.url:
|
||||||
remote_error = "{source} Error for url: {url}".format(
|
remote_error = "{source} Error for url: {url}".format(
|
||||||
source=self.source, url=self.url)
|
source=self.source, url=self.url
|
||||||
|
)
|
||||||
if self.details:
|
if self.details:
|
||||||
remote_error += ', '
|
remote_error += ', '
|
||||||
if self.details:
|
if self.details:
|
||||||
@ -104,31 +112,37 @@ class HttpException(SDKException, _rex.HTTPError):
|
|||||||
|
|
||||||
return "{message}: {remote_error}".format(
|
return "{message}: {remote_error}".format(
|
||||||
message=super(HttpException, self).__str__(),
|
message=super(HttpException, self).__str__(),
|
||||||
remote_error=remote_error)
|
remote_error=remote_error,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BadRequestException(HttpException):
|
class BadRequestException(HttpException):
|
||||||
"""HTTP 400 Bad Request."""
|
"""HTTP 400 Bad Request."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ForbiddenException(HttpException):
|
class ForbiddenException(HttpException):
|
||||||
"""HTTP 403 Forbidden Request."""
|
"""HTTP 403 Forbidden Request."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ConflictException(HttpException):
|
class ConflictException(HttpException):
|
||||||
"""HTTP 409 Conflict."""
|
"""HTTP 409 Conflict."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class PreconditionFailedException(HttpException):
|
class PreconditionFailedException(HttpException):
|
||||||
"""HTTP 412 Precondition Failed."""
|
"""HTTP 412 Precondition Failed."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MethodNotSupported(SDKException):
|
class MethodNotSupported(SDKException):
|
||||||
"""The resource does not support this operation type."""
|
"""The resource does not support this operation type."""
|
||||||
|
|
||||||
def __init__(self, resource, method):
|
def __init__(self, resource, method):
|
||||||
# This needs to work with both classes and instances.
|
# This needs to work with both classes and instances.
|
||||||
try:
|
try:
|
||||||
@ -136,18 +150,23 @@ class MethodNotSupported(SDKException):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
name = resource.__class__.__name__
|
name = resource.__class__.__name__
|
||||||
|
|
||||||
message = ('The %s method is not supported for %s.%s' %
|
message = 'The %s method is not supported for %s.%s' % (
|
||||||
(method, resource.__module__, name))
|
method,
|
||||||
|
resource.__module__,
|
||||||
|
name,
|
||||||
|
)
|
||||||
super(MethodNotSupported, self).__init__(message=message)
|
super(MethodNotSupported, self).__init__(message=message)
|
||||||
|
|
||||||
|
|
||||||
class DuplicateResource(SDKException):
|
class DuplicateResource(SDKException):
|
||||||
"""More than one resource exists with that name."""
|
"""More than one resource exists with that name."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ResourceNotFound(HttpException):
|
class ResourceNotFound(HttpException):
|
||||||
"""No resource exists with that name or id."""
|
"""No resource exists with that name or id."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -156,16 +175,19 @@ NotFoundException = ResourceNotFound
|
|||||||
|
|
||||||
class ResourceTimeout(SDKException):
|
class ResourceTimeout(SDKException):
|
||||||
"""Timeout waiting for resource."""
|
"""Timeout waiting for resource."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ResourceFailure(SDKException):
|
class ResourceFailure(SDKException):
|
||||||
"""General resource failure."""
|
"""General resource failure."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class InvalidResourceQuery(SDKException):
|
class InvalidResourceQuery(SDKException):
|
||||||
"""Invalid query params for resource."""
|
"""Invalid query params for resource."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -225,8 +247,9 @@ def raise_from_response(response, error_message=None):
|
|||||||
details = response.text
|
details = response.text
|
||||||
elif response.content and 'text/html' in content_type:
|
elif response.content and 'text/html' in content_type:
|
||||||
# Split the lines, strip whitespace and inline HTML from the response.
|
# Split the lines, strip whitespace and inline HTML from the response.
|
||||||
details = [re.sub(r'<.+?>', '', i.strip())
|
details = [
|
||||||
for i in response.text.splitlines()]
|
re.sub(r'<.+?>', '', i.strip()) for i in response.text.splitlines()
|
||||||
|
]
|
||||||
details = list(set([msg for msg in details if msg]))
|
details = list(set([msg for msg in details if msg]))
|
||||||
# Return joined string separated by colons.
|
# Return joined string separated by colons.
|
||||||
details = ': '.join(details)
|
details = ': '.join(details)
|
||||||
@ -238,8 +261,11 @@ def raise_from_response(response, error_message=None):
|
|||||||
request_id = response.headers.get('x-openstack-request-id')
|
request_id = response.headers.get('x-openstack-request-id')
|
||||||
|
|
||||||
raise cls(
|
raise cls(
|
||||||
message=error_message, response=response, details=details,
|
message=error_message,
|
||||||
http_status=http_status, request_id=request_id
|
response=response,
|
||||||
|
details=details,
|
||||||
|
http_status=http_status,
|
||||||
|
request_id=request_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -249,6 +275,7 @@ class UnsupportedServiceVersion(Warning):
|
|||||||
|
|
||||||
class ArgumentDeprecationWarning(Warning):
|
class ArgumentDeprecationWarning(Warning):
|
||||||
"""A deprecated argument has been provided."""
|
"""A deprecated argument has been provided."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,7 +61,8 @@ class ConnectionFixture(fixtures.Fixture):
|
|||||||
templates = {}
|
templates = {}
|
||||||
for k, v in self._endpoint_templates.items():
|
for k, v in self._endpoint_templates.items():
|
||||||
suffix = self._suffixes.get(
|
suffix = self._suffixes.get(
|
||||||
alias, self._suffixes.get(service_type, ''))
|
alias, self._suffixes.get(service_type, '')
|
||||||
|
)
|
||||||
# For a keystone v2 catalog, we want to list the
|
# For a keystone v2 catalog, we want to list the
|
||||||
# versioned endpoint in the catalog, because that's
|
# versioned endpoint in the catalog, because that's
|
||||||
# more likely how those were deployed.
|
# more likely how those were deployed.
|
||||||
@ -88,10 +89,8 @@ class ConnectionFixture(fixtures.Fixture):
|
|||||||
continue
|
continue
|
||||||
service_name = service['project']
|
service_name = service['project']
|
||||||
ets = self._get_endpoint_templates(service_type)
|
ets = self._get_endpoint_templates(service_type)
|
||||||
v3_svc = self.v3_token.add_service(
|
v3_svc = self.v3_token.add_service(service_type, name=service_name)
|
||||||
service_type, name=service_name)
|
v2_svc = self.v2_token.add_service(service_type, name=service_name)
|
||||||
v2_svc = self.v2_token.add_service(
|
|
||||||
service_type, name=service_name)
|
|
||||||
v3_svc.add_standard_endpoints(region='RegionOne', **ets)
|
v3_svc.add_standard_endpoints(region='RegionOne', **ets)
|
||||||
if service_type == 'identity':
|
if service_type == 'identity':
|
||||||
ets = self._get_endpoint_templates(service_type, v2=True)
|
ets = self._get_endpoint_templates(service_type, v2=True)
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
|
|
||||||
class Formatter:
|
class Formatter:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def serialize(cls, value):
|
def serialize(cls, value):
|
||||||
"""Return a string representing the formatted value"""
|
"""Return a string representing the formatted value"""
|
||||||
@ -25,7 +24,6 @@ class Formatter:
|
|||||||
|
|
||||||
|
|
||||||
class BoolStr(Formatter):
|
class BoolStr(Formatter):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def deserialize(cls, value):
|
def deserialize(cls, value):
|
||||||
"""Convert a boolean string to a boolean"""
|
"""Convert a boolean string to a boolean"""
|
||||||
@ -35,8 +33,9 @@ class BoolStr(Formatter):
|
|||||||
elif "false" == expr:
|
elif "false" == expr:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unable to deserialize boolean string: %s"
|
raise ValueError(
|
||||||
% value)
|
"Unable to deserialize boolean string: %s" % value
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def serialize(cls, value):
|
def serialize(cls, value):
|
||||||
@ -47,5 +46,4 @@ class BoolStr(Formatter):
|
|||||||
else:
|
else:
|
||||||
return "false"
|
return "false"
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unable to serialize boolean string: %s"
|
raise ValueError("Unable to serialize boolean string: %s" % value)
|
||||||
% value)
|
|
||||||
|
@ -437,8 +437,7 @@ class Proxy(adapter.Adapter, Generic[T]):
|
|||||||
self, '_connection', getattr(self.session, '_sdk_connection', None)
|
self, '_connection', getattr(self.session, '_sdk_connection', None)
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_resource(self, resource_type: Type[T], value,
|
def _get_resource(self, resource_type: Type[T], value, **attrs) -> T:
|
||||||
**attrs) -> T:
|
|
||||||
"""Get a resource object to work on
|
"""Get a resource object to work on
|
||||||
|
|
||||||
:param resource_type: The type of resource to operate on. This should
|
:param resource_type: The type of resource to operate on. This should
|
||||||
@ -484,8 +483,9 @@ class Proxy(adapter.Adapter, Generic[T]):
|
|||||||
value = resource.Resource._get_id(parent)
|
value = resource.Resource._get_id(parent)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def _find(self, resource_type: Type[T], name_or_id, ignore_missing=True,
|
def _find(
|
||||||
**attrs) -> Optional[T]:
|
self, resource_type: Type[T], name_or_id, ignore_missing=True, **attrs
|
||||||
|
) -> Optional[T]:
|
||||||
"""Find a resource
|
"""Find a resource
|
||||||
|
|
||||||
:param name_or_id: The name or ID of a resource to find.
|
:param name_or_id: The name or ID of a resource to find.
|
||||||
@ -505,8 +505,9 @@ class Proxy(adapter.Adapter, Generic[T]):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@_check_resource(strict=False)
|
@_check_resource(strict=False)
|
||||||
def _delete(self, resource_type: Type[T], value, ignore_missing=True,
|
def _delete(
|
||||||
**attrs):
|
self, resource_type: Type[T], value, ignore_missing=True, **attrs
|
||||||
|
):
|
||||||
"""Delete a resource
|
"""Delete a resource
|
||||||
|
|
||||||
:param resource_type: The type of resource to delete. This should
|
:param resource_type: The type of resource to delete. This should
|
||||||
@ -542,8 +543,9 @@ class Proxy(adapter.Adapter, Generic[T]):
|
|||||||
return rv
|
return rv
|
||||||
|
|
||||||
@_check_resource(strict=False)
|
@_check_resource(strict=False)
|
||||||
def _update(self, resource_type: Type[T], value, base_path=None,
|
def _update(
|
||||||
**attrs) -> T:
|
self, resource_type: Type[T], value, base_path=None, **attrs
|
||||||
|
) -> T:
|
||||||
"""Update a resource
|
"""Update a resource
|
||||||
|
|
||||||
:param resource_type: The type of resource to update.
|
:param resource_type: The type of resource to update.
|
||||||
@ -591,8 +593,9 @@ class Proxy(adapter.Adapter, Generic[T]):
|
|||||||
res = resource_type.new(connection=conn, **attrs)
|
res = resource_type.new(connection=conn, **attrs)
|
||||||
return res.create(self, base_path=base_path)
|
return res.create(self, base_path=base_path)
|
||||||
|
|
||||||
def _bulk_create(self, resource_type: Type[T], data, base_path=None
|
def _bulk_create(
|
||||||
) -> Generator[T, None, None]:
|
self, resource_type: Type[T], data, base_path=None
|
||||||
|
) -> Generator[T, None, None]:
|
||||||
"""Create a resource from attributes
|
"""Create a resource from attributes
|
||||||
|
|
||||||
:param resource_type: The type of resource to create.
|
:param resource_type: The type of resource to create.
|
||||||
@ -614,13 +617,13 @@ class Proxy(adapter.Adapter, Generic[T]):
|
|||||||
|
|
||||||
@_check_resource(strict=False)
|
@_check_resource(strict=False)
|
||||||
def _get(
|
def _get(
|
||||||
self,
|
self,
|
||||||
resource_type: Type[T],
|
resource_type: Type[T],
|
||||||
value=None,
|
value=None,
|
||||||
requires_id=True,
|
requires_id=True,
|
||||||
base_path=None,
|
base_path=None,
|
||||||
skip_cache=False,
|
skip_cache=False,
|
||||||
**attrs
|
**attrs
|
||||||
):
|
):
|
||||||
"""Fetch a resource
|
"""Fetch a resource
|
||||||
|
|
||||||
@ -657,12 +660,12 @@ class Proxy(adapter.Adapter, Generic[T]):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _list(
|
def _list(
|
||||||
self,
|
self,
|
||||||
resource_type: Type[T],
|
resource_type: Type[T],
|
||||||
paginated=True,
|
paginated=True,
|
||||||
base_path=None,
|
base_path=None,
|
||||||
jmespath_filters=None,
|
jmespath_filters=None,
|
||||||
**attrs
|
**attrs
|
||||||
) -> Generator[T, None, None]:
|
) -> Generator[T, None, None]:
|
||||||
"""List a resource
|
"""List a resource
|
||||||
|
|
||||||
@ -690,8 +693,7 @@ class Proxy(adapter.Adapter, Generic[T]):
|
|||||||
the ``resource_type``.
|
the ``resource_type``.
|
||||||
"""
|
"""
|
||||||
data = resource_type.list(
|
data = resource_type.list(
|
||||||
self, paginated=paginated, base_path=base_path,
|
self, paginated=paginated, base_path=base_path, **attrs
|
||||||
**attrs
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if jmespath_filters and isinstance(jmespath_filters, str):
|
if jmespath_filters and isinstance(jmespath_filters, str):
|
||||||
@ -699,8 +701,9 @@ class Proxy(adapter.Adapter, Generic[T]):
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def _head(self, resource_type: Type[T], value=None, base_path=None,
|
def _head(
|
||||||
**attrs):
|
self, resource_type: Type[T], value=None, base_path=None, **attrs
|
||||||
|
):
|
||||||
"""Retrieve a resource's header
|
"""Retrieve a resource's header
|
||||||
|
|
||||||
:param resource_type: The type of resource to retrieve.
|
:param resource_type: The type of resource to retrieve.
|
||||||
|
@ -207,15 +207,14 @@ class _BaseComponent:
|
|||||||
def warn_if_deprecated_property(self, value):
|
def warn_if_deprecated_property(self, value):
|
||||||
deprecated = object.__getattribute__(self, 'deprecated')
|
deprecated = object.__getattribute__(self, 'deprecated')
|
||||||
deprecation_reason = object.__getattribute__(
|
deprecation_reason = object.__getattribute__(
|
||||||
self, 'deprecation_reason',
|
self,
|
||||||
|
'deprecation_reason',
|
||||||
)
|
)
|
||||||
|
|
||||||
if value and deprecated:
|
if value and deprecated:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"The field %r has been deprecated. %s" % (
|
"The field %r has been deprecated. %s"
|
||||||
self.name,
|
% (self.name, deprecation_reason or "Avoid usage."),
|
||||||
deprecation_reason or "Avoid usage."
|
|
||||||
),
|
|
||||||
os_warnings.RemovedFieldWarning,
|
os_warnings.RemovedFieldWarning,
|
||||||
)
|
)
|
||||||
return value
|
return value
|
||||||
@ -1027,9 +1026,7 @@ class Resource(dict):
|
|||||||
converted = []
|
converted = []
|
||||||
for raw in value:
|
for raw in value:
|
||||||
if isinstance(raw, Resource):
|
if isinstance(raw, Resource):
|
||||||
converted.append(
|
converted.append(raw.to_dict(_to_munch=to_munch))
|
||||||
raw.to_dict(_to_munch=to_munch)
|
|
||||||
)
|
|
||||||
elif isinstance(raw, dict) and to_munch:
|
elif isinstance(raw, dict) and to_munch:
|
||||||
converted.append(utils.Munch(raw))
|
converted.append(utils.Munch(raw))
|
||||||
else:
|
else:
|
||||||
@ -1223,10 +1220,7 @@ class Resource(dict):
|
|||||||
requires_id = self.requires_id
|
requires_id = self.requires_id
|
||||||
|
|
||||||
# Conditionally construct arguments for _prepare_request_body
|
# Conditionally construct arguments for _prepare_request_body
|
||||||
request_kwargs = {
|
request_kwargs = {"patch": patch, "prepend_key": prepend_key}
|
||||||
"patch": patch,
|
|
||||||
"prepend_key": prepend_key
|
|
||||||
}
|
|
||||||
if resource_request_key is not None:
|
if resource_request_key is not None:
|
||||||
request_kwargs['resource_request_key'] = resource_request_key
|
request_kwargs['resource_request_key'] = resource_request_key
|
||||||
body = self._prepare_request_body(**request_kwargs)
|
body = self._prepare_request_body(**request_kwargs)
|
||||||
@ -1443,7 +1437,7 @@ class Resource(dict):
|
|||||||
resource_request_key=None,
|
resource_request_key=None,
|
||||||
resource_response_key=None,
|
resource_response_key=None,
|
||||||
microversion=None,
|
microversion=None,
|
||||||
**params
|
**params,
|
||||||
):
|
):
|
||||||
"""Create a remote resource based on this instance.
|
"""Create a remote resource based on this instance.
|
||||||
|
|
||||||
@ -1532,8 +1526,7 @@ class Resource(dict):
|
|||||||
# fetch the body if it's required but not returned by create
|
# fetch the body if it's required but not returned by create
|
||||||
fetch_kwargs = {}
|
fetch_kwargs = {}
|
||||||
if resource_response_key is not None:
|
if resource_response_key is not None:
|
||||||
fetch_kwargs = \
|
fetch_kwargs = {'resource_response_key': resource_response_key}
|
||||||
{'resource_response_key': resource_response_key}
|
|
||||||
return self.fetch(session, **fetch_kwargs)
|
return self.fetch(session, **fetch_kwargs)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -1681,7 +1674,8 @@ class Resource(dict):
|
|||||||
raise exceptions.MethodNotSupported(self, 'fetch')
|
raise exceptions.MethodNotSupported(self, 'fetch')
|
||||||
|
|
||||||
request = self._prepare_request(
|
request = self._prepare_request(
|
||||||
requires_id=requires_id, base_path=base_path,
|
requires_id=requires_id,
|
||||||
|
base_path=base_path,
|
||||||
)
|
)
|
||||||
session = self._get_session(session)
|
session = self._get_session(session)
|
||||||
if microversion is None:
|
if microversion is None:
|
||||||
@ -1931,8 +1925,9 @@ class Resource(dict):
|
|||||||
retry_on_conflict=retry_on_conflict,
|
retry_on_conflict=retry_on_conflict,
|
||||||
)
|
)
|
||||||
|
|
||||||
def delete(self, session, error_message=None, *, microversion=None,
|
def delete(
|
||||||
**kwargs):
|
self, session, error_message=None, *, microversion=None, **kwargs
|
||||||
|
):
|
||||||
"""Delete the remote resource based on this instance.
|
"""Delete the remote resource based on this instance.
|
||||||
|
|
||||||
:param session: The session to use for making this request.
|
:param session: The session to use for making this request.
|
||||||
@ -1948,8 +1943,9 @@ class Resource(dict):
|
|||||||
the resource was not found.
|
the resource was not found.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
response = self._raw_delete(session, microversion=microversion,
|
response = self._raw_delete(
|
||||||
**kwargs)
|
session, microversion=microversion, **kwargs
|
||||||
|
)
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if error_message:
|
if error_message:
|
||||||
kwargs['error_message'] = error_message
|
kwargs['error_message'] = error_message
|
||||||
@ -2116,7 +2112,8 @@ class Resource(dict):
|
|||||||
for key in client_filters.keys():
|
for key in client_filters.keys():
|
||||||
if isinstance(client_filters[key], dict):
|
if isinstance(client_filters[key], dict):
|
||||||
if not _dict_filter(
|
if not _dict_filter(
|
||||||
client_filters[key], value.get(key, None)):
|
client_filters[key], value.get(key, None)
|
||||||
|
):
|
||||||
filters_matched = False
|
filters_matched = False
|
||||||
break
|
break
|
||||||
elif value.get(key, None) != client_filters[key]:
|
elif value.get(key, None) != client_filters[key]:
|
||||||
@ -2176,7 +2173,7 @@ class Resource(dict):
|
|||||||
# Glance has a next field in the main body
|
# Glance has a next field in the main body
|
||||||
next_link = next_link or data.get('next')
|
next_link = next_link or data.get('next')
|
||||||
if next_link and next_link.startswith('/v'):
|
if next_link and next_link.startswith('/v'):
|
||||||
next_link = next_link[next_link.find('/', 1):]
|
next_link = next_link[next_link.find('/', 1) :]
|
||||||
|
|
||||||
if not next_link and 'next' in response.links:
|
if not next_link and 'next' in response.links:
|
||||||
# RFC5988 specifies Link headers and requests parses them if they
|
# RFC5988 specifies Link headers and requests parses them if they
|
||||||
@ -2281,8 +2278,11 @@ class Resource(dict):
|
|||||||
**params,
|
**params,
|
||||||
)
|
)
|
||||||
return match.fetch(session, microversion=microversion, **params)
|
return match.fetch(session, microversion=microversion, **params)
|
||||||
except (exceptions.NotFoundException, exceptions.BadRequestException,
|
except (
|
||||||
exceptions.ForbiddenException):
|
exceptions.NotFoundException,
|
||||||
|
exceptions.BadRequestException,
|
||||||
|
exceptions.ForbiddenException,
|
||||||
|
):
|
||||||
# NOTE(gtema): There are few places around openstack that return
|
# NOTE(gtema): There are few places around openstack that return
|
||||||
# 400 if we try to GET resource and it doesn't exist.
|
# 400 if we try to GET resource and it doesn't exist.
|
||||||
pass
|
pass
|
||||||
|
@ -36,7 +36,9 @@ class _ServiceDisabledProxyShim:
|
|||||||
raise exceptions.ServiceDisabledException(
|
raise exceptions.ServiceDisabledException(
|
||||||
"Service '{service_type}' is disabled because its configuration "
|
"Service '{service_type}' is disabled because its configuration "
|
||||||
"could not be loaded. {reason}".format(
|
"could not be loaded. {reason}".format(
|
||||||
service_type=self.service_type, reason=self.reason or ''))
|
service_type=self.service_type, reason=self.reason or ''
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ServiceDescription:
|
class ServiceDescription:
|
||||||
@ -73,9 +75,8 @@ class ServiceDescription:
|
|||||||
"""
|
"""
|
||||||
self.service_type = service_type or self.service_type
|
self.service_type = service_type or self.service_type
|
||||||
self.supported_versions = (
|
self.supported_versions = (
|
||||||
supported_versions
|
supported_versions or self.supported_versions or {}
|
||||||
or self.supported_versions
|
)
|
||||||
or {})
|
|
||||||
|
|
||||||
self.aliases = aliases or self.aliases
|
self.aliases = aliases or self.aliases
|
||||||
self.all_types = [service_type] + self.aliases
|
self.all_types = [service_type] + self.aliases
|
||||||
@ -135,7 +136,9 @@ class ServiceDescription:
|
|||||||
"Failed to create a working proxy for service {service_type}: "
|
"Failed to create a working proxy for service {service_type}: "
|
||||||
"{message}".format(
|
"{message}".format(
|
||||||
service_type=self.service_type,
|
service_type=self.service_type,
|
||||||
message=exc or "No valid endpoint was discoverable."))
|
message=exc or "No valid endpoint was discoverable.",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def _make_proxy(self, instance):
|
def _make_proxy(self, instance):
|
||||||
"""Create a Proxy for the service in question.
|
"""Create a Proxy for the service in question.
|
||||||
@ -148,7 +151,8 @@ class ServiceDescription:
|
|||||||
if not config.has_service(self.service_type):
|
if not config.has_service(self.service_type):
|
||||||
return _ServiceDisabledProxyShim(
|
return _ServiceDisabledProxyShim(
|
||||||
self.service_type,
|
self.service_type,
|
||||||
config.get_disabled_reason(self.service_type))
|
config.get_disabled_reason(self.service_type),
|
||||||
|
)
|
||||||
|
|
||||||
# We don't know anything about this service, so the user is
|
# We don't know anything about this service, so the user is
|
||||||
# explicitly just using us for a passthrough REST adapter.
|
# explicitly just using us for a passthrough REST adapter.
|
||||||
@ -186,13 +190,12 @@ class ServiceDescription:
|
|||||||
" {service_type} is not known or supported by"
|
" {service_type} is not known or supported by"
|
||||||
" openstacksdk. The resulting Proxy object will only"
|
" openstacksdk. The resulting Proxy object will only"
|
||||||
" have direct passthrough REST capabilities.".format(
|
" have direct passthrough REST capabilities.".format(
|
||||||
version=version_string,
|
version=version_string, service_type=self.service_type
|
||||||
service_type=self.service_type),
|
),
|
||||||
category=exceptions.UnsupportedServiceVersion)
|
category=exceptions.UnsupportedServiceVersion,
|
||||||
|
)
|
||||||
elif endpoint_override:
|
elif endpoint_override:
|
||||||
temp_adapter = config.get_session_client(
|
temp_adapter = config.get_session_client(self.service_type)
|
||||||
self.service_type
|
|
||||||
)
|
|
||||||
api_version = temp_adapter.get_endpoint_data().api_version
|
api_version = temp_adapter.get_endpoint_data().api_version
|
||||||
proxy_class = self.supported_versions.get(str(api_version[0]))
|
proxy_class = self.supported_versions.get(str(api_version[0]))
|
||||||
if proxy_class:
|
if proxy_class:
|
||||||
@ -207,9 +210,10 @@ class ServiceDescription:
|
|||||||
" is not supported by openstacksdk. The resulting Proxy"
|
" is not supported by openstacksdk. The resulting Proxy"
|
||||||
" object will only have direct passthrough REST"
|
" object will only have direct passthrough REST"
|
||||||
" capabilities.".format(
|
" capabilities.".format(
|
||||||
version=api_version,
|
version=api_version, service_type=self.service_type
|
||||||
service_type=self.service_type),
|
),
|
||||||
category=exceptions.UnsupportedServiceVersion)
|
category=exceptions.UnsupportedServiceVersion,
|
||||||
|
)
|
||||||
|
|
||||||
if proxy_obj:
|
if proxy_obj:
|
||||||
|
|
||||||
@ -225,7 +229,9 @@ class ServiceDescription:
|
|||||||
raise exceptions.ServiceDiscoveryException(
|
raise exceptions.ServiceDiscoveryException(
|
||||||
"Failed to create a working proxy for service "
|
"Failed to create a working proxy for service "
|
||||||
"{service_type}: No endpoint data found.".format(
|
"{service_type}: No endpoint data found.".format(
|
||||||
service_type=self.service_type))
|
service_type=self.service_type
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# If we've gotten here with a proxy object it means we have
|
# If we've gotten here with a proxy object it means we have
|
||||||
# an endpoint_override in place. If the catalog_url and
|
# an endpoint_override in place. If the catalog_url and
|
||||||
@ -235,7 +241,8 @@ class ServiceDescription:
|
|||||||
# so that subsequent discovery calls don't get made incorrectly.
|
# so that subsequent discovery calls don't get made incorrectly.
|
||||||
if data.catalog_url != data.service_url:
|
if data.catalog_url != data.service_url:
|
||||||
ep_key = '{service_type}_endpoint_override'.format(
|
ep_key = '{service_type}_endpoint_override'.format(
|
||||||
service_type=self.service_type.replace('-', '_'))
|
service_type=self.service_type.replace('-', '_')
|
||||||
|
)
|
||||||
config.config[ep_key] = data.service_url
|
config.config[ep_key] = data.service_url
|
||||||
proxy_obj = config.get_session_client(
|
proxy_obj = config.get_session_client(
|
||||||
self.service_type,
|
self.service_type,
|
||||||
@ -248,16 +255,16 @@ class ServiceDescription:
|
|||||||
if version_string:
|
if version_string:
|
||||||
version_kwargs['version'] = version_string
|
version_kwargs['version'] = version_string
|
||||||
else:
|
else:
|
||||||
supported_versions = sorted([
|
supported_versions = sorted(
|
||||||
int(f) for f in self.supported_versions])
|
[int(f) for f in self.supported_versions]
|
||||||
|
)
|
||||||
version_kwargs['min_version'] = str(supported_versions[0])
|
version_kwargs['min_version'] = str(supported_versions[0])
|
||||||
version_kwargs['max_version'] = '{version}.latest'.format(
|
version_kwargs['max_version'] = '{version}.latest'.format(
|
||||||
version=str(supported_versions[-1]))
|
version=str(supported_versions[-1])
|
||||||
|
)
|
||||||
|
|
||||||
temp_adapter = config.get_session_client(
|
temp_adapter = config.get_session_client(
|
||||||
self.service_type,
|
self.service_type, allow_version_hack=True, **version_kwargs
|
||||||
allow_version_hack=True,
|
|
||||||
**version_kwargs
|
|
||||||
)
|
)
|
||||||
found_version = temp_adapter.get_api_major_version()
|
found_version = temp_adapter.get_api_major_version()
|
||||||
if found_version is None:
|
if found_version is None:
|
||||||
@ -268,14 +275,18 @@ class ServiceDescription:
|
|||||||
" exists but does not have any supported versions.".format(
|
" exists but does not have any supported versions.".format(
|
||||||
service_type=self.service_type,
|
service_type=self.service_type,
|
||||||
cloud=instance.name,
|
cloud=instance.name,
|
||||||
region_name=region_name))
|
region_name=region_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise exceptions.NotSupported(
|
raise exceptions.NotSupported(
|
||||||
"The {service_type} service for {cloud}:{region_name}"
|
"The {service_type} service for {cloud}:{region_name}"
|
||||||
" exists but no version was discoverable.".format(
|
" exists but no version was discoverable.".format(
|
||||||
service_type=self.service_type,
|
service_type=self.service_type,
|
||||||
cloud=instance.name,
|
cloud=instance.name,
|
||||||
region_name=region_name))
|
region_name=region_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
proxy_class = self.supported_versions.get(str(found_version[0]))
|
proxy_class = self.supported_versions.get(str(found_version[0]))
|
||||||
if proxy_class:
|
if proxy_class:
|
||||||
return config.get_session_client(
|
return config.get_session_client(
|
||||||
@ -294,8 +305,10 @@ class ServiceDescription:
|
|||||||
"Service {service_type} has no discoverable version."
|
"Service {service_type} has no discoverable version."
|
||||||
" The resulting Proxy object will only have direct"
|
" The resulting Proxy object will only have direct"
|
||||||
" passthrough REST capabilities.".format(
|
" passthrough REST capabilities.".format(
|
||||||
service_type=self.service_type),
|
service_type=self.service_type
|
||||||
category=exceptions.UnsupportedServiceVersion)
|
),
|
||||||
|
category=exceptions.UnsupportedServiceVersion,
|
||||||
|
)
|
||||||
return temp_adapter
|
return temp_adapter
|
||||||
|
|
||||||
def __set__(self, instance, value):
|
def __set__(self, instance, value):
|
||||||
|
@ -47,7 +47,9 @@ class TestCase(base.BaseTestCase):
|
|||||||
test_timeout = int(test_timeout * self.TIMEOUT_SCALING_FACTOR)
|
test_timeout = int(test_timeout * self.TIMEOUT_SCALING_FACTOR)
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable(
|
fixtures.EnvironmentVariable(
|
||||||
'OS_TEST_TIMEOUT', str(test_timeout)))
|
'OS_TEST_TIMEOUT', str(test_timeout)
|
||||||
|
)
|
||||||
|
)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# Let oslotest do its thing
|
# Let oslotest do its thing
|
||||||
pass
|
pass
|
||||||
@ -90,7 +92,8 @@ class TestCase(base.BaseTestCase):
|
|||||||
if isinstance(second, utils.Munch):
|
if isinstance(second, utils.Munch):
|
||||||
second = second.toDict()
|
second = second.toDict()
|
||||||
return super(TestCase, self).assertEqual(
|
return super(TestCase, self).assertEqual(
|
||||||
first, second, *args, **kwargs)
|
first, second, *args, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
def printLogs(self, *args):
|
def printLogs(self, *args):
|
||||||
self._log_stream.seek(0)
|
self._log_stream.seek(0)
|
||||||
@ -104,16 +107,18 @@ class TestCase(base.BaseTestCase):
|
|||||||
if not x:
|
if not x:
|
||||||
break
|
break
|
||||||
yield x.encode('utf8')
|
yield x.encode('utf8')
|
||||||
|
|
||||||
content = testtools.content.content_from_reader(
|
content = testtools.content.content_from_reader(
|
||||||
reader,
|
reader, testtools.content_type.UTF8_TEXT, False
|
||||||
testtools.content_type.UTF8_TEXT,
|
)
|
||||||
False)
|
|
||||||
self.addDetail('logging', content)
|
self.addDetail('logging', content)
|
||||||
|
|
||||||
def add_info_on_exception(self, name, text):
|
def add_info_on_exception(self, name, text):
|
||||||
def add_content(unused):
|
def add_content(unused):
|
||||||
self.addDetail(name, testtools.content.text_content(
|
self.addDetail(
|
||||||
pprint.pformat(text)))
|
name, testtools.content.text_content(pprint.pformat(text))
|
||||||
|
)
|
||||||
|
|
||||||
self.addOnException(add_content)
|
self.addOnException(add_content)
|
||||||
|
|
||||||
def assertSubdict(self, part, whole):
|
def assertSubdict(self, part, whole):
|
||||||
@ -124,11 +129,18 @@ class TestCase(base.BaseTestCase):
|
|||||||
if not whole[key] and part[key]:
|
if not whole[key] and part[key]:
|
||||||
missing_keys.append(key)
|
missing_keys.append(key)
|
||||||
if missing_keys:
|
if missing_keys:
|
||||||
self.fail("Keys %s are in %s but not in %s" %
|
self.fail(
|
||||||
(missing_keys, part, whole))
|
"Keys %s are in %s but not in %s" % (missing_keys, part, whole)
|
||||||
wrong_values = [(key, part[key], whole[key])
|
)
|
||||||
for key in part if part[key] != whole[key]]
|
wrong_values = [
|
||||||
|
(key, part[key], whole[key])
|
||||||
|
for key in part
|
||||||
|
if part[key] != whole[key]
|
||||||
|
]
|
||||||
if wrong_values:
|
if wrong_values:
|
||||||
self.fail("Mismatched values: %s" %
|
self.fail(
|
||||||
", ".join("for %s got %s and %s" % tpl
|
"Mismatched values: %s"
|
||||||
for tpl in wrong_values))
|
% ", ".join(
|
||||||
|
"for %s got %s and %s" % tpl for tpl in wrong_values
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@ -32,7 +32,8 @@ CHOCOLATE_FLAVOR_ID = u'0c1d9008-f546-4608-9e8f-f8bdaec8ddde'
|
|||||||
STRAWBERRY_FLAVOR_ID = u'0c1d9008-f546-4608-9e8f-f8bdaec8dddf'
|
STRAWBERRY_FLAVOR_ID = u'0c1d9008-f546-4608-9e8f-f8bdaec8dddf'
|
||||||
COMPUTE_ENDPOINT = 'https://compute.example.com/v2.1'
|
COMPUTE_ENDPOINT = 'https://compute.example.com/v2.1'
|
||||||
ORCHESTRATION_ENDPOINT = 'https://orchestration.example.com/v1/{p}'.format(
|
ORCHESTRATION_ENDPOINT = 'https://orchestration.example.com/v1/{p}'.format(
|
||||||
p=PROJECT_ID)
|
p=PROJECT_ID
|
||||||
|
)
|
||||||
NO_MD5 = '93b885adfe0da089cdf634904fd59f71'
|
NO_MD5 = '93b885adfe0da089cdf634904fd59f71'
|
||||||
NO_SHA256 = '6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d'
|
NO_SHA256 = '6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d'
|
||||||
FAKE_PUBLIC_KEY = (
|
FAKE_PUBLIC_KEY = (
|
||||||
@ -41,7 +42,8 @@ FAKE_PUBLIC_KEY = (
|
|||||||
"sZacm0cZNuL69EObEGHdprfGJQajrpz22NQoCD8TFB8Wv+8om9NH9Le6s+WPe98WC77KLw8qg"
|
"sZacm0cZNuL69EObEGHdprfGJQajrpz22NQoCD8TFB8Wv+8om9NH9Le6s+WPe98WC77KLw8qg"
|
||||||
"fQsbIey+JawPWl4O67ZdL5xrypuRjfIPWjgy/VH85IXg/Z/GONZ2nxHgSShMkwqSFECAC5L3P"
|
"fQsbIey+JawPWl4O67ZdL5xrypuRjfIPWjgy/VH85IXg/Z/GONZ2nxHgSShMkwqSFECAC5L3P"
|
||||||
"HB+0+/12M/iikdatFSVGjpuHvkLOs3oe7m6HlOfluSJ85BzLWBbvva93qkGmLg4ZAc8rPh2O+"
|
"HB+0+/12M/iikdatFSVGjpuHvkLOs3oe7m6HlOfluSJ85BzLWBbvva93qkGmLg4ZAc8rPh2O+"
|
||||||
"YIsBUHNLLMM/oQp Generated-by-Nova\n")
|
"YIsBUHNLLMM/oQp Generated-by-Nova\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def make_fake_flavor(flavor_id, name, ram=100, disk=1600, vcpus=24):
|
def make_fake_flavor(flavor_id, name, ram=100, disk=1600, vcpus=24):
|
||||||
@ -50,29 +52,36 @@ def make_fake_flavor(flavor_id, name, ram=100, disk=1600, vcpus=24):
|
|||||||
u'OS-FLV-EXT-DATA:ephemeral': 0,
|
u'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||||
u'disk': disk,
|
u'disk': disk,
|
||||||
u'id': flavor_id,
|
u'id': flavor_id,
|
||||||
u'links': [{
|
u'links': [
|
||||||
u'href': u'{endpoint}/flavors/{id}'.format(
|
{
|
||||||
endpoint=COMPUTE_ENDPOINT, id=flavor_id),
|
u'href': u'{endpoint}/flavors/{id}'.format(
|
||||||
u'rel': u'self'
|
endpoint=COMPUTE_ENDPOINT, id=flavor_id
|
||||||
}, {
|
),
|
||||||
u'href': u'{endpoint}/flavors/{id}'.format(
|
u'rel': u'self',
|
||||||
endpoint=COMPUTE_ENDPOINT, id=flavor_id),
|
},
|
||||||
u'rel': u'bookmark'
|
{
|
||||||
}],
|
u'href': u'{endpoint}/flavors/{id}'.format(
|
||||||
|
endpoint=COMPUTE_ENDPOINT, id=flavor_id
|
||||||
|
),
|
||||||
|
u'rel': u'bookmark',
|
||||||
|
},
|
||||||
|
],
|
||||||
u'name': name,
|
u'name': name,
|
||||||
u'os-flavor-access:is_public': True,
|
u'os-flavor-access:is_public': True,
|
||||||
u'ram': ram,
|
u'ram': ram,
|
||||||
u'rxtx_factor': 1.0,
|
u'rxtx_factor': 1.0,
|
||||||
u'swap': u'',
|
u'swap': u'',
|
||||||
u'vcpus': vcpus
|
u'vcpus': vcpus,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FAKE_FLAVOR = make_fake_flavor(FLAVOR_ID, 'vanilla')
|
FAKE_FLAVOR = make_fake_flavor(FLAVOR_ID, 'vanilla')
|
||||||
FAKE_CHOCOLATE_FLAVOR = make_fake_flavor(
|
FAKE_CHOCOLATE_FLAVOR = make_fake_flavor(
|
||||||
CHOCOLATE_FLAVOR_ID, 'chocolate', ram=200)
|
CHOCOLATE_FLAVOR_ID, 'chocolate', ram=200
|
||||||
|
)
|
||||||
FAKE_STRAWBERRY_FLAVOR = make_fake_flavor(
|
FAKE_STRAWBERRY_FLAVOR = make_fake_flavor(
|
||||||
STRAWBERRY_FLAVOR_ID, 'strawberry', ram=300)
|
STRAWBERRY_FLAVOR_ID, 'strawberry', ram=300
|
||||||
|
)
|
||||||
FAKE_FLAVOR_LIST = [FAKE_FLAVOR, FAKE_CHOCOLATE_FLAVOR, FAKE_STRAWBERRY_FLAVOR]
|
FAKE_FLAVOR_LIST = [FAKE_FLAVOR, FAKE_CHOCOLATE_FLAVOR, FAKE_STRAWBERRY_FLAVOR]
|
||||||
FAKE_TEMPLATE = '''heat_template_version: 2014-10-16
|
FAKE_TEMPLATE = '''heat_template_version: 2014-10-16
|
||||||
|
|
||||||
@ -95,8 +104,14 @@ FAKE_TEMPLATE_CONTENT = template_format.parse(FAKE_TEMPLATE)
|
|||||||
|
|
||||||
|
|
||||||
def make_fake_server(
|
def make_fake_server(
|
||||||
server_id, name, status='ACTIVE', admin_pass=None,
|
server_id,
|
||||||
addresses=None, image=None, flavor=None):
|
name,
|
||||||
|
status='ACTIVE',
|
||||||
|
admin_pass=None,
|
||||||
|
addresses=None,
|
||||||
|
image=None,
|
||||||
|
flavor=None,
|
||||||
|
):
|
||||||
if addresses is None:
|
if addresses is None:
|
||||||
if status == 'ACTIVE':
|
if status == 'ACTIVE':
|
||||||
addresses = {
|
addresses = {
|
||||||
@ -105,25 +120,28 @@ def make_fake_server(
|
|||||||
"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:df:b0:8d",
|
"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:df:b0:8d",
|
||||||
"version": 6,
|
"version": 6,
|
||||||
"addr": "fddb:b018:307:0:f816:3eff:fedf:b08d",
|
"addr": "fddb:b018:307:0:f816:3eff:fedf:b08d",
|
||||||
"OS-EXT-IPS:type": "fixed"},
|
"OS-EXT-IPS:type": "fixed",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:df:b0:8d",
|
"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:df:b0:8d",
|
||||||
"version": 4,
|
"version": 4,
|
||||||
"addr": "10.1.0.9",
|
"addr": "10.1.0.9",
|
||||||
"OS-EXT-IPS:type": "fixed"},
|
"OS-EXT-IPS:type": "fixed",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:df:b0:8d",
|
"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:df:b0:8d",
|
||||||
"version": 4,
|
"version": 4,
|
||||||
"addr": "172.24.5.5",
|
"addr": "172.24.5.5",
|
||||||
"OS-EXT-IPS:type": "floating"}]}
|
"OS-EXT-IPS:type": "floating",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
addresses = {}
|
addresses = {}
|
||||||
if image is None:
|
if image is None:
|
||||||
image = {"id": "217f3ab1-03e0-4450-bf27-63d52b421e9e",
|
image = {"id": "217f3ab1-03e0-4450-bf27-63d52b421e9e", "links": []}
|
||||||
"links": []}
|
|
||||||
if flavor is None:
|
if flavor is None:
|
||||||
flavor = {"id": "64",
|
flavor = {"id": "64", "links": []}
|
||||||
"links": []}
|
|
||||||
|
|
||||||
server = {
|
server = {
|
||||||
"OS-EXT-STS:task_state": None,
|
"OS-EXT-STS:task_state": None,
|
||||||
@ -152,7 +170,8 @@ def make_fake_server(
|
|||||||
"created": "2017-03-23T23:57:12Z",
|
"created": "2017-03-23T23:57:12Z",
|
||||||
"tenant_id": PROJECT_ID,
|
"tenant_id": PROJECT_ID,
|
||||||
"os-extended-volumes:volumes_attached": [],
|
"os-extended-volumes:volumes_attached": [],
|
||||||
"config_drive": "True"}
|
"config_drive": "True",
|
||||||
|
}
|
||||||
if admin_pass:
|
if admin_pass:
|
||||||
server['adminPass'] = admin_pass
|
server['adminPass'] = admin_pass
|
||||||
return json.loads(json.dumps(server))
|
return json.loads(json.dumps(server))
|
||||||
@ -188,7 +207,8 @@ def make_fake_stack(id, name, description=None, status='CREATE_COMPLETE'):
|
|||||||
|
|
||||||
|
|
||||||
def make_fake_stack_event(
|
def make_fake_stack_event(
|
||||||
id, name, status='CREATE_COMPLETED', resource_name='id'):
|
id, name, status='CREATE_COMPLETED', resource_name='id'
|
||||||
|
):
|
||||||
event_id = uuid.uuid4().hex
|
event_id = uuid.uuid4().hex
|
||||||
self_url = "{endpoint}/stacks/{name}/{id}/resources/{name}/events/{event}"
|
self_url = "{endpoint}/stacks/{name}/{id}/resources/{name}/events/{event}"
|
||||||
resource_url = "{endpoint}/stacks/{name}/{id}/resources/{name}"
|
resource_url = "{endpoint}/stacks/{name}/{id}/resources/{name}"
|
||||||
@ -199,19 +219,25 @@ def make_fake_stack_event(
|
|||||||
{
|
{
|
||||||
"href": self_url.format(
|
"href": self_url.format(
|
||||||
endpoint=ORCHESTRATION_ENDPOINT,
|
endpoint=ORCHESTRATION_ENDPOINT,
|
||||||
name=name, id=id, event=event_id),
|
name=name,
|
||||||
"rel": "self"
|
id=id,
|
||||||
}, {
|
event=event_id,
|
||||||
|
),
|
||||||
|
"rel": "self",
|
||||||
|
},
|
||||||
|
{
|
||||||
"href": resource_url.format(
|
"href": resource_url.format(
|
||||||
endpoint=ORCHESTRATION_ENDPOINT,
|
endpoint=ORCHESTRATION_ENDPOINT, name=name, id=id
|
||||||
name=name, id=id),
|
),
|
||||||
"rel": "resource"
|
"rel": "resource",
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"href": "{endpoint}/stacks/{name}/{id}".format(
|
"href": "{endpoint}/stacks/{name}/{id}".format(
|
||||||
endpoint=ORCHESTRATION_ENDPOINT,
|
endpoint=ORCHESTRATION_ENDPOINT, name=name, id=id
|
||||||
name=name, id=id),
|
),
|
||||||
"rel": "stack"
|
"rel": "stack",
|
||||||
}],
|
},
|
||||||
|
],
|
||||||
"logical_resource_id": name,
|
"logical_resource_id": name,
|
||||||
"resource_status": status,
|
"resource_status": status,
|
||||||
"resource_status_reason": "",
|
"resource_status_reason": "",
|
||||||
@ -221,10 +247,14 @@ def make_fake_stack_event(
|
|||||||
|
|
||||||
|
|
||||||
def make_fake_image(
|
def make_fake_image(
|
||||||
image_id=None, md5=NO_MD5, sha256=NO_SHA256, status='active',
|
image_id=None,
|
||||||
image_name=u'fake_image',
|
md5=NO_MD5,
|
||||||
data=None,
|
sha256=NO_SHA256,
|
||||||
checksum=u'ee36e35a297980dee1b514de9803ec6d'):
|
status='active',
|
||||||
|
image_name=u'fake_image',
|
||||||
|
data=None,
|
||||||
|
checksum=u'ee36e35a297980dee1b514de9803ec6d',
|
||||||
|
):
|
||||||
if data:
|
if data:
|
||||||
md5 = utils.md5(usedforsecurity=False)
|
md5 = utils.md5(usedforsecurity=False)
|
||||||
sha256 = hashlib.sha256()
|
sha256 = hashlib.sha256()
|
||||||
@ -249,9 +279,9 @@ def make_fake_image(
|
|||||||
u'status': status,
|
u'status': status,
|
||||||
u'tags': [],
|
u'tags': [],
|
||||||
u'visibility': u'private',
|
u'visibility': u'private',
|
||||||
u'locations': [{
|
u'locations': [
|
||||||
u'url': u'http://127.0.0.1/images/' + image_id,
|
{u'url': u'http://127.0.0.1/images/' + image_id, u'metadata': {}}
|
||||||
u'metadata': {}}],
|
],
|
||||||
u'min_disk': 40,
|
u'min_disk': 40,
|
||||||
u'virtual_size': None,
|
u'virtual_size': None,
|
||||||
u'name': image_name,
|
u'name': image_name,
|
||||||
@ -260,16 +290,16 @@ def make_fake_image(
|
|||||||
u'owner_specified.openstack.md5': md5 or NO_MD5,
|
u'owner_specified.openstack.md5': md5 or NO_MD5,
|
||||||
u'owner_specified.openstack.sha256': sha256 or NO_SHA256,
|
u'owner_specified.openstack.sha256': sha256 or NO_SHA256,
|
||||||
u'owner_specified.openstack.object': 'images/{name}'.format(
|
u'owner_specified.openstack.object': 'images/{name}'.format(
|
||||||
name=image_name),
|
name=image_name
|
||||||
u'protected': False}
|
),
|
||||||
|
u'protected': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def make_fake_machine(machine_name, machine_id=None):
|
def make_fake_machine(machine_name, machine_id=None):
|
||||||
if not machine_id:
|
if not machine_id:
|
||||||
machine_id = uuid.uuid4().hex
|
machine_id = uuid.uuid4().hex
|
||||||
return meta.obj_to_munch(FakeMachine(
|
return meta.obj_to_munch(FakeMachine(id=machine_id, name=machine_name))
|
||||||
id=machine_id,
|
|
||||||
name=machine_name))
|
|
||||||
|
|
||||||
|
|
||||||
def make_fake_port(address, node_id=None, port_id=None):
|
def make_fake_port(address, node_id=None, port_id=None):
|
||||||
@ -277,10 +307,9 @@ def make_fake_port(address, node_id=None, port_id=None):
|
|||||||
node_id = uuid.uuid4().hex
|
node_id = uuid.uuid4().hex
|
||||||
if not port_id:
|
if not port_id:
|
||||||
port_id = uuid.uuid4().hex
|
port_id = uuid.uuid4().hex
|
||||||
return meta.obj_to_munch(FakeMachinePort(
|
return meta.obj_to_munch(
|
||||||
id=port_id,
|
FakeMachinePort(id=port_id, address=address, node_id=node_id)
|
||||||
address=address,
|
)
|
||||||
node_id=node_id))
|
|
||||||
|
|
||||||
|
|
||||||
class FakeFloatingIP:
|
class FakeFloatingIP:
|
||||||
@ -293,63 +322,58 @@ class FakeFloatingIP:
|
|||||||
|
|
||||||
|
|
||||||
def make_fake_server_group(id, name, policies):
|
def make_fake_server_group(id, name, policies):
|
||||||
return json.loads(json.dumps({
|
return json.loads(
|
||||||
'id': id,
|
json.dumps(
|
||||||
'name': name,
|
{
|
||||||
'policies': policies,
|
'id': id,
|
||||||
'members': [],
|
'name': name,
|
||||||
'metadata': {},
|
'policies': policies,
|
||||||
}))
|
'members': [],
|
||||||
|
'metadata': {},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def make_fake_hypervisor(id, name):
|
def make_fake_hypervisor(id, name):
|
||||||
return json.loads(json.dumps({
|
return json.loads(
|
||||||
'id': id,
|
json.dumps(
|
||||||
'hypervisor_hostname': name,
|
{
|
||||||
'state': 'up',
|
'id': id,
|
||||||
'status': 'enabled',
|
'hypervisor_hostname': name,
|
||||||
"cpu_info": {
|
'state': 'up',
|
||||||
"arch": "x86_64",
|
'status': 'enabled',
|
||||||
"model": "Nehalem",
|
"cpu_info": {
|
||||||
"vendor": "Intel",
|
"arch": "x86_64",
|
||||||
"features": [
|
"model": "Nehalem",
|
||||||
"pge",
|
"vendor": "Intel",
|
||||||
"clflush"
|
"features": ["pge", "clflush"],
|
||||||
],
|
"topology": {"cores": 1, "threads": 1, "sockets": 4},
|
||||||
"topology": {
|
},
|
||||||
"cores": 1,
|
"current_workload": 0,
|
||||||
"threads": 1,
|
"status": "enabled",
|
||||||
"sockets": 4
|
"state": "up",
|
||||||
|
"disk_available_least": 0,
|
||||||
|
"host_ip": "1.1.1.1",
|
||||||
|
"free_disk_gb": 1028,
|
||||||
|
"free_ram_mb": 7680,
|
||||||
|
"hypervisor_type": "fake",
|
||||||
|
"hypervisor_version": 1000,
|
||||||
|
"local_gb": 1028,
|
||||||
|
"local_gb_used": 0,
|
||||||
|
"memory_mb": 8192,
|
||||||
|
"memory_mb_used": 512,
|
||||||
|
"running_vms": 0,
|
||||||
|
"service": {"host": "host1", "id": 7, "disabled_reason": None},
|
||||||
|
"vcpus": 1,
|
||||||
|
"vcpus_used": 0,
|
||||||
}
|
}
|
||||||
},
|
)
|
||||||
"current_workload": 0,
|
)
|
||||||
"status": "enabled",
|
|
||||||
"state": "up",
|
|
||||||
"disk_available_least": 0,
|
|
||||||
"host_ip": "1.1.1.1",
|
|
||||||
"free_disk_gb": 1028,
|
|
||||||
"free_ram_mb": 7680,
|
|
||||||
"hypervisor_type": "fake",
|
|
||||||
"hypervisor_version": 1000,
|
|
||||||
"local_gb": 1028,
|
|
||||||
"local_gb_used": 0,
|
|
||||||
"memory_mb": 8192,
|
|
||||||
"memory_mb_used": 512,
|
|
||||||
"running_vms": 0,
|
|
||||||
"service": {
|
|
||||||
"host": "host1",
|
|
||||||
"id": 7,
|
|
||||||
"disabled_reason": None
|
|
||||||
},
|
|
||||||
"vcpus": 1,
|
|
||||||
"vcpus_used": 0
|
|
||||||
}))
|
|
||||||
|
|
||||||
|
|
||||||
class FakeVolume:
|
class FakeVolume:
|
||||||
def __init__(
|
def __init__(self, id, status, name, attachments=[], size=75):
|
||||||
self, id, status, name, attachments=[],
|
|
||||||
size=75):
|
|
||||||
self.id = id
|
self.id = id
|
||||||
self.status = status
|
self.status = status
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -366,8 +390,7 @@ class FakeVolume:
|
|||||||
|
|
||||||
|
|
||||||
class FakeVolumeSnapshot:
|
class FakeVolumeSnapshot:
|
||||||
def __init__(
|
def __init__(self, id, status, name, description, size=75):
|
||||||
self, id, status, name, description, size=75):
|
|
||||||
self.id = id
|
self.id = id
|
||||||
self.status = status
|
self.status = status
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -380,10 +403,20 @@ class FakeVolumeSnapshot:
|
|||||||
|
|
||||||
|
|
||||||
class FakeMachine:
|
class FakeMachine:
|
||||||
def __init__(self, id, name=None, driver=None, driver_info=None,
|
def __init__(
|
||||||
chassis_uuid=None, instance_info=None, instance_uuid=None,
|
self,
|
||||||
properties=None, reservation=None, last_error=None,
|
id,
|
||||||
provision_state='available'):
|
name=None,
|
||||||
|
driver=None,
|
||||||
|
driver_info=None,
|
||||||
|
chassis_uuid=None,
|
||||||
|
instance_info=None,
|
||||||
|
instance_uuid=None,
|
||||||
|
properties=None,
|
||||||
|
reservation=None,
|
||||||
|
last_error=None,
|
||||||
|
provision_state='available',
|
||||||
|
):
|
||||||
self.uuid = id
|
self.uuid = id
|
||||||
self.name = name
|
self.name = name
|
||||||
self.driver = driver
|
self.driver = driver
|
||||||
@ -405,50 +438,69 @@ class FakeMachinePort:
|
|||||||
|
|
||||||
|
|
||||||
def make_fake_neutron_security_group(
|
def make_fake_neutron_security_group(
|
||||||
id, name, description, rules, stateful=True, project_id=None):
|
id, name, description, rules, stateful=True, project_id=None
|
||||||
|
):
|
||||||
if not rules:
|
if not rules:
|
||||||
rules = []
|
rules = []
|
||||||
if not project_id:
|
if not project_id:
|
||||||
project_id = PROJECT_ID
|
project_id = PROJECT_ID
|
||||||
return json.loads(json.dumps({
|
return json.loads(
|
||||||
'id': id,
|
json.dumps(
|
||||||
'name': name,
|
{
|
||||||
'description': description,
|
'id': id,
|
||||||
'stateful': stateful,
|
'name': name,
|
||||||
'project_id': project_id,
|
'description': description,
|
||||||
'tenant_id': project_id,
|
'stateful': stateful,
|
||||||
'security_group_rules': rules,
|
'project_id': project_id,
|
||||||
}))
|
'tenant_id': project_id,
|
||||||
|
'security_group_rules': rules,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def make_fake_nova_security_group_rule(
|
def make_fake_nova_security_group_rule(
|
||||||
id, from_port, to_port, ip_protocol, cidr):
|
id, from_port, to_port, ip_protocol, cidr
|
||||||
return json.loads(json.dumps({
|
):
|
||||||
'id': id,
|
return json.loads(
|
||||||
'from_port': int(from_port),
|
json.dumps(
|
||||||
'to_port': int(to_port),
|
{
|
||||||
'ip_protcol': 'tcp',
|
'id': id,
|
||||||
'ip_range': {
|
'from_port': int(from_port),
|
||||||
'cidr': cidr
|
'to_port': int(to_port),
|
||||||
}
|
'ip_protcol': 'tcp',
|
||||||
}))
|
'ip_range': {'cidr': cidr},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def make_fake_nova_security_group(id, name, description, rules):
|
def make_fake_nova_security_group(id, name, description, rules):
|
||||||
if not rules:
|
if not rules:
|
||||||
rules = []
|
rules = []
|
||||||
return json.loads(json.dumps({
|
return json.loads(
|
||||||
'id': id,
|
json.dumps(
|
||||||
'name': name,
|
{
|
||||||
'description': description,
|
'id': id,
|
||||||
'tenant_id': PROJECT_ID,
|
'name': name,
|
||||||
'rules': rules,
|
'description': description,
|
||||||
}))
|
'tenant_id': PROJECT_ID,
|
||||||
|
'rules': rules,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class FakeNovaSecgroupRule:
|
class FakeNovaSecgroupRule:
|
||||||
def __init__(self, id, from_port=None, to_port=None, ip_protocol=None,
|
def __init__(
|
||||||
cidr=None, parent_group_id=None):
|
self,
|
||||||
|
id,
|
||||||
|
from_port=None,
|
||||||
|
to_port=None,
|
||||||
|
ip_protocol=None,
|
||||||
|
cidr=None,
|
||||||
|
parent_group_id=None,
|
||||||
|
):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.from_port = from_port
|
self.from_port = from_port
|
||||||
self.to_port = to_port
|
self.to_port = to_port
|
||||||
@ -465,8 +517,7 @@ class FakeHypervisor:
|
|||||||
|
|
||||||
|
|
||||||
class FakeZone:
|
class FakeZone:
|
||||||
def __init__(self, id, name, type_, email, description,
|
def __init__(self, id, name, type_, email, description, ttl, masters):
|
||||||
ttl, masters):
|
|
||||||
self.id = id
|
self.id = id
|
||||||
self.name = name
|
self.name = name
|
||||||
self.type_ = type_
|
self.type_ = type_
|
||||||
@ -477,8 +528,7 @@ class FakeZone:
|
|||||||
|
|
||||||
|
|
||||||
class FakeRecordset:
|
class FakeRecordset:
|
||||||
def __init__(self, zone, id, name, type_, description,
|
def __init__(self, zone, id, name, type_, description, ttl, records):
|
||||||
ttl, records):
|
|
||||||
self.zone = zone
|
self.zone = zone
|
||||||
self.id = id
|
self.id = id
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -488,22 +538,27 @@ class FakeRecordset:
|
|||||||
self.records = records
|
self.records = records
|
||||||
|
|
||||||
|
|
||||||
def make_fake_aggregate(id, name, availability_zone='nova',
|
def make_fake_aggregate(
|
||||||
metadata=None, hosts=None):
|
id, name, availability_zone='nova', metadata=None, hosts=None
|
||||||
|
):
|
||||||
if not metadata:
|
if not metadata:
|
||||||
metadata = {}
|
metadata = {}
|
||||||
if not hosts:
|
if not hosts:
|
||||||
hosts = []
|
hosts = []
|
||||||
return json.loads(json.dumps({
|
return json.loads(
|
||||||
"availability_zone": availability_zone,
|
json.dumps(
|
||||||
"created_at": datetime.datetime.now().isoformat(),
|
{
|
||||||
"deleted": False,
|
"availability_zone": availability_zone,
|
||||||
"deleted_at": None,
|
"created_at": datetime.datetime.now().isoformat(),
|
||||||
"hosts": hosts,
|
"deleted": False,
|
||||||
"id": int(id),
|
"deleted_at": None,
|
||||||
"metadata": {
|
"hosts": hosts,
|
||||||
"availability_zone": availability_zone,
|
"id": int(id),
|
||||||
},
|
"metadata": {
|
||||||
"name": name,
|
"availability_zone": availability_zone,
|
||||||
"updated_at": None,
|
},
|
||||||
}))
|
"name": name,
|
||||||
|
"updated_at": None,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@ -51,10 +51,12 @@ class BaseFunctionalTest(base.TestCase):
|
|||||||
|
|
||||||
self._demo_name = os.environ.get('OPENSTACKSDK_DEMO_CLOUD', 'devstack')
|
self._demo_name = os.environ.get('OPENSTACKSDK_DEMO_CLOUD', 'devstack')
|
||||||
self._demo_name_alt = os.environ.get(
|
self._demo_name_alt = os.environ.get(
|
||||||
'OPENSTACKSDK_DEMO_CLOUD_ALT', 'devstack-alt',
|
'OPENSTACKSDK_DEMO_CLOUD_ALT',
|
||||||
|
'devstack-alt',
|
||||||
)
|
)
|
||||||
self._op_name = os.environ.get(
|
self._op_name = os.environ.get(
|
||||||
'OPENSTACKSDK_OPERATOR_CLOUD', 'devstack-admin',
|
'OPENSTACKSDK_OPERATOR_CLOUD',
|
||||||
|
'devstack-admin',
|
||||||
)
|
)
|
||||||
|
|
||||||
self.config = openstack.config.OpenStackConfig()
|
self.config = openstack.config.OpenStackConfig()
|
||||||
@ -64,8 +66,9 @@ class BaseFunctionalTest(base.TestCase):
|
|||||||
else:
|
else:
|
||||||
self.operator_cloud = None
|
self.operator_cloud = None
|
||||||
|
|
||||||
self.identity_version = \
|
self.identity_version = self.user_cloud.config.get_api_version(
|
||||||
self.user_cloud.config.get_api_version('identity')
|
'identity'
|
||||||
|
)
|
||||||
|
|
||||||
self.flavor = self._pick_flavor()
|
self.flavor = self._pick_flavor()
|
||||||
self.image = self._pick_image()
|
self.image = self._pick_image()
|
||||||
@ -73,8 +76,11 @@ class BaseFunctionalTest(base.TestCase):
|
|||||||
# Defines default timeout for wait_for methods used
|
# Defines default timeout for wait_for methods used
|
||||||
# in the functional tests
|
# in the functional tests
|
||||||
self._wait_for_timeout = int(
|
self._wait_for_timeout = int(
|
||||||
os.getenv(self._wait_for_timeout_key, os.getenv(
|
os.getenv(
|
||||||
'OPENSTACKSDK_FUNC_TEST_TIMEOUT', 300)))
|
self._wait_for_timeout_key,
|
||||||
|
os.getenv('OPENSTACKSDK_FUNC_TEST_TIMEOUT', 300),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def _set_user_cloud(self, **kwargs):
|
def _set_user_cloud(self, **kwargs):
|
||||||
user_config = self.config.get_one(cloud=self._demo_name, **kwargs)
|
user_config = self.config.get_one(cloud=self._demo_name, **kwargs)
|
||||||
@ -85,7 +91,8 @@ class BaseFunctionalTest(base.TestCase):
|
|||||||
# it
|
# it
|
||||||
if self._demo_name_alt:
|
if self._demo_name_alt:
|
||||||
user_config_alt = self.config.get_one(
|
user_config_alt = self.config.get_one(
|
||||||
cloud=self._demo_name_alt, **kwargs)
|
cloud=self._demo_name_alt, **kwargs
|
||||||
|
)
|
||||||
self.user_cloud_alt = connection.Connection(config=user_config_alt)
|
self.user_cloud_alt = connection.Connection(config=user_config_alt)
|
||||||
_disable_keep_alive(self.user_cloud_alt)
|
_disable_keep_alive(self.user_cloud_alt)
|
||||||
else:
|
else:
|
||||||
@ -119,7 +126,8 @@ class BaseFunctionalTest(base.TestCase):
|
|||||||
return flavor
|
return flavor
|
||||||
|
|
||||||
raise self.failureException(
|
raise self.failureException(
|
||||||
"Cloud does not have flavor '%s'", flavor_name,
|
"Cloud does not have flavor '%s'",
|
||||||
|
flavor_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Enable running functional tests against RAX, which requires
|
# Enable running functional tests against RAX, which requires
|
||||||
@ -159,7 +167,8 @@ class BaseFunctionalTest(base.TestCase):
|
|||||||
return image
|
return image
|
||||||
|
|
||||||
raise self.failureException(
|
raise self.failureException(
|
||||||
"Cloud does not have image '%s'", image_name,
|
"Cloud does not have image '%s'",
|
||||||
|
image_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
for image in images:
|
for image in images:
|
||||||
@ -186,6 +195,7 @@ class BaseFunctionalTest(base.TestCase):
|
|||||||
def cleanup():
|
def cleanup():
|
||||||
result = func(*args, **kwargs)
|
result = func(*args, **kwargs)
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
self.addCleanup(cleanup)
|
self.addCleanup(cleanup)
|
||||||
|
|
||||||
def require_service(self, service_type, min_microversion=None, **kwargs):
|
def require_service(self, service_type, min_microversion=None, **kwargs):
|
||||||
@ -201,14 +211,18 @@ class BaseFunctionalTest(base.TestCase):
|
|||||||
:returns: True if the service exists, otherwise False.
|
:returns: True if the service exists, otherwise False.
|
||||||
"""
|
"""
|
||||||
if not self.conn.has_service(service_type):
|
if not self.conn.has_service(service_type):
|
||||||
self.skipTest('Service {service_type} not found in cloud'.format(
|
self.skipTest(
|
||||||
service_type=service_type))
|
'Service {service_type} not found in cloud'.format(
|
||||||
|
service_type=service_type
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if not min_microversion:
|
if not min_microversion:
|
||||||
return
|
return
|
||||||
|
|
||||||
data = self.conn.session.get_endpoint_data(
|
data = self.conn.session.get_endpoint_data(
|
||||||
service_type=service_type, **kwargs)
|
service_type=service_type, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
if not (
|
if not (
|
||||||
data.min_microversion
|
data.min_microversion
|
||||||
@ -230,12 +244,11 @@ class BaseFunctionalTest(base.TestCase):
|
|||||||
# unix_t is also used to easier determine orphans when running real
|
# unix_t is also used to easier determine orphans when running real
|
||||||
# functional tests on a real cloud
|
# functional tests on a real cloud
|
||||||
return (prefix if prefix else '') + "{time}-{uuid}".format(
|
return (prefix if prefix else '') + "{time}-{uuid}".format(
|
||||||
time=int(time.time()),
|
time=int(time.time()), uuid=uuid.uuid4().hex
|
||||||
uuid=uuid.uuid4().hex)
|
)
|
||||||
|
|
||||||
|
|
||||||
class KeystoneBaseFunctionalTest(BaseFunctionalTest):
|
class KeystoneBaseFunctionalTest(BaseFunctionalTest):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(KeystoneBaseFunctionalTest, self).setUp()
|
super(KeystoneBaseFunctionalTest, self).setUp()
|
||||||
|
|
||||||
|
@ -37,44 +37,49 @@ from openstack.tests import fakes
|
|||||||
_ProjectData = collections.namedtuple(
|
_ProjectData = collections.namedtuple(
|
||||||
'ProjectData',
|
'ProjectData',
|
||||||
'project_id, project_name, enabled, domain_id, description, '
|
'project_id, project_name, enabled, domain_id, description, '
|
||||||
'parent_id, json_response, json_request')
|
'parent_id, json_response, json_request',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
_UserData = collections.namedtuple(
|
_UserData = collections.namedtuple(
|
||||||
'UserData',
|
'UserData',
|
||||||
'user_id, password, name, email, description, domain_id, enabled, '
|
'user_id, password, name, email, description, domain_id, enabled, '
|
||||||
'json_response, json_request')
|
'json_response, json_request',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
_GroupData = collections.namedtuple(
|
_GroupData = collections.namedtuple(
|
||||||
'GroupData',
|
'GroupData',
|
||||||
'group_id, group_name, domain_id, description, json_response, '
|
'group_id, group_name, domain_id, description, json_response, '
|
||||||
'json_request')
|
'json_request',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
_DomainData = collections.namedtuple(
|
_DomainData = collections.namedtuple(
|
||||||
'DomainData',
|
'DomainData',
|
||||||
'domain_id, domain_name, description, json_response, '
|
'domain_id, domain_name, description, json_response, ' 'json_request',
|
||||||
'json_request')
|
)
|
||||||
|
|
||||||
|
|
||||||
_ServiceData = collections.namedtuple(
|
_ServiceData = collections.namedtuple(
|
||||||
'Servicedata',
|
'Servicedata',
|
||||||
'service_id, service_name, service_type, description, enabled, '
|
'service_id, service_name, service_type, description, enabled, '
|
||||||
'json_response_v3, json_response_v2, json_request')
|
'json_response_v3, json_response_v2, json_request',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
_EndpointDataV3 = collections.namedtuple(
|
_EndpointDataV3 = collections.namedtuple(
|
||||||
'EndpointData',
|
'EndpointData',
|
||||||
'endpoint_id, service_id, interface, region_id, url, enabled, '
|
'endpoint_id, service_id, interface, region_id, url, enabled, '
|
||||||
'json_response, json_request')
|
'json_response, json_request',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# NOTE(notmorgan): Shade does not support domain-specific roles
|
# NOTE(notmorgan): Shade does not support domain-specific roles
|
||||||
# This should eventually be fixed if it becomes a main-stream feature.
|
# This should eventually be fixed if it becomes a main-stream feature.
|
||||||
_RoleData = collections.namedtuple(
|
_RoleData = collections.namedtuple(
|
||||||
'RoleData',
|
'RoleData', 'role_id, role_name, json_response, json_request'
|
||||||
'role_id, role_name, json_response, json_request')
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestCase(base.TestCase):
|
class TestCase(base.TestCase):
|
||||||
@ -92,17 +97,20 @@ class TestCase(base.TestCase):
|
|||||||
def _nosleep(seconds):
|
def _nosleep(seconds):
|
||||||
return realsleep(seconds * 0.0001)
|
return realsleep(seconds * 0.0001)
|
||||||
|
|
||||||
self.sleep_fixture = self.useFixture(fixtures.MonkeyPatch(
|
self.sleep_fixture = self.useFixture(
|
||||||
'time.sleep',
|
fixtures.MonkeyPatch('time.sleep', _nosleep)
|
||||||
_nosleep))
|
)
|
||||||
self.fixtures_directory = 'openstack/tests/unit/fixtures'
|
self.fixtures_directory = 'openstack/tests/unit/fixtures'
|
||||||
self.os_fixture = self.useFixture(
|
self.os_fixture = self.useFixture(
|
||||||
os_fixture.ConnectionFixture(project_id=fakes.PROJECT_ID))
|
os_fixture.ConnectionFixture(project_id=fakes.PROJECT_ID)
|
||||||
|
)
|
||||||
|
|
||||||
# Isolate openstack.config from test environment
|
# Isolate openstack.config from test environment
|
||||||
config = tempfile.NamedTemporaryFile(delete=False)
|
config = tempfile.NamedTemporaryFile(delete=False)
|
||||||
cloud_path = '%s/clouds/%s' % (self.fixtures_directory,
|
cloud_path = '%s/clouds/%s' % (
|
||||||
cloud_config_fixture)
|
self.fixtures_directory,
|
||||||
|
cloud_config_fixture,
|
||||||
|
)
|
||||||
with open(cloud_path, 'rb') as f:
|
with open(cloud_path, 'rb') as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
config.write(content)
|
config.write(content)
|
||||||
@ -115,7 +123,8 @@ class TestCase(base.TestCase):
|
|||||||
self.config = occ.OpenStackConfig(
|
self.config = occ.OpenStackConfig(
|
||||||
config_files=[config.name],
|
config_files=[config.name],
|
||||||
vendor_files=[vendor.name],
|
vendor_files=[vendor.name],
|
||||||
secure_files=['non-existant'])
|
secure_files=['non-existant'],
|
||||||
|
)
|
||||||
|
|
||||||
self.oslo_config_dict = {
|
self.oslo_config_dict = {
|
||||||
# All defaults for nova
|
# All defaults for nova
|
||||||
@ -126,7 +135,7 @@ class TestCase(base.TestCase):
|
|||||||
'heat': {
|
'heat': {
|
||||||
'region_name': 'SpecialRegion',
|
'region_name': 'SpecialRegion',
|
||||||
'interface': 'internal',
|
'interface': 'internal',
|
||||||
'endpoint_override': 'https://example.org:8888/heat/v2'
|
'endpoint_override': 'https://example.org:8888/heat/v2',
|
||||||
},
|
},
|
||||||
# test a service with dashes
|
# test a service with dashes
|
||||||
'ironic_inspector': {
|
'ironic_inspector': {
|
||||||
@ -151,7 +160,8 @@ class TestCase(base.TestCase):
|
|||||||
# request in the correct orders.
|
# request in the correct orders.
|
||||||
self._uri_registry = collections.OrderedDict()
|
self._uri_registry = collections.OrderedDict()
|
||||||
self.discovery_json = os.path.join(
|
self.discovery_json = os.path.join(
|
||||||
self.fixtures_directory, 'discovery.json')
|
self.fixtures_directory, 'discovery.json'
|
||||||
|
)
|
||||||
self.use_keystone_v3()
|
self.use_keystone_v3()
|
||||||
self.__register_uris_called = False
|
self.__register_uris_called = False
|
||||||
|
|
||||||
@ -166,11 +176,18 @@ class TestCase(base.TestCase):
|
|||||||
return conf
|
return conf
|
||||||
|
|
||||||
# TODO(shade) Update this to handle service type aliases
|
# TODO(shade) Update this to handle service type aliases
|
||||||
def get_mock_url(self, service_type, interface='public', resource=None,
|
def get_mock_url(
|
||||||
append=None, base_url_append=None,
|
self,
|
||||||
qs_elements=None):
|
service_type,
|
||||||
|
interface='public',
|
||||||
|
resource=None,
|
||||||
|
append=None,
|
||||||
|
base_url_append=None,
|
||||||
|
qs_elements=None,
|
||||||
|
):
|
||||||
endpoint_url = self.cloud.endpoint_for(
|
endpoint_url = self.cloud.endpoint_for(
|
||||||
service_type=service_type, interface=interface)
|
service_type=service_type, interface=interface
|
||||||
|
)
|
||||||
# Strip trailing slashes, so as not to produce double-slashes below
|
# Strip trailing slashes, so as not to produce double-slashes below
|
||||||
if endpoint_url.endswith('/'):
|
if endpoint_url.endswith('/'):
|
||||||
endpoint_url = endpoint_url[:-1]
|
endpoint_url = endpoint_url[:-1]
|
||||||
@ -184,13 +201,17 @@ class TestCase(base.TestCase):
|
|||||||
to_join.extend([urllib.parse.quote(i) for i in append])
|
to_join.extend([urllib.parse.quote(i) for i in append])
|
||||||
if qs_elements is not None:
|
if qs_elements is not None:
|
||||||
qs = '?%s' % '&'.join(qs_elements)
|
qs = '?%s' % '&'.join(qs_elements)
|
||||||
return '%(uri)s%(qs)s' % {
|
return '%(uri)s%(qs)s' % {'uri': '/'.join(to_join), 'qs': qs}
|
||||||
'uri': '/'.join(to_join),
|
|
||||||
'qs': qs}
|
|
||||||
|
|
||||||
def mock_for_keystone_projects(self, project=None, v3=True,
|
def mock_for_keystone_projects(
|
||||||
list_get=False, id_get=False,
|
self,
|
||||||
project_list=None, project_count=None):
|
project=None,
|
||||||
|
v3=True,
|
||||||
|
list_get=False,
|
||||||
|
id_get=False,
|
||||||
|
project_list=None,
|
||||||
|
project_count=None,
|
||||||
|
):
|
||||||
if project:
|
if project:
|
||||||
assert not (project_list or project_count)
|
assert not (project_list or project_count)
|
||||||
elif project_list:
|
elif project_list:
|
||||||
@ -198,8 +219,9 @@ class TestCase(base.TestCase):
|
|||||||
elif project_count:
|
elif project_count:
|
||||||
assert not (project or project_list)
|
assert not (project or project_list)
|
||||||
else:
|
else:
|
||||||
raise Exception('Must specify a project, project_list, '
|
raise Exception(
|
||||||
'or project_count')
|
'Must specify a project, project_list, ' 'or project_count'
|
||||||
|
)
|
||||||
assert list_get or id_get
|
assert list_get or id_get
|
||||||
|
|
||||||
base_url_append = 'v3' if v3 else None
|
base_url_append = 'v3' if v3 else None
|
||||||
@ -207,40 +229,57 @@ class TestCase(base.TestCase):
|
|||||||
project_list = [project]
|
project_list = [project]
|
||||||
elif project_count:
|
elif project_count:
|
||||||
# Generate multiple projects
|
# Generate multiple projects
|
||||||
project_list = [self._get_project_data(v3=v3)
|
project_list = [
|
||||||
for c in range(0, project_count)]
|
self._get_project_data(v3=v3) for c in range(0, project_count)
|
||||||
|
]
|
||||||
uri_mock_list = []
|
uri_mock_list = []
|
||||||
if list_get:
|
if list_get:
|
||||||
uri_mock_list.append(
|
uri_mock_list.append(
|
||||||
dict(method='GET',
|
dict(
|
||||||
uri=self.get_mock_url(
|
method='GET',
|
||||||
service_type='identity',
|
uri=self.get_mock_url(
|
||||||
interface='admin',
|
service_type='identity',
|
||||||
resource='projects',
|
interface='admin',
|
||||||
base_url_append=base_url_append),
|
resource='projects',
|
||||||
status_code=200,
|
base_url_append=base_url_append,
|
||||||
json={'projects': [p.json_response['project']
|
),
|
||||||
for p in project_list]})
|
status_code=200,
|
||||||
|
json={
|
||||||
|
'projects': [
|
||||||
|
p.json_response['project'] for p in project_list
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
)
|
)
|
||||||
if id_get:
|
if id_get:
|
||||||
for p in project_list:
|
for p in project_list:
|
||||||
uri_mock_list.append(
|
uri_mock_list.append(
|
||||||
dict(method='GET',
|
dict(
|
||||||
uri=self.get_mock_url(
|
method='GET',
|
||||||
service_type='identity',
|
uri=self.get_mock_url(
|
||||||
interface='admin',
|
service_type='identity',
|
||||||
resource='projects',
|
interface='admin',
|
||||||
append=[p.project_id],
|
resource='projects',
|
||||||
base_url_append=base_url_append),
|
append=[p.project_id],
|
||||||
status_code=200,
|
base_url_append=base_url_append,
|
||||||
json=p.json_response)
|
),
|
||||||
|
status_code=200,
|
||||||
|
json=p.json_response,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
self.__do_register_uris(uri_mock_list)
|
self.__do_register_uris(uri_mock_list)
|
||||||
return project_list
|
return project_list
|
||||||
|
|
||||||
def _get_project_data(self, project_name=None, enabled=None,
|
def _get_project_data(
|
||||||
domain_id=None, description=None, v3=True,
|
self,
|
||||||
project_id=None, parent_id=None):
|
project_name=None,
|
||||||
|
enabled=None,
|
||||||
|
domain_id=None,
|
||||||
|
description=None,
|
||||||
|
v3=True,
|
||||||
|
project_id=None,
|
||||||
|
parent_id=None,
|
||||||
|
):
|
||||||
project_name = project_name or self.getUniqueString('projectName')
|
project_name = project_name or self.getUniqueString('projectName')
|
||||||
project_id = uuid.UUID(project_id or uuid.uuid4().hex).hex
|
project_id = uuid.UUID(project_id or uuid.uuid4().hex).hex
|
||||||
if parent_id:
|
if parent_id:
|
||||||
@ -264,9 +303,16 @@ class TestCase(base.TestCase):
|
|||||||
response['description'] = description
|
response['description'] = description
|
||||||
request['description'] = description
|
request['description'] = description
|
||||||
request.setdefault('description', None)
|
request.setdefault('description', None)
|
||||||
return _ProjectData(project_id, project_name, enabled, domain_id,
|
return _ProjectData(
|
||||||
description, parent_id,
|
project_id,
|
||||||
{'project': response}, {'project': request})
|
project_name,
|
||||||
|
enabled,
|
||||||
|
domain_id,
|
||||||
|
description,
|
||||||
|
parent_id,
|
||||||
|
{'project': response},
|
||||||
|
{'project': request},
|
||||||
|
)
|
||||||
|
|
||||||
def _get_group_data(self, name=None, domain_id=None, description=None):
|
def _get_group_data(self, name=None, domain_id=None, description=None):
|
||||||
group_id = uuid.uuid4().hex
|
group_id = uuid.uuid4().hex
|
||||||
@ -278,8 +324,14 @@ class TestCase(base.TestCase):
|
|||||||
response['description'] = description
|
response['description'] = description
|
||||||
request['description'] = description
|
request['description'] = description
|
||||||
|
|
||||||
return _GroupData(group_id, name, domain_id, description,
|
return _GroupData(
|
||||||
{'group': response}, {'group': request})
|
group_id,
|
||||||
|
name,
|
||||||
|
domain_id,
|
||||||
|
description,
|
||||||
|
{'group': response},
|
||||||
|
{'group': request},
|
||||||
|
)
|
||||||
|
|
||||||
def _get_user_data(self, name=None, password=None, **kwargs):
|
def _get_user_data(self, name=None, password=None, **kwargs):
|
||||||
|
|
||||||
@ -305,16 +357,27 @@ class TestCase(base.TestCase):
|
|||||||
if response['description']:
|
if response['description']:
|
||||||
request['description'] = response['description']
|
request['description'] = response['description']
|
||||||
|
|
||||||
self.assertIs(0, len(kwargs), message='extra key-word args received '
|
self.assertIs(
|
||||||
'on _get_user_data')
|
0,
|
||||||
|
len(kwargs),
|
||||||
|
message='extra key-word args received ' 'on _get_user_data',
|
||||||
|
)
|
||||||
|
|
||||||
return _UserData(user_id, password, name, response['email'],
|
return _UserData(
|
||||||
response['description'], response.get('domain_id'),
|
user_id,
|
||||||
response.get('enabled'), {'user': response},
|
password,
|
||||||
{'user': request})
|
name,
|
||||||
|
response['email'],
|
||||||
|
response['description'],
|
||||||
|
response.get('domain_id'),
|
||||||
|
response.get('enabled'),
|
||||||
|
{'user': response},
|
||||||
|
{'user': request},
|
||||||
|
)
|
||||||
|
|
||||||
def _get_domain_data(self, domain_name=None, description=None,
|
def _get_domain_data(
|
||||||
enabled=None):
|
self, domain_name=None, description=None, enabled=None
|
||||||
|
):
|
||||||
domain_id = uuid.uuid4().hex
|
domain_id = uuid.uuid4().hex
|
||||||
domain_name = domain_name or self.getUniqueString('domainName')
|
domain_name = domain_name or self.getUniqueString('domainName')
|
||||||
response = {'id': domain_id, 'name': domain_name}
|
response = {'id': domain_id, 'name': domain_name}
|
||||||
@ -326,41 +389,76 @@ class TestCase(base.TestCase):
|
|||||||
response['description'] = description
|
response['description'] = description
|
||||||
request['description'] = description
|
request['description'] = description
|
||||||
response.setdefault('enabled', True)
|
response.setdefault('enabled', True)
|
||||||
return _DomainData(domain_id, domain_name, description,
|
return _DomainData(
|
||||||
{'domain': response}, {'domain': request})
|
domain_id,
|
||||||
|
domain_name,
|
||||||
|
description,
|
||||||
|
{'domain': response},
|
||||||
|
{'domain': request},
|
||||||
|
)
|
||||||
|
|
||||||
def _get_service_data(self, type=None, name=None, description=None,
|
def _get_service_data(
|
||||||
enabled=True):
|
self, type=None, name=None, description=None, enabled=True
|
||||||
|
):
|
||||||
service_id = uuid.uuid4().hex
|
service_id = uuid.uuid4().hex
|
||||||
name = name or uuid.uuid4().hex
|
name = name or uuid.uuid4().hex
|
||||||
type = type or uuid.uuid4().hex
|
type = type or uuid.uuid4().hex
|
||||||
|
|
||||||
response = {'id': service_id, 'name': name, 'type': type,
|
response = {
|
||||||
'enabled': enabled}
|
'id': service_id,
|
||||||
|
'name': name,
|
||||||
|
'type': type,
|
||||||
|
'enabled': enabled,
|
||||||
|
}
|
||||||
if description is not None:
|
if description is not None:
|
||||||
response['description'] = description
|
response['description'] = description
|
||||||
request = response.copy()
|
request = response.copy()
|
||||||
request.pop('id')
|
request.pop('id')
|
||||||
return _ServiceData(service_id, name, type, description, enabled,
|
return _ServiceData(
|
||||||
{'service': response},
|
service_id,
|
||||||
{'OS-KSADM:service': response}, request)
|
name,
|
||||||
|
type,
|
||||||
|
description,
|
||||||
|
enabled,
|
||||||
|
{'service': response},
|
||||||
|
{'OS-KSADM:service': response},
|
||||||
|
request,
|
||||||
|
)
|
||||||
|
|
||||||
def _get_endpoint_v3_data(self, service_id=None, region=None,
|
def _get_endpoint_v3_data(
|
||||||
url=None, interface=None, enabled=True):
|
self,
|
||||||
|
service_id=None,
|
||||||
|
region=None,
|
||||||
|
url=None,
|
||||||
|
interface=None,
|
||||||
|
enabled=True,
|
||||||
|
):
|
||||||
endpoint_id = uuid.uuid4().hex
|
endpoint_id = uuid.uuid4().hex
|
||||||
service_id = service_id or uuid.uuid4().hex
|
service_id = service_id or uuid.uuid4().hex
|
||||||
region = region or uuid.uuid4().hex
|
region = region or uuid.uuid4().hex
|
||||||
url = url or 'https://example.com/'
|
url = url or 'https://example.com/'
|
||||||
interface = interface or uuid.uuid4().hex
|
interface = interface or uuid.uuid4().hex
|
||||||
|
|
||||||
response = {'id': endpoint_id, 'service_id': service_id,
|
response = {
|
||||||
'region_id': region, 'interface': interface,
|
'id': endpoint_id,
|
||||||
'url': url, 'enabled': enabled}
|
'service_id': service_id,
|
||||||
|
'region_id': region,
|
||||||
|
'interface': interface,
|
||||||
|
'url': url,
|
||||||
|
'enabled': enabled,
|
||||||
|
}
|
||||||
request = response.copy()
|
request = response.copy()
|
||||||
request.pop('id')
|
request.pop('id')
|
||||||
return _EndpointDataV3(endpoint_id, service_id, interface, region,
|
return _EndpointDataV3(
|
||||||
url, enabled, {'endpoint': response},
|
endpoint_id,
|
||||||
{'endpoint': request})
|
service_id,
|
||||||
|
interface,
|
||||||
|
region,
|
||||||
|
url,
|
||||||
|
enabled,
|
||||||
|
{'endpoint': response},
|
||||||
|
{'endpoint': request},
|
||||||
|
)
|
||||||
|
|
||||||
def _get_role_data(self, role_name=None):
|
def _get_role_data(self, role_name=None):
|
||||||
role_id = uuid.uuid4().hex
|
role_id = uuid.uuid4().hex
|
||||||
@ -368,20 +466,28 @@ class TestCase(base.TestCase):
|
|||||||
request = {'name': role_name}
|
request = {'name': role_name}
|
||||||
response = request.copy()
|
response = request.copy()
|
||||||
response['id'] = role_id
|
response['id'] = role_id
|
||||||
return _RoleData(role_id, role_name, {'role': response},
|
return _RoleData(
|
||||||
{'role': request})
|
role_id, role_name, {'role': response}, {'role': request}
|
||||||
|
)
|
||||||
|
|
||||||
def use_broken_keystone(self):
|
def use_broken_keystone(self):
|
||||||
self.adapter = self.useFixture(rm_fixture.Fixture())
|
self.adapter = self.useFixture(rm_fixture.Fixture())
|
||||||
self.calls = []
|
self.calls = []
|
||||||
self._uri_registry.clear()
|
self._uri_registry.clear()
|
||||||
self.__do_register_uris([
|
self.__do_register_uris(
|
||||||
dict(method='GET', uri='https://identity.example.com/',
|
[
|
||||||
text=open(self.discovery_json, 'r').read()),
|
dict(
|
||||||
dict(method='POST',
|
method='GET',
|
||||||
uri='https://identity.example.com/v3/auth/tokens',
|
uri='https://identity.example.com/',
|
||||||
status_code=400),
|
text=open(self.discovery_json, 'r').read(),
|
||||||
])
|
),
|
||||||
|
dict(
|
||||||
|
method='POST',
|
||||||
|
uri='https://identity.example.com/v3/auth/tokens',
|
||||||
|
status_code=400,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
self._make_test_cloud(identity_api_version='3')
|
self._make_test_cloud(identity_api_version='3')
|
||||||
|
|
||||||
def use_nothing(self):
|
def use_nothing(self):
|
||||||
@ -389,40 +495,38 @@ class TestCase(base.TestCase):
|
|||||||
self._uri_registry.clear()
|
self._uri_registry.clear()
|
||||||
|
|
||||||
def get_keystone_v3_token(
|
def get_keystone_v3_token(
|
||||||
self,
|
self,
|
||||||
project_name='admin',
|
project_name='admin',
|
||||||
):
|
):
|
||||||
return dict(
|
return dict(
|
||||||
method='POST',
|
method='POST',
|
||||||
uri='https://identity.example.com/v3/auth/tokens',
|
uri='https://identity.example.com/v3/auth/tokens',
|
||||||
headers={
|
headers={'X-Subject-Token': self.getUniqueString('KeystoneToken')},
|
||||||
'X-Subject-Token': self.getUniqueString('KeystoneToken')
|
|
||||||
},
|
|
||||||
json=self.os_fixture.v3_token,
|
json=self.os_fixture.v3_token,
|
||||||
validate=dict(json={
|
validate=dict(
|
||||||
'auth': {
|
json={
|
||||||
'identity': {
|
'auth': {
|
||||||
'methods': ['password'],
|
'identity': {
|
||||||
'password': {
|
'methods': ['password'],
|
||||||
'user': {
|
'password': {
|
||||||
'domain': {
|
'user': {
|
||||||
'name': 'default',
|
'domain': {
|
||||||
},
|
'name': 'default',
|
||||||
'name': 'admin',
|
},
|
||||||
'password': 'password'
|
'name': 'admin',
|
||||||
}
|
'password': 'password',
|
||||||
}
|
}
|
||||||
},
|
|
||||||
'scope': {
|
|
||||||
'project': {
|
|
||||||
'domain': {
|
|
||||||
'name': 'default'
|
|
||||||
},
|
},
|
||||||
'name': project_name
|
},
|
||||||
}
|
'scope': {
|
||||||
|
'project': {
|
||||||
|
'domain': {'name': 'default'},
|
||||||
|
'name': project_name,
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_keystone_discovery(self):
|
def get_keystone_discovery(self):
|
||||||
@ -437,10 +541,12 @@ class TestCase(base.TestCase):
|
|||||||
self.adapter = self.useFixture(rm_fixture.Fixture())
|
self.adapter = self.useFixture(rm_fixture.Fixture())
|
||||||
self.calls = []
|
self.calls = []
|
||||||
self._uri_registry.clear()
|
self._uri_registry.clear()
|
||||||
self.__do_register_uris([
|
self.__do_register_uris(
|
||||||
self.get_keystone_discovery(),
|
[
|
||||||
self.get_keystone_v3_token(),
|
self.get_keystone_discovery(),
|
||||||
])
|
self.get_keystone_v3_token(),
|
||||||
|
]
|
||||||
|
)
|
||||||
self._make_test_cloud(identity_api_version='3')
|
self._make_test_cloud(identity_api_version='3')
|
||||||
|
|
||||||
def use_keystone_v2(self):
|
def use_keystone_v2(self):
|
||||||
@ -448,119 +554,171 @@ class TestCase(base.TestCase):
|
|||||||
self.calls = []
|
self.calls = []
|
||||||
self._uri_registry.clear()
|
self._uri_registry.clear()
|
||||||
|
|
||||||
self.__do_register_uris([
|
self.__do_register_uris(
|
||||||
self.get_keystone_discovery(),
|
[
|
||||||
dict(method='POST',
|
self.get_keystone_discovery(),
|
||||||
uri='https://identity.example.com/v2.0/tokens',
|
dict(
|
||||||
json=self.os_fixture.v2_token,
|
method='POST',
|
||||||
),
|
uri='https://identity.example.com/v2.0/tokens',
|
||||||
])
|
json=self.os_fixture.v2_token,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
self._make_test_cloud(cloud_name='_test_cloud_v2_',
|
self._make_test_cloud(
|
||||||
identity_api_version='2.0')
|
cloud_name='_test_cloud_v2_', identity_api_version='2.0'
|
||||||
|
)
|
||||||
|
|
||||||
def _make_test_cloud(self, cloud_name='_test_cloud_', **kwargs):
|
def _make_test_cloud(self, cloud_name='_test_cloud_', **kwargs):
|
||||||
test_cloud = os.environ.get('OPENSTACKSDK_OS_CLOUD', cloud_name)
|
test_cloud = os.environ.get('OPENSTACKSDK_OS_CLOUD', cloud_name)
|
||||||
self.cloud_config = self.config.get_one(
|
self.cloud_config = self.config.get_one(
|
||||||
cloud=test_cloud, validate=True, **kwargs)
|
cloud=test_cloud, validate=True, **kwargs
|
||||||
|
)
|
||||||
self.cloud = openstack.connection.Connection(
|
self.cloud = openstack.connection.Connection(
|
||||||
config=self.cloud_config, strict=self.strict_cloud)
|
config=self.cloud_config, strict=self.strict_cloud
|
||||||
|
)
|
||||||
|
|
||||||
def get_cinder_discovery_mock_dict(
|
def get_cinder_discovery_mock_dict(
|
||||||
self,
|
self,
|
||||||
block_storage_version_json='block-storage-version.json',
|
block_storage_version_json='block-storage-version.json',
|
||||||
block_storage_discovery_url='https://block-storage.example.com/'):
|
block_storage_discovery_url='https://block-storage.example.com/',
|
||||||
|
):
|
||||||
discovery_fixture = os.path.join(
|
discovery_fixture = os.path.join(
|
||||||
self.fixtures_directory, block_storage_version_json)
|
self.fixtures_directory, block_storage_version_json
|
||||||
return dict(method='GET', uri=block_storage_discovery_url,
|
)
|
||||||
text=open(discovery_fixture, 'r').read())
|
return dict(
|
||||||
|
method='GET',
|
||||||
|
uri=block_storage_discovery_url,
|
||||||
|
text=open(discovery_fixture, 'r').read(),
|
||||||
|
)
|
||||||
|
|
||||||
def get_glance_discovery_mock_dict(
|
def get_glance_discovery_mock_dict(
|
||||||
self,
|
self,
|
||||||
image_version_json='image-version.json',
|
image_version_json='image-version.json',
|
||||||
image_discovery_url='https://image.example.com/'):
|
image_discovery_url='https://image.example.com/',
|
||||||
|
):
|
||||||
discovery_fixture = os.path.join(
|
discovery_fixture = os.path.join(
|
||||||
self.fixtures_directory, image_version_json)
|
self.fixtures_directory, image_version_json
|
||||||
return dict(method='GET', uri=image_discovery_url,
|
)
|
||||||
status_code=300,
|
return dict(
|
||||||
text=open(discovery_fixture, 'r').read())
|
method='GET',
|
||||||
|
uri=image_discovery_url,
|
||||||
|
status_code=300,
|
||||||
|
text=open(discovery_fixture, 'r').read(),
|
||||||
|
)
|
||||||
|
|
||||||
def get_nova_discovery_mock_dict(
|
def get_nova_discovery_mock_dict(
|
||||||
self,
|
self,
|
||||||
compute_version_json='compute-version.json',
|
compute_version_json='compute-version.json',
|
||||||
compute_discovery_url='https://compute.example.com/v2.1/'):
|
compute_discovery_url='https://compute.example.com/v2.1/',
|
||||||
|
):
|
||||||
discovery_fixture = os.path.join(
|
discovery_fixture = os.path.join(
|
||||||
self.fixtures_directory, compute_version_json)
|
self.fixtures_directory, compute_version_json
|
||||||
|
)
|
||||||
return dict(
|
return dict(
|
||||||
method='GET',
|
method='GET',
|
||||||
uri=compute_discovery_url,
|
uri=compute_discovery_url,
|
||||||
text=open(discovery_fixture, 'r').read())
|
text=open(discovery_fixture, 'r').read(),
|
||||||
|
)
|
||||||
|
|
||||||
def get_placement_discovery_mock_dict(
|
def get_placement_discovery_mock_dict(
|
||||||
self, discovery_fixture='placement.json'):
|
self, discovery_fixture='placement.json'
|
||||||
|
):
|
||||||
discovery_fixture = os.path.join(
|
discovery_fixture = os.path.join(
|
||||||
self.fixtures_directory, discovery_fixture)
|
self.fixtures_directory, discovery_fixture
|
||||||
return dict(method='GET', uri="https://placement.example.com/",
|
)
|
||||||
text=open(discovery_fixture, 'r').read())
|
return dict(
|
||||||
|
method='GET',
|
||||||
|
uri="https://placement.example.com/",
|
||||||
|
text=open(discovery_fixture, 'r').read(),
|
||||||
|
)
|
||||||
|
|
||||||
def get_designate_discovery_mock_dict(self):
|
def get_designate_discovery_mock_dict(self):
|
||||||
discovery_fixture = os.path.join(
|
discovery_fixture = os.path.join(self.fixtures_directory, "dns.json")
|
||||||
self.fixtures_directory, "dns.json")
|
return dict(
|
||||||
return dict(method='GET', uri="https://dns.example.com/",
|
method='GET',
|
||||||
text=open(discovery_fixture, 'r').read())
|
uri="https://dns.example.com/",
|
||||||
|
text=open(discovery_fixture, 'r').read(),
|
||||||
|
)
|
||||||
|
|
||||||
def get_ironic_discovery_mock_dict(self):
|
def get_ironic_discovery_mock_dict(self):
|
||||||
discovery_fixture = os.path.join(
|
discovery_fixture = os.path.join(
|
||||||
self.fixtures_directory, "baremetal.json")
|
self.fixtures_directory, "baremetal.json"
|
||||||
return dict(method='GET', uri="https://baremetal.example.com/",
|
)
|
||||||
text=open(discovery_fixture, 'r').read())
|
return dict(
|
||||||
|
method='GET',
|
||||||
|
uri="https://baremetal.example.com/",
|
||||||
|
text=open(discovery_fixture, 'r').read(),
|
||||||
|
)
|
||||||
|
|
||||||
def get_senlin_discovery_mock_dict(self):
|
def get_senlin_discovery_mock_dict(self):
|
||||||
discovery_fixture = os.path.join(
|
discovery_fixture = os.path.join(
|
||||||
self.fixtures_directory, "clustering.json")
|
self.fixtures_directory, "clustering.json"
|
||||||
return dict(method='GET', uri="https://clustering.example.com/",
|
)
|
||||||
text=open(discovery_fixture, 'r').read())
|
return dict(
|
||||||
|
method='GET',
|
||||||
|
uri="https://clustering.example.com/",
|
||||||
|
text=open(discovery_fixture, 'r').read(),
|
||||||
|
)
|
||||||
|
|
||||||
def use_compute_discovery(
|
def use_compute_discovery(
|
||||||
self, compute_version_json='compute-version.json',
|
self,
|
||||||
compute_discovery_url='https://compute.example.com/v2.1/'):
|
compute_version_json='compute-version.json',
|
||||||
self.__do_register_uris([
|
compute_discovery_url='https://compute.example.com/v2.1/',
|
||||||
self.get_nova_discovery_mock_dict(
|
):
|
||||||
compute_version_json, compute_discovery_url),
|
self.__do_register_uris(
|
||||||
])
|
[
|
||||||
|
self.get_nova_discovery_mock_dict(
|
||||||
|
compute_version_json, compute_discovery_url
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
def get_cyborg_discovery_mock_dict(self):
|
def get_cyborg_discovery_mock_dict(self):
|
||||||
discovery_fixture = os.path.join(
|
discovery_fixture = os.path.join(
|
||||||
self.fixtures_directory, "accelerator.json")
|
self.fixtures_directory, "accelerator.json"
|
||||||
return dict(method='GET', uri="https://accelerator.example.com/",
|
)
|
||||||
text=open(discovery_fixture, 'r').read())
|
return dict(
|
||||||
|
method='GET',
|
||||||
|
uri="https://accelerator.example.com/",
|
||||||
|
text=open(discovery_fixture, 'r').read(),
|
||||||
|
)
|
||||||
|
|
||||||
def get_manila_discovery_mock_dict(self):
|
def get_manila_discovery_mock_dict(self):
|
||||||
discovery_fixture = os.path.join(
|
discovery_fixture = os.path.join(
|
||||||
self.fixtures_directory, "shared-file-system.json")
|
self.fixtures_directory, "shared-file-system.json"
|
||||||
return dict(method='GET',
|
)
|
||||||
uri="https://shared-file-system.example.com/",
|
return dict(
|
||||||
text=open(discovery_fixture, 'r').read())
|
method='GET',
|
||||||
|
uri="https://shared-file-system.example.com/",
|
||||||
|
text=open(discovery_fixture, 'r').read(),
|
||||||
|
)
|
||||||
|
|
||||||
def use_glance(
|
def use_glance(
|
||||||
self, image_version_json='image-version.json',
|
self,
|
||||||
image_discovery_url='https://image.example.com/'):
|
image_version_json='image-version.json',
|
||||||
|
image_discovery_url='https://image.example.com/',
|
||||||
|
):
|
||||||
# NOTE(notmorgan): This method is only meant to be used in "setUp"
|
# NOTE(notmorgan): This method is only meant to be used in "setUp"
|
||||||
# where the ordering of the url being registered is tightly controlled
|
# where the ordering of the url being registered is tightly controlled
|
||||||
# if the functionality of .use_glance is meant to be used during an
|
# if the functionality of .use_glance is meant to be used during an
|
||||||
# actual test case, use .get_glance_discovery_mock and apply to the
|
# actual test case, use .get_glance_discovery_mock and apply to the
|
||||||
# right location in the mock_uris when calling .register_uris
|
# right location in the mock_uris when calling .register_uris
|
||||||
self.__do_register_uris([
|
self.__do_register_uris(
|
||||||
self.get_glance_discovery_mock_dict(
|
[
|
||||||
image_version_json, image_discovery_url)])
|
self.get_glance_discovery_mock_dict(
|
||||||
|
image_version_json, image_discovery_url
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
def use_cinder(self):
|
def use_cinder(self):
|
||||||
self.__do_register_uris([
|
self.__do_register_uris([self.get_cinder_discovery_mock_dict()])
|
||||||
self.get_cinder_discovery_mock_dict()])
|
|
||||||
|
|
||||||
def use_placement(self, **kwargs):
|
def use_placement(self, **kwargs):
|
||||||
self.__do_register_uris([
|
self.__do_register_uris(
|
||||||
self.get_placement_discovery_mock_dict(**kwargs)])
|
[self.get_placement_discovery_mock_dict(**kwargs)]
|
||||||
|
)
|
||||||
|
|
||||||
def use_designate(self):
|
def use_designate(self):
|
||||||
# NOTE(slaweq): This method is only meant to be used in "setUp"
|
# NOTE(slaweq): This method is only meant to be used in "setUp"
|
||||||
@ -568,8 +726,7 @@ class TestCase(base.TestCase):
|
|||||||
# if the functionality of .use_designate is meant to be used during an
|
# if the functionality of .use_designate is meant to be used during an
|
||||||
# actual test case, use .get_designate_discovery_mock and apply to the
|
# actual test case, use .get_designate_discovery_mock and apply to the
|
||||||
# right location in the mock_uris when calling .register_uris
|
# right location in the mock_uris when calling .register_uris
|
||||||
self.__do_register_uris([
|
self.__do_register_uris([self.get_designate_discovery_mock_dict()])
|
||||||
self.get_designate_discovery_mock_dict()])
|
|
||||||
|
|
||||||
def use_ironic(self):
|
def use_ironic(self):
|
||||||
# NOTE(TheJulia): This method is only meant to be used in "setUp"
|
# NOTE(TheJulia): This method is only meant to be used in "setUp"
|
||||||
@ -577,8 +734,7 @@ class TestCase(base.TestCase):
|
|||||||
# if the functionality of .use_ironic is meant to be used during an
|
# if the functionality of .use_ironic is meant to be used during an
|
||||||
# actual test case, use .get_ironic_discovery_mock and apply to the
|
# actual test case, use .get_ironic_discovery_mock and apply to the
|
||||||
# right location in the mock_uris when calling .register_uris
|
# right location in the mock_uris when calling .register_uris
|
||||||
self.__do_register_uris([
|
self.__do_register_uris([self.get_ironic_discovery_mock_dict()])
|
||||||
self.get_ironic_discovery_mock_dict()])
|
|
||||||
|
|
||||||
def use_senlin(self):
|
def use_senlin(self):
|
||||||
# NOTE(elachance): This method is only meant to be used in "setUp"
|
# NOTE(elachance): This method is only meant to be used in "setUp"
|
||||||
@ -586,8 +742,7 @@ class TestCase(base.TestCase):
|
|||||||
# if the functionality of .use_senlin is meant to be used during an
|
# if the functionality of .use_senlin is meant to be used during an
|
||||||
# actual test case, use .get_senlin_discovery_mock and apply to the
|
# actual test case, use .get_senlin_discovery_mock and apply to the
|
||||||
# right location in the mock_uris when calling .register_uris
|
# right location in the mock_uris when calling .register_uris
|
||||||
self.__do_register_uris([
|
self.__do_register_uris([self.get_senlin_discovery_mock_dict()])
|
||||||
self.get_senlin_discovery_mock_dict()])
|
|
||||||
|
|
||||||
def use_cyborg(self):
|
def use_cyborg(self):
|
||||||
# NOTE(s_shogo): This method is only meant to be used in "setUp"
|
# NOTE(s_shogo): This method is only meant to be used in "setUp"
|
||||||
@ -595,8 +750,7 @@ class TestCase(base.TestCase):
|
|||||||
# if the functionality of .use_cyborg is meant to be used during an
|
# if the functionality of .use_cyborg is meant to be used during an
|
||||||
# actual test case, use .get_cyborg_discovery_mock and apply to the
|
# actual test case, use .get_cyborg_discovery_mock and apply to the
|
||||||
# right location in the mock_uris when calling .register_uris
|
# right location in the mock_uris when calling .register_uris
|
||||||
self.__do_register_uris([
|
self.__do_register_uris([self.get_cyborg_discovery_mock_dict()])
|
||||||
self.get_cyborg_discovery_mock_dict()])
|
|
||||||
|
|
||||||
def use_manila(self):
|
def use_manila(self):
|
||||||
# NOTE(gouthamr): This method is only meant to be used in "setUp"
|
# NOTE(gouthamr): This method is only meant to be used in "setUp"
|
||||||
@ -604,8 +758,7 @@ class TestCase(base.TestCase):
|
|||||||
# if the functionality of .use_manila is meant to be used during an
|
# if the functionality of .use_manila is meant to be used during an
|
||||||
# actual test case, use .get_manila_discovery_mock and apply to the
|
# actual test case, use .get_manila_discovery_mock and apply to the
|
||||||
# right location in the mock_uris when calling .register_uris
|
# right location in the mock_uris when calling .register_uris
|
||||||
self.__do_register_uris([
|
self.__do_register_uris([self.get_manila_discovery_mock_dict()])
|
||||||
self.get_manila_discovery_mock_dict()])
|
|
||||||
|
|
||||||
def register_uris(self, uri_mock_list=None):
|
def register_uris(self, uri_mock_list=None):
|
||||||
"""Mock a list of URIs and responses via requests mock.
|
"""Mock a list of URIs and responses via requests mock.
|
||||||
@ -645,10 +798,11 @@ class TestCase(base.TestCase):
|
|||||||
|
|
||||||
def __do_register_uris(self, uri_mock_list=None):
|
def __do_register_uris(self, uri_mock_list=None):
|
||||||
for to_mock in uri_mock_list:
|
for to_mock in uri_mock_list:
|
||||||
kw_params = {k: to_mock.pop(k)
|
kw_params = {
|
||||||
for k in ('request_headers', 'complete_qs',
|
k: to_mock.pop(k)
|
||||||
'_real_http')
|
for k in ('request_headers', 'complete_qs', '_real_http')
|
||||||
if k in to_mock}
|
if k in to_mock
|
||||||
|
}
|
||||||
|
|
||||||
method = to_mock.pop('method')
|
method = to_mock.pop('method')
|
||||||
uri = to_mock.pop('uri')
|
uri = to_mock.pop('uri')
|
||||||
@ -656,44 +810,51 @@ class TestCase(base.TestCase):
|
|||||||
# case "|" is used so that the split can be a bit easier on
|
# case "|" is used so that the split can be a bit easier on
|
||||||
# maintainers of this code.
|
# maintainers of this code.
|
||||||
key = '{method}|{uri}|{params}'.format(
|
key = '{method}|{uri}|{params}'.format(
|
||||||
method=method, uri=uri, params=kw_params)
|
method=method, uri=uri, params=kw_params
|
||||||
|
)
|
||||||
validate = to_mock.pop('validate', {})
|
validate = to_mock.pop('validate', {})
|
||||||
valid_keys = set(['json', 'headers', 'params', 'data'])
|
valid_keys = set(['json', 'headers', 'params', 'data'])
|
||||||
invalid_keys = set(validate.keys()) - valid_keys
|
invalid_keys = set(validate.keys()) - valid_keys
|
||||||
if invalid_keys:
|
if invalid_keys:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"Invalid values passed to validate: {keys}".format(
|
"Invalid values passed to validate: {keys}".format(
|
||||||
keys=invalid_keys))
|
keys=invalid_keys
|
||||||
headers = structures.CaseInsensitiveDict(to_mock.pop('headers',
|
)
|
||||||
{}))
|
)
|
||||||
|
headers = structures.CaseInsensitiveDict(
|
||||||
|
to_mock.pop('headers', {})
|
||||||
|
)
|
||||||
if 'content-type' not in headers:
|
if 'content-type' not in headers:
|
||||||
headers[u'content-type'] = 'application/json'
|
headers[u'content-type'] = 'application/json'
|
||||||
|
|
||||||
if 'exc' not in to_mock:
|
if 'exc' not in to_mock:
|
||||||
to_mock['headers'] = headers
|
to_mock['headers'] = headers
|
||||||
|
|
||||||
self.calls += [
|
self.calls += [dict(method=method, url=uri, **validate)]
|
||||||
dict(
|
|
||||||
method=method,
|
|
||||||
url=uri, **validate)
|
|
||||||
]
|
|
||||||
self._uri_registry.setdefault(
|
self._uri_registry.setdefault(
|
||||||
key, {'response_list': [], 'kw_params': kw_params})
|
key, {'response_list': [], 'kw_params': kw_params}
|
||||||
|
)
|
||||||
if self._uri_registry[key]['kw_params'] != kw_params:
|
if self._uri_registry[key]['kw_params'] != kw_params:
|
||||||
raise AssertionError(
|
raise AssertionError(
|
||||||
'PROGRAMMING ERROR: key-word-params '
|
'PROGRAMMING ERROR: key-word-params '
|
||||||
'should be part of the uri_key and cannot change, '
|
'should be part of the uri_key and cannot change, '
|
||||||
'it will affect the matcher in requests_mock. '
|
'it will affect the matcher in requests_mock. '
|
||||||
'%(old)r != %(new)r' %
|
'%(old)r != %(new)r'
|
||||||
{'old': self._uri_registry[key]['kw_params'],
|
% {
|
||||||
'new': kw_params})
|
'old': self._uri_registry[key]['kw_params'],
|
||||||
|
'new': kw_params,
|
||||||
|
}
|
||||||
|
)
|
||||||
self._uri_registry[key]['response_list'].append(to_mock)
|
self._uri_registry[key]['response_list'].append(to_mock)
|
||||||
|
|
||||||
for mocked, params in self._uri_registry.items():
|
for mocked, params in self._uri_registry.items():
|
||||||
mock_method, mock_uri, _ignored = mocked.split('|', 2)
|
mock_method, mock_uri, _ignored = mocked.split('|', 2)
|
||||||
self.adapter.register_uri(
|
self.adapter.register_uri(
|
||||||
mock_method, mock_uri, params['response_list'],
|
mock_method,
|
||||||
**params['kw_params'])
|
mock_uri,
|
||||||
|
params['response_list'],
|
||||||
|
**params['kw_params']
|
||||||
|
)
|
||||||
|
|
||||||
def assert_no_calls(self):
|
def assert_no_calls(self):
|
||||||
# TODO(mordred) For now, creating the adapter for self.conn is
|
# TODO(mordred) For now, creating the adapter for self.conn is
|
||||||
@ -704,46 +865,65 @@ class TestCase(base.TestCase):
|
|||||||
|
|
||||||
def assert_calls(self, stop_after=None, do_count=True):
|
def assert_calls(self, stop_after=None, do_count=True):
|
||||||
for (x, (call, history)) in enumerate(
|
for (x, (call, history)) in enumerate(
|
||||||
zip(self.calls, self.adapter.request_history)):
|
zip(self.calls, self.adapter.request_history)
|
||||||
|
):
|
||||||
if stop_after and x > stop_after:
|
if stop_after and x > stop_after:
|
||||||
break
|
break
|
||||||
|
|
||||||
call_uri_parts = urllib.parse.urlparse(call['url'])
|
call_uri_parts = urllib.parse.urlparse(call['url'])
|
||||||
history_uri_parts = urllib.parse.urlparse(history.url)
|
history_uri_parts = urllib.parse.urlparse(history.url)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
(call['method'], call_uri_parts.scheme, call_uri_parts.netloc,
|
(
|
||||||
call_uri_parts.path, call_uri_parts.params,
|
call['method'],
|
||||||
urllib.parse.parse_qs(call_uri_parts.query)),
|
call_uri_parts.scheme,
|
||||||
(history.method, history_uri_parts.scheme,
|
call_uri_parts.netloc,
|
||||||
history_uri_parts.netloc, history_uri_parts.path,
|
call_uri_parts.path,
|
||||||
history_uri_parts.params,
|
call_uri_parts.params,
|
||||||
urllib.parse.parse_qs(history_uri_parts.query)),
|
urllib.parse.parse_qs(call_uri_parts.query),
|
||||||
('REST mismatch on call %(index)d. Expected %(call)r. '
|
),
|
||||||
'Got %(history)r). '
|
(
|
||||||
'NOTE: query string order differences wont cause mismatch' %
|
history.method,
|
||||||
{
|
history_uri_parts.scheme,
|
||||||
'index': x,
|
history_uri_parts.netloc,
|
||||||
'call': '{method} {url}'.format(method=call['method'],
|
history_uri_parts.path,
|
||||||
url=call['url']),
|
history_uri_parts.params,
|
||||||
'history': '{method} {url}'.format(
|
urllib.parse.parse_qs(history_uri_parts.query),
|
||||||
method=history.method,
|
),
|
||||||
url=history.url)})
|
(
|
||||||
|
'REST mismatch on call %(index)d. Expected %(call)r. '
|
||||||
|
'Got %(history)r). '
|
||||||
|
'NOTE: query string order differences wont cause mismatch'
|
||||||
|
% {
|
||||||
|
'index': x,
|
||||||
|
'call': '{method} {url}'.format(
|
||||||
|
method=call['method'], url=call['url']
|
||||||
|
),
|
||||||
|
'history': '{method} {url}'.format(
|
||||||
|
method=history.method, url=history.url
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
)
|
)
|
||||||
if 'json' in call:
|
if 'json' in call:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
call['json'], history.json(),
|
call['json'],
|
||||||
'json content mismatch in call {index}'.format(index=x))
|
history.json(),
|
||||||
|
'json content mismatch in call {index}'.format(index=x),
|
||||||
|
)
|
||||||
# headers in a call isn't exhaustive - it's checking to make sure
|
# headers in a call isn't exhaustive - it's checking to make sure
|
||||||
# a specific header or headers are there, not that they are the
|
# a specific header or headers are there, not that they are the
|
||||||
# only headers
|
# only headers
|
||||||
if 'headers' in call:
|
if 'headers' in call:
|
||||||
for key, value in call['headers'].items():
|
for key, value in call['headers'].items():
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
value, history.headers[key],
|
value,
|
||||||
'header mismatch in call {index}'.format(index=x))
|
history.headers[key],
|
||||||
|
'header mismatch in call {index}'.format(index=x),
|
||||||
|
)
|
||||||
if do_count:
|
if do_count:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
len(self.calls), len(self.adapter.request_history))
|
len(self.calls), len(self.adapter.request_history)
|
||||||
|
)
|
||||||
|
|
||||||
def assertResourceEqual(self, actual, expected, resource_type):
|
def assertResourceEqual(self, actual, expected, resource_type):
|
||||||
"""Helper for the assertEqual which compares Resource object against
|
"""Helper for the assertEqual which compares Resource object against
|
||||||
@ -756,7 +936,7 @@ class TestCase(base.TestCase):
|
|||||||
"""
|
"""
|
||||||
return self.assertEqual(
|
return self.assertEqual(
|
||||||
resource_type(**expected).to_dict(computed=False),
|
resource_type(**expected).to_dict(computed=False),
|
||||||
actual.to_dict(computed=False)
|
actual.to_dict(computed=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
def assertResourceListEqual(self, actual, expected, resource_type):
|
def assertResourceListEqual(self, actual, expected, resource_type):
|
||||||
@ -771,12 +951,11 @@ class TestCase(base.TestCase):
|
|||||||
"""
|
"""
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[resource_type(**f).to_dict(computed=False) for f in expected],
|
[resource_type(**f).to_dict(computed=False) for f in expected],
|
||||||
[f.to_dict(computed=False) for f in actual]
|
[f.to_dict(computed=False) for f in actual],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class IronicTestCase(TestCase):
|
class IronicTestCase(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(IronicTestCase, self).setUp()
|
super(IronicTestCase, self).setUp()
|
||||||
self.use_ironic()
|
self.use_ironic()
|
||||||
|
@ -706,7 +706,9 @@ class TestCreateServer(base.TestCase):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
self.cloud.create_server(
|
self.cloud.create_server(
|
||||||
'server-name', dict(id='image-id'), dict(id='flavor-id'),
|
'server-name',
|
||||||
|
dict(id='image-id'),
|
||||||
|
dict(id='flavor-id'),
|
||||||
wait=True,
|
wait=True,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ IDENTIFIER = 'IDENTIFIER'
|
|||||||
|
|
||||||
|
|
||||||
class TestMetadata(base.TestCase):
|
class TestMetadata(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestMetadata, self).setUp()
|
super(TestMetadata, self).setUp()
|
||||||
|
|
||||||
@ -95,8 +94,7 @@ class TestMetadata(base.TestCase):
|
|||||||
self.assertEqual(res, result)
|
self.assertEqual(res, result)
|
||||||
url = self.base_path + '/' + res.id + '/metadata'
|
url = self.base_path + '/' + res.id + '/metadata'
|
||||||
self.session.post.assert_called_once_with(
|
self.session.post.assert_called_once_with(
|
||||||
url,
|
url, json={'metadata': {'foo': 'bar'}}
|
||||||
json={'metadata': {'foo': 'bar'}}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_replace_metadata(self):
|
def test_replace_metadata(self):
|
||||||
@ -109,8 +107,7 @@ class TestMetadata(base.TestCase):
|
|||||||
self.assertEqual(res, result)
|
self.assertEqual(res, result)
|
||||||
url = self.base_path + '/' + res.id + '/metadata'
|
url = self.base_path + '/' + res.id + '/metadata'
|
||||||
self.session.put.assert_called_once_with(
|
self.session.put.assert_called_once_with(
|
||||||
url,
|
url, json={'metadata': {'foo': 'bar'}}
|
||||||
json={'metadata': {'foo': 'bar'}}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_delete_all_metadata(self):
|
def test_delete_all_metadata(self):
|
||||||
@ -125,9 +122,7 @@ class TestMetadata(base.TestCase):
|
|||||||
# Check passed resource is returned
|
# Check passed resource is returned
|
||||||
self.assertEqual(res, result)
|
self.assertEqual(res, result)
|
||||||
url = self.base_path + '/' + res.id + '/metadata'
|
url = self.base_path + '/' + res.id + '/metadata'
|
||||||
self.session.put.assert_called_once_with(
|
self.session.put.assert_called_once_with(url, json={'metadata': {}})
|
||||||
url,
|
|
||||||
json={'metadata': {}})
|
|
||||||
|
|
||||||
def test_get_metadata_item(self):
|
def test_get_metadata_item(self):
|
||||||
res = self.sot
|
res = self.sot
|
||||||
@ -198,5 +193,5 @@ class TestMetadata(base.TestCase):
|
|||||||
self.assertEqual(res, result)
|
self.assertEqual(res, result)
|
||||||
url = self.base_path + '/' + res.id + '/metadata/foo'
|
url = self.base_path + '/' + res.id + '/metadata/foo'
|
||||||
self.session.put.assert_called_once_with(
|
self.session.put.assert_called_once_with(
|
||||||
url,
|
url, json={'meta': {'foo': 'black'}}
|
||||||
json={'meta': {'foo': 'black'}})
|
)
|
||||||
|
@ -25,26 +25,13 @@ BASIC_EXAMPLE = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
USAGE_EXAMPLE = {
|
USAGE_EXAMPLE = {
|
||||||
"backup_gigabytes": {
|
"backup_gigabytes": {"in_use": 0, "limit": 1000, "reserved": 0},
|
||||||
"in_use": 0,
|
"backups": {"in_use": 0, "limit": 10, "reserved": 0},
|
||||||
"limit": 1000,
|
"gigabytes___DEFAULT__": {"in_use": 0, "limit": -1, "reserved": 0},
|
||||||
"reserved": 0
|
|
||||||
},
|
|
||||||
"backups": {
|
|
||||||
"in_use": 0,
|
|
||||||
"limit": 10,
|
|
||||||
"reserved": 0
|
|
||||||
},
|
|
||||||
"gigabytes___DEFAULT__": {
|
|
||||||
"in_use": 0,
|
|
||||||
"limit": -1,
|
|
||||||
"reserved": 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class TestQuotaSet(base.TestCase):
|
class TestQuotaSet(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestQuotaSet, self).setUp()
|
super(TestQuotaSet, self).setUp()
|
||||||
self.sess = mock.Mock(spec=adapter.Adapter)
|
self.sess = mock.Mock(spec=adapter.Adapter)
|
||||||
@ -64,10 +51,9 @@ class TestQuotaSet(base.TestCase):
|
|||||||
self.assertTrue(sot.allow_commit)
|
self.assertTrue(sot.allow_commit)
|
||||||
|
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
{"usage": "usage",
|
{"usage": "usage", "limit": "limit", "marker": "marker"},
|
||||||
"limit": "limit",
|
sot._query_mapping._mapping,
|
||||||
"marker": "marker"},
|
)
|
||||||
sot._query_mapping._mapping)
|
|
||||||
|
|
||||||
def test_make_basic(self):
|
def test_make_basic(self):
|
||||||
sot = _qs.QuotaSet(**BASIC_EXAMPLE)
|
sot = _qs.QuotaSet(**BASIC_EXAMPLE)
|
||||||
@ -87,10 +73,8 @@ class TestQuotaSet(base.TestCase):
|
|||||||
sot.fetch(self.sess)
|
sot.fetch(self.sess)
|
||||||
|
|
||||||
self.sess.get.assert_called_with(
|
self.sess.get.assert_called_with(
|
||||||
'/os-quota-sets/proj',
|
'/os-quota-sets/proj', microversion=1, params={}, skip_cache=False
|
||||||
microversion=1,
|
)
|
||||||
params={},
|
|
||||||
skip_cache=False)
|
|
||||||
|
|
||||||
self.assertEqual(BASIC_EXAMPLE['backups'], sot.backups)
|
self.assertEqual(BASIC_EXAMPLE['backups'], sot.backups)
|
||||||
self.assertEqual({}, sot.reservation)
|
self.assertEqual({}, sot.reservation)
|
||||||
@ -112,11 +96,10 @@ class TestQuotaSet(base.TestCase):
|
|||||||
'/os-quota-sets/proj',
|
'/os-quota-sets/proj',
|
||||||
microversion=1,
|
microversion=1,
|
||||||
params={'usage': True},
|
params={'usage': True},
|
||||||
skip_cache=False)
|
skip_cache=False,
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(USAGE_EXAMPLE['backups']['limit'], sot.backups)
|
||||||
USAGE_EXAMPLE['backups']['limit'],
|
|
||||||
sot.backups)
|
|
||||||
|
|
||||||
def test_update_quota(self):
|
def test_update_quota(self):
|
||||||
# Use QuotaSet as if it was returned by get(usage=True)
|
# Use QuotaSet as if it was returned by get(usage=True)
|
||||||
@ -124,7 +107,8 @@ class TestQuotaSet(base.TestCase):
|
|||||||
project_id='proj',
|
project_id='proj',
|
||||||
reservation={'a': 'b'},
|
reservation={'a': 'b'},
|
||||||
usage={'c': 'd'},
|
usage={'c': 'd'},
|
||||||
foo='bar')
|
foo='bar',
|
||||||
|
)
|
||||||
|
|
||||||
resp = mock.Mock()
|
resp = mock.Mock()
|
||||||
resp.body = {'quota_set': copy.deepcopy(BASIC_EXAMPLE)}
|
resp.body = {'quota_set': copy.deepcopy(BASIC_EXAMPLE)}
|
||||||
@ -133,10 +117,7 @@ class TestQuotaSet(base.TestCase):
|
|||||||
resp.headers = {}
|
resp.headers = {}
|
||||||
self.sess.put = mock.Mock(return_value=resp)
|
self.sess.put = mock.Mock(return_value=resp)
|
||||||
|
|
||||||
sot._update(
|
sot._update(reservation={'b': 'd'}, backups=15, something_else=20)
|
||||||
reservation={'b': 'd'},
|
|
||||||
backups=15,
|
|
||||||
something_else=20)
|
|
||||||
|
|
||||||
sot.commit(self.sess)
|
sot.commit(self.sess)
|
||||||
|
|
||||||
@ -144,12 +125,8 @@ class TestQuotaSet(base.TestCase):
|
|||||||
'/os-quota-sets/proj',
|
'/os-quota-sets/proj',
|
||||||
microversion=1,
|
microversion=1,
|
||||||
headers={},
|
headers={},
|
||||||
json={
|
json={'quota_set': {'backups': 15, 'something_else': 20}},
|
||||||
'quota_set': {
|
)
|
||||||
'backups': 15,
|
|
||||||
'something_else': 20
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
def test_delete_quota(self):
|
def test_delete_quota(self):
|
||||||
# Use QuotaSet as if it was returned by get(usage=True)
|
# Use QuotaSet as if it was returned by get(usage=True)
|
||||||
@ -157,7 +134,8 @@ class TestQuotaSet(base.TestCase):
|
|||||||
project_id='proj',
|
project_id='proj',
|
||||||
reservation={'a': 'b'},
|
reservation={'a': 'b'},
|
||||||
usage={'c': 'd'},
|
usage={'c': 'd'},
|
||||||
foo='bar')
|
foo='bar',
|
||||||
|
)
|
||||||
|
|
||||||
resp = mock.Mock()
|
resp = mock.Mock()
|
||||||
resp.body = None
|
resp.body = None
|
||||||
|
@ -21,7 +21,6 @@ from openstack.tests.unit.test_resource import FakeResponse
|
|||||||
|
|
||||||
|
|
||||||
class TestTagMixin(base.TestCase):
|
class TestTagMixin(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestTagMixin, self).setUp()
|
super(TestTagMixin, self).setUp()
|
||||||
|
|
||||||
@ -94,10 +93,7 @@ class TestTagMixin(base.TestCase):
|
|||||||
# Check the passed resource is returned
|
# Check the passed resource is returned
|
||||||
self.assertEqual(res, result)
|
self.assertEqual(res, result)
|
||||||
url = self.base_path + '/' + res.id + '/tags'
|
url = self.base_path + '/' + res.id + '/tags'
|
||||||
sess.put.assert_called_once_with(
|
sess.put.assert_called_once_with(url, json={'tags': ['blue', 'green']})
|
||||||
url,
|
|
||||||
json={'tags': ['blue', 'green']}
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_remove_all_tags(self):
|
def test_remove_all_tags(self):
|
||||||
res = self.sot
|
res = self.sot
|
||||||
|
@ -48,10 +48,7 @@ USER_CONF = {
|
|||||||
'force_ipv4': True,
|
'force_ipv4': True,
|
||||||
},
|
},
|
||||||
'metrics': {
|
'metrics': {
|
||||||
'statsd': {
|
'statsd': {'host': '127.0.0.1', 'port': '1234'},
|
||||||
'host': '127.0.0.1',
|
|
||||||
'port': '1234'
|
|
||||||
},
|
|
||||||
'influxdb': {
|
'influxdb': {
|
||||||
'host': '127.0.0.1',
|
'host': '127.0.0.1',
|
||||||
'port': '1234',
|
'port': '1234',
|
||||||
@ -61,7 +58,7 @@ USER_CONF = {
|
|||||||
'database': 'database',
|
'database': 'database',
|
||||||
'measurement': 'measurement.name',
|
'measurement': 'measurement.name',
|
||||||
'timeout': 10,
|
'timeout': 10,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
'clouds': {
|
'clouds': {
|
||||||
'_test-cloud_': {
|
'_test-cloud_': {
|
||||||
@ -112,30 +109,37 @@ USER_CONF = {
|
|||||||
'domain_id': '6789',
|
'domain_id': '6789',
|
||||||
'project_domain_id': '123456789',
|
'project_domain_id': '123456789',
|
||||||
},
|
},
|
||||||
'networks': [{
|
'networks': [
|
||||||
'name': 'a-public',
|
{
|
||||||
'routes_externally': True,
|
'name': 'a-public',
|
||||||
'nat_source': True,
|
'routes_externally': True,
|
||||||
}, {
|
'nat_source': True,
|
||||||
'name': 'another-public',
|
},
|
||||||
'routes_externally': True,
|
{
|
||||||
'default_interface': True,
|
'name': 'another-public',
|
||||||
}, {
|
'routes_externally': True,
|
||||||
'name': 'a-private',
|
'default_interface': True,
|
||||||
'routes_externally': False,
|
},
|
||||||
}, {
|
{
|
||||||
'name': 'another-private',
|
'name': 'a-private',
|
||||||
'routes_externally': False,
|
'routes_externally': False,
|
||||||
'nat_destination': True,
|
},
|
||||||
}, {
|
{
|
||||||
'name': 'split-default',
|
'name': 'another-private',
|
||||||
'routes_externally': True,
|
'routes_externally': False,
|
||||||
'routes_ipv4_externally': False,
|
'nat_destination': True,
|
||||||
}, {
|
},
|
||||||
'name': 'split-no-default',
|
{
|
||||||
'routes_ipv6_externally': False,
|
'name': 'split-default',
|
||||||
'routes_ipv4_externally': True,
|
'routes_externally': True,
|
||||||
}],
|
'routes_ipv4_externally': False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'split-no-default',
|
||||||
|
'routes_ipv6_externally': False,
|
||||||
|
'routes_ipv4_externally': True,
|
||||||
|
},
|
||||||
|
],
|
||||||
'region_name': 'test-region',
|
'region_name': 'test-region',
|
||||||
},
|
},
|
||||||
'_test_cloud_regions': {
|
'_test_cloud_regions': {
|
||||||
@ -150,13 +154,13 @@ USER_CONF = {
|
|||||||
'name': 'region1',
|
'name': 'region1',
|
||||||
'values': {
|
'values': {
|
||||||
'external_network': 'region1-network',
|
'external_network': 'region1-network',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'region2',
|
'name': 'region2',
|
||||||
'values': {
|
'values': {
|
||||||
'external_network': 'my-network',
|
'external_network': 'my-network',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'region-no-value',
|
'name': 'region-no-value',
|
||||||
@ -198,13 +202,13 @@ USER_CONF = {
|
|||||||
'statsd': {
|
'statsd': {
|
||||||
'host': '127.0.0.1',
|
'host': '127.0.0.1',
|
||||||
'port': 4321,
|
'port': 4321,
|
||||||
'prefix': 'statsd.override.prefix'
|
'prefix': 'statsd.override.prefix',
|
||||||
},
|
},
|
||||||
'influxdb': {
|
'influxdb': {
|
||||||
'username': 'override-username',
|
'username': 'override-username',
|
||||||
'password': 'override-password',
|
'password': 'override-password',
|
||||||
'database': 'override-database',
|
'database': 'override-database',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -40,7 +40,6 @@ fake_services_dict = {
|
|||||||
|
|
||||||
|
|
||||||
class TestCloudRegion(base.TestCase):
|
class TestCloudRegion(base.TestCase):
|
||||||
|
|
||||||
def test_arbitrary_attributes(self):
|
def test_arbitrary_attributes(self):
|
||||||
cc = cloud_region.CloudRegion("test1", "region-al", fake_config_dict)
|
cc = cloud_region.CloudRegion("test1", "region-al", fake_config_dict)
|
||||||
self.assertEqual("test1", cc.name)
|
self.assertEqual("test1", cc.name)
|
||||||
@ -89,12 +88,10 @@ class TestCloudRegion(base.TestCase):
|
|||||||
self.assertIsNone(cc._get_config('nothing', None))
|
self.assertIsNone(cc._get_config('nothing', None))
|
||||||
# This is what is happening behind the scenes in get_default_interface.
|
# This is what is happening behind the scenes in get_default_interface.
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
fake_services_dict['interface'],
|
fake_services_dict['interface'], cc._get_config('interface', None)
|
||||||
cc._get_config('interface', None))
|
)
|
||||||
# The same call as above, but from one step up the stack
|
# The same call as above, but from one step up the stack
|
||||||
self.assertEqual(
|
self.assertEqual(fake_services_dict['interface'], cc.get_interface())
|
||||||
fake_services_dict['interface'],
|
|
||||||
cc.get_interface())
|
|
||||||
# Which finally is what is called to populate the below
|
# Which finally is what is called to populate the below
|
||||||
self.assertEqual('public', self.cloud.default_interface)
|
self.assertEqual('public', self.cloud.default_interface)
|
||||||
|
|
||||||
@ -150,16 +147,21 @@ class TestCloudRegion(base.TestCase):
|
|||||||
|
|
||||||
def test_ipv6(self):
|
def test_ipv6(self):
|
||||||
cc = cloud_region.CloudRegion(
|
cc = cloud_region.CloudRegion(
|
||||||
"test1", "region-al", fake_config_dict, force_ipv4=True)
|
"test1", "region-al", fake_config_dict, force_ipv4=True
|
||||||
|
)
|
||||||
self.assertTrue(cc.force_ipv4)
|
self.assertTrue(cc.force_ipv4)
|
||||||
|
|
||||||
def test_getters(self):
|
def test_getters(self):
|
||||||
cc = cloud_region.CloudRegion("test1", "region-al", fake_services_dict)
|
cc = cloud_region.CloudRegion("test1", "region-al", fake_services_dict)
|
||||||
|
|
||||||
self.assertEqual(['compute', 'identity', 'image', 'volume'],
|
self.assertEqual(
|
||||||
sorted(cc.get_services()))
|
['compute', 'identity', 'image', 'volume'],
|
||||||
self.assertEqual({'password': 'hunter2', 'username': 'AzureDiamond'},
|
sorted(cc.get_services()),
|
||||||
cc.get_auth_args())
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
{'password': 'hunter2', 'username': 'AzureDiamond'},
|
||||||
|
cc.get_auth_args(),
|
||||||
|
)
|
||||||
self.assertEqual('public', cc.get_interface())
|
self.assertEqual('public', cc.get_interface())
|
||||||
self.assertEqual('public', cc.get_interface('compute'))
|
self.assertEqual('public', cc.get_interface('compute'))
|
||||||
self.assertEqual('admin', cc.get_interface('identity'))
|
self.assertEqual('admin', cc.get_interface('identity'))
|
||||||
@ -170,8 +172,9 @@ class TestCloudRegion(base.TestCase):
|
|||||||
self.assertEqual('compute', cc.get_service_type('compute'))
|
self.assertEqual('compute', cc.get_service_type('compute'))
|
||||||
self.assertEqual('1', cc.get_api_version('volume'))
|
self.assertEqual('1', cc.get_api_version('volume'))
|
||||||
self.assertEqual('block-storage', cc.get_service_type('volume'))
|
self.assertEqual('block-storage', cc.get_service_type('volume'))
|
||||||
self.assertEqual('http://compute.example.com',
|
self.assertEqual(
|
||||||
cc.get_endpoint('compute'))
|
'http://compute.example.com', cc.get_endpoint('compute')
|
||||||
|
)
|
||||||
self.assertIsNone(cc.get_endpoint('image'))
|
self.assertIsNone(cc.get_endpoint('image'))
|
||||||
self.assertIsNone(cc.get_service_name('compute'))
|
self.assertIsNone(cc.get_service_name('compute'))
|
||||||
self.assertEqual('locks', cc.get_service_name('identity'))
|
self.assertEqual('locks', cc.get_service_name('identity'))
|
||||||
@ -184,38 +187,45 @@ class TestCloudRegion(base.TestCase):
|
|||||||
# We're skipping loader here, so we have to expand relevant
|
# We're skipping loader here, so we have to expand relevant
|
||||||
# parts from the rackspace profile. The thing we're testing
|
# parts from the rackspace profile. The thing we're testing
|
||||||
# is that the project_id logic works.
|
# is that the project_id logic works.
|
||||||
cc = cloud_region.CloudRegion("test1", "DFW", {
|
cc = cloud_region.CloudRegion(
|
||||||
'profile': 'rackspace',
|
"test1",
|
||||||
'region_name': 'DFW',
|
"DFW",
|
||||||
'auth': {'project_id': '123456'},
|
{
|
||||||
'block_storage_endpoint_override': 'https://example.com/v2/',
|
'profile': 'rackspace',
|
||||||
})
|
'region_name': 'DFW',
|
||||||
|
'auth': {'project_id': '123456'},
|
||||||
|
'block_storage_endpoint_override': 'https://example.com/v2/',
|
||||||
|
},
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'https://example.com/v2/123456',
|
'https://example.com/v2/123456', cc.get_endpoint('block-storage')
|
||||||
cc.get_endpoint('block-storage')
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_rackspace_workaround_only_rax(self):
|
def test_rackspace_workaround_only_rax(self):
|
||||||
cc = cloud_region.CloudRegion("test1", "DFW", {
|
cc = cloud_region.CloudRegion(
|
||||||
'region_name': 'DFW',
|
"test1",
|
||||||
'auth': {'project_id': '123456'},
|
"DFW",
|
||||||
'block_storage_endpoint_override': 'https://example.com/v2/',
|
{
|
||||||
})
|
'region_name': 'DFW',
|
||||||
|
'auth': {'project_id': '123456'},
|
||||||
|
'block_storage_endpoint_override': 'https://example.com/v2/',
|
||||||
|
},
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'https://example.com/v2/',
|
'https://example.com/v2/', cc.get_endpoint('block-storage')
|
||||||
cc.get_endpoint('block-storage')
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_region_name(self):
|
def test_get_region_name(self):
|
||||||
|
|
||||||
def assert_region_name(default, compute):
|
def assert_region_name(default, compute):
|
||||||
self.assertEqual(default, cc.region_name)
|
self.assertEqual(default, cc.region_name)
|
||||||
self.assertEqual(default, cc.get_region_name())
|
self.assertEqual(default, cc.get_region_name())
|
||||||
self.assertEqual(default, cc.get_region_name(service_type=None))
|
self.assertEqual(default, cc.get_region_name(service_type=None))
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
compute, cc.get_region_name(service_type='compute'))
|
compute, cc.get_region_name(service_type='compute')
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
default, cc.get_region_name(service_type='placement'))
|
default, cc.get_region_name(service_type='placement')
|
||||||
|
)
|
||||||
|
|
||||||
# No region_name kwarg, no regions specified in services dict
|
# No region_name kwarg, no regions specified in services dict
|
||||||
# (including the default).
|
# (including the default).
|
||||||
@ -224,14 +234,17 @@ class TestCloudRegion(base.TestCase):
|
|||||||
|
|
||||||
# Only region_name kwarg; it's returned for everything
|
# Only region_name kwarg; it's returned for everything
|
||||||
cc = cloud_region.CloudRegion(
|
cc = cloud_region.CloudRegion(
|
||||||
region_name='foo', config=fake_services_dict)
|
region_name='foo', config=fake_services_dict
|
||||||
|
)
|
||||||
assert_region_name('foo', 'foo')
|
assert_region_name('foo', 'foo')
|
||||||
|
|
||||||
# No region_name kwarg; values (including default) show through from
|
# No region_name kwarg; values (including default) show through from
|
||||||
# config dict
|
# config dict
|
||||||
services_dict = dict(
|
services_dict = dict(
|
||||||
fake_services_dict,
|
fake_services_dict,
|
||||||
region_name='the-default', compute_region_name='compute-region')
|
region_name='the-default',
|
||||||
|
compute_region_name='compute-region',
|
||||||
|
)
|
||||||
cc = cloud_region.CloudRegion(config=services_dict)
|
cc = cloud_region.CloudRegion(config=services_dict)
|
||||||
assert_region_name('the-default', 'compute-region')
|
assert_region_name('the-default', 'compute-region')
|
||||||
|
|
||||||
@ -239,9 +252,12 @@ class TestCloudRegion(base.TestCase):
|
|||||||
# compatibility), but service-specific region_name takes precedence.
|
# compatibility), but service-specific region_name takes precedence.
|
||||||
services_dict = dict(
|
services_dict = dict(
|
||||||
fake_services_dict,
|
fake_services_dict,
|
||||||
region_name='dict', compute_region_name='compute-region')
|
region_name='dict',
|
||||||
|
compute_region_name='compute-region',
|
||||||
|
)
|
||||||
cc = cloud_region.CloudRegion(
|
cc = cloud_region.CloudRegion(
|
||||||
region_name='kwarg', config=services_dict)
|
region_name='kwarg', config=services_dict
|
||||||
|
)
|
||||||
assert_region_name('kwarg', 'compute-region')
|
assert_region_name('kwarg', 'compute-region')
|
||||||
|
|
||||||
def test_aliases(self):
|
def test_aliases(self):
|
||||||
@ -265,9 +281,7 @@ class TestCloudRegion(base.TestCase):
|
|||||||
config_dict = defaults.get_defaults()
|
config_dict = defaults.get_defaults()
|
||||||
config_dict.update(fake_services_dict)
|
config_dict.update(fake_services_dict)
|
||||||
cc = cloud_region.CloudRegion("test1", "region-al", config_dict)
|
cc = cloud_region.CloudRegion("test1", "region-al", config_dict)
|
||||||
self.assertRaises(
|
self.assertRaises(exceptions.ConfigException, cc.get_session)
|
||||||
exceptions.ConfigException,
|
|
||||||
cc.get_session)
|
|
||||||
|
|
||||||
@mock.patch.object(ksa_session, 'Session')
|
@mock.patch.object(ksa_session, 'Session')
|
||||||
def test_get_session(self, mock_session):
|
def test_get_session(self, mock_session):
|
||||||
@ -277,15 +291,21 @@ class TestCloudRegion(base.TestCase):
|
|||||||
fake_session.additional_user_agent = []
|
fake_session.additional_user_agent = []
|
||||||
mock_session.return_value = fake_session
|
mock_session.return_value = fake_session
|
||||||
cc = cloud_region.CloudRegion(
|
cc = cloud_region.CloudRegion(
|
||||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock())
|
"test1", "region-al", config_dict, auth_plugin=mock.Mock()
|
||||||
|
)
|
||||||
cc.get_session()
|
cc.get_session()
|
||||||
mock_session.assert_called_with(
|
mock_session.assert_called_with(
|
||||||
auth=mock.ANY,
|
auth=mock.ANY,
|
||||||
verify=True, cert=None, timeout=None, collect_timing=None,
|
verify=True,
|
||||||
discovery_cache=None)
|
cert=None,
|
||||||
|
timeout=None,
|
||||||
|
collect_timing=None,
|
||||||
|
discovery_cache=None,
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
fake_session.additional_user_agent,
|
fake_session.additional_user_agent,
|
||||||
[('openstacksdk', openstack_version.__version__)])
|
[('openstacksdk', openstack_version.__version__)],
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(ksa_session, 'Session')
|
@mock.patch.object(ksa_session, 'Session')
|
||||||
def test_get_session_with_app_name(self, mock_session):
|
def test_get_session_with_app_name(self, mock_session):
|
||||||
@ -297,18 +317,28 @@ class TestCloudRegion(base.TestCase):
|
|||||||
fake_session.app_version = None
|
fake_session.app_version = None
|
||||||
mock_session.return_value = fake_session
|
mock_session.return_value = fake_session
|
||||||
cc = cloud_region.CloudRegion(
|
cc = cloud_region.CloudRegion(
|
||||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock(),
|
"test1",
|
||||||
app_name="test_app", app_version="test_version")
|
"region-al",
|
||||||
|
config_dict,
|
||||||
|
auth_plugin=mock.Mock(),
|
||||||
|
app_name="test_app",
|
||||||
|
app_version="test_version",
|
||||||
|
)
|
||||||
cc.get_session()
|
cc.get_session()
|
||||||
mock_session.assert_called_with(
|
mock_session.assert_called_with(
|
||||||
auth=mock.ANY,
|
auth=mock.ANY,
|
||||||
verify=True, cert=None, timeout=None, collect_timing=None,
|
verify=True,
|
||||||
discovery_cache=None)
|
cert=None,
|
||||||
|
timeout=None,
|
||||||
|
collect_timing=None,
|
||||||
|
discovery_cache=None,
|
||||||
|
)
|
||||||
self.assertEqual(fake_session.app_name, "test_app")
|
self.assertEqual(fake_session.app_name, "test_app")
|
||||||
self.assertEqual(fake_session.app_version, "test_version")
|
self.assertEqual(fake_session.app_version, "test_version")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
fake_session.additional_user_agent,
|
fake_session.additional_user_agent,
|
||||||
[('openstacksdk', openstack_version.__version__)])
|
[('openstacksdk', openstack_version.__version__)],
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(ksa_session, 'Session')
|
@mock.patch.object(ksa_session, 'Session')
|
||||||
def test_get_session_with_timeout(self, mock_session):
|
def test_get_session_with_timeout(self, mock_session):
|
||||||
@ -319,15 +349,21 @@ class TestCloudRegion(base.TestCase):
|
|||||||
config_dict.update(fake_services_dict)
|
config_dict.update(fake_services_dict)
|
||||||
config_dict['api_timeout'] = 9
|
config_dict['api_timeout'] = 9
|
||||||
cc = cloud_region.CloudRegion(
|
cc = cloud_region.CloudRegion(
|
||||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock())
|
"test1", "region-al", config_dict, auth_plugin=mock.Mock()
|
||||||
|
)
|
||||||
cc.get_session()
|
cc.get_session()
|
||||||
mock_session.assert_called_with(
|
mock_session.assert_called_with(
|
||||||
auth=mock.ANY,
|
auth=mock.ANY,
|
||||||
verify=True, cert=None, timeout=9,
|
verify=True,
|
||||||
collect_timing=None, discovery_cache=None)
|
cert=None,
|
||||||
|
timeout=9,
|
||||||
|
collect_timing=None,
|
||||||
|
discovery_cache=None,
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
fake_session.additional_user_agent,
|
fake_session.additional_user_agent,
|
||||||
[('openstacksdk', openstack_version.__version__)])
|
[('openstacksdk', openstack_version.__version__)],
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(ksa_session, 'Session')
|
@mock.patch.object(ksa_session, 'Session')
|
||||||
def test_get_session_with_timing(self, mock_session):
|
def test_get_session_with_timing(self, mock_session):
|
||||||
@ -338,35 +374,45 @@ class TestCloudRegion(base.TestCase):
|
|||||||
config_dict.update(fake_services_dict)
|
config_dict.update(fake_services_dict)
|
||||||
config_dict['timing'] = True
|
config_dict['timing'] = True
|
||||||
cc = cloud_region.CloudRegion(
|
cc = cloud_region.CloudRegion(
|
||||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock())
|
"test1", "region-al", config_dict, auth_plugin=mock.Mock()
|
||||||
|
)
|
||||||
cc.get_session()
|
cc.get_session()
|
||||||
mock_session.assert_called_with(
|
mock_session.assert_called_with(
|
||||||
auth=mock.ANY,
|
auth=mock.ANY,
|
||||||
verify=True, cert=None, timeout=None,
|
verify=True,
|
||||||
collect_timing=True, discovery_cache=None)
|
cert=None,
|
||||||
|
timeout=None,
|
||||||
|
collect_timing=True,
|
||||||
|
discovery_cache=None,
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
fake_session.additional_user_agent,
|
fake_session.additional_user_agent,
|
||||||
[('openstacksdk', openstack_version.__version__)])
|
[('openstacksdk', openstack_version.__version__)],
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(ksa_session, 'Session')
|
@mock.patch.object(ksa_session, 'Session')
|
||||||
def test_override_session_endpoint_override(self, mock_session):
|
def test_override_session_endpoint_override(self, mock_session):
|
||||||
config_dict = defaults.get_defaults()
|
config_dict = defaults.get_defaults()
|
||||||
config_dict.update(fake_services_dict)
|
config_dict.update(fake_services_dict)
|
||||||
cc = cloud_region.CloudRegion(
|
cc = cloud_region.CloudRegion(
|
||||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock())
|
"test1", "region-al", config_dict, auth_plugin=mock.Mock()
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
cc.get_session_endpoint('compute'),
|
cc.get_session_endpoint('compute'),
|
||||||
fake_services_dict['compute_endpoint_override'])
|
fake_services_dict['compute_endpoint_override'],
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(ksa_session, 'Session')
|
@mock.patch.object(ksa_session, 'Session')
|
||||||
def test_override_session_endpoint(self, mock_session):
|
def test_override_session_endpoint(self, mock_session):
|
||||||
config_dict = defaults.get_defaults()
|
config_dict = defaults.get_defaults()
|
||||||
config_dict.update(fake_services_dict)
|
config_dict.update(fake_services_dict)
|
||||||
cc = cloud_region.CloudRegion(
|
cc = cloud_region.CloudRegion(
|
||||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock())
|
"test1", "region-al", config_dict, auth_plugin=mock.Mock()
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
cc.get_session_endpoint('telemetry'),
|
cc.get_session_endpoint('telemetry'),
|
||||||
fake_services_dict['telemetry_endpoint'])
|
fake_services_dict['telemetry_endpoint'],
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session')
|
@mock.patch.object(cloud_region.CloudRegion, 'get_session')
|
||||||
def test_session_endpoint(self, mock_get_session):
|
def test_session_endpoint(self, mock_get_session):
|
||||||
@ -375,20 +421,23 @@ class TestCloudRegion(base.TestCase):
|
|||||||
config_dict = defaults.get_defaults()
|
config_dict = defaults.get_defaults()
|
||||||
config_dict.update(fake_services_dict)
|
config_dict.update(fake_services_dict)
|
||||||
cc = cloud_region.CloudRegion(
|
cc = cloud_region.CloudRegion(
|
||||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock())
|
"test1", "region-al", config_dict, auth_plugin=mock.Mock()
|
||||||
|
)
|
||||||
cc.get_session_endpoint('orchestration')
|
cc.get_session_endpoint('orchestration')
|
||||||
mock_session.get_endpoint.assert_called_with(
|
mock_session.get_endpoint.assert_called_with(
|
||||||
interface='public',
|
interface='public',
|
||||||
service_name=None,
|
service_name=None,
|
||||||
region_name='region-al',
|
region_name='region-al',
|
||||||
service_type='orchestration')
|
service_type='orchestration',
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session')
|
@mock.patch.object(cloud_region.CloudRegion, 'get_session')
|
||||||
def test_session_endpoint_not_found(self, mock_get_session):
|
def test_session_endpoint_not_found(self, mock_get_session):
|
||||||
exc_to_raise = ksa_exceptions.catalog.EndpointNotFound
|
exc_to_raise = ksa_exceptions.catalog.EndpointNotFound
|
||||||
mock_get_session.return_value.get_endpoint.side_effect = exc_to_raise
|
mock_get_session.return_value.get_endpoint.side_effect = exc_to_raise
|
||||||
cc = cloud_region.CloudRegion(
|
cc = cloud_region.CloudRegion(
|
||||||
"test1", "region-al", {}, auth_plugin=mock.Mock())
|
"test1", "region-al", {}, auth_plugin=mock.Mock()
|
||||||
|
)
|
||||||
self.assertIsNone(cc.get_session_endpoint('notfound'))
|
self.assertIsNone(cc.get_session_endpoint('notfound'))
|
||||||
|
|
||||||
def test_get_endpoint_from_catalog(self):
|
def test_get_endpoint_from_catalog(self):
|
||||||
@ -396,14 +445,20 @@ class TestCloudRegion(base.TestCase):
|
|||||||
self.cloud.config.config['dns_endpoint_override'] = dns_override
|
self.cloud.config.config['dns_endpoint_override'] = dns_override
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'https://compute.example.com/v2.1/',
|
'https://compute.example.com/v2.1/',
|
||||||
self.cloud.config.get_endpoint_from_catalog('compute'))
|
self.cloud.config.get_endpoint_from_catalog('compute'),
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'https://internal.compute.example.com/v2.1/',
|
'https://internal.compute.example.com/v2.1/',
|
||||||
self.cloud.config.get_endpoint_from_catalog(
|
self.cloud.config.get_endpoint_from_catalog(
|
||||||
'compute', interface='internal'))
|
'compute', interface='internal'
|
||||||
|
),
|
||||||
|
)
|
||||||
self.assertIsNone(
|
self.assertIsNone(
|
||||||
self.cloud.config.get_endpoint_from_catalog(
|
self.cloud.config.get_endpoint_from_catalog(
|
||||||
'compute', region_name='unknown-region'))
|
'compute', region_name='unknown-region'
|
||||||
|
)
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'https://dns.example.com',
|
'https://dns.example.com',
|
||||||
self.cloud.config.get_endpoint_from_catalog('dns'))
|
self.cloud.config.get_endpoint_from_catalog('dns'),
|
||||||
|
)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -21,52 +21,64 @@ from openstack.tests.unit.config import base
|
|||||||
|
|
||||||
|
|
||||||
class TestEnviron(base.TestCase):
|
class TestEnviron(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestEnviron, self).setUp()
|
super(TestEnviron, self).setUp()
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('OS_AUTH_URL', 'https://example.com'))
|
fixtures.EnvironmentVariable('OS_AUTH_URL', 'https://example.com')
|
||||||
|
)
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('OS_USERNAME', 'testuser'))
|
fixtures.EnvironmentVariable('OS_USERNAME', 'testuser')
|
||||||
|
)
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('OS_PASSWORD', 'testpass'))
|
fixtures.EnvironmentVariable('OS_PASSWORD', 'testpass')
|
||||||
|
)
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('OS_PROJECT_NAME', 'testproject'))
|
fixtures.EnvironmentVariable('OS_PROJECT_NAME', 'testproject')
|
||||||
|
)
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('NOVA_PROJECT_ID', 'testnova'))
|
fixtures.EnvironmentVariable('NOVA_PROJECT_ID', 'testnova')
|
||||||
|
)
|
||||||
|
|
||||||
def test_get_one(self):
|
def test_get_one(self):
|
||||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
c = config.OpenStackConfig(
|
||||||
vendor_files=[self.vendor_yaml])
|
config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]
|
||||||
|
)
|
||||||
self.assertIsInstance(c.get_one(), cloud_region.CloudRegion)
|
self.assertIsInstance(c.get_one(), cloud_region.CloudRegion)
|
||||||
|
|
||||||
def test_no_fallthrough(self):
|
def test_no_fallthrough(self):
|
||||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
c = config.OpenStackConfig(
|
||||||
vendor_files=[self.vendor_yaml])
|
config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]
|
||||||
self.assertRaises(
|
)
|
||||||
exceptions.ConfigException, c.get_one, 'openstack')
|
self.assertRaises(exceptions.ConfigException, c.get_one, 'openstack')
|
||||||
|
|
||||||
def test_envvar_name_override(self):
|
def test_envvar_name_override(self):
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('OS_CLOUD_NAME', 'override'))
|
fixtures.EnvironmentVariable('OS_CLOUD_NAME', 'override')
|
||||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
)
|
||||||
vendor_files=[self.vendor_yaml])
|
c = config.OpenStackConfig(
|
||||||
|
config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]
|
||||||
|
)
|
||||||
cc = c.get_one('override')
|
cc = c.get_one('override')
|
||||||
self._assert_cloud_details(cc)
|
self._assert_cloud_details(cc)
|
||||||
|
|
||||||
def test_envvar_prefer_ipv6_override(self):
|
def test_envvar_prefer_ipv6_override(self):
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('OS_PREFER_IPV6', 'false'))
|
fixtures.EnvironmentVariable('OS_PREFER_IPV6', 'false')
|
||||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
)
|
||||||
vendor_files=[self.vendor_yaml],
|
c = config.OpenStackConfig(
|
||||||
secure_files=[self.secure_yaml])
|
config_files=[self.cloud_yaml],
|
||||||
|
vendor_files=[self.vendor_yaml],
|
||||||
|
secure_files=[self.secure_yaml],
|
||||||
|
)
|
||||||
cc = c.get_one('_test-cloud_')
|
cc = c.get_one('_test-cloud_')
|
||||||
self.assertFalse(cc.prefer_ipv6)
|
self.assertFalse(cc.prefer_ipv6)
|
||||||
|
|
||||||
def test_environ_exists(self):
|
def test_environ_exists(self):
|
||||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
c = config.OpenStackConfig(
|
||||||
vendor_files=[self.vendor_yaml],
|
config_files=[self.cloud_yaml],
|
||||||
secure_files=[self.secure_yaml])
|
vendor_files=[self.vendor_yaml],
|
||||||
|
secure_files=[self.secure_yaml],
|
||||||
|
)
|
||||||
cc = c.get_one('envvars')
|
cc = c.get_one('envvars')
|
||||||
self._assert_cloud_details(cc)
|
self._assert_cloud_details(cc)
|
||||||
self.assertNotIn('auth_url', cc.config)
|
self.assertNotIn('auth_url', cc.config)
|
||||||
@ -79,10 +91,12 @@ class TestEnviron(base.TestCase):
|
|||||||
self._assert_cloud_details(cc)
|
self._assert_cloud_details(cc)
|
||||||
|
|
||||||
def test_environ_prefix(self):
|
def test_environ_prefix(self):
|
||||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
c = config.OpenStackConfig(
|
||||||
vendor_files=[self.vendor_yaml],
|
config_files=[self.cloud_yaml],
|
||||||
envvar_prefix='NOVA_',
|
vendor_files=[self.vendor_yaml],
|
||||||
secure_files=[self.secure_yaml])
|
envvar_prefix='NOVA_',
|
||||||
|
secure_files=[self.secure_yaml],
|
||||||
|
)
|
||||||
cc = c.get_one('envvars')
|
cc = c.get_one('envvars')
|
||||||
self._assert_cloud_details(cc)
|
self._assert_cloud_details(cc)
|
||||||
self.assertNotIn('auth_url', cc.config)
|
self.assertNotIn('auth_url', cc.config)
|
||||||
@ -95,9 +109,11 @@ class TestEnviron(base.TestCase):
|
|||||||
self._assert_cloud_details(cc)
|
self._assert_cloud_details(cc)
|
||||||
|
|
||||||
def test_get_one_with_config_files(self):
|
def test_get_one_with_config_files(self):
|
||||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
c = config.OpenStackConfig(
|
||||||
vendor_files=[self.vendor_yaml],
|
config_files=[self.cloud_yaml],
|
||||||
secure_files=[self.secure_yaml])
|
vendor_files=[self.vendor_yaml],
|
||||||
|
secure_files=[self.secure_yaml],
|
||||||
|
)
|
||||||
self.assertIsInstance(c.cloud_config, dict)
|
self.assertIsInstance(c.cloud_config, dict)
|
||||||
self.assertIn('cache', c.cloud_config)
|
self.assertIn('cache', c.cloud_config)
|
||||||
self.assertIsInstance(c.cloud_config['cache'], dict)
|
self.assertIsInstance(c.cloud_config['cache'], dict)
|
||||||
@ -111,40 +127,40 @@ class TestEnviron(base.TestCase):
|
|||||||
def test_config_file_override(self):
|
def test_config_file_override(self):
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable(
|
fixtures.EnvironmentVariable(
|
||||||
'OS_CLIENT_CONFIG_FILE', self.cloud_yaml))
|
'OS_CLIENT_CONFIG_FILE', self.cloud_yaml
|
||||||
c = config.OpenStackConfig(config_files=[],
|
)
|
||||||
vendor_files=[self.vendor_yaml])
|
)
|
||||||
|
c = config.OpenStackConfig(
|
||||||
|
config_files=[], vendor_files=[self.vendor_yaml]
|
||||||
|
)
|
||||||
cc = c.get_one('_test-cloud_')
|
cc = c.get_one('_test-cloud_')
|
||||||
self._assert_cloud_details(cc)
|
self._assert_cloud_details(cc)
|
||||||
|
|
||||||
|
|
||||||
class TestEnvvars(base.TestCase):
|
class TestEnvvars(base.TestCase):
|
||||||
|
|
||||||
def test_no_envvars(self):
|
def test_no_envvars(self):
|
||||||
self.useFixture(
|
self.useFixture(fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||||
fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
c = config.OpenStackConfig(
|
||||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]
|
||||||
vendor_files=[self.vendor_yaml])
|
)
|
||||||
self.assertRaises(
|
self.assertRaises(exceptions.ConfigException, c.get_one, 'envvars')
|
||||||
exceptions.ConfigException, c.get_one, 'envvars')
|
|
||||||
|
|
||||||
def test_test_envvars(self):
|
def test_test_envvars(self):
|
||||||
|
self.useFixture(fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
fixtures.EnvironmentVariable('OS_STDERR_CAPTURE', 'True')
|
||||||
self.useFixture(
|
)
|
||||||
fixtures.EnvironmentVariable('OS_STDERR_CAPTURE', 'True'))
|
c = config.OpenStackConfig(
|
||||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]
|
||||||
vendor_files=[self.vendor_yaml])
|
)
|
||||||
self.assertRaises(
|
self.assertRaises(exceptions.ConfigException, c.get_one, 'envvars')
|
||||||
exceptions.ConfigException, c.get_one, 'envvars')
|
|
||||||
|
|
||||||
def test_incomplete_envvars(self):
|
def test_incomplete_envvars(self):
|
||||||
self.useFixture(
|
self.useFixture(fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||||
fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
self.useFixture(fixtures.EnvironmentVariable('OS_USERNAME', 'user'))
|
||||||
self.useFixture(
|
config.OpenStackConfig(
|
||||||
fixtures.EnvironmentVariable('OS_USERNAME', 'user'))
|
config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]
|
||||||
config.OpenStackConfig(config_files=[self.cloud_yaml],
|
)
|
||||||
vendor_files=[self.vendor_yaml])
|
|
||||||
# This is broken due to an issue that's fixed in a subsequent patch
|
# This is broken due to an issue that's fixed in a subsequent patch
|
||||||
# commenting it out in this patch to keep the patch size reasonable
|
# commenting it out in this patch to keep the patch size reasonable
|
||||||
# self.assertRaises(
|
# self.assertRaises(
|
||||||
@ -152,33 +168,38 @@ class TestEnvvars(base.TestCase):
|
|||||||
# c.get_one, 'envvars')
|
# c.get_one, 'envvars')
|
||||||
|
|
||||||
def test_have_envvars(self):
|
def test_have_envvars(self):
|
||||||
|
self.useFixture(fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
fixtures.EnvironmentVariable('OS_AUTH_URL', 'http://example.com')
|
||||||
|
)
|
||||||
|
self.useFixture(fixtures.EnvironmentVariable('OS_USERNAME', 'user'))
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('OS_AUTH_URL', 'http://example.com'))
|
fixtures.EnvironmentVariable('OS_PASSWORD', 'password')
|
||||||
|
)
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('OS_USERNAME', 'user'))
|
fixtures.EnvironmentVariable('OS_PROJECT_NAME', 'project')
|
||||||
self.useFixture(
|
)
|
||||||
fixtures.EnvironmentVariable('OS_PASSWORD', 'password'))
|
c = config.OpenStackConfig(
|
||||||
self.useFixture(
|
config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]
|
||||||
fixtures.EnvironmentVariable('OS_PROJECT_NAME', 'project'))
|
)
|
||||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
|
||||||
vendor_files=[self.vendor_yaml])
|
|
||||||
cc = c.get_one('envvars')
|
cc = c.get_one('envvars')
|
||||||
self.assertEqual(cc.config['auth']['username'], 'user')
|
self.assertEqual(cc.config['auth']['username'], 'user')
|
||||||
|
|
||||||
def test_old_envvars(self):
|
def test_old_envvars(self):
|
||||||
|
self.useFixture(fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
fixtures.EnvironmentVariable('NOVA_AUTH_URL', 'http://example.com')
|
||||||
|
)
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable(
|
fixtures.EnvironmentVariable('NOVA_PASSWORD', 'password')
|
||||||
'NOVA_AUTH_URL', 'http://example.com'))
|
)
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('NOVA_PASSWORD', 'password'))
|
fixtures.EnvironmentVariable('NOVA_PROJECT_NAME', 'project')
|
||||||
self.useFixture(
|
)
|
||||||
fixtures.EnvironmentVariable('NOVA_PROJECT_NAME', 'project'))
|
c = config.OpenStackConfig(
|
||||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
config_files=[self.cloud_yaml],
|
||||||
vendor_files=[self.vendor_yaml],
|
vendor_files=[self.vendor_yaml],
|
||||||
envvar_prefix='NOVA_')
|
envvar_prefix='NOVA_',
|
||||||
|
)
|
||||||
cc = c.get_one('envvars')
|
cc = c.get_one('envvars')
|
||||||
self.assertEqual(cc.config['auth']['username'], 'nova')
|
self.assertEqual(cc.config['auth']['username'], 'nova')
|
||||||
|
@ -23,13 +23,15 @@ from openstack.tests.unit import base
|
|||||||
|
|
||||||
|
|
||||||
class TestFromConf(base.TestCase):
|
class TestFromConf(base.TestCase):
|
||||||
|
|
||||||
def _get_conn(self, **from_conf_kwargs):
|
def _get_conn(self, **from_conf_kwargs):
|
||||||
oslocfg = self._load_ks_cfg_opts()
|
oslocfg = self._load_ks_cfg_opts()
|
||||||
# Throw name in here to prove **kwargs is working
|
# Throw name in here to prove **kwargs is working
|
||||||
config = cloud_region.from_conf(
|
config = cloud_region.from_conf(
|
||||||
oslocfg, session=self.cloud.session, name='from_conf.example.com',
|
oslocfg,
|
||||||
**from_conf_kwargs)
|
session=self.cloud.session,
|
||||||
|
name='from_conf.example.com',
|
||||||
|
**from_conf_kwargs
|
||||||
|
)
|
||||||
self.assertEqual('from_conf.example.com', config.name)
|
self.assertEqual('from_conf.example.com', config.name)
|
||||||
|
|
||||||
return connection.Connection(config=config, strict_proxies=True)
|
return connection.Connection(config=config, strict_proxies=True)
|
||||||
@ -41,33 +43,48 @@ class TestFromConf(base.TestCase):
|
|||||||
discovery = {
|
discovery = {
|
||||||
"versions": {
|
"versions": {
|
||||||
"values": [
|
"values": [
|
||||||
{"status": "stable",
|
{
|
||||||
"updated": "2019-06-01T00:00:00Z",
|
"status": "stable",
|
||||||
"media-types": [{
|
"updated": "2019-06-01T00:00:00Z",
|
||||||
"base": "application/json",
|
"media-types": [
|
||||||
"type": "application/vnd.openstack.heat-v2+json"}],
|
{
|
||||||
"id": "v2.0",
|
"base": "application/json",
|
||||||
"links": [{
|
"type": "application/vnd.openstack.heat-v2+json", # noqa: E501
|
||||||
"href": "https://example.org:8888/heat/v2",
|
}
|
||||||
"rel": "self"}]
|
],
|
||||||
}]
|
"id": "v2.0",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "https://example.org:8888/heat/v2",
|
||||||
|
"rel": "self",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET',
|
[
|
||||||
uri='https://example.org:8888/heat/v2',
|
dict(
|
||||||
json=discovery),
|
method='GET',
|
||||||
dict(method='GET',
|
uri='https://example.org:8888/heat/v2',
|
||||||
uri='https://example.org:8888/heat/v2/foo',
|
json=discovery,
|
||||||
json={'foo': {}}),
|
),
|
||||||
])
|
dict(
|
||||||
|
method='GET',
|
||||||
|
uri='https://example.org:8888/heat/v2/foo',
|
||||||
|
json={'foo': {}},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
adap = conn.orchestration
|
adap = conn.orchestration
|
||||||
self.assertEqual('SpecialRegion', adap.region_name)
|
self.assertEqual('SpecialRegion', adap.region_name)
|
||||||
self.assertEqual('orchestration', adap.service_type)
|
self.assertEqual('orchestration', adap.service_type)
|
||||||
self.assertEqual('internal', adap.interface)
|
self.assertEqual('internal', adap.interface)
|
||||||
self.assertEqual('https://example.org:8888/heat/v2',
|
self.assertEqual(
|
||||||
adap.endpoint_override)
|
'https://example.org:8888/heat/v2', adap.endpoint_override
|
||||||
|
)
|
||||||
|
|
||||||
adap.get('/foo')
|
adap.get('/foo')
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
@ -80,13 +97,18 @@ class TestFromConf(base.TestCase):
|
|||||||
server_name = self.getUniqueString('name')
|
server_name = self.getUniqueString('name')
|
||||||
fake_server = fakes.make_fake_server(server_id, server_name)
|
fake_server = fakes.make_fake_server(server_id, server_name)
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
self.get_nova_discovery_mock_dict(),
|
[
|
||||||
dict(method='GET',
|
self.get_nova_discovery_mock_dict(),
|
||||||
uri=self.get_mock_url(
|
dict(
|
||||||
'compute', 'public', append=['servers', 'detail']),
|
method='GET',
|
||||||
json={'servers': [fake_server]}),
|
uri=self.get_mock_url(
|
||||||
])
|
'compute', 'public', append=['servers', 'detail']
|
||||||
|
),
|
||||||
|
json={'servers': [fake_server]},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# Nova has empty adapter config, so these default
|
# Nova has empty adapter config, so these default
|
||||||
adap = conn.compute
|
adap = conn.compute
|
||||||
@ -108,20 +130,27 @@ class TestFromConf(base.TestCase):
|
|||||||
server_name = self.getUniqueString('name')
|
server_name = self.getUniqueString('name')
|
||||||
fake_server = fakes.make_fake_server(server_id, server_name)
|
fake_server = fakes.make_fake_server(server_id, server_name)
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET',
|
[
|
||||||
uri='https://compute.example.com/v2.1/',
|
dict(
|
||||||
exc=requests.exceptions.ConnectionError),
|
method='GET',
|
||||||
self.get_nova_discovery_mock_dict(),
|
uri='https://compute.example.com/v2.1/',
|
||||||
dict(method='GET',
|
exc=requests.exceptions.ConnectionError,
|
||||||
uri=self.get_mock_url(
|
),
|
||||||
'compute', 'public', append=['servers', 'detail']),
|
self.get_nova_discovery_mock_dict(),
|
||||||
json={'servers': [fake_server]}),
|
dict(
|
||||||
])
|
method='GET',
|
||||||
|
uri=self.get_mock_url(
|
||||||
|
'compute', 'public', append=['servers', 'detail']
|
||||||
|
),
|
||||||
|
json={'servers': [fake_server]},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exceptions.ServiceDiscoveryException,
|
exceptions.ServiceDiscoveryException, getattr, conn, 'compute'
|
||||||
getattr, conn, 'compute')
|
)
|
||||||
|
|
||||||
# Nova has empty adapter config, so these default
|
# Nova has empty adapter config, so these default
|
||||||
adap = conn.compute
|
adap = conn.compute
|
||||||
@ -141,31 +170,41 @@ class TestFromConf(base.TestCase):
|
|||||||
discovery = {
|
discovery = {
|
||||||
"versions": {
|
"versions": {
|
||||||
"values": [
|
"values": [
|
||||||
{"status": "stable",
|
{
|
||||||
"id": "v1",
|
"status": "stable",
|
||||||
"links": [{
|
"id": "v1",
|
||||||
"href": "https://example.org:5050/v1",
|
"links": [
|
||||||
"rel": "self"}]
|
{
|
||||||
}]
|
"href": "https://example.org:5050/v1",
|
||||||
|
"rel": "self",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = {
|
status = {'finished': True, 'error': None}
|
||||||
'finished': True,
|
self.register_uris(
|
||||||
'error': None
|
[
|
||||||
}
|
dict(
|
||||||
self.register_uris([
|
method='GET',
|
||||||
dict(method='GET',
|
uri='https://example.org:5050',
|
||||||
uri='https://example.org:5050',
|
json=discovery,
|
||||||
json=discovery),
|
),
|
||||||
# strict-proxies means we're going to fetch the discovery
|
# strict-proxies means we're going to fetch the discovery
|
||||||
# doc from the versioned endpoint to verify it works.
|
# doc from the versioned endpoint to verify it works.
|
||||||
dict(method='GET',
|
dict(
|
||||||
uri='https://example.org:5050/v1',
|
method='GET',
|
||||||
json=discovery),
|
uri='https://example.org:5050/v1',
|
||||||
dict(method='GET',
|
json=discovery,
|
||||||
uri='https://example.org:5050/v1/introspection/abcd',
|
),
|
||||||
json=status),
|
dict(
|
||||||
])
|
method='GET',
|
||||||
|
uri='https://example.org:5050/v1/introspection/abcd',
|
||||||
|
json=status,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
adap = conn.baremetal_introspection
|
adap = conn.baremetal_introspection
|
||||||
self.assertEqual('baremetal-introspection', adap.service_type)
|
self.assertEqual('baremetal-introspection', adap.service_type)
|
||||||
@ -180,38 +219,53 @@ class TestFromConf(base.TestCase):
|
|||||||
discovery = {
|
discovery = {
|
||||||
"versions": {
|
"versions": {
|
||||||
"values": [
|
"values": [
|
||||||
{"status": "stable",
|
{
|
||||||
"id": "v1",
|
"status": "stable",
|
||||||
"links": [{
|
"id": "v1",
|
||||||
"href": "https://example.org:5050/v1",
|
"links": [
|
||||||
"rel": "self"}]
|
{
|
||||||
}]
|
"href": "https://example.org:5050/v1",
|
||||||
|
"rel": "self",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = {
|
status = {'finished': True, 'error': None}
|
||||||
'finished': True,
|
self.register_uris(
|
||||||
'error': None
|
[
|
||||||
}
|
dict(
|
||||||
self.register_uris([
|
method='GET',
|
||||||
dict(method='GET',
|
uri='https://example.org:5050',
|
||||||
uri='https://example.org:5050',
|
exc=requests.exceptions.ConnectTimeout,
|
||||||
exc=requests.exceptions.ConnectTimeout),
|
),
|
||||||
dict(method='GET',
|
dict(
|
||||||
uri='https://example.org:5050',
|
method='GET',
|
||||||
json=discovery),
|
uri='https://example.org:5050',
|
||||||
# strict-proxies means we're going to fetch the discovery
|
json=discovery,
|
||||||
# doc from the versioned endpoint to verify it works.
|
),
|
||||||
dict(method='GET',
|
# strict-proxies means we're going to fetch the discovery
|
||||||
uri='https://example.org:5050/v1',
|
# doc from the versioned endpoint to verify it works.
|
||||||
json=discovery),
|
dict(
|
||||||
dict(method='GET',
|
method='GET',
|
||||||
uri='https://example.org:5050/v1/introspection/abcd',
|
uri='https://example.org:5050/v1',
|
||||||
json=status),
|
json=discovery,
|
||||||
])
|
),
|
||||||
|
dict(
|
||||||
|
method='GET',
|
||||||
|
uri='https://example.org:5050/v1/introspection/abcd',
|
||||||
|
json=status,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exceptions.ServiceDiscoveryException,
|
exceptions.ServiceDiscoveryException,
|
||||||
getattr, conn, 'baremetal_introspection')
|
getattr,
|
||||||
|
conn,
|
||||||
|
'baremetal_introspection',
|
||||||
|
)
|
||||||
|
|
||||||
adap = conn.baremetal_introspection
|
adap = conn.baremetal_introspection
|
||||||
self.assertEqual('baremetal-introspection', adap.service_type)
|
self.assertEqual('baremetal-introspection', adap.service_type)
|
||||||
@ -220,16 +274,21 @@ class TestFromConf(base.TestCase):
|
|||||||
|
|
||||||
self.assertTrue(adap.get_introspection('abcd').is_finished)
|
self.assertTrue(adap.get_introspection('abcd').is_finished)
|
||||||
|
|
||||||
def assert_service_disabled(self, service_type, expected_reason,
|
def assert_service_disabled(
|
||||||
**from_conf_kwargs):
|
self, service_type, expected_reason, **from_conf_kwargs
|
||||||
|
):
|
||||||
conn = self._get_conn(**from_conf_kwargs)
|
conn = self._get_conn(**from_conf_kwargs)
|
||||||
# The _ServiceDisabledProxyShim loads up okay...
|
# The _ServiceDisabledProxyShim loads up okay...
|
||||||
adap = getattr(conn, service_type)
|
adap = getattr(conn, service_type)
|
||||||
# ...but freaks out if you try to use it.
|
# ...but freaks out if you try to use it.
|
||||||
ex = self.assertRaises(
|
ex = self.assertRaises(
|
||||||
exceptions.ServiceDisabledException, getattr, adap, 'get')
|
exceptions.ServiceDisabledException, getattr, adap, 'get'
|
||||||
self.assertIn("Service '%s' is disabled because its configuration "
|
)
|
||||||
"could not be loaded." % service_type, ex.message)
|
self.assertIn(
|
||||||
|
"Service '%s' is disabled because its configuration "
|
||||||
|
"could not be loaded." % service_type,
|
||||||
|
ex.message,
|
||||||
|
)
|
||||||
self.assertIn(expected_reason, ex.message)
|
self.assertIn(expected_reason, ex.message)
|
||||||
|
|
||||||
def test_no_such_conf_section(self):
|
def test_no_such_conf_section(self):
|
||||||
@ -238,15 +297,18 @@ class TestFromConf(base.TestCase):
|
|||||||
self.assert_service_disabled(
|
self.assert_service_disabled(
|
||||||
'orchestration',
|
'orchestration',
|
||||||
"No section for project 'heat' (service type 'orchestration') was "
|
"No section for project 'heat' (service type 'orchestration') was "
|
||||||
"present in the config.")
|
"present in the config.",
|
||||||
|
)
|
||||||
|
|
||||||
def test_no_such_conf_section_ignore_service_type(self):
|
def test_no_such_conf_section_ignore_service_type(self):
|
||||||
"""Ignore absent conf section if service type not requested."""
|
"""Ignore absent conf section if service type not requested."""
|
||||||
del self.oslo_config_dict['heat']
|
del self.oslo_config_dict['heat']
|
||||||
self.assert_service_disabled(
|
self.assert_service_disabled(
|
||||||
'orchestration', "Not in the list of requested service_types.",
|
'orchestration',
|
||||||
|
"Not in the list of requested service_types.",
|
||||||
# 'orchestration' absent from this list
|
# 'orchestration' absent from this list
|
||||||
service_types=['compute'])
|
service_types=['compute'],
|
||||||
|
)
|
||||||
|
|
||||||
def test_no_adapter_opts(self):
|
def test_no_adapter_opts(self):
|
||||||
"""Conf section present, but opts for service type not registered."""
|
"""Conf section present, but opts for service type not registered."""
|
||||||
@ -254,15 +316,18 @@ class TestFromConf(base.TestCase):
|
|||||||
self.assert_service_disabled(
|
self.assert_service_disabled(
|
||||||
'orchestration',
|
'orchestration',
|
||||||
"Encountered an exception attempting to process config for "
|
"Encountered an exception attempting to process config for "
|
||||||
"project 'heat' (service type 'orchestration'): no such option")
|
"project 'heat' (service type 'orchestration'): no such option",
|
||||||
|
)
|
||||||
|
|
||||||
def test_no_adapter_opts_ignore_service_type(self):
|
def test_no_adapter_opts_ignore_service_type(self):
|
||||||
"""Ignore unregistered conf section if service type not requested."""
|
"""Ignore unregistered conf section if service type not requested."""
|
||||||
self.oslo_config_dict['heat'] = None
|
self.oslo_config_dict['heat'] = None
|
||||||
self.assert_service_disabled(
|
self.assert_service_disabled(
|
||||||
'orchestration', "Not in the list of requested service_types.",
|
'orchestration',
|
||||||
|
"Not in the list of requested service_types.",
|
||||||
# 'orchestration' absent from this list
|
# 'orchestration' absent from this list
|
||||||
service_types=['compute'])
|
service_types=['compute'],
|
||||||
|
)
|
||||||
|
|
||||||
def test_invalid_adapter_opts(self):
|
def test_invalid_adapter_opts(self):
|
||||||
"""Adapter opts are bogus, in exception-raising ways."""
|
"""Adapter opts are bogus, in exception-raising ways."""
|
||||||
@ -274,24 +339,31 @@ class TestFromConf(base.TestCase):
|
|||||||
'orchestration',
|
'orchestration',
|
||||||
"Encountered an exception attempting to process config for "
|
"Encountered an exception attempting to process config for "
|
||||||
"project 'heat' (service type 'orchestration'): interface and "
|
"project 'heat' (service type 'orchestration'): interface and "
|
||||||
"valid_interfaces are mutually exclusive.")
|
"valid_interfaces are mutually exclusive.",
|
||||||
|
)
|
||||||
|
|
||||||
def test_no_session(self):
|
def test_no_session(self):
|
||||||
# TODO(efried): Currently calling without a Session is not implemented.
|
# TODO(efried): Currently calling without a Session is not implemented.
|
||||||
self.assertRaises(exceptions.ConfigException,
|
self.assertRaises(
|
||||||
cloud_region.from_conf, self._load_ks_cfg_opts())
|
exceptions.ConfigException,
|
||||||
|
cloud_region.from_conf,
|
||||||
|
self._load_ks_cfg_opts(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_no_endpoint(self):
|
def test_no_endpoint(self):
|
||||||
"""Conf contains adapter opts, but service type not in catalog."""
|
"""Conf contains adapter opts, but service type not in catalog."""
|
||||||
self.os_fixture.v3_token.remove_service('monitoring')
|
self.os_fixture.v3_token.remove_service('monitoring')
|
||||||
conn = self._get_conn()
|
conn = self._get_conn()
|
||||||
# Monasca is not in the service catalog
|
# Monasca is not in the service catalog
|
||||||
self.assertRaises(ks_exc.catalog.EndpointNotFound,
|
self.assertRaises(
|
||||||
getattr, conn, 'monitoring')
|
ks_exc.catalog.EndpointNotFound, getattr, conn, 'monitoring'
|
||||||
|
)
|
||||||
|
|
||||||
def test_no_endpoint_ignore_service_type(self):
|
def test_no_endpoint_ignore_service_type(self):
|
||||||
"""Bogus service type disabled if not in requested service_types."""
|
"""Bogus service type disabled if not in requested service_types."""
|
||||||
self.assert_service_disabled(
|
self.assert_service_disabled(
|
||||||
'monitoring', "Not in the list of requested service_types.",
|
'monitoring',
|
||||||
|
"Not in the list of requested service_types.",
|
||||||
# 'monitoring' absent from this list
|
# 'monitoring' absent from this list
|
||||||
service_types={'compute', 'orchestration', 'bogus'})
|
service_types={'compute', 'orchestration', 'bogus'},
|
||||||
|
)
|
||||||
|
@ -30,7 +30,8 @@ class TestFromSession(base.TestCase):
|
|||||||
|
|
||||||
def test_from_session(self):
|
def test_from_session(self):
|
||||||
config = cloud_region.from_session(
|
config = cloud_region.from_session(
|
||||||
self.cloud.session, region_name=self.test_region)
|
self.cloud.session, region_name=self.test_region
|
||||||
|
)
|
||||||
self.assertEqual(config.name, 'identity.example.com')
|
self.assertEqual(config.name, 'identity.example.com')
|
||||||
if not self.test_region:
|
if not self.test_region:
|
||||||
self.assertIsNone(config.region_name)
|
self.assertIsNone(config.region_name)
|
||||||
@ -40,13 +41,18 @@ class TestFromSession(base.TestCase):
|
|||||||
server_id = str(uuid.uuid4())
|
server_id = str(uuid.uuid4())
|
||||||
server_name = self.getUniqueString('name')
|
server_name = self.getUniqueString('name')
|
||||||
fake_server = fakes.make_fake_server(server_id, server_name)
|
fake_server = fakes.make_fake_server(server_id, server_name)
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
self.get_nova_discovery_mock_dict(),
|
[
|
||||||
dict(method='GET',
|
self.get_nova_discovery_mock_dict(),
|
||||||
uri=self.get_mock_url(
|
dict(
|
||||||
'compute', 'public', append=['servers', 'detail']),
|
method='GET',
|
||||||
json={'servers': [fake_server]}),
|
uri=self.get_mock_url(
|
||||||
])
|
'compute', 'public', append=['servers', 'detail']
|
||||||
|
),
|
||||||
|
json={'servers': [fake_server]},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
conn = connection.Connection(config=config)
|
conn = connection.Connection(config=config)
|
||||||
s = next(conn.compute.servers())
|
s = next(conn.compute.servers())
|
||||||
|
@ -19,17 +19,16 @@ from openstack.tests.unit.config import base
|
|||||||
class TestInit(base.TestCase):
|
class TestInit(base.TestCase):
|
||||||
def test_get_cloud_region_without_arg_parser(self):
|
def test_get_cloud_region_without_arg_parser(self):
|
||||||
cloud_region = openstack.config.get_cloud_region(
|
cloud_region = openstack.config.get_cloud_region(
|
||||||
options=None, validate=False)
|
options=None, validate=False
|
||||||
|
)
|
||||||
self.assertIsInstance(
|
self.assertIsInstance(
|
||||||
cloud_region,
|
cloud_region, openstack.config.cloud_region.CloudRegion
|
||||||
openstack.config.cloud_region.CloudRegion
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_cloud_region_with_arg_parser(self):
|
def test_get_cloud_region_with_arg_parser(self):
|
||||||
cloud_region = openstack.config.get_cloud_region(
|
cloud_region = openstack.config.get_cloud_region(
|
||||||
options=argparse.ArgumentParser(),
|
options=argparse.ArgumentParser(), validate=False
|
||||||
validate=False)
|
)
|
||||||
self.assertIsInstance(
|
self.assertIsInstance(
|
||||||
cloud_region,
|
cloud_region, openstack.config.cloud_region.CloudRegion
|
||||||
openstack.config.cloud_region.CloudRegion
|
|
||||||
)
|
)
|
||||||
|
@ -24,7 +24,6 @@ from openstack.tests.unit.config import base
|
|||||||
|
|
||||||
|
|
||||||
class TestConfig(base.TestCase):
|
class TestConfig(base.TestCase):
|
||||||
|
|
||||||
def json_diagnostics(self, exc_info):
|
def json_diagnostics(self, exc_info):
|
||||||
self.addDetail('filename', content.text_content(self.filename))
|
self.addDetail('filename', content.text_content(self.filename))
|
||||||
for error in sorted(self.validator.iter_errors(self.json_data)):
|
for error in sorted(self.validator.iter_errors(self.json_data)):
|
||||||
@ -32,8 +31,8 @@ class TestConfig(base.TestCase):
|
|||||||
|
|
||||||
def test_defaults_valid_json(self):
|
def test_defaults_valid_json(self):
|
||||||
_schema_path = os.path.join(
|
_schema_path = os.path.join(
|
||||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
os.path.dirname(os.path.realpath(defaults.__file__)), 'schema.json'
|
||||||
'schema.json')
|
)
|
||||||
with open(_schema_path, 'r') as f:
|
with open(_schema_path, 'r') as f:
|
||||||
schema = json.load(f)
|
schema = json.load(f)
|
||||||
self.validator = jsonschema.Draft4Validator(schema)
|
self.validator = jsonschema.Draft4Validator(schema)
|
||||||
@ -41,7 +40,8 @@ class TestConfig(base.TestCase):
|
|||||||
|
|
||||||
self.filename = os.path.join(
|
self.filename = os.path.join(
|
||||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
os.path.dirname(os.path.realpath(defaults.__file__)),
|
||||||
'defaults.json')
|
'defaults.json',
|
||||||
|
)
|
||||||
with open(self.filename, 'r') as f:
|
with open(self.filename, 'r') as f:
|
||||||
self.json_data = json.load(f)
|
self.json_data = json.load(f)
|
||||||
|
|
||||||
@ -50,7 +50,8 @@ class TestConfig(base.TestCase):
|
|||||||
def test_vendors_valid_json(self):
|
def test_vendors_valid_json(self):
|
||||||
_schema_path = os.path.join(
|
_schema_path = os.path.join(
|
||||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
os.path.dirname(os.path.realpath(defaults.__file__)),
|
||||||
'vendor-schema.json')
|
'vendor-schema.json',
|
||||||
|
)
|
||||||
with open(_schema_path, 'r') as f:
|
with open(_schema_path, 'r') as f:
|
||||||
schema = json.load(f)
|
schema = json.load(f)
|
||||||
self.validator = jsonschema.Draft4Validator(schema)
|
self.validator = jsonschema.Draft4Validator(schema)
|
||||||
@ -58,8 +59,8 @@ class TestConfig(base.TestCase):
|
|||||||
self.addOnException(self.json_diagnostics)
|
self.addOnException(self.json_diagnostics)
|
||||||
|
|
||||||
_vendors_path = os.path.join(
|
_vendors_path = os.path.join(
|
||||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
os.path.dirname(os.path.realpath(defaults.__file__)), 'vendors'
|
||||||
'vendors')
|
)
|
||||||
for self.filename in glob.glob(os.path.join(_vendors_path, '*.json')):
|
for self.filename in glob.glob(os.path.join(_vendors_path, '*.json')):
|
||||||
with open(self.filename, 'r') as f:
|
with open(self.filename, 'r') as f:
|
||||||
self.json_data = json.load(f)
|
self.json_data = json.load(f)
|
||||||
|
@ -21,14 +21,17 @@ from openstack import exceptions
|
|||||||
from openstack.tests.unit.config import base
|
from openstack.tests.unit.config import base
|
||||||
|
|
||||||
FILES = {
|
FILES = {
|
||||||
'yaml': textwrap.dedent('''
|
'yaml': textwrap.dedent(
|
||||||
|
'''
|
||||||
foo: bar
|
foo: bar
|
||||||
baz:
|
baz:
|
||||||
- 1
|
- 1
|
||||||
- 2
|
- 2
|
||||||
- 3
|
- 3
|
||||||
'''),
|
'''
|
||||||
'json': textwrap.dedent('''
|
),
|
||||||
|
'json': textwrap.dedent(
|
||||||
|
'''
|
||||||
{
|
{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
"baz": [
|
"baz": [
|
||||||
@ -37,18 +40,20 @@ FILES = {
|
|||||||
3
|
3
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
'''),
|
'''
|
||||||
'txt': textwrap.dedent('''
|
),
|
||||||
|
'txt': textwrap.dedent(
|
||||||
|
'''
|
||||||
foo
|
foo
|
||||||
bar baz
|
bar baz
|
||||||
test
|
test
|
||||||
one two
|
one two
|
||||||
'''),
|
'''
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class TestLoader(base.TestCase):
|
class TestLoader(base.TestCase):
|
||||||
|
|
||||||
def test_base_load_yaml_json_file(self):
|
def test_base_load_yaml_json_file(self):
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
tested_files = []
|
tested_files = []
|
||||||
@ -59,7 +64,8 @@ class TestLoader(base.TestCase):
|
|||||||
tested_files.append(fn)
|
tested_files.append(fn)
|
||||||
|
|
||||||
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
||||||
tested_files)
|
tested_files
|
||||||
|
)
|
||||||
# NOTE(hberaud): Prefer to test path rather than file because
|
# NOTE(hberaud): Prefer to test path rather than file because
|
||||||
# our FILES var is a dict so results are appened
|
# our FILES var is a dict so results are appened
|
||||||
# without keeping the initial order (python 3.5)
|
# without keeping the initial order (python 3.5)
|
||||||
@ -77,7 +83,8 @@ class TestLoader(base.TestCase):
|
|||||||
tested_files.append(fn)
|
tested_files.append(fn)
|
||||||
|
|
||||||
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
||||||
tested_files)
|
tested_files
|
||||||
|
)
|
||||||
# NOTE(hberaud): Prefer to test path rather than file because
|
# NOTE(hberaud): Prefer to test path rather than file because
|
||||||
# our FILES var is a dict so results are appened
|
# our FILES var is a dict so results are appened
|
||||||
# without keeping the initial order (python 3.5)
|
# without keeping the initial order (python 3.5)
|
||||||
@ -92,7 +99,8 @@ class TestLoader(base.TestCase):
|
|||||||
tested_files.append(fn)
|
tested_files.append(fn)
|
||||||
|
|
||||||
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
||||||
tested_files)
|
tested_files
|
||||||
|
)
|
||||||
self.assertEqual(fn, path)
|
self.assertEqual(fn, path)
|
||||||
|
|
||||||
def test__load_yaml_json_file_without_perm(self):
|
def test__load_yaml_json_file_without_perm(self):
|
||||||
@ -105,7 +113,8 @@ class TestLoader(base.TestCase):
|
|||||||
tested_files.append(fn)
|
tested_files.append(fn)
|
||||||
|
|
||||||
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
||||||
tested_files)
|
tested_files
|
||||||
|
)
|
||||||
self.assertEqual(None, path)
|
self.assertEqual(None, path)
|
||||||
|
|
||||||
def test__load_yaml_json_file_nonexisting(self):
|
def test__load_yaml_json_file_nonexisting(self):
|
||||||
@ -114,28 +123,56 @@ class TestLoader(base.TestCase):
|
|||||||
tested_files.append(fn)
|
tested_files.append(fn)
|
||||||
|
|
||||||
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
||||||
tested_files)
|
tested_files
|
||||||
|
)
|
||||||
self.assertEqual(None, path)
|
self.assertEqual(None, path)
|
||||||
|
|
||||||
|
|
||||||
class TestFixArgv(base.TestCase):
|
class TestFixArgv(base.TestCase):
|
||||||
def test_no_changes(self):
|
def test_no_changes(self):
|
||||||
argv = ['-a', '-b', '--long-arg', '--multi-value', 'key1=value1',
|
argv = [
|
||||||
'--multi-value', 'key2=value2']
|
'-a',
|
||||||
|
'-b',
|
||||||
|
'--long-arg',
|
||||||
|
'--multi-value',
|
||||||
|
'key1=value1',
|
||||||
|
'--multi-value',
|
||||||
|
'key2=value2',
|
||||||
|
]
|
||||||
expected = argv[:]
|
expected = argv[:]
|
||||||
loader._fix_argv(argv)
|
loader._fix_argv(argv)
|
||||||
self.assertEqual(expected, argv)
|
self.assertEqual(expected, argv)
|
||||||
|
|
||||||
def test_replace(self):
|
def test_replace(self):
|
||||||
argv = ['-a', '-b', '--long-arg', '--multi_value', 'key1=value1',
|
argv = [
|
||||||
'--multi_value', 'key2=value2']
|
'-a',
|
||||||
expected = ['-a', '-b', '--long-arg', '--multi-value', 'key1=value1',
|
'-b',
|
||||||
'--multi-value', 'key2=value2']
|
'--long-arg',
|
||||||
|
'--multi_value',
|
||||||
|
'key1=value1',
|
||||||
|
'--multi_value',
|
||||||
|
'key2=value2',
|
||||||
|
]
|
||||||
|
expected = [
|
||||||
|
'-a',
|
||||||
|
'-b',
|
||||||
|
'--long-arg',
|
||||||
|
'--multi-value',
|
||||||
|
'key1=value1',
|
||||||
|
'--multi-value',
|
||||||
|
'key2=value2',
|
||||||
|
]
|
||||||
loader._fix_argv(argv)
|
loader._fix_argv(argv)
|
||||||
self.assertEqual(expected, argv)
|
self.assertEqual(expected, argv)
|
||||||
|
|
||||||
def test_mix(self):
|
def test_mix(self):
|
||||||
argv = ['-a', '-b', '--long-arg', '--multi_value', 'key1=value1',
|
argv = [
|
||||||
'--multi-value', 'key2=value2']
|
'-a',
|
||||||
self.assertRaises(exceptions.ConfigException,
|
'-b',
|
||||||
loader._fix_argv, argv)
|
'--long-arg',
|
||||||
|
'--multi_value',
|
||||||
|
'key1=value1',
|
||||||
|
'--multi-value',
|
||||||
|
'key2=value2',
|
||||||
|
]
|
||||||
|
self.assertRaises(exceptions.ConfigException, loader._fix_argv, argv)
|
||||||
|
@ -70,9 +70,13 @@ clouds:
|
|||||||
password: {password}
|
password: {password}
|
||||||
project_name: {project}
|
project_name: {project}
|
||||||
cacert: {cacert}
|
cacert: {cacert}
|
||||||
""".format(auth_url=CONFIG_AUTH_URL, username=CONFIG_USERNAME,
|
""".format(
|
||||||
password=CONFIG_PASSWORD, project=CONFIG_PROJECT,
|
auth_url=CONFIG_AUTH_URL,
|
||||||
cacert=CONFIG_CACERT)
|
username=CONFIG_USERNAME,
|
||||||
|
password=CONFIG_PASSWORD,
|
||||||
|
project=CONFIG_PROJECT,
|
||||||
|
cacert=CONFIG_CACERT,
|
||||||
|
)
|
||||||
|
|
||||||
VENDOR_CONFIG = """
|
VENDOR_CONFIG = """
|
||||||
{{
|
{{
|
||||||
@ -84,7 +88,9 @@ VENDOR_CONFIG = """
|
|||||||
"vendor_hook": "openstack.tests.unit.test_connection:vendor_hook"
|
"vendor_hook": "openstack.tests.unit.test_connection:vendor_hook"
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
""".format(auth_url=CONFIG_AUTH_URL)
|
""".format(
|
||||||
|
auth_url=CONFIG_AUTH_URL
|
||||||
|
)
|
||||||
|
|
||||||
PUBLIC_CLOUDS_YAML = """
|
PUBLIC_CLOUDS_YAML = """
|
||||||
public-clouds:
|
public-clouds:
|
||||||
@ -92,11 +98,12 @@ public-clouds:
|
|||||||
auth:
|
auth:
|
||||||
auth_url: {auth_url}
|
auth_url: {auth_url}
|
||||||
vendor_hook: openstack.tests.unit.test_connection:vendor_hook
|
vendor_hook: openstack.tests.unit.test_connection:vendor_hook
|
||||||
""".format(auth_url=CONFIG_AUTH_URL)
|
""".format(
|
||||||
|
auth_url=CONFIG_AUTH_URL
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class _TestConnectionBase(base.TestCase):
|
class _TestConnectionBase(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(_TestConnectionBase, self).setUp()
|
super(_TestConnectionBase, self).setUp()
|
||||||
# Create a temporary directory where our test config will live
|
# Create a temporary directory where our test config will live
|
||||||
@ -107,8 +114,9 @@ class _TestConnectionBase(base.TestCase):
|
|||||||
with open(config_path, "w") as conf:
|
with open(config_path, "w") as conf:
|
||||||
conf.write(CLOUD_CONFIG)
|
conf.write(CLOUD_CONFIG)
|
||||||
|
|
||||||
self.useFixture(fixtures.EnvironmentVariable(
|
self.useFixture(
|
||||||
"OS_CLIENT_CONFIG_FILE", config_path))
|
fixtures.EnvironmentVariable("OS_CLIENT_CONFIG_FILE", config_path)
|
||||||
|
)
|
||||||
self.use_keystone_v2()
|
self.use_keystone_v2()
|
||||||
|
|
||||||
|
|
||||||
@ -152,104 +160,127 @@ class TestConnection(_TestConnectionBase):
|
|||||||
# conn.workflow.__class__.__module__)
|
# conn.workflow.__class__.__module__)
|
||||||
|
|
||||||
def test_create_unknown_proxy(self):
|
def test_create_unknown_proxy(self):
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
self.get_placement_discovery_mock_dict(),
|
[
|
||||||
])
|
self.get_placement_discovery_mock_dict(),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
def closure():
|
def closure():
|
||||||
return self.cloud.placement
|
return self.cloud.placement
|
||||||
|
|
||||||
self.assertThat(
|
self.assertThat(closure, matchers.Warnings(matchers.HasLength(0)))
|
||||||
closure,
|
|
||||||
matchers.Warnings(matchers.HasLength(0)))
|
|
||||||
|
|
||||||
self.assertIsInstance(
|
self.assertIsInstance(self.cloud.placement, proxy.Proxy)
|
||||||
self.cloud.placement,
|
|
||||||
proxy.Proxy)
|
|
||||||
|
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
|
|
||||||
def test_create_connection_version_param_default(self):
|
def test_create_connection_version_param_default(self):
|
||||||
c1 = connection.Connection(cloud='sample-cloud')
|
c1 = connection.Connection(cloud='sample-cloud')
|
||||||
conn = connection.Connection(session=c1.session)
|
conn = connection.Connection(session=c1.session)
|
||||||
self.assertEqual('openstack.identity.v3._proxy',
|
self.assertEqual(
|
||||||
conn.identity.__class__.__module__)
|
'openstack.identity.v3._proxy', conn.identity.__class__.__module__
|
||||||
|
)
|
||||||
|
|
||||||
def test_create_connection_version_param_string(self):
|
def test_create_connection_version_param_string(self):
|
||||||
c1 = connection.Connection(cloud='sample-cloud')
|
c1 = connection.Connection(cloud='sample-cloud')
|
||||||
conn = connection.Connection(
|
conn = connection.Connection(
|
||||||
session=c1.session, identity_api_version='2')
|
session=c1.session, identity_api_version='2'
|
||||||
self.assertEqual('openstack.identity.v2._proxy',
|
)
|
||||||
conn.identity.__class__.__module__)
|
self.assertEqual(
|
||||||
|
'openstack.identity.v2._proxy', conn.identity.__class__.__module__
|
||||||
|
)
|
||||||
|
|
||||||
def test_create_connection_version_param_int(self):
|
def test_create_connection_version_param_int(self):
|
||||||
c1 = connection.Connection(cloud='sample-cloud')
|
c1 = connection.Connection(cloud='sample-cloud')
|
||||||
conn = connection.Connection(
|
conn = connection.Connection(
|
||||||
session=c1.session, identity_api_version=3)
|
session=c1.session, identity_api_version=3
|
||||||
self.assertEqual('openstack.identity.v3._proxy',
|
)
|
||||||
conn.identity.__class__.__module__)
|
self.assertEqual(
|
||||||
|
'openstack.identity.v3._proxy', conn.identity.__class__.__module__
|
||||||
|
)
|
||||||
|
|
||||||
def test_create_connection_version_param_bogus(self):
|
def test_create_connection_version_param_bogus(self):
|
||||||
c1 = connection.Connection(cloud='sample-cloud')
|
c1 = connection.Connection(cloud='sample-cloud')
|
||||||
conn = connection.Connection(
|
conn = connection.Connection(
|
||||||
session=c1.session, identity_api_version='red')
|
session=c1.session, identity_api_version='red'
|
||||||
|
)
|
||||||
# TODO(mordred) This is obviously silly behavior
|
# TODO(mordred) This is obviously silly behavior
|
||||||
self.assertEqual('openstack.identity.v3._proxy',
|
self.assertEqual(
|
||||||
conn.identity.__class__.__module__)
|
'openstack.identity.v3._proxy', conn.identity.__class__.__module__
|
||||||
|
)
|
||||||
|
|
||||||
def test_from_config_given_config(self):
|
def test_from_config_given_config(self):
|
||||||
cloud_region = (openstack.config.OpenStackConfig().
|
cloud_region = openstack.config.OpenStackConfig().get_one(
|
||||||
get_one("sample-cloud"))
|
"sample-cloud"
|
||||||
|
)
|
||||||
|
|
||||||
sot = connection.from_config(config=cloud_region)
|
sot = connection.from_config(config=cloud_region)
|
||||||
|
|
||||||
self.assertEqual(CONFIG_USERNAME,
|
self.assertEqual(
|
||||||
sot.config.config['auth']['username'])
|
CONFIG_USERNAME, sot.config.config['auth']['username']
|
||||||
self.assertEqual(CONFIG_PASSWORD,
|
)
|
||||||
sot.config.config['auth']['password'])
|
self.assertEqual(
|
||||||
self.assertEqual(CONFIG_AUTH_URL,
|
CONFIG_PASSWORD, sot.config.config['auth']['password']
|
||||||
sot.config.config['auth']['auth_url'])
|
)
|
||||||
self.assertEqual(CONFIG_PROJECT,
|
self.assertEqual(
|
||||||
sot.config.config['auth']['project_name'])
|
CONFIG_AUTH_URL, sot.config.config['auth']['auth_url']
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
CONFIG_PROJECT, sot.config.config['auth']['project_name']
|
||||||
|
)
|
||||||
|
|
||||||
def test_from_config_given_cloud(self):
|
def test_from_config_given_cloud(self):
|
||||||
sot = connection.from_config(cloud="sample-cloud")
|
sot = connection.from_config(cloud="sample-cloud")
|
||||||
|
|
||||||
self.assertEqual(CONFIG_USERNAME,
|
self.assertEqual(
|
||||||
sot.config.config['auth']['username'])
|
CONFIG_USERNAME, sot.config.config['auth']['username']
|
||||||
self.assertEqual(CONFIG_PASSWORD,
|
)
|
||||||
sot.config.config['auth']['password'])
|
self.assertEqual(
|
||||||
self.assertEqual(CONFIG_AUTH_URL,
|
CONFIG_PASSWORD, sot.config.config['auth']['password']
|
||||||
sot.config.config['auth']['auth_url'])
|
)
|
||||||
self.assertEqual(CONFIG_PROJECT,
|
self.assertEqual(
|
||||||
sot.config.config['auth']['project_name'])
|
CONFIG_AUTH_URL, sot.config.config['auth']['auth_url']
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
CONFIG_PROJECT, sot.config.config['auth']['project_name']
|
||||||
|
)
|
||||||
|
|
||||||
def test_from_config_given_cloud_config(self):
|
def test_from_config_given_cloud_config(self):
|
||||||
cloud_region = (openstack.config.OpenStackConfig().
|
cloud_region = openstack.config.OpenStackConfig().get_one(
|
||||||
get_one("sample-cloud"))
|
"sample-cloud"
|
||||||
|
)
|
||||||
|
|
||||||
sot = connection.from_config(cloud_config=cloud_region)
|
sot = connection.from_config(cloud_config=cloud_region)
|
||||||
|
|
||||||
self.assertEqual(CONFIG_USERNAME,
|
self.assertEqual(
|
||||||
sot.config.config['auth']['username'])
|
CONFIG_USERNAME, sot.config.config['auth']['username']
|
||||||
self.assertEqual(CONFIG_PASSWORD,
|
)
|
||||||
sot.config.config['auth']['password'])
|
self.assertEqual(
|
||||||
self.assertEqual(CONFIG_AUTH_URL,
|
CONFIG_PASSWORD, sot.config.config['auth']['password']
|
||||||
sot.config.config['auth']['auth_url'])
|
)
|
||||||
self.assertEqual(CONFIG_PROJECT,
|
self.assertEqual(
|
||||||
sot.config.config['auth']['project_name'])
|
CONFIG_AUTH_URL, sot.config.config['auth']['auth_url']
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
CONFIG_PROJECT, sot.config.config['auth']['project_name']
|
||||||
|
)
|
||||||
|
|
||||||
def test_from_config_given_cloud_name(self):
|
def test_from_config_given_cloud_name(self):
|
||||||
sot = connection.from_config(cloud_name="sample-cloud")
|
sot = connection.from_config(cloud_name="sample-cloud")
|
||||||
|
|
||||||
self.assertEqual(CONFIG_USERNAME,
|
self.assertEqual(
|
||||||
sot.config.config['auth']['username'])
|
CONFIG_USERNAME, sot.config.config['auth']['username']
|
||||||
self.assertEqual(CONFIG_PASSWORD,
|
)
|
||||||
sot.config.config['auth']['password'])
|
self.assertEqual(
|
||||||
self.assertEqual(CONFIG_AUTH_URL,
|
CONFIG_PASSWORD, sot.config.config['auth']['password']
|
||||||
sot.config.config['auth']['auth_url'])
|
)
|
||||||
self.assertEqual(CONFIG_PROJECT,
|
self.assertEqual(
|
||||||
sot.config.config['auth']['project_name'])
|
CONFIG_AUTH_URL, sot.config.config['auth']['auth_url']
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
CONFIG_PROJECT, sot.config.config['auth']['project_name']
|
||||||
|
)
|
||||||
|
|
||||||
def test_from_config_verify(self):
|
def test_from_config_verify(self):
|
||||||
sot = connection.from_config(cloud="insecure-cloud")
|
sot = connection.from_config(cloud="insecure-cloud")
|
||||||
@ -268,25 +299,32 @@ class TestOsloConfig(_TestConnectionBase):
|
|||||||
def test_from_conf(self):
|
def test_from_conf(self):
|
||||||
c1 = connection.Connection(cloud='sample-cloud')
|
c1 = connection.Connection(cloud='sample-cloud')
|
||||||
conn = connection.Connection(
|
conn = connection.Connection(
|
||||||
session=c1.session, oslo_conf=self._load_ks_cfg_opts())
|
session=c1.session, oslo_conf=self._load_ks_cfg_opts()
|
||||||
|
)
|
||||||
# There was no config for keystone
|
# There was no config for keystone
|
||||||
self.assertIsInstance(
|
self.assertIsInstance(
|
||||||
conn.identity, service_description._ServiceDisabledProxyShim)
|
conn.identity, service_description._ServiceDisabledProxyShim
|
||||||
|
)
|
||||||
# But nova was in there
|
# But nova was in there
|
||||||
self.assertEqual('openstack.compute.v2._proxy',
|
self.assertEqual(
|
||||||
conn.compute.__class__.__module__)
|
'openstack.compute.v2._proxy', conn.compute.__class__.__module__
|
||||||
|
)
|
||||||
|
|
||||||
def test_from_conf_filter_service_types(self):
|
def test_from_conf_filter_service_types(self):
|
||||||
c1 = connection.Connection(cloud='sample-cloud')
|
c1 = connection.Connection(cloud='sample-cloud')
|
||||||
conn = connection.Connection(
|
conn = connection.Connection(
|
||||||
session=c1.session, oslo_conf=self._load_ks_cfg_opts(),
|
session=c1.session,
|
||||||
service_types={'orchestration', 'i-am-ignored'})
|
oslo_conf=self._load_ks_cfg_opts(),
|
||||||
|
service_types={'orchestration', 'i-am-ignored'},
|
||||||
|
)
|
||||||
# There was no config for keystone
|
# There was no config for keystone
|
||||||
self.assertIsInstance(
|
self.assertIsInstance(
|
||||||
conn.identity, service_description._ServiceDisabledProxyShim)
|
conn.identity, service_description._ServiceDisabledProxyShim
|
||||||
|
)
|
||||||
# Nova was in there, but disabled because not requested
|
# Nova was in there, but disabled because not requested
|
||||||
self.assertIsInstance(
|
self.assertIsInstance(
|
||||||
conn.compute, service_description._ServiceDisabledProxyShim)
|
conn.compute, service_description._ServiceDisabledProxyShim
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestNetworkConnection(base.TestCase):
|
class TestNetworkConnection(base.TestCase):
|
||||||
@ -298,15 +336,18 @@ class TestNetworkConnection(base.TestCase):
|
|||||||
svc.add_endpoint(
|
svc.add_endpoint(
|
||||||
interface='public',
|
interface='public',
|
||||||
url='https://network.example.com/v2.0',
|
url='https://network.example.com/v2.0',
|
||||||
region='RegionOne')
|
region='RegionOne',
|
||||||
|
)
|
||||||
self.use_keystone_v3()
|
self.use_keystone_v3()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'openstack.network.v2._proxy',
|
'openstack.network.v2._proxy',
|
||||||
self.cloud.network.__class__.__module__)
|
self.cloud.network.__class__.__module__,
|
||||||
|
)
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"https://network.example.com/v2.0",
|
"https://network.example.com/v2.0",
|
||||||
self.cloud.network.get_endpoint())
|
self.cloud.network.get_endpoint(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestNetworkConnectionSuffix(base.TestCase):
|
class TestNetworkConnectionSuffix(base.TestCase):
|
||||||
@ -316,15 +357,16 @@ class TestNetworkConnectionSuffix(base.TestCase):
|
|||||||
def test_network_proxy(self):
|
def test_network_proxy(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'openstack.network.v2._proxy',
|
'openstack.network.v2._proxy',
|
||||||
self.cloud.network.__class__.__module__)
|
self.cloud.network.__class__.__module__,
|
||||||
|
)
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"https://network.example.com/v2.0",
|
"https://network.example.com/v2.0",
|
||||||
self.cloud.network.get_endpoint())
|
self.cloud.network.get_endpoint(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestAuthorize(base.TestCase):
|
class TestAuthorize(base.TestCase):
|
||||||
|
|
||||||
def test_authorize_works(self):
|
def test_authorize_works(self):
|
||||||
res = self.cloud.authorize()
|
res = self.cloud.authorize()
|
||||||
self.assertEqual('KeystoneToken-1', res)
|
self.assertEqual('KeystoneToken-1', res)
|
||||||
@ -332,12 +374,12 @@ class TestAuthorize(base.TestCase):
|
|||||||
def test_authorize_failure(self):
|
def test_authorize_failure(self):
|
||||||
self.use_broken_keystone()
|
self.use_broken_keystone()
|
||||||
|
|
||||||
self.assertRaises(openstack.exceptions.SDKException,
|
self.assertRaises(
|
||||||
self.cloud.authorize)
|
openstack.exceptions.SDKException, self.cloud.authorize
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestNewService(base.TestCase):
|
class TestNewService(base.TestCase):
|
||||||
|
|
||||||
def test_add_service_v1(self):
|
def test_add_service_v1(self):
|
||||||
svc = self.os_fixture.v3_token.add_service('fake')
|
svc = self.os_fixture.v3_token.add_service('fake')
|
||||||
svc.add_endpoint(
|
svc.add_endpoint(
|
||||||
@ -355,21 +397,30 @@ class TestNewService(base.TestCase):
|
|||||||
# Ensure no discovery calls made
|
# Ensure no discovery calls made
|
||||||
self.assertEqual(0, len(self.adapter.request_history))
|
self.assertEqual(0, len(self.adapter.request_history))
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET',
|
[
|
||||||
uri='https://fake.example.com',
|
dict(
|
||||||
status_code=404),
|
method='GET',
|
||||||
dict(method='GET',
|
uri='https://fake.example.com',
|
||||||
uri='https://fake.example.com/v1/',
|
status_code=404,
|
||||||
status_code=404),
|
),
|
||||||
dict(method='GET',
|
dict(
|
||||||
uri=self.get_mock_url('fake'),
|
method='GET',
|
||||||
status_code=404),
|
uri='https://fake.example.com/v1/',
|
||||||
])
|
status_code=404,
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
method='GET',
|
||||||
|
uri=self.get_mock_url('fake'),
|
||||||
|
status_code=404,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'openstack.tests.unit.fake.v1._proxy',
|
'openstack.tests.unit.fake.v1._proxy',
|
||||||
conn.fake.__class__.__module__)
|
conn.fake.__class__.__module__,
|
||||||
|
)
|
||||||
self.assertTrue(conn.fake.dummy())
|
self.assertTrue(conn.fake.dummy())
|
||||||
|
|
||||||
def test_add_service_v2(self):
|
def test_add_service_v2(self):
|
||||||
@ -382,17 +433,25 @@ class TestNewService(base.TestCase):
|
|||||||
self.use_keystone_v3()
|
self.use_keystone_v3()
|
||||||
conn = self.cloud
|
conn = self.cloud
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET',
|
[
|
||||||
uri='https://fake.example.com',
|
dict(
|
||||||
status_code=404),
|
method='GET',
|
||||||
dict(method='GET',
|
uri='https://fake.example.com',
|
||||||
uri='https://fake.example.com/v2/',
|
status_code=404,
|
||||||
status_code=404),
|
),
|
||||||
dict(method='GET',
|
dict(
|
||||||
uri=self.get_mock_url('fake'),
|
method='GET',
|
||||||
status_code=404),
|
uri='https://fake.example.com/v2/',
|
||||||
])
|
status_code=404,
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
method='GET',
|
||||||
|
uri=self.get_mock_url('fake'),
|
||||||
|
status_code=404,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
service = fake_service.FakeService('fake')
|
service = fake_service.FakeService('fake')
|
||||||
|
|
||||||
@ -400,7 +459,8 @@ class TestNewService(base.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'openstack.tests.unit.fake.v2._proxy',
|
'openstack.tests.unit.fake.v2._proxy',
|
||||||
conn.fake.__class__.__module__)
|
conn.fake.__class__.__module__,
|
||||||
|
)
|
||||||
self.assertFalse(conn.fake.dummy())
|
self.assertFalse(conn.fake.dummy())
|
||||||
|
|
||||||
def test_replace_system_service(self):
|
def test_replace_system_service(self):
|
||||||
@ -416,17 +476,25 @@ class TestNewService(base.TestCase):
|
|||||||
# delete native dns service
|
# delete native dns service
|
||||||
delattr(conn, 'dns')
|
delattr(conn, 'dns')
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET',
|
[
|
||||||
uri='https://fake.example.com',
|
dict(
|
||||||
status_code=404),
|
method='GET',
|
||||||
dict(method='GET',
|
uri='https://fake.example.com',
|
||||||
uri='https://fake.example.com/v2/',
|
status_code=404,
|
||||||
status_code=404),
|
),
|
||||||
dict(method='GET',
|
dict(
|
||||||
uri=self.get_mock_url('fake'),
|
method='GET',
|
||||||
status_code=404),
|
uri='https://fake.example.com/v2/',
|
||||||
])
|
status_code=404,
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
method='GET',
|
||||||
|
uri=self.get_mock_url('fake'),
|
||||||
|
status_code=404,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# add fake service with alias 'DNS'
|
# add fake service with alias 'DNS'
|
||||||
service = fake_service.FakeService('fake', aliases=['dns'])
|
service = fake_service.FakeService('fake', aliases=['dns'])
|
||||||
@ -441,7 +509,6 @@ def vendor_hook(conn):
|
|||||||
|
|
||||||
|
|
||||||
class TestVendorProfile(base.TestCase):
|
class TestVendorProfile(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestVendorProfile, self).setUp()
|
super(TestVendorProfile, self).setUp()
|
||||||
# Create a temporary directory where our test config will live
|
# Create a temporary directory where our test config will live
|
||||||
@ -456,12 +523,14 @@ class TestVendorProfile(base.TestCase):
|
|||||||
with open(public_clouds, "w") as conf:
|
with open(public_clouds, "w") as conf:
|
||||||
conf.write(PUBLIC_CLOUDS_YAML)
|
conf.write(PUBLIC_CLOUDS_YAML)
|
||||||
|
|
||||||
self.useFixture(fixtures.EnvironmentVariable(
|
self.useFixture(
|
||||||
"OS_CLIENT_CONFIG_FILE", config_path))
|
fixtures.EnvironmentVariable("OS_CLIENT_CONFIG_FILE", config_path)
|
||||||
|
)
|
||||||
self.use_keystone_v2()
|
self.use_keystone_v2()
|
||||||
|
|
||||||
self.config = openstack.config.loader.OpenStackConfig(
|
self.config = openstack.config.loader.OpenStackConfig(
|
||||||
vendor_files=[public_clouds])
|
vendor_files=[public_clouds]
|
||||||
|
)
|
||||||
|
|
||||||
def test_conn_from_profile(self):
|
def test_conn_from_profile(self):
|
||||||
|
|
||||||
@ -483,7 +552,7 @@ class TestVendorProfile(base.TestCase):
|
|||||||
|
|
||||||
conn = connection.Connection(
|
conn = connection.Connection(
|
||||||
cloud='sample-cloud',
|
cloud='sample-cloud',
|
||||||
vendor_hook='openstack.tests.unit.test_connection:vendor_hook'
|
vendor_hook='openstack.tests.unit.test_connection:vendor_hook',
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual('test_val', conn.test)
|
self.assertEqual('test_val', conn.test)
|
||||||
@ -492,7 +561,7 @@ class TestVendorProfile(base.TestCase):
|
|||||||
|
|
||||||
conn = connection.Connection(
|
conn = connection.Connection(
|
||||||
cloud='sample-cloud',
|
cloud='sample-cloud',
|
||||||
vendor_hook='openstack.tests.unit.test_connection:missing'
|
vendor_hook='openstack.tests.unit.test_connection:missing',
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertIsNotNone(conn)
|
self.assertIsNotNone(conn)
|
||||||
|
@ -23,13 +23,14 @@ from openstack.tests.unit import base
|
|||||||
class Test_Exception(base.TestCase):
|
class Test_Exception(base.TestCase):
|
||||||
def test_method_not_supported(self):
|
def test_method_not_supported(self):
|
||||||
exc = exceptions.MethodNotSupported(self.__class__, 'list')
|
exc = exceptions.MethodNotSupported(self.__class__, 'list')
|
||||||
expected = ('The list method is not supported for '
|
expected = (
|
||||||
+ 'openstack.tests.unit.test_exceptions.Test_Exception')
|
'The list method is not supported for '
|
||||||
|
+ 'openstack.tests.unit.test_exceptions.Test_Exception'
|
||||||
|
)
|
||||||
self.assertEqual(expected, str(exc))
|
self.assertEqual(expected, str(exc))
|
||||||
|
|
||||||
|
|
||||||
class Test_HttpException(base.TestCase):
|
class Test_HttpException(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(Test_HttpException, self).setUp()
|
super(Test_HttpException, self).setUp()
|
||||||
self.message = "mayday"
|
self.message = "mayday"
|
||||||
@ -38,32 +39,38 @@ class Test_HttpException(base.TestCase):
|
|||||||
raise exceptions.HttpException(*args, **kwargs)
|
raise exceptions.HttpException(*args, **kwargs)
|
||||||
|
|
||||||
def test_message(self):
|
def test_message(self):
|
||||||
exc = self.assertRaises(exceptions.HttpException,
|
exc = self.assertRaises(
|
||||||
self._do_raise, self.message)
|
exceptions.HttpException, self._do_raise, self.message
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(self.message, exc.message)
|
self.assertEqual(self.message, exc.message)
|
||||||
|
|
||||||
def test_details(self):
|
def test_details(self):
|
||||||
details = "some details"
|
details = "some details"
|
||||||
exc = self.assertRaises(exceptions.HttpException,
|
exc = self.assertRaises(
|
||||||
self._do_raise, self.message,
|
exceptions.HttpException,
|
||||||
details=details)
|
self._do_raise,
|
||||||
|
self.message,
|
||||||
|
details=details,
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(self.message, exc.message)
|
self.assertEqual(self.message, exc.message)
|
||||||
self.assertEqual(details, exc.details)
|
self.assertEqual(details, exc.details)
|
||||||
|
|
||||||
def test_http_status(self):
|
def test_http_status(self):
|
||||||
http_status = 123
|
http_status = 123
|
||||||
exc = self.assertRaises(exceptions.HttpException,
|
exc = self.assertRaises(
|
||||||
self._do_raise, self.message,
|
exceptions.HttpException,
|
||||||
http_status=http_status)
|
self._do_raise,
|
||||||
|
self.message,
|
||||||
|
http_status=http_status,
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(self.message, exc.message)
|
self.assertEqual(self.message, exc.message)
|
||||||
self.assertEqual(http_status, exc.status_code)
|
self.assertEqual(http_status, exc.status_code)
|
||||||
|
|
||||||
|
|
||||||
class TestRaiseFromResponse(base.TestCase):
|
class TestRaiseFromResponse(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestRaiseFromResponse, self).setUp()
|
super(TestRaiseFromResponse, self).setUp()
|
||||||
self.message = "Where is my kitty?"
|
self.message = "Where is my kitty?"
|
||||||
@ -83,14 +90,16 @@ class TestRaiseFromResponse(base.TestCase):
|
|||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
'x-openstack-request-id': uuid.uuid4().hex,
|
'x-openstack-request-id': uuid.uuid4().hex,
|
||||||
}
|
}
|
||||||
exc = self.assertRaises(exceptions.NotFoundException,
|
exc = self.assertRaises(
|
||||||
self._do_raise, response,
|
exceptions.NotFoundException,
|
||||||
error_message=self.message)
|
self._do_raise,
|
||||||
|
response,
|
||||||
|
error_message=self.message,
|
||||||
|
)
|
||||||
self.assertEqual(self.message, exc.message)
|
self.assertEqual(self.message, exc.message)
|
||||||
self.assertEqual(response.status_code, exc.status_code)
|
self.assertEqual(response.status_code, exc.status_code)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
response.headers.get('x-openstack-request-id'),
|
response.headers.get('x-openstack-request-id'), exc.request_id
|
||||||
exc.request_id
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_raise_bad_request_exception(self):
|
def test_raise_bad_request_exception(self):
|
||||||
@ -100,14 +109,16 @@ class TestRaiseFromResponse(base.TestCase):
|
|||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
'x-openstack-request-id': uuid.uuid4().hex,
|
'x-openstack-request-id': uuid.uuid4().hex,
|
||||||
}
|
}
|
||||||
exc = self.assertRaises(exceptions.BadRequestException,
|
exc = self.assertRaises(
|
||||||
self._do_raise, response,
|
exceptions.BadRequestException,
|
||||||
error_message=self.message)
|
self._do_raise,
|
||||||
|
response,
|
||||||
|
error_message=self.message,
|
||||||
|
)
|
||||||
self.assertEqual(self.message, exc.message)
|
self.assertEqual(self.message, exc.message)
|
||||||
self.assertEqual(response.status_code, exc.status_code)
|
self.assertEqual(response.status_code, exc.status_code)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
response.headers.get('x-openstack-request-id'),
|
response.headers.get('x-openstack-request-id'), exc.request_id
|
||||||
exc.request_id
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_raise_http_exception(self):
|
def test_raise_http_exception(self):
|
||||||
@ -117,14 +128,16 @@ class TestRaiseFromResponse(base.TestCase):
|
|||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
'x-openstack-request-id': uuid.uuid4().hex,
|
'x-openstack-request-id': uuid.uuid4().hex,
|
||||||
}
|
}
|
||||||
exc = self.assertRaises(exceptions.HttpException,
|
exc = self.assertRaises(
|
||||||
self._do_raise, response,
|
exceptions.HttpException,
|
||||||
error_message=self.message)
|
self._do_raise,
|
||||||
|
response,
|
||||||
|
error_message=self.message,
|
||||||
|
)
|
||||||
self.assertEqual(self.message, exc.message)
|
self.assertEqual(self.message, exc.message)
|
||||||
self.assertEqual(response.status_code, exc.status_code)
|
self.assertEqual(response.status_code, exc.status_code)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
response.headers.get('x-openstack-request-id'),
|
response.headers.get('x-openstack-request-id'), exc.request_id
|
||||||
exc.request_id
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_raise_compute_format(self):
|
def test_raise_compute_format(self):
|
||||||
@ -139,9 +152,12 @@ class TestRaiseFromResponse(base.TestCase):
|
|||||||
'code': 404,
|
'code': 404,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exc = self.assertRaises(exceptions.NotFoundException,
|
exc = self.assertRaises(
|
||||||
self._do_raise, response,
|
exceptions.NotFoundException,
|
||||||
error_message=self.message)
|
self._do_raise,
|
||||||
|
response,
|
||||||
|
error_message=self.message,
|
||||||
|
)
|
||||||
self.assertEqual(response.status_code, exc.status_code)
|
self.assertEqual(response.status_code, exc.status_code)
|
||||||
self.assertEqual(self.message, exc.details)
|
self.assertEqual(self.message, exc.details)
|
||||||
self.assertIn(self.message, str(exc))
|
self.assertIn(self.message, str(exc))
|
||||||
@ -159,9 +175,12 @@ class TestRaiseFromResponse(base.TestCase):
|
|||||||
'detail': '',
|
'detail': '',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exc = self.assertRaises(exceptions.NotFoundException,
|
exc = self.assertRaises(
|
||||||
self._do_raise, response,
|
exceptions.NotFoundException,
|
||||||
error_message=self.message)
|
self._do_raise,
|
||||||
|
response,
|
||||||
|
error_message=self.message,
|
||||||
|
)
|
||||||
self.assertEqual(response.status_code, exc.status_code)
|
self.assertEqual(response.status_code, exc.status_code)
|
||||||
self.assertEqual(self.message, exc.details)
|
self.assertEqual(self.message, exc.details)
|
||||||
self.assertIn(self.message, str(exc))
|
self.assertIn(self.message, str(exc))
|
||||||
@ -173,15 +192,20 @@ class TestRaiseFromResponse(base.TestCase):
|
|||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
}
|
}
|
||||||
response.json.return_value = {
|
response.json.return_value = {
|
||||||
'error_message': json.dumps({
|
'error_message': json.dumps(
|
||||||
'faultstring': self.message,
|
{
|
||||||
'faultcode': 'Client',
|
'faultstring': self.message,
|
||||||
'debuginfo': None,
|
'faultcode': 'Client',
|
||||||
})
|
'debuginfo': None,
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
exc = self.assertRaises(exceptions.NotFoundException,
|
exc = self.assertRaises(
|
||||||
self._do_raise, response,
|
exceptions.NotFoundException,
|
||||||
error_message=self.message)
|
self._do_raise,
|
||||||
|
response,
|
||||||
|
error_message=self.message,
|
||||||
|
)
|
||||||
self.assertEqual(response.status_code, exc.status_code)
|
self.assertEqual(response.status_code, exc.status_code)
|
||||||
self.assertEqual(self.message, exc.details)
|
self.assertEqual(self.message, exc.details)
|
||||||
self.assertIn(self.message, str(exc))
|
self.assertIn(self.message, str(exc))
|
||||||
@ -199,9 +223,12 @@ class TestRaiseFromResponse(base.TestCase):
|
|||||||
'debuginfo': None,
|
'debuginfo': None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exc = self.assertRaises(exceptions.NotFoundException,
|
exc = self.assertRaises(
|
||||||
self._do_raise, response,
|
exceptions.NotFoundException,
|
||||||
error_message=self.message)
|
self._do_raise,
|
||||||
|
response,
|
||||||
|
error_message=self.message,
|
||||||
|
)
|
||||||
self.assertEqual(response.status_code, exc.status_code)
|
self.assertEqual(response.status_code, exc.status_code)
|
||||||
self.assertEqual(self.message, exc.details)
|
self.assertEqual(self.message, exc.details)
|
||||||
self.assertIn(self.message, str(exc))
|
self.assertIn(self.message, str(exc))
|
||||||
@ -217,9 +244,12 @@ class TestRaiseFromResponse(base.TestCase):
|
|||||||
'faultcode': 'Client',
|
'faultcode': 'Client',
|
||||||
'debuginfo': None,
|
'debuginfo': None,
|
||||||
}
|
}
|
||||||
exc = self.assertRaises(exceptions.NotFoundException,
|
exc = self.assertRaises(
|
||||||
self._do_raise, response,
|
exceptions.NotFoundException,
|
||||||
error_message=self.message)
|
self._do_raise,
|
||||||
|
response,
|
||||||
|
error_message=self.message,
|
||||||
|
)
|
||||||
self.assertEqual(response.status_code, exc.status_code)
|
self.assertEqual(response.status_code, exc.status_code)
|
||||||
self.assertEqual(self.message, exc.details)
|
self.assertEqual(self.message, exc.details)
|
||||||
self.assertIn(self.message, str(exc))
|
self.assertIn(self.message, str(exc))
|
||||||
|
@ -15,7 +15,6 @@ from openstack.tests.unit import base
|
|||||||
|
|
||||||
|
|
||||||
class TestBoolStrFormatter(base.TestCase):
|
class TestBoolStrFormatter(base.TestCase):
|
||||||
|
|
||||||
def test_deserialize(self):
|
def test_deserialize(self):
|
||||||
self.assertTrue(format.BoolStr.deserialize(True))
|
self.assertTrue(format.BoolStr.deserialize(True))
|
||||||
self.assertTrue(format.BoolStr.deserialize('True'))
|
self.assertTrue(format.BoolStr.deserialize('True'))
|
||||||
|
@ -49,12 +49,23 @@ class HackingTestCase(base.TestCase):
|
|||||||
just assertTrue if the check is expected to fail and assertFalse if it
|
just assertTrue if the check is expected to fail and assertFalse if it
|
||||||
should pass.
|
should pass.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def test_assert_no_setupclass(self):
|
def test_assert_no_setupclass(self):
|
||||||
self.assertEqual(len(list(_hacking.assert_no_setupclass(
|
self.assertEqual(
|
||||||
"def setUpClass(cls)"))), 1)
|
len(list(_hacking.assert_no_setupclass("def setUpClass(cls)"))), 1
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(len(list(_hacking.assert_no_setupclass(
|
self.assertEqual(
|
||||||
"# setUpClass is evil"))), 0)
|
len(list(_hacking.assert_no_setupclass("# setUpClass is evil"))), 0
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(len(list(_hacking.assert_no_setupclass(
|
self.assertEqual(
|
||||||
"def setUpClassyDrinkingLocation(cls)"))), 0)
|
len(
|
||||||
|
list(
|
||||||
|
_hacking.assert_no_setupclass(
|
||||||
|
"def setUpClassyDrinkingLocation(cls)"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
@ -16,7 +16,6 @@ from openstack.tests.unit import base
|
|||||||
|
|
||||||
|
|
||||||
class TestMicroversions(base.TestCase):
|
class TestMicroversions(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestMicroversions, self).setUp()
|
super(TestMicroversions, self).setUp()
|
||||||
self.use_compute_discovery()
|
self.use_compute_discovery()
|
||||||
@ -27,7 +26,8 @@ class TestMicroversions(base.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exceptions.ConfigException,
|
exceptions.ConfigException,
|
||||||
self.cloud.get_server, 'doesNotExist',
|
self.cloud.get_server,
|
||||||
|
'doesNotExist',
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
@ -38,7 +38,8 @@ class TestMicroversions(base.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exceptions.ConfigException,
|
exceptions.ConfigException,
|
||||||
self.cloud.get_server, 'doesNotExist',
|
self.cloud.get_server,
|
||||||
|
'doesNotExist',
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
@ -49,7 +50,8 @@ class TestMicroversions(base.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exceptions.ConfigException,
|
exceptions.ConfigException,
|
||||||
self.cloud.get_server, 'doesNotExist',
|
self.cloud.get_server,
|
||||||
|
'doesNotExist',
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
@ -60,7 +62,8 @@ class TestMicroversions(base.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exceptions.ConfigException,
|
exceptions.ConfigException,
|
||||||
self.cloud.get_server, 'doesNotExist',
|
self.cloud.get_server,
|
||||||
|
'doesNotExist',
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
@ -72,13 +75,18 @@ class TestMicroversions(base.TestCase):
|
|||||||
server1 = fakes.make_fake_server('123', 'mickey')
|
server1 = fakes.make_fake_server('123', 'mickey')
|
||||||
server2 = fakes.make_fake_server('345', 'mouse')
|
server2 = fakes.make_fake_server('345', 'mouse')
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET',
|
[
|
||||||
uri=self.get_mock_url(
|
dict(
|
||||||
'compute', 'public', append=['servers', 'detail']),
|
method='GET',
|
||||||
request_headers={'OpenStack-API-Version': 'compute 2.42'},
|
uri=self.get_mock_url(
|
||||||
json={'servers': [server1, server2]}),
|
'compute', 'public', append=['servers', 'detail']
|
||||||
])
|
),
|
||||||
|
request_headers={'OpenStack-API-Version': 'compute 2.42'},
|
||||||
|
json={'servers': [server1, server2]},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
r = self.cloud.get_server('mickey', bare=True)
|
r = self.cloud.get_server('mickey', bare=True)
|
||||||
self.assertIsNotNone(r)
|
self.assertIsNotNone(r)
|
||||||
@ -93,13 +101,18 @@ class TestMicroversions(base.TestCase):
|
|||||||
server1 = fakes.make_fake_server('123', 'mickey')
|
server1 = fakes.make_fake_server('123', 'mickey')
|
||||||
server2 = fakes.make_fake_server('345', 'mouse')
|
server2 = fakes.make_fake_server('345', 'mouse')
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET',
|
[
|
||||||
uri=self.get_mock_url(
|
dict(
|
||||||
'compute', 'public', append=['servers', 'detail']),
|
method='GET',
|
||||||
request_headers={'OpenStack-API-Version': 'compute 2.42'},
|
uri=self.get_mock_url(
|
||||||
json={'servers': [server1, server2]}),
|
'compute', 'public', append=['servers', 'detail']
|
||||||
])
|
),
|
||||||
|
request_headers={'OpenStack-API-Version': 'compute 2.42'},
|
||||||
|
json={'servers': [server1, server2]},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
r = self.cloud.get_server('mickey', bare=True)
|
r = self.cloud.get_server('mickey', bare=True)
|
||||||
self.assertIsNotNone(r)
|
self.assertIsNotNone(r)
|
||||||
|
@ -18,18 +18,20 @@ from openstack.tests.unit import base
|
|||||||
|
|
||||||
|
|
||||||
class TestMissingVersion(base.TestCase):
|
class TestMissingVersion(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestMissingVersion, self).setUp()
|
super(TestMissingVersion, self).setUp()
|
||||||
self.os_fixture.clear_tokens()
|
self.os_fixture.clear_tokens()
|
||||||
svc = self.os_fixture.v3_token.add_service('image')
|
svc = self.os_fixture.v3_token.add_service('image')
|
||||||
svc.add_endpoint(
|
svc.add_endpoint(
|
||||||
url='https://example.com/image/',
|
url='https://example.com/image/',
|
||||||
region='RegionOne', interface='public')
|
region='RegionOne',
|
||||||
|
interface='public',
|
||||||
|
)
|
||||||
self.use_keystone_v3()
|
self.use_keystone_v3()
|
||||||
self.use_glance(
|
self.use_glance(
|
||||||
image_version_json='bad-glance-version.json',
|
image_version_json='bad-glance-version.json',
|
||||||
image_discovery_url='https://example.com/image/')
|
image_discovery_url='https://example.com/image/',
|
||||||
|
)
|
||||||
|
|
||||||
def test_unsupported_version(self):
|
def test_unsupported_version(self):
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ from openstack.tests.unit import base
|
|||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class TestPlacementRest(base.TestCase):
|
class TestPlacementRest(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestPlacementRest, self).setUp()
|
super(TestPlacementRest, self).setUp()
|
||||||
self.use_placement()
|
self.use_placement()
|
||||||
@ -29,8 +28,10 @@ class TestPlacementRest(base.TestCase):
|
|||||||
uri = dict(
|
uri = dict(
|
||||||
method='GET',
|
method='GET',
|
||||||
uri=self.get_mock_url(
|
uri=self.get_mock_url(
|
||||||
'placement', 'public', append=['allocation_candidates']),
|
'placement', 'public', append=['allocation_candidates']
|
||||||
json={})
|
),
|
||||||
|
json={},
|
||||||
|
)
|
||||||
if status_code is not None:
|
if status_code is not None:
|
||||||
uri['status_code'] = status_code
|
uri['status_code'] = status_code
|
||||||
self.register_uris([uri])
|
self.register_uris([uri])
|
||||||
@ -38,8 +39,8 @@ class TestPlacementRest(base.TestCase):
|
|||||||
def _validate_resp(self, resp, status_code):
|
def _validate_resp(self, resp, status_code):
|
||||||
self.assertEqual(status_code, resp.status_code)
|
self.assertEqual(status_code, resp.status_code)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'https://placement.example.com/allocation_candidates',
|
'https://placement.example.com/allocation_candidates', resp.url
|
||||||
resp.url)
|
)
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
|
|
||||||
@ddt.data({}, {'raise_exc': False}, {'raise_exc': True})
|
@ddt.data({}, {'raise_exc': False}, {'raise_exc': True})
|
||||||
@ -61,18 +62,20 @@ class TestPlacementRest(base.TestCase):
|
|||||||
# raise_exc=True raises a ksa exception appropriate to the status code
|
# raise_exc=True raises a ksa exception appropriate to the status code
|
||||||
ex = self.assertRaises(
|
ex = self.assertRaises(
|
||||||
exceptions.InternalServerError,
|
exceptions.InternalServerError,
|
||||||
self.cloud.placement.get, '/allocation_candidates', raise_exc=True)
|
self.cloud.placement.get,
|
||||||
|
'/allocation_candidates',
|
||||||
|
raise_exc=True,
|
||||||
|
)
|
||||||
self._validate_resp(ex.response, 500)
|
self._validate_resp(ex.response, 500)
|
||||||
|
|
||||||
def test_microversion_discovery(self):
|
def test_microversion_discovery(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
(1, 17),
|
(1, 17), self.cloud.placement.get_endpoint_data().max_microversion
|
||||||
self.cloud.placement.get_endpoint_data().max_microversion)
|
)
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
|
|
||||||
|
|
||||||
class TestBadPlacementRest(base.TestCase):
|
class TestBadPlacementRest(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.skipTest('Need to re-add support for broken placement versions')
|
self.skipTest('Need to re-add support for broken placement versions')
|
||||||
super(TestBadPlacementRest, self).setUp()
|
super(TestBadPlacementRest, self).setUp()
|
||||||
@ -85,8 +88,10 @@ class TestBadPlacementRest(base.TestCase):
|
|||||||
uri = dict(
|
uri = dict(
|
||||||
method='GET',
|
method='GET',
|
||||||
uri=self.get_mock_url(
|
uri=self.get_mock_url(
|
||||||
'placement', 'public', append=['allocation_candidates']),
|
'placement', 'public', append=['allocation_candidates']
|
||||||
json={})
|
),
|
||||||
|
json={},
|
||||||
|
)
|
||||||
if status_code is not None:
|
if status_code is not None:
|
||||||
uri['status_code'] = status_code
|
uri['status_code'] = status_code
|
||||||
self.register_uris([uri])
|
self.register_uris([uri])
|
||||||
@ -94,8 +99,8 @@ class TestBadPlacementRest(base.TestCase):
|
|||||||
def _validate_resp(self, resp, status_code):
|
def _validate_resp(self, resp, status_code):
|
||||||
self.assertEqual(status_code, resp.status_code)
|
self.assertEqual(status_code, resp.status_code)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'https://placement.example.com/allocation_candidates',
|
'https://placement.example.com/allocation_candidates', resp.url
|
||||||
resp.url)
|
)
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
|
|
||||||
def test_discovery(self):
|
def test_discovery(self):
|
||||||
|
@ -58,7 +58,6 @@ class HeadableResource(resource.Resource):
|
|||||||
|
|
||||||
|
|
||||||
class TestProxyPrivate(base.TestCase):
|
class TestProxyPrivate(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestProxyPrivate, self).setUp()
|
super(TestProxyPrivate, self).setUp()
|
||||||
|
|
||||||
@ -88,9 +87,14 @@ class TestProxyPrivate(base.TestCase):
|
|||||||
|
|
||||||
def test__check_resource_strict_id(self):
|
def test__check_resource_strict_id(self):
|
||||||
decorated = proxy._check_resource(strict=True)(self.sot.method)
|
decorated = proxy._check_resource(strict=True)(self.sot.method)
|
||||||
self.assertRaisesRegex(ValueError, "A Resource must be passed",
|
self.assertRaisesRegex(
|
||||||
decorated, self.sot, resource.Resource,
|
ValueError,
|
||||||
"this-is-not-a-resource")
|
"A Resource must be passed",
|
||||||
|
decorated,
|
||||||
|
self.sot,
|
||||||
|
resource.Resource,
|
||||||
|
"this-is-not-a-resource",
|
||||||
|
)
|
||||||
|
|
||||||
def test__check_resource_incorrect_resource(self):
|
def test__check_resource_incorrect_resource(self):
|
||||||
class OneType(resource.Resource):
|
class OneType(resource.Resource):
|
||||||
@ -101,9 +105,14 @@ class TestProxyPrivate(base.TestCase):
|
|||||||
|
|
||||||
value = AnotherType()
|
value = AnotherType()
|
||||||
decorated = proxy._check_resource(strict=False)(self.sot.method)
|
decorated = proxy._check_resource(strict=False)(self.sot.method)
|
||||||
self.assertRaisesRegex(ValueError,
|
self.assertRaisesRegex(
|
||||||
"Expected OneType but received AnotherType",
|
ValueError,
|
||||||
decorated, self.sot, OneType, value)
|
"Expected OneType but received AnotherType",
|
||||||
|
decorated,
|
||||||
|
self.sot,
|
||||||
|
OneType,
|
||||||
|
value,
|
||||||
|
)
|
||||||
|
|
||||||
def test__get_uri_attribute_no_parent(self):
|
def test__get_uri_attribute_no_parent(self):
|
||||||
class Child(resource.Resource):
|
class Child(resource.Resource):
|
||||||
@ -161,7 +170,8 @@ class TestProxyPrivate(base.TestCase):
|
|||||||
result = self.fake_proxy._get_resource(Fake, id, **attrs)
|
result = self.fake_proxy._get_resource(Fake, id, **attrs)
|
||||||
|
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
dict(id=id, connection=mock.ANY, **attrs), Fake.call)
|
dict(id=id, connection=mock.ANY, **attrs), Fake.call
|
||||||
|
)
|
||||||
self.assertEqual(value, result)
|
self.assertEqual(value, result)
|
||||||
|
|
||||||
def test__get_resource_from_resource(self):
|
def test__get_resource_from_resource(self):
|
||||||
@ -170,8 +180,7 @@ class TestProxyPrivate(base.TestCase):
|
|||||||
|
|
||||||
attrs = {"first": "Brian", "last": "Curtin"}
|
attrs = {"first": "Brian", "last": "Curtin"}
|
||||||
|
|
||||||
result = self.fake_proxy._get_resource(resource.Resource,
|
result = self.fake_proxy._get_resource(resource.Resource, res, **attrs)
|
||||||
res, **attrs)
|
|
||||||
|
|
||||||
res._update.assert_called_once_with(**attrs)
|
res._update.assert_called_once_with(**attrs)
|
||||||
self.assertEqual(result, res)
|
self.assertEqual(result, res)
|
||||||
@ -193,7 +202,6 @@ class TestProxyPrivate(base.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestProxyDelete(base.TestCase):
|
class TestProxyDelete(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestProxyDelete, self).setUp()
|
super(TestProxyDelete, self).setUp()
|
||||||
|
|
||||||
@ -215,7 +223,8 @@ class TestProxyDelete(base.TestCase):
|
|||||||
|
|
||||||
self.sot._delete(DeleteableResource, self.fake_id)
|
self.sot._delete(DeleteableResource, self.fake_id)
|
||||||
DeleteableResource.new.assert_called_with(
|
DeleteableResource.new.assert_called_with(
|
||||||
connection=self.cloud, id=self.fake_id)
|
connection=self.cloud, id=self.fake_id
|
||||||
|
)
|
||||||
self.res.delete.assert_called_with(self.sot)
|
self.res.delete.assert_called_with(self.sot)
|
||||||
|
|
||||||
# Delete generally doesn't return anything, so we will normally
|
# Delete generally doesn't return anything, so we will normally
|
||||||
@ -227,32 +236,42 @@ class TestProxyDelete(base.TestCase):
|
|||||||
|
|
||||||
def test_delete_ignore_missing(self):
|
def test_delete_ignore_missing(self):
|
||||||
self.res.delete.side_effect = exceptions.ResourceNotFound(
|
self.res.delete.side_effect = exceptions.ResourceNotFound(
|
||||||
message="test", http_status=404)
|
message="test", http_status=404
|
||||||
|
)
|
||||||
|
|
||||||
rv = self.sot._delete(DeleteableResource, self.fake_id)
|
rv = self.sot._delete(DeleteableResource, self.fake_id)
|
||||||
self.assertIsNone(rv)
|
self.assertIsNone(rv)
|
||||||
|
|
||||||
def test_delete_NotFound(self):
|
def test_delete_NotFound(self):
|
||||||
self.res.delete.side_effect = exceptions.ResourceNotFound(
|
self.res.delete.side_effect = exceptions.ResourceNotFound(
|
||||||
message="test", http_status=404)
|
message="test", http_status=404
|
||||||
|
)
|
||||||
|
|
||||||
self.assertRaisesRegex(
|
self.assertRaisesRegex(
|
||||||
exceptions.ResourceNotFound,
|
exceptions.ResourceNotFound,
|
||||||
# TODO(shade) The mocks here are hiding the thing we want to test.
|
# TODO(shade) The mocks here are hiding the thing we want to test.
|
||||||
"test",
|
"test",
|
||||||
self.sot._delete, DeleteableResource, self.res,
|
self.sot._delete,
|
||||||
ignore_missing=False)
|
DeleteableResource,
|
||||||
|
self.res,
|
||||||
|
ignore_missing=False,
|
||||||
|
)
|
||||||
|
|
||||||
def test_delete_HttpException(self):
|
def test_delete_HttpException(self):
|
||||||
self.res.delete.side_effect = exceptions.HttpException(
|
self.res.delete.side_effect = exceptions.HttpException(
|
||||||
message="test", http_status=500)
|
message="test", http_status=500
|
||||||
|
)
|
||||||
|
|
||||||
self.assertRaises(exceptions.HttpException, self.sot._delete,
|
self.assertRaises(
|
||||||
DeleteableResource, self.res, ignore_missing=False)
|
exceptions.HttpException,
|
||||||
|
self.sot._delete,
|
||||||
|
DeleteableResource,
|
||||||
|
self.res,
|
||||||
|
ignore_missing=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestProxyUpdate(base.TestCase):
|
class TestProxyUpdate(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestProxyUpdate, self).setUp()
|
super(TestProxyUpdate, self).setUp()
|
||||||
|
|
||||||
@ -280,8 +299,9 @@ class TestProxyUpdate(base.TestCase):
|
|||||||
|
|
||||||
def test_update_resource_override_base_path(self):
|
def test_update_resource_override_base_path(self):
|
||||||
base_path = 'dummy'
|
base_path = 'dummy'
|
||||||
rv = self.sot._update(UpdateableResource, self.res,
|
rv = self.sot._update(
|
||||||
base_path=base_path, **self.attrs)
|
UpdateableResource, self.res, base_path=base_path, **self.attrs
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(rv, self.fake_result)
|
self.assertEqual(rv, self.fake_result)
|
||||||
self.res._update.assert_called_once_with(**self.attrs)
|
self.res._update.assert_called_once_with(**self.attrs)
|
||||||
@ -295,7 +315,6 @@ class TestProxyUpdate(base.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestProxyCreate(base.TestCase):
|
class TestProxyCreate(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestProxyCreate, self).setUp()
|
super(TestProxyCreate, self).setUp()
|
||||||
|
|
||||||
@ -317,7 +336,8 @@ class TestProxyCreate(base.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(rv, self.fake_result)
|
self.assertEqual(rv, self.fake_result)
|
||||||
CreateableResource.new.assert_called_once_with(
|
CreateableResource.new.assert_called_once_with(
|
||||||
connection=self.cloud, **attrs)
|
connection=self.cloud, **attrs
|
||||||
|
)
|
||||||
self.res.create.assert_called_once_with(self.sot, base_path=None)
|
self.res.create.assert_called_once_with(self.sot, base_path=None)
|
||||||
|
|
||||||
def test_create_attributes_override_base_path(self):
|
def test_create_attributes_override_base_path(self):
|
||||||
@ -329,12 +349,12 @@ class TestProxyCreate(base.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(rv, self.fake_result)
|
self.assertEqual(rv, self.fake_result)
|
||||||
CreateableResource.new.assert_called_once_with(
|
CreateableResource.new.assert_called_once_with(
|
||||||
connection=self.cloud, **attrs)
|
connection=self.cloud, **attrs
|
||||||
|
)
|
||||||
self.res.create.assert_called_once_with(self.sot, base_path=base_path)
|
self.res.create.assert_called_once_with(self.sot, base_path=base_path)
|
||||||
|
|
||||||
|
|
||||||
class TestProxyBulkCreate(base.TestCase):
|
class TestProxyBulkCreate(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestProxyBulkCreate, self).setUp()
|
super(TestProxyBulkCreate, self).setUp()
|
||||||
|
|
||||||
@ -353,8 +373,9 @@ class TestProxyBulkCreate(base.TestCase):
|
|||||||
rv = self.sot._bulk_create(self.cls, self.data)
|
rv = self.sot._bulk_create(self.cls, self.data)
|
||||||
|
|
||||||
self.assertEqual(rv, self.result)
|
self.assertEqual(rv, self.result)
|
||||||
self.cls.bulk_create.assert_called_once_with(self.sot, self.data,
|
self.cls.bulk_create.assert_called_once_with(
|
||||||
base_path=None)
|
self.sot, self.data, base_path=None
|
||||||
|
)
|
||||||
|
|
||||||
def test_bulk_create_attributes_override_base_path(self):
|
def test_bulk_create_attributes_override_base_path(self):
|
||||||
base_path = 'dummy'
|
base_path = 'dummy'
|
||||||
@ -362,12 +383,12 @@ class TestProxyBulkCreate(base.TestCase):
|
|||||||
rv = self.sot._bulk_create(self.cls, self.data, base_path=base_path)
|
rv = self.sot._bulk_create(self.cls, self.data, base_path=base_path)
|
||||||
|
|
||||||
self.assertEqual(rv, self.result)
|
self.assertEqual(rv, self.result)
|
||||||
self.cls.bulk_create.assert_called_once_with(self.sot, self.data,
|
self.cls.bulk_create.assert_called_once_with(
|
||||||
base_path=base_path)
|
self.sot, self.data, base_path=base_path
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestProxyGet(base.TestCase):
|
class TestProxyGet(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestProxyGet, self).setUp()
|
super(TestProxyGet, self).setUp()
|
||||||
|
|
||||||
@ -389,10 +410,12 @@ class TestProxyGet(base.TestCase):
|
|||||||
rv = self.sot._get(RetrieveableResource, self.res)
|
rv = self.sot._get(RetrieveableResource, self.res)
|
||||||
|
|
||||||
self.res.fetch.assert_called_with(
|
self.res.fetch.assert_called_with(
|
||||||
self.sot, requires_id=True,
|
self.sot,
|
||||||
|
requires_id=True,
|
||||||
base_path=None,
|
base_path=None,
|
||||||
skip_cache=mock.ANY,
|
skip_cache=mock.ANY,
|
||||||
error_message=mock.ANY)
|
error_message=mock.ANY,
|
||||||
|
)
|
||||||
self.assertEqual(rv, self.fake_result)
|
self.assertEqual(rv, self.fake_result)
|
||||||
|
|
||||||
def test_get_resource_with_args(self):
|
def test_get_resource_with_args(self):
|
||||||
@ -401,46 +424,62 @@ class TestProxyGet(base.TestCase):
|
|||||||
|
|
||||||
self.res._update.assert_called_once_with(**args)
|
self.res._update.assert_called_once_with(**args)
|
||||||
self.res.fetch.assert_called_with(
|
self.res.fetch.assert_called_with(
|
||||||
self.sot, requires_id=True, base_path=None,
|
self.sot,
|
||||||
|
requires_id=True,
|
||||||
|
base_path=None,
|
||||||
skip_cache=mock.ANY,
|
skip_cache=mock.ANY,
|
||||||
error_message=mock.ANY)
|
error_message=mock.ANY,
|
||||||
|
)
|
||||||
self.assertEqual(rv, self.fake_result)
|
self.assertEqual(rv, self.fake_result)
|
||||||
|
|
||||||
def test_get_id(self):
|
def test_get_id(self):
|
||||||
rv = self.sot._get(RetrieveableResource, self.fake_id)
|
rv = self.sot._get(RetrieveableResource, self.fake_id)
|
||||||
|
|
||||||
RetrieveableResource.new.assert_called_with(
|
RetrieveableResource.new.assert_called_with(
|
||||||
connection=self.cloud, id=self.fake_id)
|
connection=self.cloud, id=self.fake_id
|
||||||
|
)
|
||||||
self.res.fetch.assert_called_with(
|
self.res.fetch.assert_called_with(
|
||||||
self.sot, requires_id=True, base_path=None,
|
self.sot,
|
||||||
|
requires_id=True,
|
||||||
|
base_path=None,
|
||||||
skip_cache=mock.ANY,
|
skip_cache=mock.ANY,
|
||||||
error_message=mock.ANY)
|
error_message=mock.ANY,
|
||||||
|
)
|
||||||
self.assertEqual(rv, self.fake_result)
|
self.assertEqual(rv, self.fake_result)
|
||||||
|
|
||||||
def test_get_base_path(self):
|
def test_get_base_path(self):
|
||||||
base_path = 'dummy'
|
base_path = 'dummy'
|
||||||
rv = self.sot._get(RetrieveableResource, self.fake_id,
|
rv = self.sot._get(
|
||||||
base_path=base_path)
|
RetrieveableResource, self.fake_id, base_path=base_path
|
||||||
|
)
|
||||||
|
|
||||||
RetrieveableResource.new.assert_called_with(
|
RetrieveableResource.new.assert_called_with(
|
||||||
connection=self.cloud, id=self.fake_id)
|
connection=self.cloud, id=self.fake_id
|
||||||
|
)
|
||||||
self.res.fetch.assert_called_with(
|
self.res.fetch.assert_called_with(
|
||||||
self.sot, requires_id=True, base_path=base_path,
|
self.sot,
|
||||||
|
requires_id=True,
|
||||||
|
base_path=base_path,
|
||||||
skip_cache=mock.ANY,
|
skip_cache=mock.ANY,
|
||||||
error_message=mock.ANY)
|
error_message=mock.ANY,
|
||||||
|
)
|
||||||
self.assertEqual(rv, self.fake_result)
|
self.assertEqual(rv, self.fake_result)
|
||||||
|
|
||||||
def test_get_not_found(self):
|
def test_get_not_found(self):
|
||||||
self.res.fetch.side_effect = exceptions.ResourceNotFound(
|
self.res.fetch.side_effect = exceptions.ResourceNotFound(
|
||||||
message="test", http_status=404)
|
message="test", http_status=404
|
||||||
|
)
|
||||||
|
|
||||||
self.assertRaisesRegex(
|
self.assertRaisesRegex(
|
||||||
exceptions.ResourceNotFound,
|
exceptions.ResourceNotFound,
|
||||||
"test", self.sot._get, RetrieveableResource, self.res)
|
"test",
|
||||||
|
self.sot._get,
|
||||||
|
RetrieveableResource,
|
||||||
|
self.res,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestProxyList(base.TestCase):
|
class TestProxyList(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestProxyList, self).setUp()
|
super(TestProxyList, self).setUp()
|
||||||
|
|
||||||
@ -455,12 +494,17 @@ class TestProxyList(base.TestCase):
|
|||||||
ListableResource.list.return_value = self.fake_response
|
ListableResource.list.return_value = self.fake_response
|
||||||
|
|
||||||
def _test_list(self, paginated, base_path=None):
|
def _test_list(self, paginated, base_path=None):
|
||||||
rv = self.sot._list(ListableResource, paginated=paginated,
|
rv = self.sot._list(
|
||||||
base_path=base_path, **self.args)
|
ListableResource,
|
||||||
|
paginated=paginated,
|
||||||
|
base_path=base_path,
|
||||||
|
**self.args,
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(self.fake_response, rv)
|
self.assertEqual(self.fake_response, rv)
|
||||||
ListableResource.list.assert_called_once_with(
|
ListableResource.list.assert_called_once_with(
|
||||||
self.sot, paginated=paginated, base_path=base_path, **self.args)
|
self.sot, paginated=paginated, base_path=base_path, **self.args
|
||||||
|
)
|
||||||
|
|
||||||
def test_list_paginated(self):
|
def test_list_paginated(self):
|
||||||
self._test_list(True)
|
self._test_list(True)
|
||||||
@ -481,21 +525,24 @@ class TestProxyList(base.TestCase):
|
|||||||
FilterableResource.list.return_value = fake_response
|
FilterableResource.list.return_value = fake_response
|
||||||
|
|
||||||
rv = self.sot._list(
|
rv = self.sot._list(
|
||||||
FilterableResource, paginated=False,
|
FilterableResource,
|
||||||
base_path=None, jmespath_filters="[?c=='c']"
|
paginated=False,
|
||||||
|
base_path=None,
|
||||||
|
jmespath_filters="[?c=='c']",
|
||||||
)
|
)
|
||||||
self.assertEqual(3, len(rv))
|
self.assertEqual(3, len(rv))
|
||||||
|
|
||||||
# Test filtering based on unknown attribute
|
# Test filtering based on unknown attribute
|
||||||
rv = self.sot._list(
|
rv = self.sot._list(
|
||||||
FilterableResource, paginated=False,
|
FilterableResource,
|
||||||
base_path=None, jmespath_filters="[?d=='c']"
|
paginated=False,
|
||||||
|
base_path=None,
|
||||||
|
jmespath_filters="[?d=='c']",
|
||||||
)
|
)
|
||||||
self.assertEqual(0, len(rv))
|
self.assertEqual(0, len(rv))
|
||||||
|
|
||||||
|
|
||||||
class TestProxyHead(base.TestCase):
|
class TestProxyHead(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestProxyHead, self).setUp()
|
super(TestProxyHead, self).setUp()
|
||||||
|
|
||||||
@ -530,7 +577,8 @@ class TestProxyHead(base.TestCase):
|
|||||||
rv = self.sot._head(HeadableResource, self.fake_id)
|
rv = self.sot._head(HeadableResource, self.fake_id)
|
||||||
|
|
||||||
HeadableResource.new.assert_called_with(
|
HeadableResource.new.assert_called_with(
|
||||||
connection=self.cloud, id=self.fake_id)
|
connection=self.cloud, id=self.fake_id
|
||||||
|
)
|
||||||
self.res.head.assert_called_with(self.sot, base_path=None)
|
self.res.head.assert_called_with(self.sot, base_path=None)
|
||||||
self.assertEqual(rv, self.fake_result)
|
self.assertEqual(rv, self.fake_result)
|
||||||
|
|
||||||
@ -546,10 +594,14 @@ class TestExtractName(base.TestCase):
|
|||||||
('networks_arg', dict(url='/v2.0/networks/1', parts=['network'])),
|
('networks_arg', dict(url='/v2.0/networks/1', parts=['network'])),
|
||||||
('tokens', dict(url='/v3/tokens', parts=['tokens'])),
|
('tokens', dict(url='/v3/tokens', parts=['tokens'])),
|
||||||
('discovery', dict(url='/', parts=['discovery'])),
|
('discovery', dict(url='/', parts=['discovery'])),
|
||||||
('secgroups', dict(
|
(
|
||||||
url='/servers/1/os-security-groups',
|
'secgroups',
|
||||||
parts=['server', 'os-security-groups'])),
|
dict(
|
||||||
('bm_chassis', dict(url='/v1/chassis/id', parts=['chassis']))
|
url='/servers/1/os-security-groups',
|
||||||
|
parts=['server', 'os-security-groups'],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('bm_chassis', dict(url='/v1/chassis/id', parts=['chassis'])),
|
||||||
]
|
]
|
||||||
|
|
||||||
def test_extract_name(self):
|
def test_extract_name(self):
|
||||||
@ -559,7 +611,6 @@ class TestExtractName(base.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestProxyCache(base.TestCase):
|
class TestProxyCache(base.TestCase):
|
||||||
|
|
||||||
class Res(resource.Resource):
|
class Res(resource.Resource):
|
||||||
base_path = 'fake'
|
base_path = 'fake'
|
||||||
|
|
||||||
@ -570,7 +621,8 @@ class TestProxyCache(base.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestProxyCache, self).setUp(
|
super(TestProxyCache, self).setUp(
|
||||||
cloud_config_fixture='clouds_cache.yaml')
|
cloud_config_fixture='clouds_cache.yaml'
|
||||||
|
)
|
||||||
|
|
||||||
self.session = mock.Mock()
|
self.session = mock.Mock()
|
||||||
self.session._sdk_connection = self.cloud
|
self.session._sdk_connection = self.cloud
|
||||||
@ -581,19 +633,15 @@ class TestProxyCache(base.TestCase):
|
|||||||
self.response.history = []
|
self.response.history = []
|
||||||
self.response.headers = {}
|
self.response.headers = {}
|
||||||
self.response.body = {}
|
self.response.body = {}
|
||||||
self.response.json = mock.Mock(
|
self.response.json = mock.Mock(return_value=self.response.body)
|
||||||
return_value=self.response.body)
|
self.session.request = mock.Mock(return_value=self.response)
|
||||||
self.session.request = mock.Mock(
|
|
||||||
return_value=self.response)
|
|
||||||
|
|
||||||
self.sot = proxy.Proxy(self.session)
|
self.sot = proxy.Proxy(self.session)
|
||||||
self.sot._connection = self.cloud
|
self.sot._connection = self.cloud
|
||||||
self.sot.service_type = 'srv'
|
self.sot.service_type = 'srv'
|
||||||
|
|
||||||
def _get_key(self, id):
|
def _get_key(self, id):
|
||||||
return (
|
return f"srv.fake.fake/{id}." "{'microversion': None, 'params': {}}"
|
||||||
f"srv.fake.fake/{id}."
|
|
||||||
"{'microversion': None, 'params': {}}")
|
|
||||||
|
|
||||||
def test_get_not_in_cache(self):
|
def test_get_not_in_cache(self):
|
||||||
self.cloud._cache_expirations['srv.fake'] = 5
|
self.cloud._cache_expirations['srv.fake'] = 5
|
||||||
@ -602,15 +650,15 @@ class TestProxyCache(base.TestCase):
|
|||||||
self.session.request.assert_called_with(
|
self.session.request.assert_called_with(
|
||||||
'fake/1',
|
'fake/1',
|
||||||
'GET',
|
'GET',
|
||||||
connect_retries=mock.ANY, raise_exc=mock.ANY,
|
connect_retries=mock.ANY,
|
||||||
|
raise_exc=mock.ANY,
|
||||||
global_request_id=mock.ANY,
|
global_request_id=mock.ANY,
|
||||||
endpoint_filter=mock.ANY,
|
endpoint_filter=mock.ANY,
|
||||||
headers=mock.ANY,
|
headers=mock.ANY,
|
||||||
microversion=mock.ANY, params=mock.ANY
|
microversion=mock.ANY,
|
||||||
|
params=mock.ANY,
|
||||||
)
|
)
|
||||||
self.assertIn(
|
self.assertIn(self._get_key(1), self.cloud._api_cache_keys)
|
||||||
self._get_key(1),
|
|
||||||
self.cloud._api_cache_keys)
|
|
||||||
|
|
||||||
def test_get_from_cache(self):
|
def test_get_from_cache(self):
|
||||||
key = self._get_key(2)
|
key = self._get_key(2)
|
||||||
@ -639,9 +687,7 @@ class TestProxyCache(base.TestCase):
|
|||||||
|
|
||||||
self.session.request.assert_called()
|
self.session.request.assert_called()
|
||||||
self.assertIsNotNone(self.cloud._cache.get(key))
|
self.assertIsNotNone(self.cloud._cache.get(key))
|
||||||
self.assertEqual(
|
self.assertEqual('NoValue', type(self.cloud._cache.get(key)).__name__)
|
||||||
'NoValue',
|
|
||||||
type(self.cloud._cache.get(key)).__name__)
|
|
||||||
self.assertNotIn(key, self.cloud._api_cache_keys)
|
self.assertNotIn(key, self.cloud._api_cache_keys)
|
||||||
|
|
||||||
# next get call again triggers API
|
# next get call again triggers API
|
||||||
@ -663,13 +709,10 @@ class TestProxyCache(base.TestCase):
|
|||||||
# validate we got empty body as expected, and not what is in cache
|
# validate we got empty body as expected, and not what is in cache
|
||||||
self.assertEqual(dict(), self.response.body)
|
self.assertEqual(dict(), self.response.body)
|
||||||
self.assertNotIn(key, self.cloud._api_cache_keys)
|
self.assertNotIn(key, self.cloud._api_cache_keys)
|
||||||
self.assertEqual(
|
self.assertEqual('NoValue', type(self.cloud._cache.get(key)).__name__)
|
||||||
'NoValue',
|
|
||||||
type(self.cloud._cache.get(key)).__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class TestProxyCleanup(base.TestCase):
|
class TestProxyCleanup(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestProxyCleanup, self).setUp()
|
super(TestProxyCleanup, self).setUp()
|
||||||
|
|
||||||
@ -693,40 +736,28 @@ class TestProxyCleanup(base.TestCase):
|
|||||||
def test_filters_evaluation_created_at(self):
|
def test_filters_evaluation_created_at(self):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
self.sot._service_cleanup_resource_filters_evaluation(
|
self.sot._service_cleanup_resource_filters_evaluation(
|
||||||
self.res,
|
self.res, filters={'created_at': '2020-02-03T00:00:00'}
|
||||||
filters={
|
|
||||||
'created_at': '2020-02-03T00:00:00'
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_filters_evaluation_created_at_not(self):
|
def test_filters_evaluation_created_at_not(self):
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
self.sot._service_cleanup_resource_filters_evaluation(
|
self.sot._service_cleanup_resource_filters_evaluation(
|
||||||
self.res,
|
self.res, filters={'created_at': '2020-01-01T00:00:00'}
|
||||||
filters={
|
|
||||||
'created_at': '2020-01-01T00:00:00'
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_filters_evaluation_updated_at(self):
|
def test_filters_evaluation_updated_at(self):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
self.sot._service_cleanup_resource_filters_evaluation(
|
self.sot._service_cleanup_resource_filters_evaluation(
|
||||||
self.res,
|
self.res, filters={'updated_at': '2020-02-03T00:00:00'}
|
||||||
filters={
|
|
||||||
'updated_at': '2020-02-03T00:00:00'
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_filters_evaluation_updated_at_not(self):
|
def test_filters_evaluation_updated_at_not(self):
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
self.sot._service_cleanup_resource_filters_evaluation(
|
self.sot._service_cleanup_resource_filters_evaluation(
|
||||||
self.res,
|
self.res, filters={'updated_at': '2020-01-01T00:00:00'}
|
||||||
filters={
|
|
||||||
'updated_at': '2020-01-01T00:00:00'
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -734,9 +765,7 @@ class TestProxyCleanup(base.TestCase):
|
|||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
self.sot._service_cleanup_resource_filters_evaluation(
|
self.sot._service_cleanup_resource_filters_evaluation(
|
||||||
self.res_no_updated,
|
self.res_no_updated,
|
||||||
filters={
|
filters={'updated_at': '2020-01-01T00:00:00'},
|
||||||
'updated_at': '2020-01-01T00:00:00'
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -750,19 +779,14 @@ class TestProxyCleanup(base.TestCase):
|
|||||||
def test_service_cleanup_dry_run(self):
|
def test_service_cleanup_dry_run(self):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
self.sot._service_cleanup_del_res(
|
self.sot._service_cleanup_del_res(
|
||||||
self.delete_mock,
|
self.delete_mock, self.res, dry_run=True
|
||||||
self.res,
|
|
||||||
dry_run=True
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.delete_mock.assert_not_called()
|
self.delete_mock.assert_not_called()
|
||||||
|
|
||||||
def test_service_cleanup_dry_run_default(self):
|
def test_service_cleanup_dry_run_default(self):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
self.sot._service_cleanup_del_res(
|
self.sot._service_cleanup_del_res(self.delete_mock, self.res)
|
||||||
self.delete_mock,
|
|
||||||
self.res
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
self.delete_mock.assert_not_called()
|
self.delete_mock.assert_not_called()
|
||||||
|
|
||||||
@ -783,7 +807,7 @@ class TestProxyCleanup(base.TestCase):
|
|||||||
self.delete_mock,
|
self.delete_mock,
|
||||||
self.res,
|
self.res,
|
||||||
dry_run=False,
|
dry_run=False,
|
||||||
identified_resources=rd
|
identified_resources=rd,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.delete_mock.assert_called_with(self.res)
|
self.delete_mock.assert_called_with(self.res)
|
||||||
@ -795,7 +819,7 @@ class TestProxyCleanup(base.TestCase):
|
|||||||
self.delete_mock,
|
self.delete_mock,
|
||||||
self.res,
|
self.res,
|
||||||
dry_run=False,
|
dry_run=False,
|
||||||
resource_evaluation_fn=lambda x, y, z: False
|
resource_evaluation_fn=lambda x, y, z: False,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.delete_mock.assert_not_called()
|
self.delete_mock.assert_not_called()
|
||||||
@ -806,7 +830,7 @@ class TestProxyCleanup(base.TestCase):
|
|||||||
self.delete_mock,
|
self.delete_mock,
|
||||||
self.res,
|
self.res,
|
||||||
dry_run=False,
|
dry_run=False,
|
||||||
resource_evaluation_fn=lambda x, y, z: True
|
resource_evaluation_fn=lambda x, y, z: True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.delete_mock.assert_called()
|
self.delete_mock.assert_called()
|
||||||
@ -818,7 +842,7 @@ class TestProxyCleanup(base.TestCase):
|
|||||||
self.res,
|
self.res,
|
||||||
dry_run=False,
|
dry_run=False,
|
||||||
resource_evaluation_fn=lambda x, y, z: False,
|
resource_evaluation_fn=lambda x, y, z: False,
|
||||||
filters={'created_at': '2200-01-01'}
|
filters={'created_at': '2200-01-01'},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -828,7 +852,7 @@ class TestProxyCleanup(base.TestCase):
|
|||||||
self.delete_mock,
|
self.delete_mock,
|
||||||
self.res,
|
self.res,
|
||||||
dry_run=False,
|
dry_run=False,
|
||||||
filters={'created_at': '2200-01-01'}
|
filters={'created_at': '2200-01-01'},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.delete_mock.assert_called()
|
self.delete_mock.assert_called()
|
||||||
@ -841,7 +865,7 @@ class TestProxyCleanup(base.TestCase):
|
|||||||
self.res,
|
self.res,
|
||||||
dry_run=False,
|
dry_run=False,
|
||||||
client_status_queue=q,
|
client_status_queue=q,
|
||||||
filters={'created_at': '2200-01-01'}
|
filters={'created_at': '2200-01-01'},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.assertEqual(self.res, q.get_nowait())
|
self.assertEqual(self.res, q.get_nowait())
|
||||||
|
@ -21,18 +21,27 @@ class TestProxyBase(base.TestCase):
|
|||||||
self.session = mock.Mock()
|
self.session = mock.Mock()
|
||||||
|
|
||||||
def _verify(
|
def _verify(
|
||||||
self, mock_method, test_method, *,
|
self,
|
||||||
method_args=None, method_kwargs=None, method_result=None,
|
mock_method,
|
||||||
expected_args=None, expected_kwargs=None, expected_result=None,
|
test_method,
|
||||||
|
*,
|
||||||
|
method_args=None,
|
||||||
|
method_kwargs=None,
|
||||||
|
method_result=None,
|
||||||
|
expected_args=None,
|
||||||
|
expected_kwargs=None,
|
||||||
|
expected_result=None,
|
||||||
):
|
):
|
||||||
with mock.patch(mock_method) as mocked:
|
with mock.patch(mock_method) as mocked:
|
||||||
mocked.return_value = expected_result
|
mocked.return_value = expected_result
|
||||||
if any([
|
if any(
|
||||||
method_args,
|
[
|
||||||
method_kwargs,
|
method_args,
|
||||||
expected_args,
|
method_kwargs,
|
||||||
expected_kwargs,
|
expected_args,
|
||||||
]):
|
expected_kwargs,
|
||||||
|
]
|
||||||
|
):
|
||||||
method_args = method_args or ()
|
method_args = method_args or ()
|
||||||
method_kwargs = method_kwargs or {}
|
method_kwargs = method_kwargs or {}
|
||||||
expected_args = expected_args or ()
|
expected_args = expected_args or ()
|
||||||
@ -77,9 +86,16 @@ class TestProxyBase(base.TestCase):
|
|||||||
mocked.assert_called_with(test_method.__self__)
|
mocked.assert_called_with(test_method.__self__)
|
||||||
|
|
||||||
def verify_create(
|
def verify_create(
|
||||||
self, test_method, resource_type, base_path=None, *,
|
self,
|
||||||
method_args=None, method_kwargs=None,
|
test_method,
|
||||||
expected_args=None, expected_kwargs=None, expected_result="result",
|
resource_type,
|
||||||
|
base_path=None,
|
||||||
|
*,
|
||||||
|
method_args=None,
|
||||||
|
method_kwargs=None,
|
||||||
|
expected_args=None,
|
||||||
|
expected_kwargs=None,
|
||||||
|
expected_result="result",
|
||||||
mock_method="openstack.proxy.Proxy._create",
|
mock_method="openstack.proxy.Proxy._create",
|
||||||
):
|
):
|
||||||
if method_args is None:
|
if method_args is None:
|
||||||
@ -103,9 +119,15 @@ class TestProxyBase(base.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def verify_delete(
|
def verify_delete(
|
||||||
self, test_method, resource_type, ignore_missing=True, *,
|
self,
|
||||||
method_args=None, method_kwargs=None,
|
test_method,
|
||||||
expected_args=None, expected_kwargs=None,
|
resource_type,
|
||||||
|
ignore_missing=True,
|
||||||
|
*,
|
||||||
|
method_args=None,
|
||||||
|
method_kwargs=None,
|
||||||
|
expected_args=None,
|
||||||
|
expected_kwargs=None,
|
||||||
mock_method="openstack.proxy.Proxy._delete",
|
mock_method="openstack.proxy.Proxy._delete",
|
||||||
):
|
):
|
||||||
if method_args is None:
|
if method_args is None:
|
||||||
@ -128,9 +150,16 @@ class TestProxyBase(base.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def verify_get(
|
def verify_get(
|
||||||
self, test_method, resource_type, requires_id=False, base_path=None, *,
|
self,
|
||||||
method_args=None, method_kwargs=None,
|
test_method,
|
||||||
expected_args=None, expected_kwargs=None,
|
resource_type,
|
||||||
|
requires_id=False,
|
||||||
|
base_path=None,
|
||||||
|
*,
|
||||||
|
method_args=None,
|
||||||
|
method_kwargs=None,
|
||||||
|
expected_args=None,
|
||||||
|
expected_kwargs=None,
|
||||||
mock_method="openstack.proxy.Proxy._get",
|
mock_method="openstack.proxy.Proxy._get",
|
||||||
):
|
):
|
||||||
if method_args is None:
|
if method_args is None:
|
||||||
@ -156,15 +185,23 @@ class TestProxyBase(base.TestCase):
|
|||||||
proxy._get_resource = mock.Mock(return_value=res)
|
proxy._get_resource = mock.Mock(return_value=res)
|
||||||
proxy._get(resource_type)
|
proxy._get(resource_type)
|
||||||
res.fetch.assert_called_once_with(
|
res.fetch.assert_called_once_with(
|
||||||
proxy, requires_id=True,
|
proxy,
|
||||||
|
requires_id=True,
|
||||||
base_path=None,
|
base_path=None,
|
||||||
error_message=mock.ANY,
|
error_message=mock.ANY,
|
||||||
skip_cache=False)
|
skip_cache=False,
|
||||||
|
)
|
||||||
|
|
||||||
def verify_head(
|
def verify_head(
|
||||||
self, test_method, resource_type, base_path=None, *,
|
self,
|
||||||
method_args=None, method_kwargs=None,
|
test_method,
|
||||||
expected_args=None, expected_kwargs=None,
|
resource_type,
|
||||||
|
base_path=None,
|
||||||
|
*,
|
||||||
|
method_args=None,
|
||||||
|
method_kwargs=None,
|
||||||
|
expected_args=None,
|
||||||
|
expected_kwargs=None,
|
||||||
mock_method="openstack.proxy.Proxy._head",
|
mock_method="openstack.proxy.Proxy._head",
|
||||||
):
|
):
|
||||||
if method_args is None:
|
if method_args is None:
|
||||||
@ -184,10 +221,16 @@ class TestProxyBase(base.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def verify_find(
|
def verify_find(
|
||||||
self, test_method, resource_type, name_or_id='resource_name',
|
self,
|
||||||
ignore_missing=True, *,
|
test_method,
|
||||||
method_args=None, method_kwargs=None,
|
resource_type,
|
||||||
expected_args=None, expected_kwargs=None,
|
name_or_id='resource_name',
|
||||||
|
ignore_missing=True,
|
||||||
|
*,
|
||||||
|
method_args=None,
|
||||||
|
method_kwargs=None,
|
||||||
|
expected_args=None,
|
||||||
|
expected_kwargs=None,
|
||||||
mock_method="openstack.proxy.Proxy._find",
|
mock_method="openstack.proxy.Proxy._find",
|
||||||
):
|
):
|
||||||
method_args = [name_or_id] + (method_args or [])
|
method_args = [name_or_id] + (method_args or [])
|
||||||
@ -206,9 +249,16 @@ class TestProxyBase(base.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def verify_list(
|
def verify_list(
|
||||||
self, test_method, resource_type, paginated=None, base_path=None, *,
|
self,
|
||||||
method_args=None, method_kwargs=None,
|
test_method,
|
||||||
expected_args=None, expected_kwargs=None,
|
resource_type,
|
||||||
|
paginated=None,
|
||||||
|
base_path=None,
|
||||||
|
*,
|
||||||
|
method_args=None,
|
||||||
|
method_kwargs=None,
|
||||||
|
expected_args=None,
|
||||||
|
expected_kwargs=None,
|
||||||
mock_method="openstack.proxy.Proxy._list",
|
mock_method="openstack.proxy.Proxy._list",
|
||||||
):
|
):
|
||||||
if method_args is None:
|
if method_args is None:
|
||||||
@ -234,9 +284,16 @@ class TestProxyBase(base.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def verify_update(
|
def verify_update(
|
||||||
self, test_method, resource_type, base_path=None, *,
|
self,
|
||||||
method_args=None, method_kwargs=None,
|
test_method,
|
||||||
expected_args=None, expected_kwargs=None, expected_result="result",
|
resource_type,
|
||||||
|
base_path=None,
|
||||||
|
*,
|
||||||
|
method_args=None,
|
||||||
|
method_kwargs=None,
|
||||||
|
expected_args=None,
|
||||||
|
expected_kwargs=None,
|
||||||
|
expected_result="result",
|
||||||
mock_method="openstack.proxy.Proxy._update",
|
mock_method="openstack.proxy.Proxy._update",
|
||||||
):
|
):
|
||||||
if method_args is None:
|
if method_args is None:
|
||||||
@ -259,7 +316,8 @@ class TestProxyBase(base.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def verify_wait_for_status(
|
def verify_wait_for_status(
|
||||||
self, test_method,
|
self,
|
||||||
|
test_method,
|
||||||
mock_method="openstack.resource.wait_for_status",
|
mock_method="openstack.resource.wait_for_status",
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -66,16 +66,17 @@ class StatsdFixture(fixtures.Fixture):
|
|||||||
|
|
||||||
|
|
||||||
class TestStats(base.TestCase):
|
class TestStats(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.statsd = StatsdFixture()
|
self.statsd = StatsdFixture()
|
||||||
self.useFixture(self.statsd)
|
self.useFixture(self.statsd)
|
||||||
# note, use 127.0.0.1 rather than localhost to avoid getting ipv6
|
# note, use 127.0.0.1 rather than localhost to avoid getting ipv6
|
||||||
# see: https://github.com/jsocol/pystatsd/issues/61
|
# see: https://github.com/jsocol/pystatsd/issues/61
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('STATSD_HOST', '127.0.0.1'))
|
fixtures.EnvironmentVariable('STATSD_HOST', '127.0.0.1')
|
||||||
|
)
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.EnvironmentVariable('STATSD_PORT', str(self.statsd.port)))
|
fixtures.EnvironmentVariable('STATSD_PORT', str(self.statsd.port))
|
||||||
|
)
|
||||||
|
|
||||||
self.add_info_on_exception('statsd_content', self.statsd.stats)
|
self.add_info_on_exception('statsd_content', self.statsd.stats)
|
||||||
# Set up the above things before the super setup so that we have the
|
# Set up the above things before the super setup so that we have the
|
||||||
@ -93,7 +94,8 @@ class TestStats(base.TestCase):
|
|||||||
samples.append(s)
|
samples.append(s)
|
||||||
self.addDetail(
|
self.addDetail(
|
||||||
'prometheus_samples',
|
'prometheus_samples',
|
||||||
testtools.content.text_content(pprint.pformat(samples)))
|
testtools.content.text_content(pprint.pformat(samples)),
|
||||||
|
)
|
||||||
|
|
||||||
def assert_reported_stat(self, key, value=None, kind=None):
|
def assert_reported_stat(self, key, value=None, kind=None):
|
||||||
"""Check statsd output
|
"""Check statsd output
|
||||||
@ -127,7 +129,8 @@ class TestStats(base.TestCase):
|
|||||||
# newlines; thus we first flatten the stats out into
|
# newlines; thus we first flatten the stats out into
|
||||||
# single entries.
|
# single entries.
|
||||||
stats = itertools.chain.from_iterable(
|
stats = itertools.chain.from_iterable(
|
||||||
[s.decode('utf-8').split('\n') for s in self.statsd.stats])
|
[s.decode('utf-8').split('\n') for s in self.statsd.stats]
|
||||||
|
)
|
||||||
for stat in stats:
|
for stat in stats:
|
||||||
k, v = stat.split(':')
|
k, v = stat.split(':')
|
||||||
if key == k:
|
if key == k:
|
||||||
@ -166,127 +169,184 @@ class TestStats(base.TestCase):
|
|||||||
def test_list_projects(self):
|
def test_list_projects(self):
|
||||||
|
|
||||||
mock_uri = self.get_mock_url(
|
mock_uri = self.get_mock_url(
|
||||||
service_type='identity', resource='projects',
|
service_type='identity', resource='projects', base_url_append='v3'
|
||||||
base_url_append='v3')
|
)
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET', uri=mock_uri, status_code=200,
|
[
|
||||||
json={'projects': []})])
|
dict(
|
||||||
|
method='GET',
|
||||||
|
uri=mock_uri,
|
||||||
|
status_code=200,
|
||||||
|
json={'projects': []},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
self.cloud.list_projects()
|
self.cloud.list_projects()
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
|
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.identity.GET.projects.200', value='1', kind='c')
|
'openstack.api.identity.GET.projects.200', value='1', kind='c'
|
||||||
|
)
|
||||||
self.assert_prometheus_stat(
|
self.assert_prometheus_stat(
|
||||||
'openstack_http_requests_total', 1, dict(
|
'openstack_http_requests_total',
|
||||||
|
1,
|
||||||
|
dict(
|
||||||
service_type='identity',
|
service_type='identity',
|
||||||
endpoint=mock_uri,
|
endpoint=mock_uri,
|
||||||
method='GET',
|
method='GET',
|
||||||
status_code='200'))
|
status_code='200',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def test_projects(self):
|
def test_projects(self):
|
||||||
mock_uri = self.get_mock_url(
|
mock_uri = self.get_mock_url(
|
||||||
service_type='identity', resource='projects',
|
service_type='identity', resource='projects', base_url_append='v3'
|
||||||
base_url_append='v3')
|
)
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET', uri=mock_uri, status_code=200,
|
[
|
||||||
json={'projects': []})])
|
dict(
|
||||||
|
method='GET',
|
||||||
|
uri=mock_uri,
|
||||||
|
status_code=200,
|
||||||
|
json={'projects': []},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
list(self.cloud.identity.projects())
|
list(self.cloud.identity.projects())
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
|
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.identity.GET.projects.200', value='1', kind='c')
|
'openstack.api.identity.GET.projects.200', value='1', kind='c'
|
||||||
|
)
|
||||||
self.assert_prometheus_stat(
|
self.assert_prometheus_stat(
|
||||||
'openstack_http_requests_total', 1, dict(
|
'openstack_http_requests_total',
|
||||||
|
1,
|
||||||
|
dict(
|
||||||
service_type='identity',
|
service_type='identity',
|
||||||
endpoint=mock_uri,
|
endpoint=mock_uri,
|
||||||
method='GET',
|
method='GET',
|
||||||
status_code='200'))
|
status_code='200',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def test_servers(self):
|
def test_servers(self):
|
||||||
|
|
||||||
mock_uri = 'https://compute.example.com/v2.1/servers/detail'
|
mock_uri = 'https://compute.example.com/v2.1/servers/detail'
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
self.get_nova_discovery_mock_dict(),
|
[
|
||||||
dict(method='GET', uri=mock_uri, status_code=200,
|
self.get_nova_discovery_mock_dict(),
|
||||||
json={'servers': []})])
|
dict(
|
||||||
|
method='GET',
|
||||||
|
uri=mock_uri,
|
||||||
|
status_code=200,
|
||||||
|
json={'servers': []},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
list(self.cloud.compute.servers())
|
list(self.cloud.compute.servers())
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
|
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.compute.GET.servers_detail.200',
|
'openstack.api.compute.GET.servers_detail.200', value='1', kind='c'
|
||||||
value='1', kind='c')
|
)
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.compute.GET.servers_detail.200',
|
'openstack.api.compute.GET.servers_detail.200',
|
||||||
value='0', kind='ms')
|
value='0',
|
||||||
|
kind='ms',
|
||||||
|
)
|
||||||
self.assert_prometheus_stat(
|
self.assert_prometheus_stat(
|
||||||
'openstack_http_requests_total', 1, dict(
|
'openstack_http_requests_total',
|
||||||
|
1,
|
||||||
|
dict(
|
||||||
service_type='compute',
|
service_type='compute',
|
||||||
endpoint=mock_uri,
|
endpoint=mock_uri,
|
||||||
method='GET',
|
method='GET',
|
||||||
status_code='200'))
|
status_code='200',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def test_servers_no_detail(self):
|
def test_servers_no_detail(self):
|
||||||
|
|
||||||
mock_uri = 'https://compute.example.com/v2.1/servers'
|
mock_uri = 'https://compute.example.com/v2.1/servers'
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET', uri=mock_uri, status_code=200,
|
[
|
||||||
json={'servers': []})])
|
dict(
|
||||||
|
method='GET',
|
||||||
|
uri=mock_uri,
|
||||||
|
status_code=200,
|
||||||
|
json={'servers': []},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
self.cloud.compute.get('/servers')
|
self.cloud.compute.get('/servers')
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
|
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.compute.GET.servers.200', value='1', kind='c')
|
'openstack.api.compute.GET.servers.200', value='1', kind='c'
|
||||||
|
)
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.compute.GET.servers.200', value='0', kind='ms')
|
'openstack.api.compute.GET.servers.200', value='0', kind='ms'
|
||||||
|
)
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.compute.GET.servers.attempted', value='1', kind='c')
|
'openstack.api.compute.GET.servers.attempted', value='1', kind='c'
|
||||||
|
)
|
||||||
self.assert_prometheus_stat(
|
self.assert_prometheus_stat(
|
||||||
'openstack_http_requests_total', 1, dict(
|
'openstack_http_requests_total',
|
||||||
|
1,
|
||||||
|
dict(
|
||||||
service_type='compute',
|
service_type='compute',
|
||||||
endpoint=mock_uri,
|
endpoint=mock_uri,
|
||||||
method='GET',
|
method='GET',
|
||||||
status_code='200'))
|
status_code='200',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def test_servers_error(self):
|
def test_servers_error(self):
|
||||||
|
|
||||||
mock_uri = 'https://compute.example.com/v2.1/servers'
|
mock_uri = 'https://compute.example.com/v2.1/servers'
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET', uri=mock_uri, status_code=500,
|
[dict(method='GET', uri=mock_uri, status_code=500, json={})]
|
||||||
json={})])
|
)
|
||||||
|
|
||||||
self.cloud.compute.get('/servers')
|
self.cloud.compute.get('/servers')
|
||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
|
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.compute.GET.servers.500', value='1', kind='c')
|
'openstack.api.compute.GET.servers.500', value='1', kind='c'
|
||||||
|
)
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.compute.GET.servers.500', value='0', kind='ms')
|
'openstack.api.compute.GET.servers.500', value='0', kind='ms'
|
||||||
|
)
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.compute.GET.servers.attempted', value='1', kind='c')
|
'openstack.api.compute.GET.servers.attempted', value='1', kind='c'
|
||||||
|
)
|
||||||
self.assert_prometheus_stat(
|
self.assert_prometheus_stat(
|
||||||
'openstack_http_requests_total', 1, dict(
|
'openstack_http_requests_total',
|
||||||
|
1,
|
||||||
|
dict(
|
||||||
service_type='compute',
|
service_type='compute',
|
||||||
endpoint=mock_uri,
|
endpoint=mock_uri,
|
||||||
method='GET',
|
method='GET',
|
||||||
status_code='500'))
|
status_code='500',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def test_timeout(self):
|
def test_timeout(self):
|
||||||
|
|
||||||
mock_uri = 'https://compute.example.com/v2.1/servers'
|
mock_uri = 'https://compute.example.com/v2.1/servers'
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET', uri=mock_uri,
|
[dict(method='GET', uri=mock_uri, exc=rexceptions.ConnectTimeout)]
|
||||||
exc=rexceptions.ConnectTimeout)
|
)
|
||||||
])
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.cloud.compute.get('/servers')
|
self.cloud.compute.get('/servers')
|
||||||
@ -294,13 +354,14 @@ class TestStats(base.TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.compute.GET.servers.failed', value='1', kind='c')
|
'openstack.api.compute.GET.servers.failed', value='1', kind='c'
|
||||||
|
)
|
||||||
self.assert_reported_stat(
|
self.assert_reported_stat(
|
||||||
'openstack.api.compute.GET.servers.attempted', value='1', kind='c')
|
'openstack.api.compute.GET.servers.attempted', value='1', kind='c'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestNoStats(base.TestCase):
|
class TestNoStats(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestNoStats, self).setUp()
|
super(TestNoStats, self).setUp()
|
||||||
self.statsd = StatsdFixture()
|
self.statsd = StatsdFixture()
|
||||||
@ -309,12 +370,19 @@ class TestNoStats(base.TestCase):
|
|||||||
def test_no_stats(self):
|
def test_no_stats(self):
|
||||||
|
|
||||||
mock_uri = self.get_mock_url(
|
mock_uri = self.get_mock_url(
|
||||||
service_type='identity', resource='projects',
|
service_type='identity', resource='projects', base_url_append='v3'
|
||||||
base_url_append='v3')
|
)
|
||||||
|
|
||||||
self.register_uris([
|
self.register_uris(
|
||||||
dict(method='GET', uri=mock_uri, status_code=200,
|
[
|
||||||
json={'projects': []})])
|
dict(
|
||||||
|
method='GET',
|
||||||
|
uri=mock_uri,
|
||||||
|
status_code=200,
|
||||||
|
json={'projects': []},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
self.cloud.identity._statsd_client = None
|
self.cloud.identity._statsd_client = None
|
||||||
list(self.cloud.identity.projects())
|
list(self.cloud.identity.projects())
|
||||||
|
@ -29,7 +29,6 @@ from openstack import utils
|
|||||||
|
|
||||||
|
|
||||||
class Test_enable_logging(base.TestCase):
|
class Test_enable_logging(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(Test_enable_logging, self).setUp()
|
super(Test_enable_logging, self).setUp()
|
||||||
self.openstack_logger = mock.Mock()
|
self.openstack_logger = mock.Mock()
|
||||||
@ -54,10 +53,11 @@ class Test_enable_logging(base.TestCase):
|
|||||||
self.stevedore_logger,
|
self.stevedore_logger,
|
||||||
self.ksa_logger_1,
|
self.ksa_logger_1,
|
||||||
self.ksa_logger_2,
|
self.ksa_logger_2,
|
||||||
self.ksa_logger_3
|
self.ksa_logger_3,
|
||||||
]
|
]
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.MonkeyPatch('logging.getLogger', self.fake_get_logger))
|
fixtures.MonkeyPatch('logging.getLogger', self.fake_get_logger)
|
||||||
|
)
|
||||||
|
|
||||||
def _console_tests(self, level, debug, stream):
|
def _console_tests(self, level, debug, stream):
|
||||||
|
|
||||||
@ -69,7 +69,8 @@ class Test_enable_logging(base.TestCase):
|
|||||||
def _file_tests(self, level, debug):
|
def _file_tests(self, level, debug):
|
||||||
file_handler = mock.Mock()
|
file_handler = mock.Mock()
|
||||||
self.useFixture(
|
self.useFixture(
|
||||||
fixtures.MonkeyPatch('logging.FileHandler', file_handler))
|
fixtures.MonkeyPatch('logging.FileHandler', file_handler)
|
||||||
|
)
|
||||||
fake_path = "fake/path.log"
|
fake_path = "fake/path.log"
|
||||||
|
|
||||||
openstack.enable_logging(debug=debug, path=fake_path)
|
openstack.enable_logging(debug=debug, path=fake_path)
|
||||||
@ -85,7 +86,8 @@ class Test_enable_logging(base.TestCase):
|
|||||||
self.assertEqual(self.openstack_logger.addHandler.call_count, 1)
|
self.assertEqual(self.openstack_logger.addHandler.call_count, 1)
|
||||||
self.assertIsInstance(
|
self.assertIsInstance(
|
||||||
self.openstack_logger.addHandler.call_args_list[0][0][0],
|
self.openstack_logger.addHandler.call_args_list[0][0][0],
|
||||||
logging.StreamHandler)
|
logging.StreamHandler,
|
||||||
|
)
|
||||||
|
|
||||||
def test_debug_console_stderr(self):
|
def test_debug_console_stderr(self):
|
||||||
self._console_tests(logging.DEBUG, True, sys.stderr)
|
self._console_tests(logging.DEBUG, True, sys.stderr)
|
||||||
@ -107,7 +109,6 @@ class Test_enable_logging(base.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class Test_urljoin(base.TestCase):
|
class Test_urljoin(base.TestCase):
|
||||||
|
|
||||||
def test_strings(self):
|
def test_strings(self):
|
||||||
root = "http://www.example.com"
|
root = "http://www.example.com"
|
||||||
leaves = "foo", "bar"
|
leaves = "foo", "bar"
|
||||||
@ -138,21 +139,20 @@ class TestSupportsMicroversion(base.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestSupportsMicroversion, self).setUp()
|
super(TestSupportsMicroversion, self).setUp()
|
||||||
self.adapter = mock.Mock(spec=['get_endpoint_data'])
|
self.adapter = mock.Mock(spec=['get_endpoint_data'])
|
||||||
self.endpoint_data = mock.Mock(spec=['min_microversion',
|
self.endpoint_data = mock.Mock(
|
||||||
'max_microversion'],
|
spec=['min_microversion', 'max_microversion'],
|
||||||
min_microversion='1.1',
|
min_microversion='1.1',
|
||||||
max_microversion='1.99')
|
max_microversion='1.99',
|
||||||
|
)
|
||||||
self.adapter.get_endpoint_data.return_value = self.endpoint_data
|
self.adapter.get_endpoint_data.return_value = self.endpoint_data
|
||||||
|
|
||||||
def test_requested_supported_no_default(self):
|
def test_requested_supported_no_default(self):
|
||||||
self.adapter.default_microversion = None
|
self.adapter.default_microversion = None
|
||||||
self.assertTrue(
|
self.assertTrue(utils.supports_microversion(self.adapter, '1.2'))
|
||||||
utils.supports_microversion(self.adapter, '1.2'))
|
|
||||||
|
|
||||||
def test_requested_not_supported_no_default(self):
|
def test_requested_not_supported_no_default(self):
|
||||||
self.adapter.default_microversion = None
|
self.adapter.default_microversion = None
|
||||||
self.assertFalse(
|
self.assertFalse(utils.supports_microversion(self.adapter, '2.2'))
|
||||||
utils.supports_microversion(self.adapter, '2.2'))
|
|
||||||
|
|
||||||
def test_requested_not_supported_no_default_exception(self):
|
def test_requested_not_supported_no_default_exception(self):
|
||||||
self.adapter.default_microversion = None
|
self.adapter.default_microversion = None
|
||||||
@ -161,22 +161,20 @@ class TestSupportsMicroversion(base.TestCase):
|
|||||||
utils.supports_microversion,
|
utils.supports_microversion,
|
||||||
self.adapter,
|
self.adapter,
|
||||||
'2.2',
|
'2.2',
|
||||||
True)
|
True,
|
||||||
|
)
|
||||||
|
|
||||||
def test_requested_supported_higher_default(self):
|
def test_requested_supported_higher_default(self):
|
||||||
self.adapter.default_microversion = '1.8'
|
self.adapter.default_microversion = '1.8'
|
||||||
self.assertTrue(
|
self.assertTrue(utils.supports_microversion(self.adapter, '1.6'))
|
||||||
utils.supports_microversion(self.adapter, '1.6'))
|
|
||||||
|
|
||||||
def test_requested_supported_equal_default(self):
|
def test_requested_supported_equal_default(self):
|
||||||
self.adapter.default_microversion = '1.8'
|
self.adapter.default_microversion = '1.8'
|
||||||
self.assertTrue(
|
self.assertTrue(utils.supports_microversion(self.adapter, '1.8'))
|
||||||
utils.supports_microversion(self.adapter, '1.8'))
|
|
||||||
|
|
||||||
def test_requested_supported_lower_default(self):
|
def test_requested_supported_lower_default(self):
|
||||||
self.adapter.default_microversion = '1.2'
|
self.adapter.default_microversion = '1.2'
|
||||||
self.assertFalse(
|
self.assertFalse(utils.supports_microversion(self.adapter, '1.8'))
|
||||||
utils.supports_microversion(self.adapter, '1.8'))
|
|
||||||
|
|
||||||
def test_requested_supported_lower_default_exception(self):
|
def test_requested_supported_lower_default_exception(self):
|
||||||
self.adapter.default_microversion = '1.2'
|
self.adapter.default_microversion = '1.2'
|
||||||
@ -185,54 +183,58 @@ class TestSupportsMicroversion(base.TestCase):
|
|||||||
utils.supports_microversion,
|
utils.supports_microversion,
|
||||||
self.adapter,
|
self.adapter,
|
||||||
'1.8',
|
'1.8',
|
||||||
True)
|
True,
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch('openstack.utils.supports_microversion')
|
@mock.patch('openstack.utils.supports_microversion')
|
||||||
def test_require_microversion(self, sm_mock):
|
def test_require_microversion(self, sm_mock):
|
||||||
utils.require_microversion(self.adapter, '1.2')
|
utils.require_microversion(self.adapter, '1.2')
|
||||||
sm_mock.assert_called_with(self.adapter,
|
sm_mock.assert_called_with(self.adapter, '1.2', raise_exception=True)
|
||||||
'1.2',
|
|
||||||
raise_exception=True)
|
|
||||||
|
|
||||||
|
|
||||||
class TestMaximumSupportedMicroversion(base.TestCase):
|
class TestMaximumSupportedMicroversion(base.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestMaximumSupportedMicroversion, self).setUp()
|
super(TestMaximumSupportedMicroversion, self).setUp()
|
||||||
self.adapter = mock.Mock(spec=['get_endpoint_data'])
|
self.adapter = mock.Mock(spec=['get_endpoint_data'])
|
||||||
self.endpoint_data = mock.Mock(spec=['min_microversion',
|
self.endpoint_data = mock.Mock(
|
||||||
'max_microversion'],
|
spec=['min_microversion', 'max_microversion'],
|
||||||
min_microversion=None,
|
min_microversion=None,
|
||||||
max_microversion='1.99')
|
max_microversion='1.99',
|
||||||
|
)
|
||||||
self.adapter.get_endpoint_data.return_value = self.endpoint_data
|
self.adapter.get_endpoint_data.return_value = self.endpoint_data
|
||||||
|
|
||||||
def test_with_none(self):
|
def test_with_none(self):
|
||||||
self.assertIsNone(utils.maximum_supported_microversion(self.adapter,
|
self.assertIsNone(
|
||||||
None))
|
utils.maximum_supported_microversion(self.adapter, None)
|
||||||
|
)
|
||||||
|
|
||||||
def test_with_value(self):
|
def test_with_value(self):
|
||||||
self.assertEqual('1.42',
|
self.assertEqual(
|
||||||
utils.maximum_supported_microversion(self.adapter,
|
'1.42', utils.maximum_supported_microversion(self.adapter, '1.42')
|
||||||
'1.42'))
|
)
|
||||||
|
|
||||||
def test_value_more_than_max(self):
|
def test_value_more_than_max(self):
|
||||||
self.assertEqual('1.99',
|
self.assertEqual(
|
||||||
utils.maximum_supported_microversion(self.adapter,
|
'1.99', utils.maximum_supported_microversion(self.adapter, '1.100')
|
||||||
'1.100'))
|
)
|
||||||
|
|
||||||
def test_value_less_than_min(self):
|
def test_value_less_than_min(self):
|
||||||
self.endpoint_data.min_microversion = '1.42'
|
self.endpoint_data.min_microversion = '1.42'
|
||||||
self.assertIsNone(utils.maximum_supported_microversion(self.adapter,
|
self.assertIsNone(
|
||||||
'1.2'))
|
utils.maximum_supported_microversion(self.adapter, '1.2')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestOsServiceTypesVersion(base.TestCase):
|
class TestOsServiceTypesVersion(base.TestCase):
|
||||||
def test_ost_version(self):
|
def test_ost_version(self):
|
||||||
ost_version = '2019-05-01T19:53:21.498745'
|
ost_version = '2019-05-01T19:53:21.498745'
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
ost_version, os_service_types.ServiceTypes().version,
|
ost_version,
|
||||||
|
os_service_types.ServiceTypes().version,
|
||||||
"This project must be pinned to the latest version of "
|
"This project must be pinned to the latest version of "
|
||||||
"os-service-types. Please bump requirements.txt and "
|
"os-service-types. Please bump requirements.txt and "
|
||||||
"lower-constraints.txt accordingly.")
|
"lower-constraints.txt accordingly.",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestTinyDAG(base.TestCase):
|
class TestTinyDAG(base.TestCase):
|
||||||
@ -243,7 +245,7 @@ class TestTinyDAG(base.TestCase):
|
|||||||
'd': ['e'],
|
'd': ['e'],
|
||||||
'e': [],
|
'e': [],
|
||||||
'f': ['e'],
|
'f': ['e'],
|
||||||
'g': ['e']
|
'g': ['e'],
|
||||||
}
|
}
|
||||||
|
|
||||||
def _verify_order(self, test_graph, test_list):
|
def _verify_order(self, test_graph, test_list):
|
||||||
@ -306,13 +308,13 @@ def test_walker_fn(graph, node, lst):
|
|||||||
|
|
||||||
|
|
||||||
class Test_md5(base.TestCase):
|
class Test_md5(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(Test_md5, self).setUp()
|
super(Test_md5, self).setUp()
|
||||||
self.md5_test_data = "Openstack forever".encode('utf-8')
|
self.md5_test_data = "Openstack forever".encode('utf-8')
|
||||||
try:
|
try:
|
||||||
self.md5_digest = hashlib.md5( # nosec
|
self.md5_digest = hashlib.md5( # nosec
|
||||||
self.md5_test_data).hexdigest()
|
self.md5_test_data
|
||||||
|
).hexdigest()
|
||||||
self.fips_enabled = False
|
self.fips_enabled = False
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.md5_digest = '0d6dc3c588ae71a04ce9a6beebbbba06'
|
self.md5_digest = '0d6dc3c588ae71a04ce9a6beebbbba06'
|
||||||
@ -327,15 +329,17 @@ class Test_md5(base.TestCase):
|
|||||||
# [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
|
# [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
|
||||||
self.assertRaises(ValueError, utils.md5, self.md5_test_data)
|
self.assertRaises(ValueError, utils.md5, self.md5_test_data)
|
||||||
if not self.fips_enabled:
|
if not self.fips_enabled:
|
||||||
digest = utils.md5(self.md5_test_data,
|
digest = utils.md5(
|
||||||
usedforsecurity=True).hexdigest()
|
self.md5_test_data, usedforsecurity=True
|
||||||
|
).hexdigest()
|
||||||
self.assertEqual(digest, self.md5_digest)
|
self.assertEqual(digest, self.md5_digest)
|
||||||
else:
|
else:
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
ValueError, utils.md5, self.md5_test_data,
|
ValueError, utils.md5, self.md5_test_data, usedforsecurity=True
|
||||||
usedforsecurity=True)
|
)
|
||||||
digest = utils.md5(self.md5_test_data,
|
digest = utils.md5(
|
||||||
usedforsecurity=False).hexdigest()
|
self.md5_test_data, usedforsecurity=False
|
||||||
|
).hexdigest()
|
||||||
self.assertEqual(digest, self.md5_digest)
|
self.assertEqual(digest, self.md5_digest)
|
||||||
|
|
||||||
def test_md5_without_data(self):
|
def test_md5_without_data(self):
|
||||||
@ -363,25 +367,25 @@ class Test_md5(base.TestCase):
|
|||||||
self.assertRaises(TypeError, hashlib.md5, u'foo')
|
self.assertRaises(TypeError, hashlib.md5, u'foo')
|
||||||
self.assertRaises(TypeError, utils.md5, u'foo')
|
self.assertRaises(TypeError, utils.md5, u'foo')
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
TypeError, utils.md5, u'foo', usedforsecurity=True)
|
TypeError, utils.md5, u'foo', usedforsecurity=True
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.assertRaises(ValueError, hashlib.md5, u'foo')
|
self.assertRaises(ValueError, hashlib.md5, u'foo')
|
||||||
self.assertRaises(ValueError, utils.md5, u'foo')
|
self.assertRaises(ValueError, utils.md5, u'foo')
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
ValueError, utils.md5, u'foo', usedforsecurity=True)
|
ValueError, utils.md5, u'foo', usedforsecurity=True
|
||||||
self.assertRaises(
|
)
|
||||||
TypeError, utils.md5, u'foo', usedforsecurity=False)
|
self.assertRaises(TypeError, utils.md5, u'foo', usedforsecurity=False)
|
||||||
|
|
||||||
def test_none_data_raises_type_error(self):
|
def test_none_data_raises_type_error(self):
|
||||||
if not self.fips_enabled:
|
if not self.fips_enabled:
|
||||||
self.assertRaises(TypeError, hashlib.md5, None)
|
self.assertRaises(TypeError, hashlib.md5, None)
|
||||||
self.assertRaises(TypeError, utils.md5, None)
|
self.assertRaises(TypeError, utils.md5, None)
|
||||||
self.assertRaises(
|
self.assertRaises(TypeError, utils.md5, None, usedforsecurity=True)
|
||||||
TypeError, utils.md5, None, usedforsecurity=True)
|
|
||||||
else:
|
else:
|
||||||
self.assertRaises(ValueError, hashlib.md5, None)
|
self.assertRaises(ValueError, hashlib.md5, None)
|
||||||
self.assertRaises(ValueError, utils.md5, None)
|
self.assertRaises(ValueError, utils.md5, None)
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
ValueError, utils.md5, None, usedforsecurity=True)
|
ValueError, utils.md5, None, usedforsecurity=True
|
||||||
self.assertRaises(
|
)
|
||||||
TypeError, utils.md5, None, usedforsecurity=False)
|
self.assertRaises(TypeError, utils.md5, None, usedforsecurity=False)
|
||||||
|
@ -57,7 +57,8 @@ def iterate_timeout(timeout, message, wait=2):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
raise exceptions.SDKException(
|
raise exceptions.SDKException(
|
||||||
"Wait value must be an int or float value. {wait} given"
|
"Wait value must be an int or float value. {wait} given"
|
||||||
" instead".format(wait=wait))
|
" instead".format(wait=wait)
|
||||||
|
)
|
||||||
|
|
||||||
start = time.time()
|
start = time.time()
|
||||||
count = 0
|
count = 0
|
||||||
@ -76,6 +77,7 @@ def get_string_format_keys(fmt_string, old_style=True):
|
|||||||
use the old style string formatting.
|
use the old style string formatting.
|
||||||
"""
|
"""
|
||||||
if old_style:
|
if old_style:
|
||||||
|
|
||||||
class AccessSaver:
|
class AccessSaver:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.keys = []
|
self.keys = []
|
||||||
@ -115,25 +117,29 @@ def supports_microversion(adapter, microversion, raise_exception=False):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
endpoint_data = adapter.get_endpoint_data()
|
endpoint_data = adapter.get_endpoint_data()
|
||||||
if (endpoint_data.min_microversion
|
if (
|
||||||
and endpoint_data.max_microversion
|
endpoint_data.min_microversion
|
||||||
and discover.version_between(
|
and endpoint_data.max_microversion
|
||||||
endpoint_data.min_microversion,
|
and discover.version_between(
|
||||||
endpoint_data.max_microversion,
|
endpoint_data.min_microversion,
|
||||||
microversion)):
|
endpoint_data.max_microversion,
|
||||||
|
microversion,
|
||||||
|
)
|
||||||
|
):
|
||||||
if adapter.default_microversion is not None:
|
if adapter.default_microversion is not None:
|
||||||
# If default_microversion is set - evaluate
|
# If default_microversion is set - evaluate
|
||||||
# whether it match the expectation
|
# whether it match the expectation
|
||||||
candidate = discover.normalize_version_number(
|
candidate = discover.normalize_version_number(
|
||||||
adapter.default_microversion)
|
adapter.default_microversion
|
||||||
|
)
|
||||||
required = discover.normalize_version_number(microversion)
|
required = discover.normalize_version_number(microversion)
|
||||||
supports = discover.version_match(required, candidate)
|
supports = discover.version_match(required, candidate)
|
||||||
if raise_exception and not supports:
|
if raise_exception and not supports:
|
||||||
raise exceptions.SDKException(
|
raise exceptions.SDKException(
|
||||||
'Required microversion {ver} is higher than currently '
|
'Required microversion {ver} is higher than currently '
|
||||||
'selected {curr}'.format(
|
'selected {curr}'.format(
|
||||||
ver=microversion,
|
ver=microversion, curr=adapter.default_microversion
|
||||||
curr=adapter.default_microversion)
|
)
|
||||||
)
|
)
|
||||||
return supports
|
return supports
|
||||||
return True
|
return True
|
||||||
@ -175,19 +181,24 @@ def pick_microversion(session, required):
|
|||||||
|
|
||||||
if session.default_microversion is not None:
|
if session.default_microversion is not None:
|
||||||
default = discover.normalize_version_number(
|
default = discover.normalize_version_number(
|
||||||
session.default_microversion)
|
session.default_microversion
|
||||||
|
)
|
||||||
|
|
||||||
if required is None:
|
if required is None:
|
||||||
required = default
|
required = default
|
||||||
else:
|
else:
|
||||||
required = (default if discover.version_match(required, default)
|
required = (
|
||||||
else required)
|
default
|
||||||
|
if discover.version_match(required, default)
|
||||||
|
else required
|
||||||
|
)
|
||||||
|
|
||||||
if required is not None:
|
if required is not None:
|
||||||
if not supports_microversion(session, required):
|
if not supports_microversion(session, required):
|
||||||
raise exceptions.SDKException(
|
raise exceptions.SDKException(
|
||||||
'Requested microversion is not supported by the server side '
|
'Requested microversion is not supported by the server side '
|
||||||
'or the default microversion is too low')
|
'or the default microversion is too low'
|
||||||
|
)
|
||||||
return discover.version_to_string(required)
|
return discover.version_to_string(required)
|
||||||
|
|
||||||
|
|
||||||
@ -212,8 +223,10 @@ def maximum_supported_microversion(adapter, client_maximum):
|
|||||||
|
|
||||||
if endpoint_data is None:
|
if endpoint_data is None:
|
||||||
log = _log.setup_logging('openstack')
|
log = _log.setup_logging('openstack')
|
||||||
log.warning('Cannot determine endpoint data for service %s',
|
log.warning(
|
||||||
adapter.service_type or adapter.service_name)
|
'Cannot determine endpoint data for service %s',
|
||||||
|
adapter.service_type or adapter.service_name,
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not endpoint_data.max_microversion:
|
if not endpoint_data.max_microversion:
|
||||||
@ -221,11 +234,13 @@ def maximum_supported_microversion(adapter, client_maximum):
|
|||||||
|
|
||||||
client_max = discover.normalize_version_number(client_maximum)
|
client_max = discover.normalize_version_number(client_maximum)
|
||||||
server_max = discover.normalize_version_number(
|
server_max = discover.normalize_version_number(
|
||||||
endpoint_data.max_microversion)
|
endpoint_data.max_microversion
|
||||||
|
)
|
||||||
|
|
||||||
if endpoint_data.min_microversion:
|
if endpoint_data.min_microversion:
|
||||||
server_min = discover.normalize_version_number(
|
server_min = discover.normalize_version_number(
|
||||||
endpoint_data.min_microversion)
|
endpoint_data.min_microversion
|
||||||
|
)
|
||||||
if client_max < server_min:
|
if client_max < server_min:
|
||||||
# NOTE(dtantsur): we may want to raise in this case, but this keeps
|
# NOTE(dtantsur): we may want to raise in this case, but this keeps
|
||||||
# the current behavior intact.
|
# the current behavior intact.
|
||||||
@ -265,6 +280,7 @@ try:
|
|||||||
# See https://docs.python.org/3.9/library/hashlib.html
|
# See https://docs.python.org/3.9/library/hashlib.html
|
||||||
md5 = hashlib.md5
|
md5 = hashlib.md5
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
|
||||||
def md5(string=b'', usedforsecurity=True):
|
def md5(string=b'', usedforsecurity=True):
|
||||||
"""Return an md5 hashlib object without usedforsecurity parameter
|
"""Return an md5 hashlib object without usedforsecurity parameter
|
||||||
For python distributions that do not yet support this keyword
|
For python distributions that do not yet support this keyword
|
||||||
@ -314,8 +330,7 @@ class TinyDAG:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def graph(self):
|
def graph(self):
|
||||||
"""Get graph as adjacency dict
|
"""Get graph as adjacency dict"""
|
||||||
"""
|
|
||||||
return self._graph
|
return self._graph
|
||||||
|
|
||||||
def add_node(self, node):
|
def add_node(self, node):
|
||||||
@ -332,8 +347,7 @@ class TinyDAG:
|
|||||||
self.add_edge(k, dep)
|
self.add_edge(k, dep)
|
||||||
|
|
||||||
def walk(self, timeout=None):
|
def walk(self, timeout=None):
|
||||||
"""Start the walking from the beginning.
|
"""Start the walking from the beginning."""
|
||||||
"""
|
|
||||||
if timeout:
|
if timeout:
|
||||||
self._wait_timeout = timeout
|
self._wait_timeout = timeout
|
||||||
return self
|
return self
|
||||||
@ -345,17 +359,16 @@ class TinyDAG:
|
|||||||
def __next__(self):
|
def __next__(self):
|
||||||
# Start waiting if it is expected to get something
|
# Start waiting if it is expected to get something
|
||||||
# (counting down from graph length to 0).
|
# (counting down from graph length to 0).
|
||||||
if (self._it_cnt > 0):
|
if self._it_cnt > 0:
|
||||||
self._it_cnt -= 1
|
self._it_cnt -= 1
|
||||||
try:
|
try:
|
||||||
res = self._queue.get(
|
res = self._queue.get(block=True, timeout=self._wait_timeout)
|
||||||
block=True,
|
|
||||||
timeout=self._wait_timeout)
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
raise exceptions.SDKException('Timeout waiting for '
|
raise exceptions.SDKException(
|
||||||
'cleanup task to complete')
|
'Timeout waiting for ' 'cleanup task to complete'
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
@ -410,13 +423,13 @@ class TinyDAG:
|
|||||||
# it we can have a reduced version.
|
# it we can have a reduced version.
|
||||||
class Munch(dict):
|
class Munch(dict):
|
||||||
"""A slightly stripped version of munch.Munch class"""
|
"""A slightly stripped version of munch.Munch class"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.update(*args, **kwargs)
|
self.update(*args, **kwargs)
|
||||||
|
|
||||||
# only called if k not found in normal places
|
# only called if k not found in normal places
|
||||||
def __getattr__(self, k):
|
def __getattr__(self, k):
|
||||||
"""Gets key if it exists, otherwise throws AttributeError.
|
"""Gets key if it exists, otherwise throws AttributeError."""
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
return object.__getattribute__(self, k)
|
return object.__getattribute__(self, k)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
@ -427,8 +440,8 @@ class Munch(dict):
|
|||||||
|
|
||||||
def __setattr__(self, k, v):
|
def __setattr__(self, k, v):
|
||||||
"""Sets attribute k if it exists, otherwise sets key k. A KeyError
|
"""Sets attribute k if it exists, otherwise sets key k. A KeyError
|
||||||
raised by set-item (only likely if you subclass Munch) will
|
raised by set-item (only likely if you subclass Munch) will
|
||||||
propagate as an AttributeError instead.
|
propagate as an AttributeError instead.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# Throws exception if not in prototype chain
|
# Throws exception if not in prototype chain
|
||||||
@ -459,8 +472,7 @@ class Munch(dict):
|
|||||||
object.__delattr__(self, k)
|
object.__delattr__(self, k)
|
||||||
|
|
||||||
def toDict(self):
|
def toDict(self):
|
||||||
"""Recursively converts a munch back into a dictionary.
|
"""Recursively converts a munch back into a dictionary."""
|
||||||
"""
|
|
||||||
return unmunchify(self)
|
return unmunchify(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -468,7 +480,7 @@ class Munch(dict):
|
|||||||
return self.toDict()
|
return self.toDict()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
"""Invertible* string-form of a Munch. """
|
"""Invertible* string-form of a Munch."""
|
||||||
return f'{self.__class__.__name__}({dict.__repr__(self)})'
|
return f'{self.__class__.__name__}({dict.__repr__(self)})'
|
||||||
|
|
||||||
def __dir__(self):
|
def __dir__(self):
|
||||||
|
@ -197,9 +197,13 @@ htmlhelp_basename = 'shadeReleaseNotesdoc'
|
|||||||
# (source start file, target name, title,
|
# (source start file, target name, title,
|
||||||
# author, documentclass [howto, manual, or own class]).
|
# author, documentclass [howto, manual, or own class]).
|
||||||
latex_documents = [
|
latex_documents = [
|
||||||
('index', 'shadeReleaseNotes.tex',
|
(
|
||||||
'Shade Release Notes Documentation',
|
'index',
|
||||||
'Shade Developers', 'manual'),
|
'shadeReleaseNotes.tex',
|
||||||
|
'Shade Release Notes Documentation',
|
||||||
|
'Shade Developers',
|
||||||
|
'manual',
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top of
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
@ -228,9 +232,13 @@ latex_documents = [
|
|||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (source start file, name, description, authors, manual section).
|
# (source start file, name, description, authors, manual section).
|
||||||
man_pages = [
|
man_pages = [
|
||||||
('index', 'shadereleasenotes',
|
(
|
||||||
'shade Release Notes Documentation',
|
'index',
|
||||||
['shade Developers'], 1)
|
'shadereleasenotes',
|
||||||
|
'shade Release Notes Documentation',
|
||||||
|
['shade Developers'],
|
||||||
|
1,
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
@ -243,11 +251,15 @@ man_pages = [
|
|||||||
# (source start file, target name, title, author,
|
# (source start file, target name, title, author,
|
||||||
# dir menu entry, description, category)
|
# dir menu entry, description, category)
|
||||||
texinfo_documents = [
|
texinfo_documents = [
|
||||||
('index', 'shadeReleaseNotes',
|
(
|
||||||
'shade Release Notes Documentation',
|
'index',
|
||||||
'shade Developers', 'shadeReleaseNotes',
|
'shadeReleaseNotes',
|
||||||
'A client library for interacting with OpenStack clouds',
|
'shade Release Notes Documentation',
|
||||||
'Miscellaneous'),
|
'shade Developers',
|
||||||
|
'shadeReleaseNotes',
|
||||||
|
'A client library for interacting with OpenStack clouds',
|
||||||
|
'Miscellaneous',
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
# Documents to append as an appendix to all manuals.
|
||||||
|
4
setup.py
4
setup.py
@ -16,6 +16,4 @@
|
|||||||
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
|
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
|
||||||
import setuptools
|
import setuptools
|
||||||
|
|
||||||
setuptools.setup(
|
setuptools.setup(setup_requires=['pbr>=2.0.0'], pbr=True)
|
||||||
setup_requires=['pbr>=2.0.0'],
|
|
||||||
pbr=True)
|
|
||||||
|
@ -36,8 +36,9 @@ def print_version(version):
|
|||||||
if version['status'] in ('CURRENT', 'stable'):
|
if version['status'] in ('CURRENT', 'stable'):
|
||||||
print(
|
print(
|
||||||
"\tVersion ID: {id} updated {updated}".format(
|
"\tVersion ID: {id} updated {updated}".format(
|
||||||
id=version.get('id'),
|
id=version.get('id'), updated=version.get('updated')
|
||||||
updated=version.get('updated')))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
verbose = '-v' in sys.argv
|
verbose = '-v' in sys.argv
|
||||||
@ -71,7 +72,8 @@ for cloud in openstack.config.OpenStackConfig().get_all_clouds():
|
|||||||
if port:
|
if port:
|
||||||
stripped = '{stripped}:{port}'.format(stripped=stripped, port=port)
|
stripped = '{stripped}:{port}'.format(stripped=stripped, port=port)
|
||||||
endpoint = urlparse.urlunsplit(
|
endpoint = urlparse.urlunsplit(
|
||||||
(url.scheme, url.netloc, stripped, url.params, url.query))
|
(url.scheme, url.netloc, stripped, url.params, url.query)
|
||||||
|
)
|
||||||
print(" also {endpoint}".format(endpoint=endpoint))
|
print(" also {endpoint}".format(endpoint=endpoint))
|
||||||
try:
|
try:
|
||||||
r = c.get(endpoint).json()
|
r = c.get(endpoint).json()
|
||||||
|
@ -35,22 +35,27 @@ for cloud in openstack.config.OpenStackConfig().get_all_clouds():
|
|||||||
have_current = True
|
have_current = True
|
||||||
print(
|
print(
|
||||||
"\tVersion ID: {id} updated {updated}".format(
|
"\tVersion ID: {id} updated {updated}".format(
|
||||||
id=version.get('id'),
|
id=version.get('id'), updated=version.get('updated')
|
||||||
updated=version.get('updated')))
|
)
|
||||||
|
)
|
||||||
|
print("\tVersion Max: {max}".format(max=version.get('version')))
|
||||||
print(
|
print(
|
||||||
"\tVersion Max: {max}".format(max=version.get('version')))
|
"\tVersion Min: {min}".format(min=version.get('min_version'))
|
||||||
print(
|
)
|
||||||
"\tVersion Min: {min}".format(min=version.get('min_version')))
|
|
||||||
if not have_current:
|
if not have_current:
|
||||||
for version in r['versions']:
|
for version in r['versions']:
|
||||||
if version['status'] == 'SUPPORTED':
|
if version['status'] == 'SUPPORTED':
|
||||||
have_current = True
|
have_current = True
|
||||||
print(
|
print(
|
||||||
"\tVersion ID: {id} updated {updated}".format(
|
"\tVersion ID: {id} updated {updated}".format(
|
||||||
id=version.get('id'),
|
id=version.get('id'), updated=version.get('updated')
|
||||||
updated=version.get('updated')))
|
)
|
||||||
|
)
|
||||||
print(
|
print(
|
||||||
"\tVersion Max: {max}".format(max=version.get('version')))
|
"\tVersion Max: {max}".format(max=version.get('version'))
|
||||||
|
)
|
||||||
print(
|
print(
|
||||||
"\tVersion Min: {min}".format(
|
"\tVersion Min: {min}".format(
|
||||||
min=version.get('min_version')))
|
min=version.get('min_version')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@ -42,16 +42,16 @@ def make_names():
|
|||||||
if desc_class.__module__ != 'openstack.service_description':
|
if desc_class.__module__ != 'openstack.service_description':
|
||||||
base_mod, dm = desc_class.__module__.rsplit('.', 1)
|
base_mod, dm = desc_class.__module__.rsplit('.', 1)
|
||||||
imports.append(
|
imports.append(
|
||||||
'from {base_mod} import {dm}'.format(
|
'from {base_mod} import {dm}'.format(base_mod=base_mod, dm=dm)
|
||||||
base_mod=base_mod,
|
)
|
||||||
dm=dm))
|
|
||||||
else:
|
else:
|
||||||
dm = 'service_description'
|
dm = 'service_description'
|
||||||
|
|
||||||
dc = desc_class.__name__
|
dc = desc_class.__name__
|
||||||
services.append(
|
services.append(
|
||||||
"{st} = {dm}.{dc}(service_type='{service_type}')".format(
|
"{st} = {dm}.{dc}(service_type='{service_type}')".format(
|
||||||
st=st, dm=dm, dc=dc, service_type=service_type),
|
st=st, dm=dm, dc=dc, service_type=service_type
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Register the descriptor class with every known alias. Don't
|
# Register the descriptor class with every known alias. Don't
|
||||||
@ -63,9 +63,8 @@ def make_names():
|
|||||||
if alias_name[-1].isdigit():
|
if alias_name[-1].isdigit():
|
||||||
continue
|
continue
|
||||||
services.append(
|
services.append(
|
||||||
'{alias_name} = {st}'.format(
|
'{alias_name} = {st}'.format(alias_name=alias_name, st=st)
|
||||||
alias_name=alias_name,
|
)
|
||||||
st=st))
|
|
||||||
services.append('')
|
services.append('')
|
||||||
print("# Generated file, to change, run tools/print-services.py")
|
print("# Generated file, to change, run tools/print-services.py")
|
||||||
for imp in sorted(imports):
|
for imp in sorted(imports):
|
||||||
|
Loading…
Reference in New Issue
Block a user