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
|
||||
# [howto/manual]).
|
||||
latex_documents = [
|
||||
('index',
|
||||
'doc-openstacksdk.tex',
|
||||
'OpenStackSDK Documentation',
|
||||
'OpenStack Foundation', 'manual'),
|
||||
(
|
||||
'index',
|
||||
'doc-openstacksdk.tex',
|
||||
'OpenStackSDK Documentation',
|
||||
'OpenStack Foundation',
|
||||
'manual',
|
||||
),
|
||||
]
|
||||
|
||||
# Allow deeper levels of nesting for \begin...\end stanzas
|
||||
|
@ -16,11 +16,11 @@ from openstack import cloud as openstack
|
||||
openstack.enable_logging(debug=True)
|
||||
|
||||
for cloud_name, region_name in [
|
||||
('my-vexxhost', 'ca-ymq-1'),
|
||||
('my-citycloud', 'Buf1'),
|
||||
('my-internap', 'ams01')]:
|
||||
('my-vexxhost', 'ca-ymq-1'),
|
||||
('my-citycloud', 'Buf1'),
|
||||
('my-internap', 'ams01'),
|
||||
]:
|
||||
# Initialize cloud
|
||||
cloud = openstack.connect(
|
||||
cloud=cloud_name, region_name=region_name)
|
||||
cloud = openstack.connect(cloud=cloud_name, region_name=region_name)
|
||||
for server in cloud.search_servers('my-server'):
|
||||
cloud.delete_server(server, wait=True, delete_ips=True)
|
||||
|
@ -16,20 +16,31 @@ from openstack import cloud as openstack
|
||||
openstack.enable_logging(debug=True)
|
||||
|
||||
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-citycloud', 'Buf1', 'Ubuntu 16.04 Xenial Xerus',
|
||||
'0dab10b5-42a2-438e-be7b-505741a7ffcc'),
|
||||
('my-internap', 'ams01', 'Ubuntu 16.04 LTS (Xenial Xerus)',
|
||||
'A1.4')]:
|
||||
(
|
||||
'my-vexxhost',
|
||||
'ca-ymq-1',
|
||||
'Ubuntu 16.04.1 LTS [2017-03-03]',
|
||||
'5cf64088-893b-46b5-9bb1-ee020277635d',
|
||||
),
|
||||
(
|
||||
'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
|
||||
cloud = openstack.connect(
|
||||
cloud=cloud_name, region_name=region_name)
|
||||
cloud = openstack.connect(cloud=cloud_name, region_name=region_name)
|
||||
|
||||
# Boot a server, wait for it to boot, and then do whatever is needed
|
||||
# to get a public ip for it.
|
||||
server = cloud.create_server(
|
||||
'my-server', image=image, flavor=dict(id=flavor_id),
|
||||
wait=True, auto_ip=True)
|
||||
'my-server',
|
||||
image=image,
|
||||
flavor=dict(id=flavor_id),
|
||||
wait=True,
|
||||
auto_ip=True,
|
||||
)
|
||||
# Delete it - this is a demo
|
||||
cloud.delete_server(server, wait=True, delete_ips=True)
|
||||
|
@ -16,21 +16,24 @@ from openstack import cloud as openstack
|
||||
openstack.enable_logging(debug=True)
|
||||
|
||||
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-citycloud', 'Buf1',
|
||||
'Ubuntu 16.04 Xenial Xerus', '4C-4GB-100GB'),
|
||||
('my-internap', 'ams01',
|
||||
'Ubuntu 16.04 LTS (Xenial Xerus)', 'A1.4')]:
|
||||
(
|
||||
'my-vexxhost',
|
||||
'ca-ymq-1',
|
||||
'Ubuntu 16.04.1 LTS [2017-03-03]',
|
||||
'v1-standard-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
|
||||
cloud = openstack.connect(
|
||||
cloud=cloud_name, region_name=region_name)
|
||||
cloud = openstack.connect(cloud=cloud_name, region_name=region_name)
|
||||
cloud.delete_server('my-server', wait=True, delete_ips=True)
|
||||
|
||||
# Boot a server, wait for it to boot, and then do whatever is needed
|
||||
# to get a public ip for it.
|
||||
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'])
|
||||
cloud.pprint(server)
|
||||
|
@ -11,8 +11,8 @@
|
||||
# under the License.
|
||||
|
||||
from openstack import cloud as openstack
|
||||
|
||||
openstack.enable_logging(debug=True)
|
||||
|
||||
cloud = openstack.connect(
|
||||
cloud='my-vexxhost', region_name='ca-ymq-1')
|
||||
cloud = openstack.connect(cloud='my-vexxhost', region_name='ca-ymq-1')
|
||||
cloud.get_image('Ubuntu 16.04.1 LTS [2017-03-03]')
|
||||
|
@ -11,9 +11,10 @@
|
||||
# under the License.
|
||||
|
||||
from openstack import cloud as openstack
|
||||
|
||||
openstack.enable_logging()
|
||||
|
||||
cloud = openstack.connect(cloud='fuga', region_name='cystack')
|
||||
cloud.pprint([
|
||||
image for image in cloud.list_images()
|
||||
if 'ubuntu' in image.name.lower()])
|
||||
cloud.pprint(
|
||||
[image for image in cloud.list_images() if 'ubuntu' in image.name.lower()]
|
||||
)
|
||||
|
@ -11,8 +11,8 @@
|
||||
# under the License.
|
||||
|
||||
from openstack import cloud as openstack
|
||||
|
||||
openstack.enable_logging(http_debug=True)
|
||||
|
||||
cloud = openstack.connect(
|
||||
cloud='my-vexxhost', region_name='ca-ymq-1')
|
||||
cloud = openstack.connect(cloud='my-vexxhost', region_name='ca-ymq-1')
|
||||
cloud.get_image('Ubuntu 16.04.1 LTS [2017-03-03]')
|
||||
|
@ -11,6 +11,7 @@
|
||||
# under the License.
|
||||
|
||||
from openstack import cloud as openstack
|
||||
|
||||
openstack.enable_logging(debug=True)
|
||||
|
||||
cloud = openstack.connect(cloud='ovh', region_name='SBG1')
|
||||
|
@ -11,9 +11,11 @@
|
||||
# under the License.
|
||||
|
||||
from openstack import cloud as openstack
|
||||
|
||||
openstack.enable_logging()
|
||||
|
||||
cloud = openstack.connect(cloud='fuga', region_name='cystack')
|
||||
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)
|
||||
|
@ -11,14 +11,18 @@
|
||||
# under the License.
|
||||
|
||||
import openstack
|
||||
|
||||
openstack.enable_logging(debug=True)
|
||||
|
||||
cloud = openstack.connect(cloud='my-citycloud', region_name='Buf1')
|
||||
try:
|
||||
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'),
|
||||
wait=True, auto_ip=True)
|
||||
wait=True,
|
||||
auto_ip=True,
|
||||
)
|
||||
|
||||
print("\n\nFull Server\n\n")
|
||||
cloud.pprint(server)
|
||||
|
@ -11,6 +11,7 @@
|
||||
# under the License.
|
||||
|
||||
import openstack
|
||||
|
||||
openstack.enable_logging(debug=True)
|
||||
|
||||
cloud = openstack.connect(cloud='rax', region_name='DFW')
|
||||
|
@ -11,6 +11,7 @@
|
||||
# under the License.
|
||||
|
||||
import openstack
|
||||
|
||||
openstack.enable_logging(debug=True)
|
||||
|
||||
cloud = openstack.connect(cloud='kiss', region_name='region1')
|
||||
|
@ -11,10 +11,11 @@
|
||||
# under the License.
|
||||
|
||||
import openstack
|
||||
|
||||
openstack.enable_logging()
|
||||
|
||||
cloud = openstack.connect(
|
||||
cloud='fuga', region_name='cystack', strict=True)
|
||||
cloud = openstack.connect(cloud='fuga', region_name='cystack', strict=True)
|
||||
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)
|
||||
|
@ -11,12 +11,15 @@
|
||||
# under the License.
|
||||
|
||||
import openstack
|
||||
|
||||
openstack.enable_logging(debug=True)
|
||||
|
||||
cloud = openstack.connect(cloud='ovh', region_name='SBG1')
|
||||
cloud.create_object(
|
||||
container='my-container', name='my-object',
|
||||
container='my-container',
|
||||
name='my-object',
|
||||
filename='/home/mordred/briarcliff.sh3d',
|
||||
segment_size=1000000)
|
||||
segment_size=1000000,
|
||||
)
|
||||
cloud.delete_object('my-container', 'my-object')
|
||||
cloud.delete_container('my-container')
|
||||
|
@ -11,12 +11,15 @@
|
||||
# under the License.
|
||||
|
||||
import openstack
|
||||
|
||||
openstack.enable_logging(debug=True)
|
||||
|
||||
cloud = openstack.connect(cloud='ovh', region_name='SBG1')
|
||||
cloud.create_object(
|
||||
container='my-container', name='my-object',
|
||||
container='my-container',
|
||||
name='my-object',
|
||||
filename='/home/mordred/briarcliff.sh3d',
|
||||
segment_size=1000000)
|
||||
segment_size=1000000,
|
||||
)
|
||||
cloud.delete_object('my-container', 'my-object')
|
||||
cloud.delete_container('my-container')
|
||||
|
@ -11,8 +11,10 @@
|
||||
# under the License.
|
||||
|
||||
import openstack
|
||||
|
||||
openstack.enable_logging(http_debug=True)
|
||||
|
||||
cloud = openstack.connect(
|
||||
cloud='datacentred', app_name='AmazingApp', app_version='1.0')
|
||||
cloud='datacentred', app_name='AmazingApp', app_version='1.0'
|
||||
)
|
||||
cloud.list_networks()
|
||||
|
@ -107,9 +107,7 @@ def replace_nodes_in_cluster(conn):
|
||||
|
||||
old_node = NODE_ID
|
||||
new_node = "cd803d4a-015d-4223-b15f-db29bad3146c"
|
||||
spec = {
|
||||
old_node: new_node
|
||||
}
|
||||
spec = {old_node: new_node}
|
||||
res = conn.clustering.replace_nodes_in_cluster(CLUSTER_ID, **spec)
|
||||
print(res)
|
||||
|
||||
@ -135,7 +133,7 @@ def resize_cluster(conn):
|
||||
'min_size': 1,
|
||||
'max_size': 6,
|
||||
'adjustment_type': 'EXACT_CAPACITY',
|
||||
'number': 2
|
||||
'number': 2,
|
||||
}
|
||||
res = conn.clustering.resize_cluster(CLUSTER_ID, **spec)
|
||||
print(res)
|
||||
@ -146,7 +144,8 @@ def attach_policy_to_cluster(conn):
|
||||
|
||||
spec = {'enabled': True}
|
||||
res = conn.clustering.attach_policy_to_cluster(
|
||||
CLUSTER_ID, POLICY_ID, **spec)
|
||||
CLUSTER_ID, POLICY_ID, **spec
|
||||
)
|
||||
print(res)
|
||||
|
||||
|
||||
|
@ -38,8 +38,8 @@ def create_policy(conn):
|
||||
'properties': {
|
||||
'criteria': 'oldest_first',
|
||||
'destroy_after_deletion': True,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
policy = conn.clustering.create_policy(attrs)
|
||||
|
@ -44,10 +44,8 @@ def create_profile(conn):
|
||||
'name': SERVER_NAME,
|
||||
'flavor': FLAVOR_NAME,
|
||||
'image': IMAGE_NAME,
|
||||
'networks': {
|
||||
'network': NETWORK_NAME
|
||||
}
|
||||
}
|
||||
'networks': {'network': NETWORK_NAME},
|
||||
},
|
||||
}
|
||||
|
||||
profile = conn.clustering.create_profile(spec)
|
||||
|
@ -39,10 +39,8 @@ def create_receiver(conn):
|
||||
"action": "CLUSTER_SCALE_OUT",
|
||||
"cluster_id": CLUSTER_ID,
|
||||
"name": FAKE_NAME,
|
||||
"params": {
|
||||
"count": "1"
|
||||
},
|
||||
"type": "webhook"
|
||||
"params": {"count": "1"},
|
||||
"type": "webhook",
|
||||
}
|
||||
|
||||
receiver = conn.clustering.create_receiver(**spec)
|
||||
@ -66,12 +64,7 @@ def find_receiver(conn):
|
||||
def update_receiver(conn):
|
||||
print("Update Receiver:")
|
||||
|
||||
spec = {
|
||||
"name": "test_receiver2",
|
||||
"params": {
|
||||
"count": "2"
|
||||
}
|
||||
}
|
||||
spec = {"name": "test_receiver2", "params": {"count": "2"}}
|
||||
receiver = conn.clustering.update_receiver(FAKE_NAME, **spec)
|
||||
print(receiver.to_dict())
|
||||
|
||||
|
@ -62,11 +62,17 @@ def create_server(conn):
|
||||
keypair = create_keypair(conn)
|
||||
|
||||
server = conn.compute.create_server(
|
||||
name=SERVER_NAME, image_id=image.id, flavor_id=flavor.id,
|
||||
networks=[{"uuid": network.id}], key_name=keypair.name)
|
||||
name=SERVER_NAME,
|
||||
image_id=image.id,
|
||||
flavor_id=flavor.id,
|
||||
networks=[{"uuid": network.id}],
|
||||
key_name=keypair.name,
|
||||
)
|
||||
|
||||
server = conn.compute.wait_for_server(server)
|
||||
|
||||
print("ssh -i {key} root@{ip}".format(
|
||||
key=PRIVATE_KEYPAIR_FILE,
|
||||
ip=server.access_ipv4))
|
||||
print(
|
||||
"ssh -i {key} root@{ip}".format(
|
||||
key=PRIVATE_KEYPAIR_FILE, ip=server.access_ipv4
|
||||
)
|
||||
)
|
||||
|
@ -45,8 +45,9 @@ class Opts:
|
||||
|
||||
|
||||
def _get_resource_value(resource_key, default):
|
||||
return config.get_extra_config(
|
||||
EXAMPLE_CONFIG_KEY).get(resource_key, default)
|
||||
return config.get_extra_config(EXAMPLE_CONFIG_KEY).get(
|
||||
resource_key, default
|
||||
)
|
||||
|
||||
|
||||
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')
|
||||
KEYPAIR_NAME = _get_resource_value('keypair_name', 'openstacksdk-example')
|
||||
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', '{ssh_dir}/id_rsa.{key}'.format(
|
||||
ssh_dir=SSH_DIR, key=KEYPAIR_NAME))
|
||||
'private_keypair_file',
|
||||
'{ssh_dir}/id_rsa.{key}'.format(ssh_dir=SSH_DIR, key=KEYPAIR_NAME),
|
||||
)
|
||||
|
||||
EXAMPLE_IMAGE_NAME = 'openstacksdk-example-public-image'
|
||||
|
||||
@ -72,8 +75,15 @@ def create_connection_from_args():
|
||||
return openstack.connect(options=parser)
|
||||
|
||||
|
||||
def create_connection(auth_url, region, project_name, username, password,
|
||||
user_domain, project_domain):
|
||||
def create_connection(
|
||||
auth_url,
|
||||
region,
|
||||
project_name,
|
||||
username,
|
||||
password,
|
||||
user_domain,
|
||||
project_domain,
|
||||
):
|
||||
return openstack.connect(
|
||||
auth_url=auth_url,
|
||||
project_name=project_name,
|
||||
|
@ -24,8 +24,10 @@ def import_image(conn):
|
||||
print("Import Image:")
|
||||
|
||||
# Url where glance can download the image
|
||||
uri = 'https://download.cirros-cloud.net/0.4.0/' \
|
||||
'cirros-0.4.0-x86_64-disk.img'
|
||||
uri = (
|
||||
'https://download.cirros-cloud.net/0.4.0/'
|
||||
'cirros-0.4.0-x86_64-disk.img'
|
||||
)
|
||||
|
||||
# Build the image attributes and import the image.
|
||||
image_attrs = {
|
||||
|
@ -18,8 +18,10 @@ List resources from the Key Manager service.
|
||||
def create_secret(conn):
|
||||
print("Create a secret:")
|
||||
|
||||
conn.key_manager.create_secret(name="My public key",
|
||||
secret_type="public",
|
||||
expiration="2020-02-28T23:59:59",
|
||||
payload="ssh rsa...",
|
||||
payload_content_type="text/plain")
|
||||
conn.key_manager.create_secret(
|
||||
name="My public key",
|
||||
secret_type="public",
|
||||
expiration="2020-02-28T23:59:59",
|
||||
payload="ssh rsa...",
|
||||
payload_content_type="text/plain",
|
||||
)
|
||||
|
@ -26,6 +26,6 @@ def list_secrets_query(conn):
|
||||
print("List Secrets:")
|
||||
|
||||
for secret in conn.key_manager.secrets(
|
||||
secret_type="symmetric",
|
||||
expiration="gte:2020-01-01T00:00:00"):
|
||||
secret_type="symmetric", expiration="gte:2020-01-01T00:00:00"
|
||||
):
|
||||
print(secret)
|
||||
|
@ -22,7 +22,8 @@ def create_network(conn):
|
||||
print("Create Network:")
|
||||
|
||||
example_network = conn.network.create_network(
|
||||
name='openstacksdk-example-project-network')
|
||||
name='openstacksdk-example-project-network'
|
||||
)
|
||||
|
||||
print(example_network)
|
||||
|
||||
@ -31,6 +32,7 @@ def create_network(conn):
|
||||
network_id=example_network.id,
|
||||
ip_version='4',
|
||||
cidr='10.0.2.0/24',
|
||||
gateway_ip='10.0.2.1')
|
||||
gateway_ip='10.0.2.1',
|
||||
)
|
||||
|
||||
print(example_subnet)
|
||||
|
@ -22,7 +22,8 @@ def delete_network(conn):
|
||||
print("Delete Network:")
|
||||
|
||||
example_network = conn.network.find_network(
|
||||
'openstacksdk-example-project-network')
|
||||
'openstacksdk-example-project-network'
|
||||
)
|
||||
|
||||
for example_subnet in example_network.subnet_ids:
|
||||
conn.network.delete_subnet(example_subnet, ignore_missing=False)
|
||||
|
@ -22,7 +22,8 @@ def open_port(conn):
|
||||
print("Open a port:")
|
||||
|
||||
example_sec_group = conn.network.create_security_group(
|
||||
name='openstacksdk-example-security-group')
|
||||
name='openstacksdk-example-security-group'
|
||||
)
|
||||
|
||||
print(example_sec_group)
|
||||
|
||||
@ -33,7 +34,8 @@ def open_port(conn):
|
||||
protocol='HTTPS',
|
||||
port_range_max='443',
|
||||
port_range_min='443',
|
||||
ethertype='IPv4')
|
||||
ethertype='IPv4',
|
||||
)
|
||||
|
||||
print(example_rule)
|
||||
|
||||
@ -42,7 +44,8 @@ def allow_ping(conn):
|
||||
print("Allow pings:")
|
||||
|
||||
example_sec_group = conn.network.create_security_group(
|
||||
name='openstacksdk-example-security-group2')
|
||||
name='openstacksdk-example-security-group2'
|
||||
)
|
||||
|
||||
print(example_sec_group)
|
||||
|
||||
@ -53,6 +56,7 @@ def allow_ping(conn):
|
||||
protocol='icmp',
|
||||
port_range_max=None,
|
||||
port_range_min=None,
|
||||
ethertype='IPv4')
|
||||
ethertype='IPv4',
|
||||
)
|
||||
|
||||
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):
|
||||
print('Reset the status of the share instance with the given '
|
||||
'share_instance_id to the given status')
|
||||
print(
|
||||
'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)
|
||||
|
||||
|
||||
|
@ -19,16 +19,18 @@ import pbr.version
|
||||
|
||||
|
||||
def show_version(args):
|
||||
print("OpenstackSDK Version %s" %
|
||||
pbr.version.VersionInfo('openstacksdk').version_string_with_vcs())
|
||||
print(
|
||||
"OpenstackSDK Version %s"
|
||||
% pbr.version.VersionInfo('openstacksdk').version_string_with_vcs()
|
||||
)
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description="Openstack SDK")
|
||||
subparsers = parser.add_subparsers(title='commands',
|
||||
dest='command')
|
||||
subparsers = parser.add_subparsers(title='commands', dest='command')
|
||||
|
||||
cmd_version = subparsers.add_parser('version',
|
||||
help='show Openstack SDK version')
|
||||
cmd_version = subparsers.add_parser(
|
||||
'version', help='show Openstack SDK version'
|
||||
)
|
||||
cmd_version.set_defaults(func=show_version)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
@ -44,7 +44,10 @@ def setup_logging(name, handlers=None, level=None):
|
||||
|
||||
|
||||
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_template='%(asctime)s %(levelname)s: %(name)s %(message)s',
|
||||
handlers=None,
|
||||
@ -121,9 +124,11 @@ def enable_logging(
|
||||
# enable_logging should not be used and instead python logging should
|
||||
# be configured directly.
|
||||
setup_logging(
|
||||
'urllib3', handlers=[logging.NullHandler()], level=logging.INFO)
|
||||
'urllib3', handlers=[logging.NullHandler()], level=logging.INFO
|
||||
)
|
||||
setup_logging(
|
||||
'stevedore', handlers=[logging.NullHandler()], level=logging.INFO)
|
||||
'stevedore', handlers=[logging.NullHandler()], level=logging.INFO
|
||||
)
|
||||
# Suppress warning about keystoneauth loggers
|
||||
setup_logging('keystoneauth.discovery')
|
||||
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.clustering import clustering_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.dns import dns_service
|
||||
from openstack.identity import identity_service
|
||||
@ -31,32 +33,52 @@ class ServicesMixin:
|
||||
|
||||
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
|
||||
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')
|
||||
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
|
||||
|
||||
message = message_service.MessageService(service_type='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_infrastructure = container_infrastructure_management
|
||||
|
||||
@ -68,17 +90,27 @@ class ServicesMixin:
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
volume = block_storage
|
||||
|
||||
@ -92,44 +124,69 @@ class ServicesMixin:
|
||||
event = service_description.ServiceDescription(service_type='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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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')
|
||||
|
||||
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 = 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')
|
||||
|
||||
instance_ha = instance_ha_service.InstanceHaService(service_type='instance-ha')
|
||||
instance_ha = instance_ha_service.InstanceHaService(
|
||||
service_type='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
|
||||
|
||||
|
@ -82,14 +82,13 @@ class MetadataMixin:
|
||||
url = utils.urljoin(self.base_path, self.id, 'metadata', key)
|
||||
response = session.get(url)
|
||||
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', {})
|
||||
# Here we need to potentially init metadata
|
||||
metadata = self.metadata or {}
|
||||
metadata[key] = meta.get(key)
|
||||
self._body.attributes.update({
|
||||
'metadata': metadata
|
||||
})
|
||||
self._body.attributes.update({'metadata': metadata})
|
||||
|
||||
return self
|
||||
|
||||
@ -101,17 +100,12 @@ class MetadataMixin:
|
||||
:param str value: The value.
|
||||
"""
|
||||
url = utils.urljoin(self.base_path, self.id, 'metadata', key)
|
||||
response = session.put(
|
||||
url,
|
||||
json={'meta': {key: value}}
|
||||
)
|
||||
response = session.put(url, json={'meta': {key: value}})
|
||||
exceptions.raise_from_response(response)
|
||||
# we do not want to update tags directly
|
||||
metadata = self.metadata
|
||||
metadata[key] = value
|
||||
self._body.attributes.update({
|
||||
'metadata': metadata
|
||||
})
|
||||
self._body.attributes.update({'metadata': metadata})
|
||||
return self
|
||||
|
||||
def delete_metadata_item(self, session, key):
|
||||
@ -132,7 +126,5 @@ class MetadataMixin:
|
||||
metadata = {}
|
||||
except ValueError:
|
||||
pass # do nothing!
|
||||
self._body.attributes.update({
|
||||
'metadata': metadata
|
||||
})
|
||||
self._body.attributes.update({'metadata': metadata})
|
||||
return self
|
||||
|
@ -26,8 +26,7 @@ class QuotaSet(resource.Resource):
|
||||
allow_delete = True
|
||||
allow_commit = True
|
||||
|
||||
_query_mapping = resource.QueryParameters(
|
||||
"usage")
|
||||
_query_mapping = resource.QueryParameters("usage")
|
||||
|
||||
# NOTE(gtema) Sadly this attribute is useless in all the methods, but keep
|
||||
# it here extra as a reminder
|
||||
@ -47,8 +46,14 @@ class QuotaSet(resource.Resource):
|
||||
|
||||
project_id = resource.URI('project_id')
|
||||
|
||||
def fetch(self, session, requires_id=False,
|
||||
base_path=None, error_message=None, **params):
|
||||
def fetch(
|
||||
self,
|
||||
session,
|
||||
requires_id=False,
|
||||
base_path=None,
|
||||
error_message=None,
|
||||
**params
|
||||
):
|
||||
return super(QuotaSet, self).fetch(
|
||||
session,
|
||||
requires_id=False,
|
||||
@ -93,8 +98,9 @@ class QuotaSet(resource.Resource):
|
||||
if 'in_use' in val:
|
||||
normalized_attrs['usage'][key] = val['in_use']
|
||||
if 'reserved' in val:
|
||||
normalized_attrs['reservation'][key] = \
|
||||
val['reserved']
|
||||
normalized_attrs['reservation'][key] = val[
|
||||
'reserved'
|
||||
]
|
||||
if 'limit' in val:
|
||||
normalized_attrs[key] = val['limit']
|
||||
else:
|
||||
|
@ -81,8 +81,9 @@ class TagMixin:
|
||||
url = utils.urljoin(self.base_path, self.id, 'tags', tag)
|
||||
session = self._get_session(session)
|
||||
response = session.get(url)
|
||||
exceptions.raise_from_response(response,
|
||||
error_message='Tag does not exist')
|
||||
exceptions.raise_from_response(
|
||||
response, error_message='Tag does not exist'
|
||||
)
|
||||
return self
|
||||
|
||||
def add_tag(self, session, tag):
|
||||
@ -98,9 +99,7 @@ class TagMixin:
|
||||
# we do not want to update tags directly
|
||||
tags = self.tags
|
||||
tags.append(tag)
|
||||
self._body.attributes.update({
|
||||
'tags': tags
|
||||
})
|
||||
self._body.attributes.update({'tags': tags})
|
||||
return self
|
||||
|
||||
def remove_tag(self, session, tag):
|
||||
@ -121,7 +120,5 @@ class TagMixin:
|
||||
tags.remove(tag)
|
||||
except ValueError:
|
||||
pass # do nothing!
|
||||
self._body.attributes.update({
|
||||
'tags': tags
|
||||
})
|
||||
self._body.attributes.update({'tags': tags})
|
||||
return self
|
||||
|
@ -18,15 +18,20 @@ from openstack.config.loader import OpenStackConfig # noqa
|
||||
|
||||
|
||||
def get_cloud_region(
|
||||
service_key=None, options=None,
|
||||
app_name=None, app_version=None,
|
||||
load_yaml_config=True,
|
||||
load_envvars=True,
|
||||
**kwargs):
|
||||
service_key=None,
|
||||
options=None,
|
||||
app_name=None,
|
||||
app_version=None,
|
||||
load_yaml_config=True,
|
||||
load_envvars=True,
|
||||
**kwargs
|
||||
):
|
||||
config = OpenStackConfig(
|
||||
load_yaml_config=load_yaml_config,
|
||||
load_envvars=load_envvars,
|
||||
app_name=app_name, app_version=app_version)
|
||||
app_name=app_name,
|
||||
app_version=app_version,
|
||||
)
|
||||
if options:
|
||||
config.register_argparse_arguments(options, sys.argv, service_key)
|
||||
parsed_options = options.parse_known_args(sys.argv)
|
||||
|
@ -22,7 +22,9 @@ def normalize_keys(config):
|
||||
elif isinstance(value, bool):
|
||||
new_config[key] = value
|
||||
elif isinstance(value, int) and key not in (
|
||||
'verbose_level', 'api_timeout'):
|
||||
'verbose_level',
|
||||
'api_timeout',
|
||||
):
|
||||
new_config[key] = str(value)
|
||||
elif isinstance(value, float):
|
||||
new_config[key] = str(value)
|
||||
|
@ -18,7 +18,6 @@ from openstack.config import cloud_region
|
||||
|
||||
|
||||
class CloudConfig(cloud_region.CloudRegion):
|
||||
|
||||
def __init__(self, name, region, config, **kwargs):
|
||||
super(CloudConfig, self).__init__(name, region, config, **kwargs)
|
||||
self.region = region
|
||||
|
@ -28,6 +28,7 @@ from keystoneauth1.loading import adapter as ks_load_adap
|
||||
from keystoneauth1 import session as ks_session
|
||||
import os_service_types
|
||||
import requestsexceptions
|
||||
|
||||
try:
|
||||
import statsd
|
||||
except ImportError:
|
||||
@ -52,9 +53,11 @@ from openstack import version as openstack_version
|
||||
_logger = _log.setup_logging('openstack')
|
||||
|
||||
SCOPE_KEYS = {
|
||||
'domain_id', 'domain_name',
|
||||
'project_id', 'project_name',
|
||||
'system_scope'
|
||||
'domain_id',
|
||||
'domain_name',
|
||||
'project_id',
|
||||
'project_name',
|
||||
'system_scope',
|
||||
}
|
||||
|
||||
# Sentinel for nonexistence
|
||||
@ -90,9 +93,15 @@ def _get_implied_microversion(version):
|
||||
return version
|
||||
|
||||
|
||||
def from_session(session, name=None, region_name=None,
|
||||
force_ipv4=False,
|
||||
app_name=None, app_version=None, **kwargs):
|
||||
def from_session(
|
||||
session,
|
||||
name=None,
|
||||
region_name=None,
|
||||
force_ipv4=False,
|
||||
app_name=None,
|
||||
app_version=None,
|
||||
**kwargs
|
||||
):
|
||||
"""Construct a CloudRegion from an existing `keystoneauth1.session.Session`
|
||||
|
||||
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.update(**kwargs)
|
||||
return CloudRegion(
|
||||
name=name, session=session, config=config_dict,
|
||||
region_name=region_name, force_ipv4=force_ipv4,
|
||||
app_name=app_name, app_version=app_version)
|
||||
name=name,
|
||||
session=session,
|
||||
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):
|
||||
@ -160,8 +174,10 @@ def from_conf(conf, session=None, service_types=None, **kwargs):
|
||||
for st in stm.all_types_by_service_type:
|
||||
if service_types is not None and st not in service_types:
|
||||
_disable_service(
|
||||
config_dict, st,
|
||||
reason="Not in the list of requested service_types.")
|
||||
config_dict,
|
||||
st,
|
||||
reason="Not in the list of requested service_types.",
|
||||
)
|
||||
continue
|
||||
project_name = stm.get_project_name(st)
|
||||
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:
|
||||
_disable_service(
|
||||
config_dict, st,
|
||||
config_dict,
|
||||
st,
|
||||
reason="No section for project '{project}' (service type "
|
||||
"'{service_type}') was present in the config."
|
||||
.format(project=project_name, service_type=st))
|
||||
"'{service_type}') was present in the config.".format(
|
||||
project=project_name, service_type=st
|
||||
),
|
||||
)
|
||||
continue
|
||||
opt_dict = {}
|
||||
# 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
|
||||
# get all the way to the point of trying the service and having
|
||||
# *that* blow up.
|
||||
reason = ("Encountered an exception attempting to process config "
|
||||
"for project '{project}' (service type "
|
||||
"'{service_type}'): {exception}".format(
|
||||
project=project_name, service_type=st, exception=e))
|
||||
_logger.warning("Disabling service '{service_type}': "
|
||||
"{reason}".format(service_type=st, reason=reason))
|
||||
reason = (
|
||||
"Encountered an exception attempting to process config "
|
||||
"for project '{project}' (service type "
|
||||
"'{service_type}'): {exception}".format(
|
||||
project=project_name, service_type=st, exception=e
|
||||
)
|
||||
)
|
||||
_logger.warning(
|
||||
"Disabling service '{service_type}': "
|
||||
"{reason}".format(service_type=st, reason=reason)
|
||||
)
|
||||
_disable_service(config_dict, st, reason=reason)
|
||||
continue
|
||||
# Load them into config_dict under keys prefixed by ${service_type}_
|
||||
for raw_name, opt_val in opt_dict.items():
|
||||
config_name = _make_key(raw_name, st)
|
||||
config_dict[config_name] = opt_val
|
||||
return CloudRegion(
|
||||
session=session, config=config_dict, **kwargs)
|
||||
return CloudRegion(session=session, config=config_dict, **kwargs)
|
||||
|
||||
|
||||
class CloudRegion:
|
||||
@ -232,18 +255,34 @@ class CloudRegion:
|
||||
|
||||
'interface': 'public'
|
||||
"""
|
||||
def __init__(self, name=None, region_name=None, config=None,
|
||||
force_ipv4=False, auth_plugin=None,
|
||||
openstack_config=None, session_constructor=None,
|
||||
app_name=None, 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):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name=None,
|
||||
region_name=None,
|
||||
config=None,
|
||||
force_ipv4=False,
|
||||
auth_plugin=None,
|
||||
openstack_config=None,
|
||||
session_constructor=None,
|
||||
app_name=None,
|
||||
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.config = _util.normalize_keys(config)
|
||||
# NOTE(efried): For backward compatibility: a) continue to accept the
|
||||
@ -294,9 +333,7 @@ class CloudRegion:
|
||||
return self.config.__iter__()
|
||||
|
||||
def __eq__(self, other):
|
||||
return (
|
||||
self.name == other.name
|
||||
and self.config == other.config)
|
||||
return self.name == other.name and self.config == other.config
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
@ -306,7 +343,8 @@ class CloudRegion:
|
||||
if self._name is None:
|
||||
try:
|
||||
self._name = urllib.parse.urlparse(
|
||||
self.get_session().auth.auth_url).hostname
|
||||
self.get_session().auth.auth_url
|
||||
).hostname
|
||||
except Exception:
|
||||
self._name = self._app_name or ''
|
||||
return self._name
|
||||
@ -352,7 +390,9 @@ class CloudRegion:
|
||||
"You are specifying a cacert for the cloud {full_name}"
|
||||
" but also to ignore the host verification. The host SSL"
|
||||
" cert will not be verified.".format(
|
||||
full_name=self.full_name))
|
||||
full_name=self.full_name
|
||||
)
|
||||
)
|
||||
|
||||
cert = self.config.get('cert')
|
||||
if cert:
|
||||
@ -365,19 +405,23 @@ class CloudRegion:
|
||||
"""Return a list of service types we know something about."""
|
||||
services = []
|
||||
for key, val in self.config.items():
|
||||
if (key.endswith('api_version')
|
||||
or key.endswith('service_type')
|
||||
or key.endswith('service_name')):
|
||||
if (
|
||||
key.endswith('api_version')
|
||||
or key.endswith('service_type')
|
||||
or key.endswith('service_name')
|
||||
):
|
||||
services.append("_".join(key.split('_')[:-2]))
|
||||
return list(set(services))
|
||||
|
||||
def get_enabled_services(self):
|
||||
services = set()
|
||||
|
||||
all_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 = [
|
||||
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_')
|
||||
)
|
||||
|
||||
for srv in all_services:
|
||||
ep = self.get_endpoint_from_catalog(srv)
|
||||
@ -390,10 +434,13 @@ class CloudRegion:
|
||||
return self.config.get('auth', {})
|
||||
|
||||
def _get_config(
|
||||
self, key, service_type,
|
||||
default=None,
|
||||
fallback_to_unprefixed=False,
|
||||
converter=None):
|
||||
self,
|
||||
key,
|
||||
service_type,
|
||||
default=None,
|
||||
fallback_to_unprefixed=False,
|
||||
converter=None,
|
||||
):
|
||||
'''Get a config value for a service_type.
|
||||
|
||||
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;
|
||||
# else use the one configured for the CloudRegion as a whole.
|
||||
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):
|
||||
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):
|
||||
version = self._get_config('api_version', service_type)
|
||||
@ -458,7 +507,8 @@ class CloudRegion:
|
||||
warnings.warn(
|
||||
"You have a configured API_VERSION with 'latest' in"
|
||||
" it. In the context of openstacksdk this doesn't make"
|
||||
" any sense.")
|
||||
" any sense."
|
||||
)
|
||||
return None
|
||||
return version
|
||||
|
||||
@ -475,9 +525,11 @@ class CloudRegion:
|
||||
# type will get us things in the right order.
|
||||
if self._service_type_manager.is_known(service_type):
|
||||
service_type = self._service_type_manager.get_service_type(
|
||||
service_type)
|
||||
service_type
|
||||
)
|
||||
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):
|
||||
return self._get_config('service_name', service_type)
|
||||
@ -492,8 +544,11 @@ class CloudRegion:
|
||||
# then the endpoint value is the endpoint_override for every
|
||||
# service.
|
||||
value = auth.get('endpoint')
|
||||
if (not value and service_type == 'identity'
|
||||
and SCOPE_KEYS.isdisjoint(set(auth.keys()))):
|
||||
if (
|
||||
not value
|
||||
and service_type == 'identity'
|
||||
and SCOPE_KEYS.isdisjoint(set(auth.keys()))
|
||||
):
|
||||
# There are a small number of unscoped identity operations.
|
||||
# Specifically, looking up a list of projects/domains/system to
|
||||
# scope to.
|
||||
@ -503,7 +558,8 @@ class CloudRegion:
|
||||
# only v1 is in the catalog but the service actually does support
|
||||
# v2. But the endpoint needs the project_id.
|
||||
service_type = self._service_type_manager.get_service_type(
|
||||
service_type)
|
||||
service_type
|
||||
)
|
||||
if (
|
||||
value
|
||||
and self.config.get('profile') == 'rackspace'
|
||||
@ -513,7 +569,8 @@ class CloudRegion:
|
||||
return value
|
||||
|
||||
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.
|
||||
|
||||
For values respecting endpoint overrides, see
|
||||
@ -537,19 +594,26 @@ class CloudRegion:
|
||||
return catalog.url_for(
|
||||
service_type=service_type,
|
||||
interface=interface,
|
||||
region_name=region_name)
|
||||
region_name=region_name,
|
||||
)
|
||||
except keystoneauth1.exceptions.catalog.EndpointNotFound:
|
||||
return None
|
||||
|
||||
def get_connect_retries(self, service_type):
|
||||
return self._get_config('connect_retries', service_type,
|
||||
fallback_to_unprefixed=True,
|
||||
converter=int)
|
||||
return self._get_config(
|
||||
'connect_retries',
|
||||
service_type,
|
||||
fallback_to_unprefixed=True,
|
||||
converter=int,
|
||||
)
|
||||
|
||||
def get_status_code_retries(self, service_type):
|
||||
return self._get_config('status_code_retries', service_type,
|
||||
fallback_to_unprefixed=True,
|
||||
converter=int)
|
||||
return self._get_config(
|
||||
'status_code_retries',
|
||||
service_type,
|
||||
fallback_to_unprefixed=True,
|
||||
converter=int,
|
||||
)
|
||||
|
||||
@property
|
||||
def prefer_ipv6(self):
|
||||
@ -612,14 +676,16 @@ class CloudRegion:
|
||||
desirable.
|
||||
"""
|
||||
self._keystone_session.additional_user_agent.append(
|
||||
('openstacksdk', openstack_version.__version__))
|
||||
('openstacksdk', openstack_version.__version__)
|
||||
)
|
||||
|
||||
def get_session(self):
|
||||
"""Return a keystoneauth session based on the auth credentials."""
|
||||
if self._keystone_session is None:
|
||||
if not self._auth:
|
||||
raise exceptions.ConfigException(
|
||||
"Problem with auth parameters")
|
||||
"Problem with auth parameters"
|
||||
)
|
||||
(verify, cert) = self.get_requests_verify_args()
|
||||
# Turn off urllib3 warnings about insecure certs if we have
|
||||
# explicitly configured requests to tell it we do not want
|
||||
@ -627,7 +693,8 @@ class CloudRegion:
|
||||
if not verify:
|
||||
self.log.debug(
|
||||
"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)
|
||||
self._keystone_session = self._session_constructor(
|
||||
auth=self._auth,
|
||||
@ -635,7 +702,8 @@ class CloudRegion:
|
||||
cert=cert,
|
||||
timeout=self.config.get('api_timeout'),
|
||||
collect_timing=self.config.get('timing'),
|
||||
discovery_cache=self._discovery_cache)
|
||||
discovery_cache=self._discovery_cache,
|
||||
)
|
||||
self.insert_user_agent()
|
||||
# Using old keystoneauth with new os-client-config fails if
|
||||
# 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)
|
||||
implied_microversion = _get_implied_microversion(version)
|
||||
if (implied_microversion and default_microversion
|
||||
and implied_microversion != default_microversion):
|
||||
if (
|
||||
implied_microversion
|
||||
and default_microversion
|
||||
and implied_microversion != default_microversion
|
||||
):
|
||||
raise exceptions.ConfigException(
|
||||
"default_microversion of {default_microversion} was given"
|
||||
" for {service_type}, but api_version looks like a"
|
||||
" microversion as well. Please set api_version to just the"
|
||||
" desired major version, or omit default_microversion".format(
|
||||
default_microversion=default_microversion,
|
||||
service_type=service_type))
|
||||
service_type=service_type,
|
||||
)
|
||||
)
|
||||
if implied_microversion:
|
||||
default_microversion = implied_microversion
|
||||
# If we're inferring a microversion, don't pass the whole
|
||||
@ -715,7 +788,8 @@ class CloudRegion:
|
||||
)
|
||||
region_versions = versions.get(region_name, {})
|
||||
interface_versions = region_versions.get(
|
||||
self.get_interface(service_type), {})
|
||||
self.get_interface(service_type), {}
|
||||
)
|
||||
return interface_versions.get(service_type, [])
|
||||
|
||||
def _get_endpoint_from_catalog(self, service_type, constructor):
|
||||
@ -729,8 +803,7 @@ class CloudRegion:
|
||||
return adapter.get_endpoint()
|
||||
|
||||
def _get_hardcoded_endpoint(self, service_type, constructor):
|
||||
endpoint = self._get_endpoint_from_catalog(
|
||||
service_type, constructor)
|
||||
endpoint = self._get_endpoint_from_catalog(service_type, constructor)
|
||||
if not endpoint.rstrip().rsplit('/')[-1] == 'v2.0':
|
||||
if not endpoint.endswith('/'):
|
||||
endpoint += '/'
|
||||
@ -738,9 +811,8 @@ class CloudRegion:
|
||||
return endpoint
|
||||
|
||||
def get_session_client(
|
||||
self, service_type, version=None,
|
||||
constructor=proxy.Proxy,
|
||||
**kwargs):
|
||||
self, service_type, version=None, constructor=proxy.Proxy, **kwargs
|
||||
):
|
||||
"""Return a prepped keystoneauth Adapter for a given service.
|
||||
|
||||
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)
|
||||
|
||||
kwargs.setdefault('region_name', self.get_region_name(service_type))
|
||||
kwargs.setdefault('connect_retries',
|
||||
self.get_connect_retries(service_type))
|
||||
kwargs.setdefault('status_code_retries',
|
||||
self.get_status_code_retries(service_type))
|
||||
kwargs.setdefault(
|
||||
'connect_retries', self.get_connect_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_client', self.get_statsd_client())
|
||||
kwargs.setdefault('prometheus_counter', self.get_prometheus_counter())
|
||||
kwargs.setdefault(
|
||||
'prometheus_histogram', self.get_prometheus_histogram())
|
||||
'prometheus_histogram', self.get_prometheus_histogram()
|
||||
)
|
||||
kwargs.setdefault('influxdb_config', self._influxdb_config)
|
||||
kwargs.setdefault('influxdb_client', self.get_influxdb_client())
|
||||
endpoint_override = self.get_endpoint(service_type)
|
||||
version = version_request.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 = (
|
||||
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
|
||||
# because neutronclient hard-codes an append of v2.0. YAY!
|
||||
@ -784,7 +861,8 @@ class CloudRegion:
|
||||
max_api_version = None
|
||||
if endpoint_override is None:
|
||||
endpoint_override = self._get_hardcoded_endpoint(
|
||||
service_type, constructor)
|
||||
service_type, constructor
|
||||
)
|
||||
|
||||
client = constructor(
|
||||
session=self.get_session(),
|
||||
@ -798,14 +876,15 @@ class CloudRegion:
|
||||
default_microversion=version_request.default_microversion,
|
||||
rate_limit=self.get_rate_limit(service_type),
|
||||
concurrency=self.get_concurrency(service_type),
|
||||
**kwargs)
|
||||
**kwargs
|
||||
)
|
||||
if version_request.default_microversion:
|
||||
default_microversion = version_request.default_microversion
|
||||
info = client.get_endpoint_data()
|
||||
if not discover.version_between(
|
||||
info.min_microversion,
|
||||
info.max_microversion,
|
||||
default_microversion
|
||||
info.min_microversion,
|
||||
info.max_microversion,
|
||||
default_microversion,
|
||||
):
|
||||
if self.get_default_microversion(service_type):
|
||||
raise exceptions.ConfigException(
|
||||
@ -816,9 +895,13 @@ class CloudRegion:
|
||||
service_type=service_type,
|
||||
default_microversion=default_microversion,
|
||||
min_microversion=discover.version_to_string(
|
||||
info.min_microversion),
|
||||
info.min_microversion
|
||||
),
|
||||
max_microversion=discover.version_to_string(
|
||||
info.max_microversion)))
|
||||
info.max_microversion
|
||||
),
|
||||
)
|
||||
)
|
||||
else:
|
||||
raise exceptions.ConfigException(
|
||||
"A default microversion for service {service_type} of"
|
||||
@ -836,13 +919,18 @@ class CloudRegion:
|
||||
api_version=self.get_api_version(service_type),
|
||||
default_microversion=default_microversion,
|
||||
min_microversion=discover.version_to_string(
|
||||
info.min_microversion),
|
||||
info.min_microversion
|
||||
),
|
||||
max_microversion=discover.version_to_string(
|
||||
info.max_microversion)))
|
||||
info.max_microversion
|
||||
),
|
||||
)
|
||||
)
|
||||
return client
|
||||
|
||||
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.
|
||||
|
||||
If a configuration lists an explicit endpoint for a service,
|
||||
@ -934,38 +1022,50 @@ class CloudRegion:
|
||||
def get_external_networks(self):
|
||||
"""Get list of network names for external networks."""
|
||||
return [
|
||||
net['name'] for net in self.config.get('networks', [])
|
||||
if net['routes_externally']]
|
||||
net['name']
|
||||
for net in self.config.get('networks', [])
|
||||
if net['routes_externally']
|
||||
]
|
||||
|
||||
def get_external_ipv4_networks(self):
|
||||
"""Get list of network names for external IPv4 networks."""
|
||||
return [
|
||||
net['name'] for net in self.config.get('networks', [])
|
||||
if net['routes_ipv4_externally']]
|
||||
net['name']
|
||||
for net in self.config.get('networks', [])
|
||||
if net['routes_ipv4_externally']
|
||||
]
|
||||
|
||||
def get_external_ipv6_networks(self):
|
||||
"""Get list of network names for external IPv6 networks."""
|
||||
return [
|
||||
net['name'] for net in self.config.get('networks', [])
|
||||
if net['routes_ipv6_externally']]
|
||||
net['name']
|
||||
for net in self.config.get('networks', [])
|
||||
if net['routes_ipv6_externally']
|
||||
]
|
||||
|
||||
def get_internal_networks(self):
|
||||
"""Get list of network names for internal networks."""
|
||||
return [
|
||||
net['name'] for net in self.config.get('networks', [])
|
||||
if not net['routes_externally']]
|
||||
net['name']
|
||||
for net in self.config.get('networks', [])
|
||||
if not net['routes_externally']
|
||||
]
|
||||
|
||||
def get_internal_ipv4_networks(self):
|
||||
"""Get list of network names for internal IPv4 networks."""
|
||||
return [
|
||||
net['name'] for net in self.config.get('networks', [])
|
||||
if not net['routes_ipv4_externally']]
|
||||
net['name']
|
||||
for net in self.config.get('networks', [])
|
||||
if not net['routes_ipv4_externally']
|
||||
]
|
||||
|
||||
def get_internal_ipv6_networks(self):
|
||||
"""Get list of network names for internal IPv6 networks."""
|
||||
return [
|
||||
net['name'] for net in self.config.get('networks', [])
|
||||
if not net['routes_ipv6_externally']]
|
||||
net['name']
|
||||
for net in self.config.get('networks', [])
|
||||
if not net['routes_ipv6_externally']
|
||||
]
|
||||
|
||||
def get_default_network(self):
|
||||
"""Get network used for default interactions."""
|
||||
@ -999,8 +1099,8 @@ class CloudRegion:
|
||||
if not key:
|
||||
return defaults
|
||||
return _util.merge_clouds(
|
||||
defaults,
|
||||
_util.normalize_keys(self._extra_config.get(key, {})))
|
||||
defaults, _util.normalize_keys(self._extra_config.get(key, {}))
|
||||
)
|
||||
|
||||
def get_client_config(self, name=None, defaults=None):
|
||||
"""Get config settings for a named client.
|
||||
@ -1020,25 +1120,29 @@ class CloudRegion:
|
||||
client section and the defaults.
|
||||
"""
|
||||
return self._get_extra_config(
|
||||
name, self._get_extra_config('client', defaults))
|
||||
name, self._get_extra_config('client', defaults)
|
||||
)
|
||||
|
||||
def get_password_callback(self):
|
||||
return self._password_callback
|
||||
|
||||
def get_rate_limit(self, service_type=None):
|
||||
return self._get_service_config(
|
||||
'rate_limit', service_type=service_type)
|
||||
'rate_limit', service_type=service_type
|
||||
)
|
||||
|
||||
def get_concurrency(self, service_type=None):
|
||||
return self._get_service_config(
|
||||
'concurrency', service_type=service_type)
|
||||
'concurrency', service_type=service_type
|
||||
)
|
||||
|
||||
def get_statsd_client(self):
|
||||
if not statsd:
|
||||
if self._statsd_host:
|
||||
self.log.warning(
|
||||
'StatsD python library is not available. '
|
||||
'Reporting disabled')
|
||||
'Reporting disabled'
|
||||
)
|
||||
return None
|
||||
statsd_args = {}
|
||||
if self._statsd_host:
|
||||
@ -1075,7 +1179,10 @@ class CloudRegion:
|
||||
'openstack_http_response_time',
|
||||
'Time taken for an http response to an OpenStack service',
|
||||
labelnames=[
|
||||
'method', 'endpoint', 'service_type', 'status_code'
|
||||
'method',
|
||||
'endpoint',
|
||||
'service_type',
|
||||
'status_code',
|
||||
],
|
||||
registry=registry,
|
||||
)
|
||||
@ -1092,7 +1199,10 @@ class CloudRegion:
|
||||
'openstack_http_requests',
|
||||
'Number of HTTP requests made to an OpenStack service',
|
||||
labelnames=[
|
||||
'method', 'endpoint', 'service_type', 'status_code'
|
||||
'method',
|
||||
'endpoint',
|
||||
'service_type',
|
||||
'status_code',
|
||||
],
|
||||
registry=registry,
|
||||
)
|
||||
@ -1103,7 +1213,8 @@ class CloudRegion:
|
||||
service_type = service_type.lower().replace('-', '_')
|
||||
key = 'has_{service_type}'.format(service_type=service_type)
|
||||
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):
|
||||
_disable_service(self.config, service_type, reason=reason)
|
||||
@ -1140,6 +1251,8 @@ class CloudRegion:
|
||||
except Exception:
|
||||
self.log.warning('Cannot establish connection to InfluxDB')
|
||||
else:
|
||||
self.log.warning('InfluxDB configuration is present, '
|
||||
'but no client library is found.')
|
||||
self.log.warning(
|
||||
'InfluxDB configuration is present, '
|
||||
'but no client library is found.'
|
||||
)
|
||||
return None
|
||||
|
@ -17,7 +17,8 @@ import os
|
||||
import threading
|
||||
|
||||
_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_lock = threading.Lock()
|
||||
|
||||
|
@ -46,19 +46,23 @@ CACHE_PATH = APPDIRS.user_cache_dir
|
||||
# see https://snapcraft.io/docs/environment-variables
|
||||
SNAP_REAL_HOME = os.getenv('SNAP_REAL_HOME')
|
||||
if SNAP_REAL_HOME:
|
||||
UNIX_CONFIG_HOME = os.path.join(os.path.join(SNAP_REAL_HOME, '.config'),
|
||||
'openstack')
|
||||
UNIX_CONFIG_HOME = os.path.join(
|
||||
os.path.join(SNAP_REAL_HOME, '.config'), 'openstack'
|
||||
)
|
||||
else:
|
||||
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'
|
||||
|
||||
SITE_CONFIG_HOME = APPDIRS.site_config_dir
|
||||
|
||||
CONFIG_SEARCH_PATH = [
|
||||
os.getcwd(),
|
||||
CONFIG_HOME, UNIX_CONFIG_HOME,
|
||||
SITE_CONFIG_HOME, UNIX_SITE_CONFIG_HOME
|
||||
CONFIG_HOME,
|
||||
UNIX_CONFIG_HOME,
|
||||
SITE_CONFIG_HOME,
|
||||
UNIX_SITE_CONFIG_HOME,
|
||||
]
|
||||
YAML_SUFFIXES = ('.yaml', '.yml')
|
||||
JSON_SUFFIXES = ('.json',)
|
||||
@ -134,8 +138,8 @@ def _fix_argv(argv):
|
||||
"The following options were given: '{options}' which contain"
|
||||
" duplicates except that one has _ and one has -. There is"
|
||||
" no sane way for us to know what you're doing. Remove the"
|
||||
" duplicate option and try again".format(
|
||||
options=','.join(overlap)))
|
||||
" duplicate option and try again".format(options=','.join(overlap))
|
||||
)
|
||||
|
||||
|
||||
class OpenStackConfig:
|
||||
@ -146,14 +150,25 @@ class OpenStackConfig:
|
||||
_cloud_region_class = cloud_region.CloudRegion
|
||||
_defaults_module = defaults
|
||||
|
||||
def __init__(self, config_files=None, vendor_files=None,
|
||||
override_defaults=None, force_ipv4=None,
|
||||
envvar_prefix=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):
|
||||
def __init__(
|
||||
self,
|
||||
config_files=None,
|
||||
vendor_files=None,
|
||||
override_defaults=None,
|
||||
force_ipv4=None,
|
||||
envvar_prefix=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._session_constructor = session_constructor
|
||||
self._app_name = app_name
|
||||
@ -196,7 +211,8 @@ class OpenStackConfig:
|
||||
_, secure_config = self._load_secure_file()
|
||||
if secure_config:
|
||||
self.cloud_config = _util.merge_clouds(
|
||||
self.cloud_config, secure_config)
|
||||
self.cloud_config, secure_config
|
||||
)
|
||||
|
||||
if not self.cloud_config:
|
||||
self.cloud_config = {'clouds': {}}
|
||||
@ -217,14 +233,20 @@ class OpenStackConfig:
|
||||
# Get the backwards compat value
|
||||
prefer_ipv6 = get_boolean(
|
||||
self._get_envvar(
|
||||
'OS_PREFER_IPV6', client_config.get(
|
||||
'prefer_ipv6', client_config.get(
|
||||
'prefer-ipv6', True))))
|
||||
'OS_PREFER_IPV6',
|
||||
client_config.get(
|
||||
'prefer_ipv6', client_config.get('prefer-ipv6', True)
|
||||
),
|
||||
)
|
||||
)
|
||||
force_ipv4 = get_boolean(
|
||||
self._get_envvar(
|
||||
'OS_FORCE_IPV4', client_config.get(
|
||||
'force_ipv4', client_config.get(
|
||||
'broken-ipv6', False))))
|
||||
'OS_FORCE_IPV4',
|
||||
client_config.get(
|
||||
'force_ipv4', client_config.get('broken-ipv6', False)
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
self.force_ipv4 = force_ipv4
|
||||
if not prefer_ipv6:
|
||||
@ -239,8 +261,10 @@ class OpenStackConfig:
|
||||
'"{0}" defines a cloud named "{1}", but'
|
||||
' OS_CLOUD_NAME is also set to "{1}". Please rename'
|
||||
' either your environment based cloud, or one of your'
|
||||
' file-based clouds.'.format(self.config_filename,
|
||||
self.envvar_key))
|
||||
' file-based clouds.'.format(
|
||||
self.config_filename, self.envvar_key
|
||||
)
|
||||
)
|
||||
|
||||
self.default_cloud = self._get_envvar('OS_CLOUD')
|
||||
|
||||
@ -259,15 +283,15 @@ class OpenStackConfig:
|
||||
# clouds.yaml.
|
||||
# The next/iter thing is for python3 compat where dict.keys
|
||||
# returns an iterator but in python2 it's a list.
|
||||
self.default_cloud = next(iter(
|
||||
self.cloud_config['clouds'].keys()))
|
||||
self.default_cloud = next(
|
||||
iter(self.cloud_config['clouds'].keys())
|
||||
)
|
||||
|
||||
# Finally, fall through and make a cloud that starts with defaults
|
||||
# because we need somewhere to put arguments, and there are neither
|
||||
# config files or env vars
|
||||
if not self.cloud_config['clouds']:
|
||||
self.cloud_config = dict(
|
||||
clouds=dict(defaults=dict(self.defaults)))
|
||||
self.cloud_config = dict(clouds=dict(defaults=dict(self.defaults)))
|
||||
self.default_cloud = 'defaults'
|
||||
|
||||
self._cache_auth = False
|
||||
@ -281,13 +305,15 @@ class OpenStackConfig:
|
||||
cache_settings = _util.normalize_keys(self.cloud_config['cache'])
|
||||
|
||||
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
|
||||
# is expiration_time. Support max_age for backwards compat.
|
||||
self._cache_expiration_time = cache_settings.get(
|
||||
'expiration_time', cache_settings.get(
|
||||
'max_age', self._cache_expiration_time))
|
||||
'expiration_time',
|
||||
cache_settings.get('max_age', self._cache_expiration_time),
|
||||
)
|
||||
|
||||
# If cache class is given, use that. If not, but if cache time
|
||||
# is given, default to memory. Otherwise, default to nothing.
|
||||
@ -295,14 +321,18 @@ class OpenStackConfig:
|
||||
if self._cache_expiration_time:
|
||||
self._cache_class = 'dogpile.cache.memory'
|
||||
self._cache_class = self.cloud_config['cache'].get(
|
||||
'class', self._cache_class)
|
||||
'class', self._cache_class
|
||||
)
|
||||
|
||||
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(
|
||||
'arguments', self._cache_arguments)
|
||||
'arguments', self._cache_arguments
|
||||
)
|
||||
self._cache_expirations = cache_settings.get(
|
||||
'expiration', self._cache_expirations)
|
||||
'expiration', self._cache_expirations
|
||||
)
|
||||
|
||||
if load_yaml_config:
|
||||
metrics_config = self.cloud_config.get('metrics', {})
|
||||
@ -326,12 +356,21 @@ class OpenStackConfig:
|
||||
use_udp = use_udp.lower() in ('true', 'yes', '1')
|
||||
elif not isinstance(use_udp, bool):
|
||||
use_udp = False
|
||||
self.log.warning('InfluxDB.use_udp value type is not '
|
||||
'supported. Use one of '
|
||||
'[true|false|yes|no|1|0]')
|
||||
self.log.warning(
|
||||
'InfluxDB.use_udp value type is not '
|
||||
'supported. Use one of '
|
||||
'[true|false|yes|no|1|0]'
|
||||
)
|
||||
config['use_udp'] = use_udp
|
||||
for key in ['host', 'port', 'username', 'password', 'database',
|
||||
'measurement', 'timeout']:
|
||||
for key in [
|
||||
'host',
|
||||
'port',
|
||||
'username',
|
||||
'password',
|
||||
'database',
|
||||
'measurement',
|
||||
'timeout',
|
||||
]:
|
||||
if key in influxdb_config:
|
||||
config[key] = influxdb_config[key]
|
||||
self._influxdb_config = config
|
||||
@ -357,20 +396,28 @@ class OpenStackConfig:
|
||||
if not envvar_prefix:
|
||||
# This makes the or below be OS_ or OS_ which is a no-op
|
||||
envvar_prefix = 'OS_'
|
||||
environkeys = [k for k in os.environ.keys()
|
||||
if (k.startswith('OS_') or k.startswith(envvar_prefix))
|
||||
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
|
||||
]
|
||||
environkeys = [
|
||||
k
|
||||
for k in os.environ.keys()
|
||||
if (k.startswith('OS_') or k.startswith(envvar_prefix))
|
||||
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:
|
||||
newkey = k.split('_', 1)[-1].lower()
|
||||
ret[newkey] = os.environ[k]
|
||||
# If the only environ keys are selectors or behavior modification,
|
||||
# don't return anything
|
||||
selectors = set([
|
||||
'OS_CLOUD', 'OS_REGION_NAME',
|
||||
'OS_CLIENT_CONFIG_FILE', 'OS_CLIENT_SECURE_FILE', 'OS_CLOUD_NAME'])
|
||||
selectors = set(
|
||||
[
|
||||
'OS_CLOUD',
|
||||
'OS_REGION_NAME',
|
||||
'OS_CLIENT_CONFIG_FILE',
|
||||
'OS_CLIENT_SECURE_FILE',
|
||||
'OS_CLOUD_NAME',
|
||||
]
|
||||
)
|
||||
if set(environkeys) - selectors:
|
||||
return ret
|
||||
return None
|
||||
@ -391,8 +438,8 @@ class OpenStackConfig:
|
||||
if not key:
|
||||
return defaults
|
||||
return _util.merge_clouds(
|
||||
defaults,
|
||||
_util.normalize_keys(self.cloud_config.get(key, {})))
|
||||
defaults, _util.normalize_keys(self.cloud_config.get(key, {}))
|
||||
)
|
||||
|
||||
def _load_config_file(self):
|
||||
return self._load_yaml_json_file(self._config_files)
|
||||
@ -427,10 +474,12 @@ class OpenStackConfig:
|
||||
for region in regions:
|
||||
if isinstance(region, dict):
|
||||
# i.e. must have name key, and only name,values keys
|
||||
if 'name' not in region or \
|
||||
not {'name', 'values'} >= set(region):
|
||||
if 'name' not in region or not {'name', 'values'} >= set(
|
||||
region
|
||||
):
|
||||
raise exceptions.ConfigException(
|
||||
'Invalid region entry at: %s' % region)
|
||||
'Invalid region entry at: %s' % region
|
||||
)
|
||||
if 'values' not in region:
|
||||
region['values'] = {}
|
||||
ret.append(copy.deepcopy(region))
|
||||
@ -460,7 +509,8 @@ class OpenStackConfig:
|
||||
warnings.warn(
|
||||
"Comma separated lists in region_name are deprecated."
|
||||
" 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)
|
||||
else:
|
||||
# crappit. we don't have a region defined.
|
||||
@ -495,7 +545,9 @@ class OpenStackConfig:
|
||||
' region names are case sensitive.'.format(
|
||||
region_name=region_name,
|
||||
region_list=','.join([r['name'] for r in regions]),
|
||||
cloud=cloud))
|
||||
cloud=cloud,
|
||||
)
|
||||
)
|
||||
|
||||
def get_cloud_names(self):
|
||||
return self.cloud_config['clouds'].keys()
|
||||
@ -506,8 +558,8 @@ class OpenStackConfig:
|
||||
# Only validate cloud name if one was given
|
||||
if name and name not in self.cloud_config['clouds']:
|
||||
raise exceptions.ConfigException(
|
||||
"Cloud {name} was not found.".format(
|
||||
name=name))
|
||||
"Cloud {name} was not found.".format(name=name)
|
||||
)
|
||||
|
||||
our_cloud = self.cloud_config['clouds'].get(name, dict())
|
||||
if profile:
|
||||
@ -536,11 +588,15 @@ class OpenStackConfig:
|
||||
warnings.warn(
|
||||
"{0} uses the keyword 'cloud' to reference a known "
|
||||
"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()
|
||||
if (vendor_file and 'public-clouds' in vendor_file
|
||||
and profile_name in vendor_file['public-clouds']):
|
||||
if (
|
||||
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])
|
||||
else:
|
||||
profile_data = vendors.get_profile(profile_name)
|
||||
@ -555,23 +611,31 @@ class OpenStackConfig:
|
||||
if status == 'deprecated':
|
||||
warnings.warn(
|
||||
"{profile_name} is deprecated: {message}".format(
|
||||
profile_name=profile_name, message=message))
|
||||
profile_name=profile_name, message=message
|
||||
)
|
||||
)
|
||||
elif status == 'shutdown':
|
||||
raise exceptions.ConfigException(
|
||||
"{profile_name} references a cloud that no longer"
|
||||
" exists: {message}".format(
|
||||
profile_name=profile_name, message=message))
|
||||
profile_name=profile_name, message=message
|
||||
)
|
||||
)
|
||||
_auth_update(cloud, profile_data)
|
||||
else:
|
||||
# Can't find the requested vendor config, go about business
|
||||
warnings.warn("Couldn't find the vendor profile '{0}', for"
|
||||
" the cloud '{1}'".format(profile_name,
|
||||
name))
|
||||
warnings.warn(
|
||||
"Couldn't find the vendor profile '{0}', for"
|
||||
" the cloud '{1}'".format(profile_name, name)
|
||||
)
|
||||
|
||||
def _project_scoped(self, cloud):
|
||||
return ('project_id' in cloud or 'project_name' in cloud
|
||||
or 'project_id' in cloud['auth']
|
||||
or 'project_name' in cloud['auth'])
|
||||
return (
|
||||
'project_id' in cloud
|
||||
or 'project_name' in cloud
|
||||
or 'project_id' in cloud['auth']
|
||||
or 'project_name' in cloud['auth']
|
||||
)
|
||||
|
||||
def _validate_networks(self, networks, key):
|
||||
value = None
|
||||
@ -580,9 +644,9 @@ class OpenStackConfig:
|
||||
raise exceptions.ConfigException(
|
||||
"Duplicate network entries for {key}: {net1} and {net2}."
|
||||
" Only one network can be flagged with {key}".format(
|
||||
key=key,
|
||||
net1=value['name'],
|
||||
net2=net['name']))
|
||||
key=key, net1=value['name'], net2=net['name']
|
||||
)
|
||||
)
|
||||
if not value and net[key]:
|
||||
value = net
|
||||
|
||||
@ -595,7 +659,8 @@ class OpenStackConfig:
|
||||
name = net.get('name')
|
||||
if not name:
|
||||
raise exceptions.ConfigException(
|
||||
'Entry in network list is missing required field "name".')
|
||||
'Entry in network list is missing required field "name".'
|
||||
)
|
||||
network = dict(
|
||||
name=name,
|
||||
routes_externally=get_boolean(net.get('routes_externally')),
|
||||
@ -605,12 +670,12 @@ class OpenStackConfig:
|
||||
)
|
||||
# routes_ipv4_externally defaults to the value of routes_externally
|
||||
network['routes_ipv4_externally'] = get_boolean(
|
||||
net.get(
|
||||
'routes_ipv4_externally', network['routes_externally']))
|
||||
net.get('routes_ipv4_externally', network['routes_externally'])
|
||||
)
|
||||
# routes_ipv6_externally defaults to the value of routes_externally
|
||||
network['routes_ipv6_externally'] = get_boolean(
|
||||
net.get(
|
||||
'routes_ipv6_externally', network['routes_externally']))
|
||||
net.get('routes_ipv6_externally', network['routes_externally'])
|
||||
)
|
||||
networks.append(network)
|
||||
|
||||
for key in ('external_network', 'internal_network'):
|
||||
@ -619,18 +684,24 @@ class OpenStackConfig:
|
||||
raise exceptions.ConfigException(
|
||||
"Both {key} and networks were specified in the config."
|
||||
" 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:
|
||||
warnings.warn(
|
||||
"{key} is deprecated. Please replace with an entry in"
|
||||
" a dict inside of the networks list with name: {name}"
|
||||
" and routes_externally: {external}".format(
|
||||
key=key, name=cloud[key], external=external))
|
||||
networks.append(dict(
|
||||
name=cloud[key],
|
||||
routes_externally=external,
|
||||
nat_destination=not external,
|
||||
default_interface=external))
|
||||
key=key, name=cloud[key], external=external
|
||||
)
|
||||
)
|
||||
networks.append(
|
||||
dict(
|
||||
name=cloud[key],
|
||||
routes_externally=external,
|
||||
nat_destination=not external,
|
||||
default_interface=external,
|
||||
)
|
||||
)
|
||||
|
||||
# Validate that we don't have duplicates
|
||||
self._validate_networks(networks, 'nat_destination')
|
||||
@ -668,7 +739,9 @@ class OpenStackConfig:
|
||||
'user_domain_name': ('user_domain_name', 'user-domain-name'),
|
||||
'project_domain_id': ('project_domain_id', 'project-domain-id'),
|
||||
'project_domain_name': (
|
||||
'project_domain_name', 'project-domain-name'),
|
||||
'project_domain_name',
|
||||
'project-domain-name',
|
||||
),
|
||||
'token': ('auth-token', 'auth_token', 'token'),
|
||||
}
|
||||
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
|
||||
# direction
|
||||
mappings['tenant_id'] = (
|
||||
'project_id', 'project-id', 'tenant_id', 'tenant-id')
|
||||
'project_id',
|
||||
'project-id',
|
||||
'tenant_id',
|
||||
'tenant-id',
|
||||
)
|
||||
mappings['tenant_name'] = (
|
||||
'project_name', 'project-name', 'tenant_name', 'tenant-name')
|
||||
'project_name',
|
||||
'project-name',
|
||||
'tenant_name',
|
||||
'tenant-name',
|
||||
)
|
||||
else:
|
||||
mappings['project_id'] = (
|
||||
'tenant_id', 'tenant-id', 'project_id', 'project-id')
|
||||
'tenant_id',
|
||||
'tenant-id',
|
||||
'project_id',
|
||||
'project-id',
|
||||
)
|
||||
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():
|
||||
target = None
|
||||
for key in possible_values:
|
||||
@ -747,7 +836,8 @@ class OpenStackConfig:
|
||||
'--os-cloud',
|
||||
metavar='<name>',
|
||||
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
|
||||
# the keystoneauth declaration of it has a default, which means
|
||||
@ -782,7 +872,8 @@ class OpenStackConfig:
|
||||
|
||||
try:
|
||||
loading.register_auth_argparse_arguments(
|
||||
parser, argv, default=default_auth_type)
|
||||
parser, argv, default=default_auth_type
|
||||
)
|
||||
except Exception:
|
||||
# Hidiing the keystoneauth exception because we're not actually
|
||||
# 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}."
|
||||
" Valid choices are: {plugin_names}.".format(
|
||||
auth_type=options.os_auth_type,
|
||||
plugin_names=",".join(plugin_names)))
|
||||
plugin_names=",".join(plugin_names),
|
||||
)
|
||||
)
|
||||
|
||||
if service_keys:
|
||||
primary_service = service_keys[0]
|
||||
@ -801,15 +894,19 @@ class OpenStackConfig:
|
||||
primary_service = None
|
||||
loading.register_session_argparse_arguments(parser)
|
||||
adapter.register_adapter_argparse_arguments(
|
||||
parser, service_type=primary_service)
|
||||
parser, service_type=primary_service
|
||||
)
|
||||
for service_key in service_keys:
|
||||
# legacy clients have un-prefixed api-version options
|
||||
parser.add_argument(
|
||||
'--{service_key}-api-version'.format(
|
||||
service_key=service_key.replace('_', '-')),
|
||||
help=argparse_mod.SUPPRESS)
|
||||
service_key=service_key.replace('_', '-')
|
||||
),
|
||||
help=argparse_mod.SUPPRESS,
|
||||
)
|
||||
adapter.register_service_adapter_argparse_arguments(
|
||||
parser, service_type=service_key)
|
||||
parser, service_type=service_key
|
||||
)
|
||||
|
||||
# Backwards compat options for legacy clients
|
||||
parser.add_argument('--http-timeout', help=argparse_mod.SUPPRESS)
|
||||
@ -837,7 +934,8 @@ class OpenStackConfig:
|
||||
service_timeout = None
|
||||
for key in cloud.keys():
|
||||
if key.endswith('timeout') and not (
|
||||
key == 'timeout' or key == 'api_timeout'):
|
||||
key == 'timeout' or key == 'api_timeout'
|
||||
):
|
||||
service_timeout = cloud[key]
|
||||
else:
|
||||
new_cloud[key] = cloud[key]
|
||||
@ -857,9 +955,11 @@ class OpenStackConfig:
|
||||
for cloud in self.get_cloud_names():
|
||||
for region in self._get_regions(cloud):
|
||||
if region:
|
||||
clouds.append(self.get_one(
|
||||
cloud, region_name=region['name']))
|
||||
clouds.append(
|
||||
self.get_one(cloud, region_name=region['name'])
|
||||
)
|
||||
return clouds
|
||||
|
||||
# TODO(mordred) Backwards compat for OSC transition
|
||||
get_all_clouds = get_all
|
||||
|
||||
@ -904,8 +1004,9 @@ class OpenStackConfig:
|
||||
if opt_name in config:
|
||||
return config[opt_name]
|
||||
else:
|
||||
deprecated = getattr(opt, 'deprecated', getattr(
|
||||
opt, 'deprecated_opts', []))
|
||||
deprecated = getattr(
|
||||
opt, 'deprecated', getattr(opt, 'deprecated_opts', [])
|
||||
)
|
||||
for d_opt in deprecated:
|
||||
d_opt_name = d_opt.name.replace('-', '_')
|
||||
if d_opt_name in config:
|
||||
@ -1027,9 +1128,9 @@ class OpenStackConfig:
|
||||
def option_prompt(self, config, p_opt):
|
||||
"""Prompt user for option that requires a value"""
|
||||
if (
|
||||
getattr(p_opt, 'prompt', None) is not None
|
||||
and p_opt.dest not in config['auth']
|
||||
and self._pw_callback is not None
|
||||
getattr(p_opt, 'prompt', None) is not None
|
||||
and p_opt.dest not in config['auth']
|
||||
and self._pw_callback is not None
|
||||
):
|
||||
config['auth'][p_opt.dest] = self._pw_callback(p_opt.prompt)
|
||||
return config
|
||||
@ -1046,8 +1147,7 @@ class OpenStackConfig:
|
||||
# Prefer the plugin configuration dest value if the value's key
|
||||
# is marked as depreciated.
|
||||
if p_opt.dest is None:
|
||||
config['auth'][p_opt.name.replace('-', '_')] = (
|
||||
winning_value)
|
||||
config['auth'][p_opt.name.replace('-', '_')] = winning_value
|
||||
else:
|
||||
config['auth'][p_opt.dest] = winning_value
|
||||
return config
|
||||
@ -1056,9 +1156,11 @@ class OpenStackConfig:
|
||||
"""Perform the set of magic argument fixups"""
|
||||
|
||||
# Infer token plugin if a token was given
|
||||
if (('auth' in config and 'token' in config['auth'])
|
||||
or ('auth_token' in config and config['auth_token'])
|
||||
or ('token' in config and config['token'])):
|
||||
if (
|
||||
('auth' in config and 'token' in config['auth'])
|
||||
or ('auth_token' in config and config['auth_token'])
|
||||
or ('token' in config and config['token'])
|
||||
):
|
||||
config.setdefault('token', config.pop('auth_token', None))
|
||||
|
||||
# Infer passcode if it was given separately
|
||||
@ -1094,12 +1196,12 @@ class OpenStackConfig:
|
||||
# more generalized
|
||||
if 'auth' in config and 'auth_url' in config['auth']:
|
||||
config['auth']['auth_url'] = config['auth']['auth_url'].format(
|
||||
**config)
|
||||
**config
|
||||
)
|
||||
|
||||
return config
|
||||
|
||||
def get_one(
|
||||
self, cloud=None, validate=True, argparse=None, **kwargs):
|
||||
def get_one(self, cloud=None, validate=True, argparse=None, **kwargs):
|
||||
"""Retrieve a single CloudRegion and merge additional options
|
||||
|
||||
:param string cloud:
|
||||
@ -1217,15 +1319,12 @@ class OpenStackConfig:
|
||||
statsd_prefix=statsd_prefix,
|
||||
influxdb_config=influxdb_config,
|
||||
)
|
||||
|
||||
# TODO(mordred) Backwards compat for OSC transition
|
||||
get_one_cloud = get_one
|
||||
|
||||
def get_one_cloud_osc(
|
||||
self,
|
||||
cloud=None,
|
||||
validate=True,
|
||||
argparse=None,
|
||||
**kwargs
|
||||
self, cloud=None, validate=True, argparse=None, **kwargs
|
||||
):
|
||||
"""Retrieve a single CloudRegion and merge additional options
|
||||
|
||||
@ -1359,10 +1458,10 @@ if __name__ == '__main__':
|
||||
if len(sys.argv) == 1:
|
||||
print_cloud = True
|
||||
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
|
||||
elif len(sys.argv) == 2 and (
|
||||
sys.argv[1] == cloud.name):
|
||||
elif len(sys.argv) == 2 and (sys.argv[1] == cloud.name):
|
||||
print_cloud = True
|
||||
|
||||
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(
|
||||
profile_name=profile_name,
|
||||
status_code=response.status_code,
|
||||
reason=response.reason))
|
||||
reason=response.reason,
|
||||
)
|
||||
)
|
||||
vendor_defaults[profile_name] = None
|
||||
return
|
||||
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
|
||||
# config from the cloud so that we can supply local overrides if needed.
|
||||
profile = _util.merge_clouds(
|
||||
vendor_data['profile'],
|
||||
vendor_defaults.get(name, {}))
|
||||
vendor_data['profile'], vendor_defaults.get(name, {})
|
||||
)
|
||||
# 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
|
||||
# pop the key to prevent doing it again in the future.
|
||||
|
@ -220,7 +220,8 @@ __all__ = [
|
||||
|
||||
if requestsexceptions.SubjectAltNameWarning:
|
||||
warnings.filterwarnings(
|
||||
'ignore', category=requestsexceptions.SubjectAltNameWarning)
|
||||
'ignore', category=requestsexceptions.SubjectAltNameWarning
|
||||
)
|
||||
|
||||
_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)
|
||||
if config is None:
|
||||
config = _config.OpenStackConfig().get_one(
|
||||
cloud=cloud, argparse=options, **kwargs)
|
||||
cloud=cloud, argparse=options, **kwargs
|
||||
)
|
||||
|
||||
return Connection(config=config)
|
||||
|
||||
@ -274,20 +276,25 @@ class Connection(
|
||||
_security_group.SecurityGroupCloudMixin,
|
||||
_shared_file_system.SharedFileSystemCloudMixin,
|
||||
):
|
||||
|
||||
def __init__(self, cloud=None, config=None, session=None,
|
||||
app_name=None, app_version=None,
|
||||
extra_services=None,
|
||||
strict=False,
|
||||
use_direct_get=False,
|
||||
task_manager=None,
|
||||
rate_limit=None,
|
||||
oslo_conf=None,
|
||||
service_types=None,
|
||||
global_request_id=None,
|
||||
strict_proxies=False,
|
||||
pool_executor=None,
|
||||
**kwargs):
|
||||
def __init__(
|
||||
self,
|
||||
cloud=None,
|
||||
config=None,
|
||||
session=None,
|
||||
app_name=None,
|
||||
app_version=None,
|
||||
extra_services=None,
|
||||
strict=False,
|
||||
use_direct_get=False,
|
||||
task_manager=None,
|
||||
rate_limit=None,
|
||||
oslo_conf=None,
|
||||
service_types=None,
|
||||
global_request_id=None,
|
||||
strict_proxies=False,
|
||||
pool_executor=None,
|
||||
**kwargs
|
||||
):
|
||||
"""Create a connection to a cloud.
|
||||
|
||||
A connection needs information about how to connect, how to
|
||||
@ -373,24 +380,32 @@ class Connection(
|
||||
if not self.config:
|
||||
if oslo_conf:
|
||||
self.config = cloud_region.from_conf(
|
||||
oslo_conf, session=session, app_name=app_name,
|
||||
app_version=app_version, service_types=service_types)
|
||||
oslo_conf,
|
||||
session=session,
|
||||
app_name=app_name,
|
||||
app_version=app_version,
|
||||
service_types=service_types,
|
||||
)
|
||||
elif session:
|
||||
self.config = cloud_region.from_session(
|
||||
session=session,
|
||||
app_name=app_name, app_version=app_version,
|
||||
app_name=app_name,
|
||||
app_version=app_version,
|
||||
load_yaml_config=False,
|
||||
load_envvars=False,
|
||||
rate_limit=rate_limit,
|
||||
**kwargs)
|
||||
**kwargs
|
||||
)
|
||||
else:
|
||||
self.config = _config.get_cloud_region(
|
||||
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_envvars=cloud is not None,
|
||||
rate_limit=rate_limit,
|
||||
**kwargs)
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self._session = None
|
||||
self._proxies = {}
|
||||
@ -440,19 +455,25 @@ class Connection(
|
||||
hook = ep.load()
|
||||
hook(self)
|
||||
except ValueError:
|
||||
self.log.warning('Hook should be in the entrypoint '
|
||||
'module:attribute format')
|
||||
self.log.warning(
|
||||
'Hook should be in the entrypoint '
|
||||
'module:attribute format'
|
||||
)
|
||||
except (ImportError, TypeError, AttributeError) as e:
|
||||
self.log.warning('Configured hook %s cannot be executed: %s',
|
||||
vendor_hook, e)
|
||||
self.log.warning(
|
||||
'Configured hook %s cannot be executed: %s', vendor_hook, e
|
||||
)
|
||||
|
||||
# Add additional metrics into the configuration according to the
|
||||
# selected connection. We don't want to deal with overall config in the
|
||||
# proxy, just pass required part.
|
||||
if (self.config._influxdb_config
|
||||
and 'additional_metric_tags' in self.config.config):
|
||||
self.config._influxdb_config['additional_metric_tags'] = \
|
||||
self.config.config['additional_metric_tags']
|
||||
if (
|
||||
self.config._influxdb_config
|
||||
and 'additional_metric_tags' in self.config.config
|
||||
):
|
||||
self.config._influxdb_config[
|
||||
'additional_metric_tags'
|
||||
] = self.config.config['additional_metric_tags']
|
||||
|
||||
def __del__(self):
|
||||
# try to force release of resources and save authorization
|
||||
@ -500,7 +521,7 @@ class Connection(
|
||||
setattr(
|
||||
self.__class__,
|
||||
attr_name.replace('-', '_'),
|
||||
property(fget=getter)
|
||||
property(fget=getter),
|
||||
)
|
||||
self.config.enable_service(service.service_type)
|
||||
|
||||
@ -527,7 +548,8 @@ class Connection(
|
||||
def _pool_executor(self):
|
||||
if not self.__pool_executor:
|
||||
self.__pool_executor = concurrent.futures.ThreadPoolExecutor(
|
||||
max_workers=5)
|
||||
max_workers=5
|
||||
)
|
||||
return self.__pool_executor
|
||||
|
||||
def close(self):
|
||||
|
@ -24,6 +24,7 @@ from requests import exceptions as _rex
|
||||
|
||||
class SDKException(Exception):
|
||||
"""The base exception class for all exceptions this library raises."""
|
||||
|
||||
def __init__(self, message=None, extra_data=None):
|
||||
self.message = self.__class__.__name__ if message is None else message
|
||||
self.extra_data = extra_data
|
||||
@ -35,6 +36,7 @@ OpenStackCloudException = SDKException
|
||||
|
||||
class EndpointNotFound(SDKException):
|
||||
"""A mismatch occurred between what the client and server expect."""
|
||||
|
||||
def __init__(self, message=None):
|
||||
super(EndpointNotFound, self).__init__(message)
|
||||
|
||||
@ -55,20 +57,25 @@ class InvalidRequest(SDKException):
|
||||
|
||||
|
||||
class HttpException(SDKException, _rex.HTTPError):
|
||||
|
||||
def __init__(self, message='Error', response=None,
|
||||
http_status=None,
|
||||
details=None, request_id=None):
|
||||
def __init__(
|
||||
self,
|
||||
message='Error',
|
||||
response=None,
|
||||
http_status=None,
|
||||
details=None,
|
||||
request_id=None,
|
||||
):
|
||||
# TODO(shade) Remove http_status parameter and the ability for response
|
||||
# to be None once we're not mocking Session everywhere.
|
||||
if not message:
|
||||
if response is not None:
|
||||
message = "{name}: {code}".format(
|
||||
name=self.__class__.__name__,
|
||||
code=response.status_code)
|
||||
name=self.__class__.__name__, code=response.status_code
|
||||
)
|
||||
else:
|
||||
message = "{name}: Unknown error".format(
|
||||
name=self.__class__.__name__)
|
||||
name=self.__class__.__name__
|
||||
)
|
||||
|
||||
# Call directly rather than via super to control parameters
|
||||
SDKException.__init__(self, message=message)
|
||||
@ -96,7 +103,8 @@ class HttpException(SDKException, _rex.HTTPError):
|
||||
return self.message
|
||||
if self.url:
|
||||
remote_error = "{source} Error for url: {url}".format(
|
||||
source=self.source, url=self.url)
|
||||
source=self.source, url=self.url
|
||||
)
|
||||
if self.details:
|
||||
remote_error += ', '
|
||||
if self.details:
|
||||
@ -104,31 +112,37 @@ class HttpException(SDKException, _rex.HTTPError):
|
||||
|
||||
return "{message}: {remote_error}".format(
|
||||
message=super(HttpException, self).__str__(),
|
||||
remote_error=remote_error)
|
||||
remote_error=remote_error,
|
||||
)
|
||||
|
||||
|
||||
class BadRequestException(HttpException):
|
||||
"""HTTP 400 Bad Request."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ForbiddenException(HttpException):
|
||||
"""HTTP 403 Forbidden Request."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ConflictException(HttpException):
|
||||
"""HTTP 409 Conflict."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class PreconditionFailedException(HttpException):
|
||||
"""HTTP 412 Precondition Failed."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class MethodNotSupported(SDKException):
|
||||
"""The resource does not support this operation type."""
|
||||
|
||||
def __init__(self, resource, method):
|
||||
# This needs to work with both classes and instances.
|
||||
try:
|
||||
@ -136,18 +150,23 @@ class MethodNotSupported(SDKException):
|
||||
except AttributeError:
|
||||
name = resource.__class__.__name__
|
||||
|
||||
message = ('The %s method is not supported for %s.%s' %
|
||||
(method, resource.__module__, name))
|
||||
message = 'The %s method is not supported for %s.%s' % (
|
||||
method,
|
||||
resource.__module__,
|
||||
name,
|
||||
)
|
||||
super(MethodNotSupported, self).__init__(message=message)
|
||||
|
||||
|
||||
class DuplicateResource(SDKException):
|
||||
"""More than one resource exists with that name."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ResourceNotFound(HttpException):
|
||||
"""No resource exists with that name or id."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@ -156,16 +175,19 @@ NotFoundException = ResourceNotFound
|
||||
|
||||
class ResourceTimeout(SDKException):
|
||||
"""Timeout waiting for resource."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ResourceFailure(SDKException):
|
||||
"""General resource failure."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class InvalidResourceQuery(SDKException):
|
||||
"""Invalid query params for resource."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@ -225,8 +247,9 @@ def raise_from_response(response, error_message=None):
|
||||
details = response.text
|
||||
elif response.content and 'text/html' in content_type:
|
||||
# Split the lines, strip whitespace and inline HTML from the response.
|
||||
details = [re.sub(r'<.+?>', '', i.strip())
|
||||
for i in response.text.splitlines()]
|
||||
details = [
|
||||
re.sub(r'<.+?>', '', i.strip()) for i in response.text.splitlines()
|
||||
]
|
||||
details = list(set([msg for msg in details if msg]))
|
||||
# Return joined string separated by colons.
|
||||
details = ': '.join(details)
|
||||
@ -238,8 +261,11 @@ def raise_from_response(response, error_message=None):
|
||||
request_id = response.headers.get('x-openstack-request-id')
|
||||
|
||||
raise cls(
|
||||
message=error_message, response=response, details=details,
|
||||
http_status=http_status, request_id=request_id
|
||||
message=error_message,
|
||||
response=response,
|
||||
details=details,
|
||||
http_status=http_status,
|
||||
request_id=request_id,
|
||||
)
|
||||
|
||||
|
||||
@ -249,6 +275,7 @@ class UnsupportedServiceVersion(Warning):
|
||||
|
||||
class ArgumentDeprecationWarning(Warning):
|
||||
"""A deprecated argument has been provided."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
@ -61,7 +61,8 @@ class ConnectionFixture(fixtures.Fixture):
|
||||
templates = {}
|
||||
for k, v in self._endpoint_templates.items():
|
||||
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
|
||||
# versioned endpoint in the catalog, because that's
|
||||
# more likely how those were deployed.
|
||||
@ -88,10 +89,8 @@ class ConnectionFixture(fixtures.Fixture):
|
||||
continue
|
||||
service_name = service['project']
|
||||
ets = self._get_endpoint_templates(service_type)
|
||||
v3_svc = self.v3_token.add_service(
|
||||
service_type, name=service_name)
|
||||
v2_svc = self.v2_token.add_service(
|
||||
service_type, name=service_name)
|
||||
v3_svc = self.v3_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)
|
||||
if service_type == 'identity':
|
||||
ets = self._get_endpoint_templates(service_type, v2=True)
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
|
||||
class Formatter:
|
||||
|
||||
@classmethod
|
||||
def serialize(cls, value):
|
||||
"""Return a string representing the formatted value"""
|
||||
@ -25,7 +24,6 @@ class Formatter:
|
||||
|
||||
|
||||
class BoolStr(Formatter):
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, value):
|
||||
"""Convert a boolean string to a boolean"""
|
||||
@ -35,8 +33,9 @@ class BoolStr(Formatter):
|
||||
elif "false" == expr:
|
||||
return False
|
||||
else:
|
||||
raise ValueError("Unable to deserialize boolean string: %s"
|
||||
% value)
|
||||
raise ValueError(
|
||||
"Unable to deserialize boolean string: %s" % value
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def serialize(cls, value):
|
||||
@ -47,5 +46,4 @@ class BoolStr(Formatter):
|
||||
else:
|
||||
return "false"
|
||||
else:
|
||||
raise ValueError("Unable to serialize boolean string: %s"
|
||||
% value)
|
||||
raise ValueError("Unable to serialize boolean string: %s" % value)
|
||||
|
@ -437,8 +437,7 @@ class Proxy(adapter.Adapter, Generic[T]):
|
||||
self, '_connection', getattr(self.session, '_sdk_connection', None)
|
||||
)
|
||||
|
||||
def _get_resource(self, resource_type: Type[T], value,
|
||||
**attrs) -> T:
|
||||
def _get_resource(self, resource_type: Type[T], value, **attrs) -> T:
|
||||
"""Get a resource object to work on
|
||||
|
||||
: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)
|
||||
return value
|
||||
|
||||
def _find(self, resource_type: Type[T], name_or_id, ignore_missing=True,
|
||||
**attrs) -> Optional[T]:
|
||||
def _find(
|
||||
self, resource_type: Type[T], name_or_id, ignore_missing=True, **attrs
|
||||
) -> Optional[T]:
|
||||
"""Find a resource
|
||||
|
||||
: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)
|
||||
def _delete(self, resource_type: Type[T], value, ignore_missing=True,
|
||||
**attrs):
|
||||
def _delete(
|
||||
self, resource_type: Type[T], value, ignore_missing=True, **attrs
|
||||
):
|
||||
"""Delete a resource
|
||||
|
||||
:param resource_type: The type of resource to delete. This should
|
||||
@ -542,8 +543,9 @@ class Proxy(adapter.Adapter, Generic[T]):
|
||||
return rv
|
||||
|
||||
@_check_resource(strict=False)
|
||||
def _update(self, resource_type: Type[T], value, base_path=None,
|
||||
**attrs) -> T:
|
||||
def _update(
|
||||
self, resource_type: Type[T], value, base_path=None, **attrs
|
||||
) -> T:
|
||||
"""Update a resource
|
||||
|
||||
: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)
|
||||
return res.create(self, base_path=base_path)
|
||||
|
||||
def _bulk_create(self, resource_type: Type[T], data, base_path=None
|
||||
) -> Generator[T, None, None]:
|
||||
def _bulk_create(
|
||||
self, resource_type: Type[T], data, base_path=None
|
||||
) -> Generator[T, None, None]:
|
||||
"""Create a resource from attributes
|
||||
|
||||
:param resource_type: The type of resource to create.
|
||||
@ -614,13 +617,13 @@ class Proxy(adapter.Adapter, Generic[T]):
|
||||
|
||||
@_check_resource(strict=False)
|
||||
def _get(
|
||||
self,
|
||||
resource_type: Type[T],
|
||||
value=None,
|
||||
requires_id=True,
|
||||
base_path=None,
|
||||
skip_cache=False,
|
||||
**attrs
|
||||
self,
|
||||
resource_type: Type[T],
|
||||
value=None,
|
||||
requires_id=True,
|
||||
base_path=None,
|
||||
skip_cache=False,
|
||||
**attrs
|
||||
):
|
||||
"""Fetch a resource
|
||||
|
||||
@ -657,12 +660,12 @@ class Proxy(adapter.Adapter, Generic[T]):
|
||||
)
|
||||
|
||||
def _list(
|
||||
self,
|
||||
resource_type: Type[T],
|
||||
paginated=True,
|
||||
base_path=None,
|
||||
jmespath_filters=None,
|
||||
**attrs
|
||||
self,
|
||||
resource_type: Type[T],
|
||||
paginated=True,
|
||||
base_path=None,
|
||||
jmespath_filters=None,
|
||||
**attrs
|
||||
) -> Generator[T, None, None]:
|
||||
"""List a resource
|
||||
|
||||
@ -690,8 +693,7 @@ class Proxy(adapter.Adapter, Generic[T]):
|
||||
the ``resource_type``.
|
||||
"""
|
||||
data = resource_type.list(
|
||||
self, paginated=paginated, base_path=base_path,
|
||||
**attrs
|
||||
self, paginated=paginated, base_path=base_path, **attrs
|
||||
)
|
||||
|
||||
if jmespath_filters and isinstance(jmespath_filters, str):
|
||||
@ -699,8 +701,9 @@ class Proxy(adapter.Adapter, Generic[T]):
|
||||
|
||||
return data
|
||||
|
||||
def _head(self, resource_type: Type[T], value=None, base_path=None,
|
||||
**attrs):
|
||||
def _head(
|
||||
self, resource_type: Type[T], value=None, base_path=None, **attrs
|
||||
):
|
||||
"""Retrieve a resource's header
|
||||
|
||||
:param resource_type: The type of resource to retrieve.
|
||||
|
@ -207,15 +207,14 @@ class _BaseComponent:
|
||||
def warn_if_deprecated_property(self, value):
|
||||
deprecated = object.__getattribute__(self, 'deprecated')
|
||||
deprecation_reason = object.__getattribute__(
|
||||
self, 'deprecation_reason',
|
||||
self,
|
||||
'deprecation_reason',
|
||||
)
|
||||
|
||||
if value and deprecated:
|
||||
warnings.warn(
|
||||
"The field %r has been deprecated. %s" % (
|
||||
self.name,
|
||||
deprecation_reason or "Avoid usage."
|
||||
),
|
||||
"The field %r has been deprecated. %s"
|
||||
% (self.name, deprecation_reason or "Avoid usage."),
|
||||
os_warnings.RemovedFieldWarning,
|
||||
)
|
||||
return value
|
||||
@ -1027,9 +1026,7 @@ class Resource(dict):
|
||||
converted = []
|
||||
for raw in value:
|
||||
if isinstance(raw, Resource):
|
||||
converted.append(
|
||||
raw.to_dict(_to_munch=to_munch)
|
||||
)
|
||||
converted.append(raw.to_dict(_to_munch=to_munch))
|
||||
elif isinstance(raw, dict) and to_munch:
|
||||
converted.append(utils.Munch(raw))
|
||||
else:
|
||||
@ -1223,10 +1220,7 @@ class Resource(dict):
|
||||
requires_id = self.requires_id
|
||||
|
||||
# Conditionally construct arguments for _prepare_request_body
|
||||
request_kwargs = {
|
||||
"patch": patch,
|
||||
"prepend_key": prepend_key
|
||||
}
|
||||
request_kwargs = {"patch": patch, "prepend_key": prepend_key}
|
||||
if resource_request_key is not None:
|
||||
request_kwargs['resource_request_key'] = resource_request_key
|
||||
body = self._prepare_request_body(**request_kwargs)
|
||||
@ -1443,7 +1437,7 @@ class Resource(dict):
|
||||
resource_request_key=None,
|
||||
resource_response_key=None,
|
||||
microversion=None,
|
||||
**params
|
||||
**params,
|
||||
):
|
||||
"""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_kwargs = {}
|
||||
if resource_response_key is not None:
|
||||
fetch_kwargs = \
|
||||
{'resource_response_key': resource_response_key}
|
||||
fetch_kwargs = {'resource_response_key': resource_response_key}
|
||||
return self.fetch(session, **fetch_kwargs)
|
||||
return self
|
||||
|
||||
@ -1681,7 +1674,8 @@ class Resource(dict):
|
||||
raise exceptions.MethodNotSupported(self, 'fetch')
|
||||
|
||||
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)
|
||||
if microversion is None:
|
||||
@ -1931,8 +1925,9 @@ class Resource(dict):
|
||||
retry_on_conflict=retry_on_conflict,
|
||||
)
|
||||
|
||||
def delete(self, session, error_message=None, *, microversion=None,
|
||||
**kwargs):
|
||||
def delete(
|
||||
self, session, error_message=None, *, microversion=None, **kwargs
|
||||
):
|
||||
"""Delete the remote resource based on this instance.
|
||||
|
||||
:param session: The session to use for making this request.
|
||||
@ -1948,8 +1943,9 @@ class Resource(dict):
|
||||
the resource was not found.
|
||||
"""
|
||||
|
||||
response = self._raw_delete(session, microversion=microversion,
|
||||
**kwargs)
|
||||
response = self._raw_delete(
|
||||
session, microversion=microversion, **kwargs
|
||||
)
|
||||
kwargs = {}
|
||||
if error_message:
|
||||
kwargs['error_message'] = error_message
|
||||
@ -2116,7 +2112,8 @@ class Resource(dict):
|
||||
for key in client_filters.keys():
|
||||
if isinstance(client_filters[key], dict):
|
||||
if not _dict_filter(
|
||||
client_filters[key], value.get(key, None)):
|
||||
client_filters[key], value.get(key, None)
|
||||
):
|
||||
filters_matched = False
|
||||
break
|
||||
elif value.get(key, None) != client_filters[key]:
|
||||
@ -2176,7 +2173,7 @@ class Resource(dict):
|
||||
# Glance has a next field in the main body
|
||||
next_link = next_link or data.get('next')
|
||||
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:
|
||||
# RFC5988 specifies Link headers and requests parses them if they
|
||||
@ -2281,8 +2278,11 @@ class Resource(dict):
|
||||
**params,
|
||||
)
|
||||
return match.fetch(session, microversion=microversion, **params)
|
||||
except (exceptions.NotFoundException, exceptions.BadRequestException,
|
||||
exceptions.ForbiddenException):
|
||||
except (
|
||||
exceptions.NotFoundException,
|
||||
exceptions.BadRequestException,
|
||||
exceptions.ForbiddenException,
|
||||
):
|
||||
# NOTE(gtema): There are few places around openstack that return
|
||||
# 400 if we try to GET resource and it doesn't exist.
|
||||
pass
|
||||
|
@ -36,7 +36,9 @@ class _ServiceDisabledProxyShim:
|
||||
raise exceptions.ServiceDisabledException(
|
||||
"Service '{service_type}' is disabled because its configuration "
|
||||
"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:
|
||||
@ -73,9 +75,8 @@ class ServiceDescription:
|
||||
"""
|
||||
self.service_type = service_type or self.service_type
|
||||
self.supported_versions = (
|
||||
supported_versions
|
||||
or self.supported_versions
|
||||
or {})
|
||||
supported_versions or self.supported_versions or {}
|
||||
)
|
||||
|
||||
self.aliases = aliases or 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}: "
|
||||
"{message}".format(
|
||||
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):
|
||||
"""Create a Proxy for the service in question.
|
||||
@ -148,7 +151,8 @@ class ServiceDescription:
|
||||
if not config.has_service(self.service_type):
|
||||
return _ServiceDisabledProxyShim(
|
||||
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
|
||||
# explicitly just using us for a passthrough REST adapter.
|
||||
@ -186,13 +190,12 @@ class ServiceDescription:
|
||||
" {service_type} is not known or supported by"
|
||||
" openstacksdk. The resulting Proxy object will only"
|
||||
" have direct passthrough REST capabilities.".format(
|
||||
version=version_string,
|
||||
service_type=self.service_type),
|
||||
category=exceptions.UnsupportedServiceVersion)
|
||||
version=version_string, service_type=self.service_type
|
||||
),
|
||||
category=exceptions.UnsupportedServiceVersion,
|
||||
)
|
||||
elif endpoint_override:
|
||||
temp_adapter = config.get_session_client(
|
||||
self.service_type
|
||||
)
|
||||
temp_adapter = config.get_session_client(self.service_type)
|
||||
api_version = temp_adapter.get_endpoint_data().api_version
|
||||
proxy_class = self.supported_versions.get(str(api_version[0]))
|
||||
if proxy_class:
|
||||
@ -207,9 +210,10 @@ class ServiceDescription:
|
||||
" is not supported by openstacksdk. The resulting Proxy"
|
||||
" object will only have direct passthrough REST"
|
||||
" capabilities.".format(
|
||||
version=api_version,
|
||||
service_type=self.service_type),
|
||||
category=exceptions.UnsupportedServiceVersion)
|
||||
version=api_version, service_type=self.service_type
|
||||
),
|
||||
category=exceptions.UnsupportedServiceVersion,
|
||||
)
|
||||
|
||||
if proxy_obj:
|
||||
|
||||
@ -225,7 +229,9 @@ class ServiceDescription:
|
||||
raise exceptions.ServiceDiscoveryException(
|
||||
"Failed to create a working proxy for service "
|
||||
"{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
|
||||
# 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.
|
||||
if data.catalog_url != data.service_url:
|
||||
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
|
||||
proxy_obj = config.get_session_client(
|
||||
self.service_type,
|
||||
@ -248,16 +255,16 @@ class ServiceDescription:
|
||||
if version_string:
|
||||
version_kwargs['version'] = version_string
|
||||
else:
|
||||
supported_versions = sorted([
|
||||
int(f) for f in self.supported_versions])
|
||||
supported_versions = sorted(
|
||||
[int(f) for f in self.supported_versions]
|
||||
)
|
||||
version_kwargs['min_version'] = str(supported_versions[0])
|
||||
version_kwargs['max_version'] = '{version}.latest'.format(
|
||||
version=str(supported_versions[-1]))
|
||||
version=str(supported_versions[-1])
|
||||
)
|
||||
|
||||
temp_adapter = config.get_session_client(
|
||||
self.service_type,
|
||||
allow_version_hack=True,
|
||||
**version_kwargs
|
||||
self.service_type, allow_version_hack=True, **version_kwargs
|
||||
)
|
||||
found_version = temp_adapter.get_api_major_version()
|
||||
if found_version is None:
|
||||
@ -268,14 +275,18 @@ class ServiceDescription:
|
||||
" exists but does not have any supported versions.".format(
|
||||
service_type=self.service_type,
|
||||
cloud=instance.name,
|
||||
region_name=region_name))
|
||||
region_name=region_name,
|
||||
)
|
||||
)
|
||||
else:
|
||||
raise exceptions.NotSupported(
|
||||
"The {service_type} service for {cloud}:{region_name}"
|
||||
" exists but no version was discoverable.".format(
|
||||
service_type=self.service_type,
|
||||
cloud=instance.name,
|
||||
region_name=region_name))
|
||||
region_name=region_name,
|
||||
)
|
||||
)
|
||||
proxy_class = self.supported_versions.get(str(found_version[0]))
|
||||
if proxy_class:
|
||||
return config.get_session_client(
|
||||
@ -294,8 +305,10 @@ class ServiceDescription:
|
||||
"Service {service_type} has no discoverable version."
|
||||
" The resulting Proxy object will only have direct"
|
||||
" passthrough REST capabilities.".format(
|
||||
service_type=self.service_type),
|
||||
category=exceptions.UnsupportedServiceVersion)
|
||||
service_type=self.service_type
|
||||
),
|
||||
category=exceptions.UnsupportedServiceVersion,
|
||||
)
|
||||
return temp_adapter
|
||||
|
||||
def __set__(self, instance, value):
|
||||
|
@ -47,7 +47,9 @@ class TestCase(base.BaseTestCase):
|
||||
test_timeout = int(test_timeout * self.TIMEOUT_SCALING_FACTOR)
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable(
|
||||
'OS_TEST_TIMEOUT', str(test_timeout)))
|
||||
'OS_TEST_TIMEOUT', str(test_timeout)
|
||||
)
|
||||
)
|
||||
except ValueError:
|
||||
# Let oslotest do its thing
|
||||
pass
|
||||
@ -90,7 +92,8 @@ class TestCase(base.BaseTestCase):
|
||||
if isinstance(second, utils.Munch):
|
||||
second = second.toDict()
|
||||
return super(TestCase, self).assertEqual(
|
||||
first, second, *args, **kwargs)
|
||||
first, second, *args, **kwargs
|
||||
)
|
||||
|
||||
def printLogs(self, *args):
|
||||
self._log_stream.seek(0)
|
||||
@ -104,16 +107,18 @@ class TestCase(base.BaseTestCase):
|
||||
if not x:
|
||||
break
|
||||
yield x.encode('utf8')
|
||||
|
||||
content = testtools.content.content_from_reader(
|
||||
reader,
|
||||
testtools.content_type.UTF8_TEXT,
|
||||
False)
|
||||
reader, testtools.content_type.UTF8_TEXT, False
|
||||
)
|
||||
self.addDetail('logging', content)
|
||||
|
||||
def add_info_on_exception(self, name, text):
|
||||
def add_content(unused):
|
||||
self.addDetail(name, testtools.content.text_content(
|
||||
pprint.pformat(text)))
|
||||
self.addDetail(
|
||||
name, testtools.content.text_content(pprint.pformat(text))
|
||||
)
|
||||
|
||||
self.addOnException(add_content)
|
||||
|
||||
def assertSubdict(self, part, whole):
|
||||
@ -124,11 +129,18 @@ class TestCase(base.BaseTestCase):
|
||||
if not whole[key] and part[key]:
|
||||
missing_keys.append(key)
|
||||
if missing_keys:
|
||||
self.fail("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]]
|
||||
self.fail(
|
||||
"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]
|
||||
]
|
||||
if wrong_values:
|
||||
self.fail("Mismatched values: %s" %
|
||||
", ".join("for %s got %s and %s" % tpl
|
||||
for tpl in wrong_values))
|
||||
self.fail(
|
||||
"Mismatched values: %s"
|
||||
% ", ".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'
|
||||
COMPUTE_ENDPOINT = 'https://compute.example.com/v2.1'
|
||||
ORCHESTRATION_ENDPOINT = 'https://orchestration.example.com/v1/{p}'.format(
|
||||
p=PROJECT_ID)
|
||||
p=PROJECT_ID
|
||||
)
|
||||
NO_MD5 = '93b885adfe0da089cdf634904fd59f71'
|
||||
NO_SHA256 = '6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d'
|
||||
FAKE_PUBLIC_KEY = (
|
||||
@ -41,7 +42,8 @@ FAKE_PUBLIC_KEY = (
|
||||
"sZacm0cZNuL69EObEGHdprfGJQajrpz22NQoCD8TFB8Wv+8om9NH9Le6s+WPe98WC77KLw8qg"
|
||||
"fQsbIey+JawPWl4O67ZdL5xrypuRjfIPWjgy/VH85IXg/Z/GONZ2nxHgSShMkwqSFECAC5L3P"
|
||||
"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):
|
||||
@ -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'disk': disk,
|
||||
u'id': flavor_id,
|
||||
u'links': [{
|
||||
u'href': u'{endpoint}/flavors/{id}'.format(
|
||||
endpoint=COMPUTE_ENDPOINT, id=flavor_id),
|
||||
u'rel': u'self'
|
||||
}, {
|
||||
u'href': u'{endpoint}/flavors/{id}'.format(
|
||||
endpoint=COMPUTE_ENDPOINT, id=flavor_id),
|
||||
u'rel': u'bookmark'
|
||||
}],
|
||||
u'links': [
|
||||
{
|
||||
u'href': u'{endpoint}/flavors/{id}'.format(
|
||||
endpoint=COMPUTE_ENDPOINT, id=flavor_id
|
||||
),
|
||||
u'rel': u'self',
|
||||
},
|
||||
{
|
||||
u'href': u'{endpoint}/flavors/{id}'.format(
|
||||
endpoint=COMPUTE_ENDPOINT, id=flavor_id
|
||||
),
|
||||
u'rel': u'bookmark',
|
||||
},
|
||||
],
|
||||
u'name': name,
|
||||
u'os-flavor-access:is_public': True,
|
||||
u'ram': ram,
|
||||
u'rxtx_factor': 1.0,
|
||||
u'swap': u'',
|
||||
u'vcpus': vcpus
|
||||
u'vcpus': vcpus,
|
||||
}
|
||||
|
||||
|
||||
FAKE_FLAVOR = make_fake_flavor(FLAVOR_ID, 'vanilla')
|
||||
FAKE_CHOCOLATE_FLAVOR = make_fake_flavor(
|
||||
CHOCOLATE_FLAVOR_ID, 'chocolate', ram=200)
|
||||
CHOCOLATE_FLAVOR_ID, 'chocolate', ram=200
|
||||
)
|
||||
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_TEMPLATE = '''heat_template_version: 2014-10-16
|
||||
|
||||
@ -95,8 +104,14 @@ FAKE_TEMPLATE_CONTENT = template_format.parse(FAKE_TEMPLATE)
|
||||
|
||||
|
||||
def make_fake_server(
|
||||
server_id, name, status='ACTIVE', admin_pass=None,
|
||||
addresses=None, image=None, flavor=None):
|
||||
server_id,
|
||||
name,
|
||||
status='ACTIVE',
|
||||
admin_pass=None,
|
||||
addresses=None,
|
||||
image=None,
|
||||
flavor=None,
|
||||
):
|
||||
if addresses is None:
|
||||
if status == 'ACTIVE':
|
||||
addresses = {
|
||||
@ -105,25 +120,28 @@ def make_fake_server(
|
||||
"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:df:b0:8d",
|
||||
"version": 6,
|
||||
"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",
|
||||
"version": 4,
|
||||
"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",
|
||||
"version": 4,
|
||||
"addr": "172.24.5.5",
|
||||
"OS-EXT-IPS:type": "floating"}]}
|
||||
"OS-EXT-IPS:type": "floating",
|
||||
},
|
||||
]
|
||||
}
|
||||
else:
|
||||
addresses = {}
|
||||
if image is None:
|
||||
image = {"id": "217f3ab1-03e0-4450-bf27-63d52b421e9e",
|
||||
"links": []}
|
||||
image = {"id": "217f3ab1-03e0-4450-bf27-63d52b421e9e", "links": []}
|
||||
if flavor is None:
|
||||
flavor = {"id": "64",
|
||||
"links": []}
|
||||
flavor = {"id": "64", "links": []}
|
||||
|
||||
server = {
|
||||
"OS-EXT-STS:task_state": None,
|
||||
@ -152,7 +170,8 @@ def make_fake_server(
|
||||
"created": "2017-03-23T23:57:12Z",
|
||||
"tenant_id": PROJECT_ID,
|
||||
"os-extended-volumes:volumes_attached": [],
|
||||
"config_drive": "True"}
|
||||
"config_drive": "True",
|
||||
}
|
||||
if admin_pass:
|
||||
server['adminPass'] = admin_pass
|
||||
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(
|
||||
id, name, status='CREATE_COMPLETED', resource_name='id'):
|
||||
id, name, status='CREATE_COMPLETED', resource_name='id'
|
||||
):
|
||||
event_id = uuid.uuid4().hex
|
||||
self_url = "{endpoint}/stacks/{name}/{id}/resources/{name}/events/{event}"
|
||||
resource_url = "{endpoint}/stacks/{name}/{id}/resources/{name}"
|
||||
@ -199,19 +219,25 @@ def make_fake_stack_event(
|
||||
{
|
||||
"href": self_url.format(
|
||||
endpoint=ORCHESTRATION_ENDPOINT,
|
||||
name=name, id=id, event=event_id),
|
||||
"rel": "self"
|
||||
}, {
|
||||
name=name,
|
||||
id=id,
|
||||
event=event_id,
|
||||
),
|
||||
"rel": "self",
|
||||
},
|
||||
{
|
||||
"href": resource_url.format(
|
||||
endpoint=ORCHESTRATION_ENDPOINT,
|
||||
name=name, id=id),
|
||||
"rel": "resource"
|
||||
}, {
|
||||
endpoint=ORCHESTRATION_ENDPOINT, name=name, id=id
|
||||
),
|
||||
"rel": "resource",
|
||||
},
|
||||
{
|
||||
"href": "{endpoint}/stacks/{name}/{id}".format(
|
||||
endpoint=ORCHESTRATION_ENDPOINT,
|
||||
name=name, id=id),
|
||||
"rel": "stack"
|
||||
}],
|
||||
endpoint=ORCHESTRATION_ENDPOINT, name=name, id=id
|
||||
),
|
||||
"rel": "stack",
|
||||
},
|
||||
],
|
||||
"logical_resource_id": name,
|
||||
"resource_status": status,
|
||||
"resource_status_reason": "",
|
||||
@ -221,10 +247,14 @@ def make_fake_stack_event(
|
||||
|
||||
|
||||
def make_fake_image(
|
||||
image_id=None, md5=NO_MD5, sha256=NO_SHA256, status='active',
|
||||
image_name=u'fake_image',
|
||||
data=None,
|
||||
checksum=u'ee36e35a297980dee1b514de9803ec6d'):
|
||||
image_id=None,
|
||||
md5=NO_MD5,
|
||||
sha256=NO_SHA256,
|
||||
status='active',
|
||||
image_name=u'fake_image',
|
||||
data=None,
|
||||
checksum=u'ee36e35a297980dee1b514de9803ec6d',
|
||||
):
|
||||
if data:
|
||||
md5 = utils.md5(usedforsecurity=False)
|
||||
sha256 = hashlib.sha256()
|
||||
@ -249,9 +279,9 @@ def make_fake_image(
|
||||
u'status': status,
|
||||
u'tags': [],
|
||||
u'visibility': u'private',
|
||||
u'locations': [{
|
||||
u'url': u'http://127.0.0.1/images/' + image_id,
|
||||
u'metadata': {}}],
|
||||
u'locations': [
|
||||
{u'url': u'http://127.0.0.1/images/' + image_id, u'metadata': {}}
|
||||
],
|
||||
u'min_disk': 40,
|
||||
u'virtual_size': None,
|
||||
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.sha256': sha256 or NO_SHA256,
|
||||
u'owner_specified.openstack.object': 'images/{name}'.format(
|
||||
name=image_name),
|
||||
u'protected': False}
|
||||
name=image_name
|
||||
),
|
||||
u'protected': False,
|
||||
}
|
||||
|
||||
|
||||
def make_fake_machine(machine_name, machine_id=None):
|
||||
if not machine_id:
|
||||
machine_id = uuid.uuid4().hex
|
||||
return meta.obj_to_munch(FakeMachine(
|
||||
id=machine_id,
|
||||
name=machine_name))
|
||||
return meta.obj_to_munch(FakeMachine(id=machine_id, name=machine_name))
|
||||
|
||||
|
||||
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
|
||||
if not port_id:
|
||||
port_id = uuid.uuid4().hex
|
||||
return meta.obj_to_munch(FakeMachinePort(
|
||||
id=port_id,
|
||||
address=address,
|
||||
node_id=node_id))
|
||||
return meta.obj_to_munch(
|
||||
FakeMachinePort(id=port_id, address=address, node_id=node_id)
|
||||
)
|
||||
|
||||
|
||||
class FakeFloatingIP:
|
||||
@ -293,63 +322,58 @@ class FakeFloatingIP:
|
||||
|
||||
|
||||
def make_fake_server_group(id, name, policies):
|
||||
return json.loads(json.dumps({
|
||||
'id': id,
|
||||
'name': name,
|
||||
'policies': policies,
|
||||
'members': [],
|
||||
'metadata': {},
|
||||
}))
|
||||
return json.loads(
|
||||
json.dumps(
|
||||
{
|
||||
'id': id,
|
||||
'name': name,
|
||||
'policies': policies,
|
||||
'members': [],
|
||||
'metadata': {},
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def make_fake_hypervisor(id, name):
|
||||
return json.loads(json.dumps({
|
||||
'id': id,
|
||||
'hypervisor_hostname': name,
|
||||
'state': 'up',
|
||||
'status': 'enabled',
|
||||
"cpu_info": {
|
||||
"arch": "x86_64",
|
||||
"model": "Nehalem",
|
||||
"vendor": "Intel",
|
||||
"features": [
|
||||
"pge",
|
||||
"clflush"
|
||||
],
|
||||
"topology": {
|
||||
"cores": 1,
|
||||
"threads": 1,
|
||||
"sockets": 4
|
||||
return json.loads(
|
||||
json.dumps(
|
||||
{
|
||||
'id': id,
|
||||
'hypervisor_hostname': name,
|
||||
'state': 'up',
|
||||
'status': 'enabled',
|
||||
"cpu_info": {
|
||||
"arch": "x86_64",
|
||||
"model": "Nehalem",
|
||||
"vendor": "Intel",
|
||||
"features": ["pge", "clflush"],
|
||||
"topology": {"cores": 1, "threads": 1, "sockets": 4},
|
||||
},
|
||||
"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,
|
||||
}
|
||||
},
|
||||
"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:
|
||||
def __init__(
|
||||
self, id, status, name, attachments=[],
|
||||
size=75):
|
||||
def __init__(self, id, status, name, attachments=[], size=75):
|
||||
self.id = id
|
||||
self.status = status
|
||||
self.name = name
|
||||
@ -366,8 +390,7 @@ class FakeVolume:
|
||||
|
||||
|
||||
class FakeVolumeSnapshot:
|
||||
def __init__(
|
||||
self, id, status, name, description, size=75):
|
||||
def __init__(self, id, status, name, description, size=75):
|
||||
self.id = id
|
||||
self.status = status
|
||||
self.name = name
|
||||
@ -380,10 +403,20 @@ class FakeVolumeSnapshot:
|
||||
|
||||
|
||||
class FakeMachine:
|
||||
def __init__(self, id, 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'):
|
||||
def __init__(
|
||||
self,
|
||||
id,
|
||||
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.name = name
|
||||
self.driver = driver
|
||||
@ -405,50 +438,69 @@ class FakeMachinePort:
|
||||
|
||||
|
||||
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:
|
||||
rules = []
|
||||
if not project_id:
|
||||
project_id = PROJECT_ID
|
||||
return json.loads(json.dumps({
|
||||
'id': id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'stateful': stateful,
|
||||
'project_id': project_id,
|
||||
'tenant_id': project_id,
|
||||
'security_group_rules': rules,
|
||||
}))
|
||||
return json.loads(
|
||||
json.dumps(
|
||||
{
|
||||
'id': id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'stateful': stateful,
|
||||
'project_id': project_id,
|
||||
'tenant_id': project_id,
|
||||
'security_group_rules': rules,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def make_fake_nova_security_group_rule(
|
||||
id, from_port, to_port, ip_protocol, cidr):
|
||||
return json.loads(json.dumps({
|
||||
'id': id,
|
||||
'from_port': int(from_port),
|
||||
'to_port': int(to_port),
|
||||
'ip_protcol': 'tcp',
|
||||
'ip_range': {
|
||||
'cidr': cidr
|
||||
}
|
||||
}))
|
||||
id, from_port, to_port, ip_protocol, cidr
|
||||
):
|
||||
return json.loads(
|
||||
json.dumps(
|
||||
{
|
||||
'id': id,
|
||||
'from_port': int(from_port),
|
||||
'to_port': int(to_port),
|
||||
'ip_protcol': 'tcp',
|
||||
'ip_range': {'cidr': cidr},
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def make_fake_nova_security_group(id, name, description, rules):
|
||||
if not rules:
|
||||
rules = []
|
||||
return json.loads(json.dumps({
|
||||
'id': id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'tenant_id': PROJECT_ID,
|
||||
'rules': rules,
|
||||
}))
|
||||
return json.loads(
|
||||
json.dumps(
|
||||
{
|
||||
'id': id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'tenant_id': PROJECT_ID,
|
||||
'rules': rules,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class FakeNovaSecgroupRule:
|
||||
def __init__(self, id, from_port=None, to_port=None, ip_protocol=None,
|
||||
cidr=None, parent_group_id=None):
|
||||
def __init__(
|
||||
self,
|
||||
id,
|
||||
from_port=None,
|
||||
to_port=None,
|
||||
ip_protocol=None,
|
||||
cidr=None,
|
||||
parent_group_id=None,
|
||||
):
|
||||
self.id = id
|
||||
self.from_port = from_port
|
||||
self.to_port = to_port
|
||||
@ -465,8 +517,7 @@ class FakeHypervisor:
|
||||
|
||||
|
||||
class FakeZone:
|
||||
def __init__(self, id, name, type_, email, description,
|
||||
ttl, masters):
|
||||
def __init__(self, id, name, type_, email, description, ttl, masters):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.type_ = type_
|
||||
@ -477,8 +528,7 @@ class FakeZone:
|
||||
|
||||
|
||||
class FakeRecordset:
|
||||
def __init__(self, zone, id, name, type_, description,
|
||||
ttl, records):
|
||||
def __init__(self, zone, id, name, type_, description, ttl, records):
|
||||
self.zone = zone
|
||||
self.id = id
|
||||
self.name = name
|
||||
@ -488,22 +538,27 @@ class FakeRecordset:
|
||||
self.records = records
|
||||
|
||||
|
||||
def make_fake_aggregate(id, name, availability_zone='nova',
|
||||
metadata=None, hosts=None):
|
||||
def make_fake_aggregate(
|
||||
id, name, availability_zone='nova', metadata=None, hosts=None
|
||||
):
|
||||
if not metadata:
|
||||
metadata = {}
|
||||
if not hosts:
|
||||
hosts = []
|
||||
return json.loads(json.dumps({
|
||||
"availability_zone": availability_zone,
|
||||
"created_at": datetime.datetime.now().isoformat(),
|
||||
"deleted": False,
|
||||
"deleted_at": None,
|
||||
"hosts": hosts,
|
||||
"id": int(id),
|
||||
"metadata": {
|
||||
"availability_zone": availability_zone,
|
||||
},
|
||||
"name": name,
|
||||
"updated_at": None,
|
||||
}))
|
||||
return json.loads(
|
||||
json.dumps(
|
||||
{
|
||||
"availability_zone": availability_zone,
|
||||
"created_at": datetime.datetime.now().isoformat(),
|
||||
"deleted": False,
|
||||
"deleted_at": None,
|
||||
"hosts": hosts,
|
||||
"id": int(id),
|
||||
"metadata": {
|
||||
"availability_zone": availability_zone,
|
||||
},
|
||||
"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_alt = os.environ.get(
|
||||
'OPENSTACKSDK_DEMO_CLOUD_ALT', 'devstack-alt',
|
||||
'OPENSTACKSDK_DEMO_CLOUD_ALT',
|
||||
'devstack-alt',
|
||||
)
|
||||
self._op_name = os.environ.get(
|
||||
'OPENSTACKSDK_OPERATOR_CLOUD', 'devstack-admin',
|
||||
'OPENSTACKSDK_OPERATOR_CLOUD',
|
||||
'devstack-admin',
|
||||
)
|
||||
|
||||
self.config = openstack.config.OpenStackConfig()
|
||||
@ -64,8 +66,9 @@ class BaseFunctionalTest(base.TestCase):
|
||||
else:
|
||||
self.operator_cloud = None
|
||||
|
||||
self.identity_version = \
|
||||
self.user_cloud.config.get_api_version('identity')
|
||||
self.identity_version = self.user_cloud.config.get_api_version(
|
||||
'identity'
|
||||
)
|
||||
|
||||
self.flavor = self._pick_flavor()
|
||||
self.image = self._pick_image()
|
||||
@ -73,8 +76,11 @@ class BaseFunctionalTest(base.TestCase):
|
||||
# Defines default timeout for wait_for methods used
|
||||
# in the functional tests
|
||||
self._wait_for_timeout = int(
|
||||
os.getenv(self._wait_for_timeout_key, os.getenv(
|
||||
'OPENSTACKSDK_FUNC_TEST_TIMEOUT', 300)))
|
||||
os.getenv(
|
||||
self._wait_for_timeout_key,
|
||||
os.getenv('OPENSTACKSDK_FUNC_TEST_TIMEOUT', 300),
|
||||
)
|
||||
)
|
||||
|
||||
def _set_user_cloud(self, **kwargs):
|
||||
user_config = self.config.get_one(cloud=self._demo_name, **kwargs)
|
||||
@ -85,7 +91,8 @@ class BaseFunctionalTest(base.TestCase):
|
||||
# it
|
||||
if self._demo_name_alt:
|
||||
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)
|
||||
_disable_keep_alive(self.user_cloud_alt)
|
||||
else:
|
||||
@ -119,7 +126,8 @@ class BaseFunctionalTest(base.TestCase):
|
||||
return flavor
|
||||
|
||||
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
|
||||
@ -159,7 +167,8 @@ class BaseFunctionalTest(base.TestCase):
|
||||
return image
|
||||
|
||||
raise self.failureException(
|
||||
"Cloud does not have image '%s'", image_name,
|
||||
"Cloud does not have image '%s'",
|
||||
image_name,
|
||||
)
|
||||
|
||||
for image in images:
|
||||
@ -186,6 +195,7 @@ class BaseFunctionalTest(base.TestCase):
|
||||
def cleanup():
|
||||
result = func(*args, **kwargs)
|
||||
self.assertIsNone(result)
|
||||
|
||||
self.addCleanup(cleanup)
|
||||
|
||||
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.
|
||||
"""
|
||||
if not self.conn.has_service(service_type):
|
||||
self.skipTest('Service {service_type} not found in cloud'.format(
|
||||
service_type=service_type))
|
||||
self.skipTest(
|
||||
'Service {service_type} not found in cloud'.format(
|
||||
service_type=service_type
|
||||
)
|
||||
)
|
||||
|
||||
if not min_microversion:
|
||||
return
|
||||
|
||||
data = self.conn.session.get_endpoint_data(
|
||||
service_type=service_type, **kwargs)
|
||||
service_type=service_type, **kwargs
|
||||
)
|
||||
|
||||
if not (
|
||||
data.min_microversion
|
||||
@ -230,12 +244,11 @@ class BaseFunctionalTest(base.TestCase):
|
||||
# unix_t is also used to easier determine orphans when running real
|
||||
# functional tests on a real cloud
|
||||
return (prefix if prefix else '') + "{time}-{uuid}".format(
|
||||
time=int(time.time()),
|
||||
uuid=uuid.uuid4().hex)
|
||||
time=int(time.time()), uuid=uuid.uuid4().hex
|
||||
)
|
||||
|
||||
|
||||
class KeystoneBaseFunctionalTest(BaseFunctionalTest):
|
||||
|
||||
def setUp(self):
|
||||
super(KeystoneBaseFunctionalTest, self).setUp()
|
||||
|
||||
|
@ -37,44 +37,49 @@ from openstack.tests import fakes
|
||||
_ProjectData = collections.namedtuple(
|
||||
'ProjectData',
|
||||
'project_id, project_name, enabled, domain_id, description, '
|
||||
'parent_id, json_response, json_request')
|
||||
'parent_id, json_response, json_request',
|
||||
)
|
||||
|
||||
|
||||
_UserData = collections.namedtuple(
|
||||
'UserData',
|
||||
'user_id, password, name, email, description, domain_id, enabled, '
|
||||
'json_response, json_request')
|
||||
'json_response, json_request',
|
||||
)
|
||||
|
||||
|
||||
_GroupData = collections.namedtuple(
|
||||
'GroupData',
|
||||
'group_id, group_name, domain_id, description, json_response, '
|
||||
'json_request')
|
||||
'json_request',
|
||||
)
|
||||
|
||||
|
||||
_DomainData = collections.namedtuple(
|
||||
'DomainData',
|
||||
'domain_id, domain_name, description, json_response, '
|
||||
'json_request')
|
||||
'domain_id, domain_name, description, json_response, ' 'json_request',
|
||||
)
|
||||
|
||||
|
||||
_ServiceData = collections.namedtuple(
|
||||
'Servicedata',
|
||||
'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(
|
||||
'EndpointData',
|
||||
'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
|
||||
# This should eventually be fixed if it becomes a main-stream feature.
|
||||
_RoleData = collections.namedtuple(
|
||||
'RoleData',
|
||||
'role_id, role_name, json_response, json_request')
|
||||
'RoleData', 'role_id, role_name, json_response, json_request'
|
||||
)
|
||||
|
||||
|
||||
class TestCase(base.TestCase):
|
||||
@ -92,17 +97,20 @@ class TestCase(base.TestCase):
|
||||
def _nosleep(seconds):
|
||||
return realsleep(seconds * 0.0001)
|
||||
|
||||
self.sleep_fixture = self.useFixture(fixtures.MonkeyPatch(
|
||||
'time.sleep',
|
||||
_nosleep))
|
||||
self.sleep_fixture = self.useFixture(
|
||||
fixtures.MonkeyPatch('time.sleep', _nosleep)
|
||||
)
|
||||
self.fixtures_directory = 'openstack/tests/unit/fixtures'
|
||||
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
|
||||
config = tempfile.NamedTemporaryFile(delete=False)
|
||||
cloud_path = '%s/clouds/%s' % (self.fixtures_directory,
|
||||
cloud_config_fixture)
|
||||
cloud_path = '%s/clouds/%s' % (
|
||||
self.fixtures_directory,
|
||||
cloud_config_fixture,
|
||||
)
|
||||
with open(cloud_path, 'rb') as f:
|
||||
content = f.read()
|
||||
config.write(content)
|
||||
@ -115,7 +123,8 @@ class TestCase(base.TestCase):
|
||||
self.config = occ.OpenStackConfig(
|
||||
config_files=[config.name],
|
||||
vendor_files=[vendor.name],
|
||||
secure_files=['non-existant'])
|
||||
secure_files=['non-existant'],
|
||||
)
|
||||
|
||||
self.oslo_config_dict = {
|
||||
# All defaults for nova
|
||||
@ -126,7 +135,7 @@ class TestCase(base.TestCase):
|
||||
'heat': {
|
||||
'region_name': 'SpecialRegion',
|
||||
'interface': 'internal',
|
||||
'endpoint_override': 'https://example.org:8888/heat/v2'
|
||||
'endpoint_override': 'https://example.org:8888/heat/v2',
|
||||
},
|
||||
# test a service with dashes
|
||||
'ironic_inspector': {
|
||||
@ -151,7 +160,8 @@ class TestCase(base.TestCase):
|
||||
# request in the correct orders.
|
||||
self._uri_registry = collections.OrderedDict()
|
||||
self.discovery_json = os.path.join(
|
||||
self.fixtures_directory, 'discovery.json')
|
||||
self.fixtures_directory, 'discovery.json'
|
||||
)
|
||||
self.use_keystone_v3()
|
||||
self.__register_uris_called = False
|
||||
|
||||
@ -166,11 +176,18 @@ class TestCase(base.TestCase):
|
||||
return conf
|
||||
|
||||
# TODO(shade) Update this to handle service type aliases
|
||||
def get_mock_url(self, service_type, interface='public', resource=None,
|
||||
append=None, base_url_append=None,
|
||||
qs_elements=None):
|
||||
def get_mock_url(
|
||||
self,
|
||||
service_type,
|
||||
interface='public',
|
||||
resource=None,
|
||||
append=None,
|
||||
base_url_append=None,
|
||||
qs_elements=None,
|
||||
):
|
||||
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
|
||||
if endpoint_url.endswith('/'):
|
||||
endpoint_url = endpoint_url[:-1]
|
||||
@ -184,13 +201,17 @@ class TestCase(base.TestCase):
|
||||
to_join.extend([urllib.parse.quote(i) for i in append])
|
||||
if qs_elements is not None:
|
||||
qs = '?%s' % '&'.join(qs_elements)
|
||||
return '%(uri)s%(qs)s' % {
|
||||
'uri': '/'.join(to_join),
|
||||
'qs': qs}
|
||||
return '%(uri)s%(qs)s' % {'uri': '/'.join(to_join), 'qs': qs}
|
||||
|
||||
def mock_for_keystone_projects(self, project=None, v3=True,
|
||||
list_get=False, id_get=False,
|
||||
project_list=None, project_count=None):
|
||||
def mock_for_keystone_projects(
|
||||
self,
|
||||
project=None,
|
||||
v3=True,
|
||||
list_get=False,
|
||||
id_get=False,
|
||||
project_list=None,
|
||||
project_count=None,
|
||||
):
|
||||
if project:
|
||||
assert not (project_list or project_count)
|
||||
elif project_list:
|
||||
@ -198,8 +219,9 @@ class TestCase(base.TestCase):
|
||||
elif project_count:
|
||||
assert not (project or project_list)
|
||||
else:
|
||||
raise Exception('Must specify a project, project_list, '
|
||||
'or project_count')
|
||||
raise Exception(
|
||||
'Must specify a project, project_list, ' 'or project_count'
|
||||
)
|
||||
assert list_get or id_get
|
||||
|
||||
base_url_append = 'v3' if v3 else None
|
||||
@ -207,40 +229,57 @@ class TestCase(base.TestCase):
|
||||
project_list = [project]
|
||||
elif project_count:
|
||||
# Generate multiple projects
|
||||
project_list = [self._get_project_data(v3=v3)
|
||||
for c in range(0, project_count)]
|
||||
project_list = [
|
||||
self._get_project_data(v3=v3) for c in range(0, project_count)
|
||||
]
|
||||
uri_mock_list = []
|
||||
if list_get:
|
||||
uri_mock_list.append(
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
service_type='identity',
|
||||
interface='admin',
|
||||
resource='projects',
|
||||
base_url_append=base_url_append),
|
||||
status_code=200,
|
||||
json={'projects': [p.json_response['project']
|
||||
for p in project_list]})
|
||||
dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
service_type='identity',
|
||||
interface='admin',
|
||||
resource='projects',
|
||||
base_url_append=base_url_append,
|
||||
),
|
||||
status_code=200,
|
||||
json={
|
||||
'projects': [
|
||||
p.json_response['project'] for p in project_list
|
||||
]
|
||||
},
|
||||
)
|
||||
)
|
||||
if id_get:
|
||||
for p in project_list:
|
||||
uri_mock_list.append(
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
service_type='identity',
|
||||
interface='admin',
|
||||
resource='projects',
|
||||
append=[p.project_id],
|
||||
base_url_append=base_url_append),
|
||||
status_code=200,
|
||||
json=p.json_response)
|
||||
dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
service_type='identity',
|
||||
interface='admin',
|
||||
resource='projects',
|
||||
append=[p.project_id],
|
||||
base_url_append=base_url_append,
|
||||
),
|
||||
status_code=200,
|
||||
json=p.json_response,
|
||||
)
|
||||
)
|
||||
self.__do_register_uris(uri_mock_list)
|
||||
return project_list
|
||||
|
||||
def _get_project_data(self, project_name=None, enabled=None,
|
||||
domain_id=None, description=None, v3=True,
|
||||
project_id=None, parent_id=None):
|
||||
def _get_project_data(
|
||||
self,
|
||||
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_id = uuid.UUID(project_id or uuid.uuid4().hex).hex
|
||||
if parent_id:
|
||||
@ -264,9 +303,16 @@ class TestCase(base.TestCase):
|
||||
response['description'] = description
|
||||
request['description'] = description
|
||||
request.setdefault('description', None)
|
||||
return _ProjectData(project_id, project_name, enabled, domain_id,
|
||||
description, parent_id,
|
||||
{'project': response}, {'project': request})
|
||||
return _ProjectData(
|
||||
project_id,
|
||||
project_name,
|
||||
enabled,
|
||||
domain_id,
|
||||
description,
|
||||
parent_id,
|
||||
{'project': response},
|
||||
{'project': request},
|
||||
)
|
||||
|
||||
def _get_group_data(self, name=None, domain_id=None, description=None):
|
||||
group_id = uuid.uuid4().hex
|
||||
@ -278,8 +324,14 @@ class TestCase(base.TestCase):
|
||||
response['description'] = description
|
||||
request['description'] = description
|
||||
|
||||
return _GroupData(group_id, name, domain_id, description,
|
||||
{'group': response}, {'group': request})
|
||||
return _GroupData(
|
||||
group_id,
|
||||
name,
|
||||
domain_id,
|
||||
description,
|
||||
{'group': response},
|
||||
{'group': request},
|
||||
)
|
||||
|
||||
def _get_user_data(self, name=None, password=None, **kwargs):
|
||||
|
||||
@ -305,16 +357,27 @@ class TestCase(base.TestCase):
|
||||
if response['description']:
|
||||
request['description'] = response['description']
|
||||
|
||||
self.assertIs(0, len(kwargs), message='extra key-word args received '
|
||||
'on _get_user_data')
|
||||
self.assertIs(
|
||||
0,
|
||||
len(kwargs),
|
||||
message='extra key-word args received ' 'on _get_user_data',
|
||||
)
|
||||
|
||||
return _UserData(user_id, password, name, response['email'],
|
||||
response['description'], response.get('domain_id'),
|
||||
response.get('enabled'), {'user': response},
|
||||
{'user': request})
|
||||
return _UserData(
|
||||
user_id,
|
||||
password,
|
||||
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,
|
||||
enabled=None):
|
||||
def _get_domain_data(
|
||||
self, domain_name=None, description=None, enabled=None
|
||||
):
|
||||
domain_id = uuid.uuid4().hex
|
||||
domain_name = domain_name or self.getUniqueString('domainName')
|
||||
response = {'id': domain_id, 'name': domain_name}
|
||||
@ -326,41 +389,76 @@ class TestCase(base.TestCase):
|
||||
response['description'] = description
|
||||
request['description'] = description
|
||||
response.setdefault('enabled', True)
|
||||
return _DomainData(domain_id, domain_name, description,
|
||||
{'domain': response}, {'domain': request})
|
||||
return _DomainData(
|
||||
domain_id,
|
||||
domain_name,
|
||||
description,
|
||||
{'domain': response},
|
||||
{'domain': request},
|
||||
)
|
||||
|
||||
def _get_service_data(self, type=None, name=None, description=None,
|
||||
enabled=True):
|
||||
def _get_service_data(
|
||||
self, type=None, name=None, description=None, enabled=True
|
||||
):
|
||||
service_id = uuid.uuid4().hex
|
||||
name = name or uuid.uuid4().hex
|
||||
type = type or uuid.uuid4().hex
|
||||
|
||||
response = {'id': service_id, 'name': name, 'type': type,
|
||||
'enabled': enabled}
|
||||
response = {
|
||||
'id': service_id,
|
||||
'name': name,
|
||||
'type': type,
|
||||
'enabled': enabled,
|
||||
}
|
||||
if description is not None:
|
||||
response['description'] = description
|
||||
request = response.copy()
|
||||
request.pop('id')
|
||||
return _ServiceData(service_id, name, type, description, enabled,
|
||||
{'service': response},
|
||||
{'OS-KSADM:service': response}, request)
|
||||
return _ServiceData(
|
||||
service_id,
|
||||
name,
|
||||
type,
|
||||
description,
|
||||
enabled,
|
||||
{'service': response},
|
||||
{'OS-KSADM:service': response},
|
||||
request,
|
||||
)
|
||||
|
||||
def _get_endpoint_v3_data(self, service_id=None, region=None,
|
||||
url=None, interface=None, enabled=True):
|
||||
def _get_endpoint_v3_data(
|
||||
self,
|
||||
service_id=None,
|
||||
region=None,
|
||||
url=None,
|
||||
interface=None,
|
||||
enabled=True,
|
||||
):
|
||||
endpoint_id = uuid.uuid4().hex
|
||||
service_id = service_id or uuid.uuid4().hex
|
||||
region = region or uuid.uuid4().hex
|
||||
url = url or 'https://example.com/'
|
||||
interface = interface or uuid.uuid4().hex
|
||||
|
||||
response = {'id': endpoint_id, 'service_id': service_id,
|
||||
'region_id': region, 'interface': interface,
|
||||
'url': url, 'enabled': enabled}
|
||||
response = {
|
||||
'id': endpoint_id,
|
||||
'service_id': service_id,
|
||||
'region_id': region,
|
||||
'interface': interface,
|
||||
'url': url,
|
||||
'enabled': enabled,
|
||||
}
|
||||
request = response.copy()
|
||||
request.pop('id')
|
||||
return _EndpointDataV3(endpoint_id, service_id, interface, region,
|
||||
url, enabled, {'endpoint': response},
|
||||
{'endpoint': request})
|
||||
return _EndpointDataV3(
|
||||
endpoint_id,
|
||||
service_id,
|
||||
interface,
|
||||
region,
|
||||
url,
|
||||
enabled,
|
||||
{'endpoint': response},
|
||||
{'endpoint': request},
|
||||
)
|
||||
|
||||
def _get_role_data(self, role_name=None):
|
||||
role_id = uuid.uuid4().hex
|
||||
@ -368,20 +466,28 @@ class TestCase(base.TestCase):
|
||||
request = {'name': role_name}
|
||||
response = request.copy()
|
||||
response['id'] = role_id
|
||||
return _RoleData(role_id, role_name, {'role': response},
|
||||
{'role': request})
|
||||
return _RoleData(
|
||||
role_id, role_name, {'role': response}, {'role': request}
|
||||
)
|
||||
|
||||
def use_broken_keystone(self):
|
||||
self.adapter = self.useFixture(rm_fixture.Fixture())
|
||||
self.calls = []
|
||||
self._uri_registry.clear()
|
||||
self.__do_register_uris([
|
||||
dict(method='GET', uri='https://identity.example.com/',
|
||||
text=open(self.discovery_json, 'r').read()),
|
||||
dict(method='POST',
|
||||
uri='https://identity.example.com/v3/auth/tokens',
|
||||
status_code=400),
|
||||
])
|
||||
self.__do_register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://identity.example.com/',
|
||||
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')
|
||||
|
||||
def use_nothing(self):
|
||||
@ -389,40 +495,38 @@ class TestCase(base.TestCase):
|
||||
self._uri_registry.clear()
|
||||
|
||||
def get_keystone_v3_token(
|
||||
self,
|
||||
project_name='admin',
|
||||
self,
|
||||
project_name='admin',
|
||||
):
|
||||
return dict(
|
||||
method='POST',
|
||||
uri='https://identity.example.com/v3/auth/tokens',
|
||||
headers={
|
||||
'X-Subject-Token': self.getUniqueString('KeystoneToken')
|
||||
},
|
||||
headers={'X-Subject-Token': self.getUniqueString('KeystoneToken')},
|
||||
json=self.os_fixture.v3_token,
|
||||
validate=dict(json={
|
||||
'auth': {
|
||||
'identity': {
|
||||
'methods': ['password'],
|
||||
'password': {
|
||||
'user': {
|
||||
'domain': {
|
||||
'name': 'default',
|
||||
},
|
||||
'name': 'admin',
|
||||
'password': 'password'
|
||||
}
|
||||
}
|
||||
},
|
||||
'scope': {
|
||||
'project': {
|
||||
'domain': {
|
||||
'name': 'default'
|
||||
validate=dict(
|
||||
json={
|
||||
'auth': {
|
||||
'identity': {
|
||||
'methods': ['password'],
|
||||
'password': {
|
||||
'user': {
|
||||
'domain': {
|
||||
'name': 'default',
|
||||
},
|
||||
'name': 'admin',
|
||||
'password': 'password',
|
||||
}
|
||||
},
|
||||
'name': project_name
|
||||
}
|
||||
},
|
||||
'scope': {
|
||||
'project': {
|
||||
'domain': {'name': 'default'},
|
||||
'name': project_name,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
def get_keystone_discovery(self):
|
||||
@ -437,10 +541,12 @@ class TestCase(base.TestCase):
|
||||
self.adapter = self.useFixture(rm_fixture.Fixture())
|
||||
self.calls = []
|
||||
self._uri_registry.clear()
|
||||
self.__do_register_uris([
|
||||
self.get_keystone_discovery(),
|
||||
self.get_keystone_v3_token(),
|
||||
])
|
||||
self.__do_register_uris(
|
||||
[
|
||||
self.get_keystone_discovery(),
|
||||
self.get_keystone_v3_token(),
|
||||
]
|
||||
)
|
||||
self._make_test_cloud(identity_api_version='3')
|
||||
|
||||
def use_keystone_v2(self):
|
||||
@ -448,119 +554,171 @@ class TestCase(base.TestCase):
|
||||
self.calls = []
|
||||
self._uri_registry.clear()
|
||||
|
||||
self.__do_register_uris([
|
||||
self.get_keystone_discovery(),
|
||||
dict(method='POST',
|
||||
uri='https://identity.example.com/v2.0/tokens',
|
||||
json=self.os_fixture.v2_token,
|
||||
),
|
||||
])
|
||||
self.__do_register_uris(
|
||||
[
|
||||
self.get_keystone_discovery(),
|
||||
dict(
|
||||
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_',
|
||||
identity_api_version='2.0')
|
||||
self._make_test_cloud(
|
||||
cloud_name='_test_cloud_v2_', identity_api_version='2.0'
|
||||
)
|
||||
|
||||
def _make_test_cloud(self, cloud_name='_test_cloud_', **kwargs):
|
||||
test_cloud = os.environ.get('OPENSTACKSDK_OS_CLOUD', cloud_name)
|
||||
self.cloud_config = self.config.get_one(
|
||||
cloud=test_cloud, validate=True, **kwargs)
|
||||
cloud=test_cloud, validate=True, **kwargs
|
||||
)
|
||||
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(
|
||||
self,
|
||||
block_storage_version_json='block-storage-version.json',
|
||||
block_storage_discovery_url='https://block-storage.example.com/'):
|
||||
self,
|
||||
block_storage_version_json='block-storage-version.json',
|
||||
block_storage_discovery_url='https://block-storage.example.com/',
|
||||
):
|
||||
discovery_fixture = os.path.join(
|
||||
self.fixtures_directory, block_storage_version_json)
|
||||
return dict(method='GET', uri=block_storage_discovery_url,
|
||||
text=open(discovery_fixture, 'r').read())
|
||||
self.fixtures_directory, block_storage_version_json
|
||||
)
|
||||
return dict(
|
||||
method='GET',
|
||||
uri=block_storage_discovery_url,
|
||||
text=open(discovery_fixture, 'r').read(),
|
||||
)
|
||||
|
||||
def get_glance_discovery_mock_dict(
|
||||
self,
|
||||
image_version_json='image-version.json',
|
||||
image_discovery_url='https://image.example.com/'):
|
||||
self,
|
||||
image_version_json='image-version.json',
|
||||
image_discovery_url='https://image.example.com/',
|
||||
):
|
||||
discovery_fixture = os.path.join(
|
||||
self.fixtures_directory, image_version_json)
|
||||
return dict(method='GET', uri=image_discovery_url,
|
||||
status_code=300,
|
||||
text=open(discovery_fixture, 'r').read())
|
||||
self.fixtures_directory, image_version_json
|
||||
)
|
||||
return dict(
|
||||
method='GET',
|
||||
uri=image_discovery_url,
|
||||
status_code=300,
|
||||
text=open(discovery_fixture, 'r').read(),
|
||||
)
|
||||
|
||||
def get_nova_discovery_mock_dict(
|
||||
self,
|
||||
compute_version_json='compute-version.json',
|
||||
compute_discovery_url='https://compute.example.com/v2.1/'):
|
||||
self,
|
||||
compute_version_json='compute-version.json',
|
||||
compute_discovery_url='https://compute.example.com/v2.1/',
|
||||
):
|
||||
discovery_fixture = os.path.join(
|
||||
self.fixtures_directory, compute_version_json)
|
||||
self.fixtures_directory, compute_version_json
|
||||
)
|
||||
return dict(
|
||||
method='GET',
|
||||
uri=compute_discovery_url,
|
||||
text=open(discovery_fixture, 'r').read())
|
||||
text=open(discovery_fixture, 'r').read(),
|
||||
)
|
||||
|
||||
def get_placement_discovery_mock_dict(
|
||||
self, discovery_fixture='placement.json'):
|
||||
self, discovery_fixture='placement.json'
|
||||
):
|
||||
discovery_fixture = os.path.join(
|
||||
self.fixtures_directory, discovery_fixture)
|
||||
return dict(method='GET', uri="https://placement.example.com/",
|
||||
text=open(discovery_fixture, 'r').read())
|
||||
self.fixtures_directory, discovery_fixture
|
||||
)
|
||||
return dict(
|
||||
method='GET',
|
||||
uri="https://placement.example.com/",
|
||||
text=open(discovery_fixture, 'r').read(),
|
||||
)
|
||||
|
||||
def get_designate_discovery_mock_dict(self):
|
||||
discovery_fixture = os.path.join(
|
||||
self.fixtures_directory, "dns.json")
|
||||
return dict(method='GET', uri="https://dns.example.com/",
|
||||
text=open(discovery_fixture, 'r').read())
|
||||
discovery_fixture = os.path.join(self.fixtures_directory, "dns.json")
|
||||
return dict(
|
||||
method='GET',
|
||||
uri="https://dns.example.com/",
|
||||
text=open(discovery_fixture, 'r').read(),
|
||||
)
|
||||
|
||||
def get_ironic_discovery_mock_dict(self):
|
||||
discovery_fixture = os.path.join(
|
||||
self.fixtures_directory, "baremetal.json")
|
||||
return dict(method='GET', uri="https://baremetal.example.com/",
|
||||
text=open(discovery_fixture, 'r').read())
|
||||
self.fixtures_directory, "baremetal.json"
|
||||
)
|
||||
return dict(
|
||||
method='GET',
|
||||
uri="https://baremetal.example.com/",
|
||||
text=open(discovery_fixture, 'r').read(),
|
||||
)
|
||||
|
||||
def get_senlin_discovery_mock_dict(self):
|
||||
discovery_fixture = os.path.join(
|
||||
self.fixtures_directory, "clustering.json")
|
||||
return dict(method='GET', uri="https://clustering.example.com/",
|
||||
text=open(discovery_fixture, 'r').read())
|
||||
self.fixtures_directory, "clustering.json"
|
||||
)
|
||||
return dict(
|
||||
method='GET',
|
||||
uri="https://clustering.example.com/",
|
||||
text=open(discovery_fixture, 'r').read(),
|
||||
)
|
||||
|
||||
def use_compute_discovery(
|
||||
self, compute_version_json='compute-version.json',
|
||||
compute_discovery_url='https://compute.example.com/v2.1/'):
|
||||
self.__do_register_uris([
|
||||
self.get_nova_discovery_mock_dict(
|
||||
compute_version_json, compute_discovery_url),
|
||||
])
|
||||
self,
|
||||
compute_version_json='compute-version.json',
|
||||
compute_discovery_url='https://compute.example.com/v2.1/',
|
||||
):
|
||||
self.__do_register_uris(
|
||||
[
|
||||
self.get_nova_discovery_mock_dict(
|
||||
compute_version_json, compute_discovery_url
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
def get_cyborg_discovery_mock_dict(self):
|
||||
discovery_fixture = os.path.join(
|
||||
self.fixtures_directory, "accelerator.json")
|
||||
return dict(method='GET', uri="https://accelerator.example.com/",
|
||||
text=open(discovery_fixture, 'r').read())
|
||||
self.fixtures_directory, "accelerator.json"
|
||||
)
|
||||
return dict(
|
||||
method='GET',
|
||||
uri="https://accelerator.example.com/",
|
||||
text=open(discovery_fixture, 'r').read(),
|
||||
)
|
||||
|
||||
def get_manila_discovery_mock_dict(self):
|
||||
discovery_fixture = os.path.join(
|
||||
self.fixtures_directory, "shared-file-system.json")
|
||||
return dict(method='GET',
|
||||
uri="https://shared-file-system.example.com/",
|
||||
text=open(discovery_fixture, 'r').read())
|
||||
self.fixtures_directory, "shared-file-system.json"
|
||||
)
|
||||
return dict(
|
||||
method='GET',
|
||||
uri="https://shared-file-system.example.com/",
|
||||
text=open(discovery_fixture, 'r').read(),
|
||||
)
|
||||
|
||||
def use_glance(
|
||||
self, image_version_json='image-version.json',
|
||||
image_discovery_url='https://image.example.com/'):
|
||||
self,
|
||||
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"
|
||||
# where the ordering of the url being registered is tightly controlled
|
||||
# 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
|
||||
# right location in the mock_uris when calling .register_uris
|
||||
self.__do_register_uris([
|
||||
self.get_glance_discovery_mock_dict(
|
||||
image_version_json, image_discovery_url)])
|
||||
self.__do_register_uris(
|
||||
[
|
||||
self.get_glance_discovery_mock_dict(
|
||||
image_version_json, image_discovery_url
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
def use_cinder(self):
|
||||
self.__do_register_uris([
|
||||
self.get_cinder_discovery_mock_dict()])
|
||||
self.__do_register_uris([self.get_cinder_discovery_mock_dict()])
|
||||
|
||||
def use_placement(self, **kwargs):
|
||||
self.__do_register_uris([
|
||||
self.get_placement_discovery_mock_dict(**kwargs)])
|
||||
self.__do_register_uris(
|
||||
[self.get_placement_discovery_mock_dict(**kwargs)]
|
||||
)
|
||||
|
||||
def use_designate(self):
|
||||
# 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
|
||||
# actual test case, use .get_designate_discovery_mock and apply to the
|
||||
# right location in the mock_uris when calling .register_uris
|
||||
self.__do_register_uris([
|
||||
self.get_designate_discovery_mock_dict()])
|
||||
self.__do_register_uris([self.get_designate_discovery_mock_dict()])
|
||||
|
||||
def use_ironic(self):
|
||||
# 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
|
||||
# actual test case, use .get_ironic_discovery_mock and apply to the
|
||||
# right location in the mock_uris when calling .register_uris
|
||||
self.__do_register_uris([
|
||||
self.get_ironic_discovery_mock_dict()])
|
||||
self.__do_register_uris([self.get_ironic_discovery_mock_dict()])
|
||||
|
||||
def use_senlin(self):
|
||||
# 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
|
||||
# actual test case, use .get_senlin_discovery_mock and apply to the
|
||||
# right location in the mock_uris when calling .register_uris
|
||||
self.__do_register_uris([
|
||||
self.get_senlin_discovery_mock_dict()])
|
||||
self.__do_register_uris([self.get_senlin_discovery_mock_dict()])
|
||||
|
||||
def use_cyborg(self):
|
||||
# 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
|
||||
# actual test case, use .get_cyborg_discovery_mock and apply to the
|
||||
# right location in the mock_uris when calling .register_uris
|
||||
self.__do_register_uris([
|
||||
self.get_cyborg_discovery_mock_dict()])
|
||||
self.__do_register_uris([self.get_cyborg_discovery_mock_dict()])
|
||||
|
||||
def use_manila(self):
|
||||
# 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
|
||||
# actual test case, use .get_manila_discovery_mock and apply to the
|
||||
# right location in the mock_uris when calling .register_uris
|
||||
self.__do_register_uris([
|
||||
self.get_manila_discovery_mock_dict()])
|
||||
self.__do_register_uris([self.get_manila_discovery_mock_dict()])
|
||||
|
||||
def register_uris(self, uri_mock_list=None):
|
||||
"""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):
|
||||
for to_mock in uri_mock_list:
|
||||
kw_params = {k: to_mock.pop(k)
|
||||
for k in ('request_headers', 'complete_qs',
|
||||
'_real_http')
|
||||
if k in to_mock}
|
||||
kw_params = {
|
||||
k: to_mock.pop(k)
|
||||
for k in ('request_headers', 'complete_qs', '_real_http')
|
||||
if k in to_mock
|
||||
}
|
||||
|
||||
method = to_mock.pop('method')
|
||||
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
|
||||
# maintainers of this code.
|
||||
key = '{method}|{uri}|{params}'.format(
|
||||
method=method, uri=uri, params=kw_params)
|
||||
method=method, uri=uri, params=kw_params
|
||||
)
|
||||
validate = to_mock.pop('validate', {})
|
||||
valid_keys = set(['json', 'headers', 'params', 'data'])
|
||||
invalid_keys = set(validate.keys()) - valid_keys
|
||||
if invalid_keys:
|
||||
raise TypeError(
|
||||
"Invalid values passed to validate: {keys}".format(
|
||||
keys=invalid_keys))
|
||||
headers = structures.CaseInsensitiveDict(to_mock.pop('headers',
|
||||
{}))
|
||||
keys=invalid_keys
|
||||
)
|
||||
)
|
||||
headers = structures.CaseInsensitiveDict(
|
||||
to_mock.pop('headers', {})
|
||||
)
|
||||
if 'content-type' not in headers:
|
||||
headers[u'content-type'] = 'application/json'
|
||||
|
||||
if 'exc' not in to_mock:
|
||||
to_mock['headers'] = headers
|
||||
|
||||
self.calls += [
|
||||
dict(
|
||||
method=method,
|
||||
url=uri, **validate)
|
||||
]
|
||||
self.calls += [dict(method=method, url=uri, **validate)]
|
||||
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:
|
||||
raise AssertionError(
|
||||
'PROGRAMMING ERROR: key-word-params '
|
||||
'should be part of the uri_key and cannot change, '
|
||||
'it will affect the matcher in requests_mock. '
|
||||
'%(old)r != %(new)r' %
|
||||
{'old': self._uri_registry[key]['kw_params'],
|
||||
'new': kw_params})
|
||||
'%(old)r != %(new)r'
|
||||
% {
|
||||
'old': self._uri_registry[key]['kw_params'],
|
||||
'new': kw_params,
|
||||
}
|
||||
)
|
||||
self._uri_registry[key]['response_list'].append(to_mock)
|
||||
|
||||
for mocked, params in self._uri_registry.items():
|
||||
mock_method, mock_uri, _ignored = mocked.split('|', 2)
|
||||
self.adapter.register_uri(
|
||||
mock_method, mock_uri, params['response_list'],
|
||||
**params['kw_params'])
|
||||
mock_method,
|
||||
mock_uri,
|
||||
params['response_list'],
|
||||
**params['kw_params']
|
||||
)
|
||||
|
||||
def assert_no_calls(self):
|
||||
# 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):
|
||||
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:
|
||||
break
|
||||
|
||||
call_uri_parts = urllib.parse.urlparse(call['url'])
|
||||
history_uri_parts = urllib.parse.urlparse(history.url)
|
||||
self.assertEqual(
|
||||
(call['method'], call_uri_parts.scheme, call_uri_parts.netloc,
|
||||
call_uri_parts.path, call_uri_parts.params,
|
||||
urllib.parse.parse_qs(call_uri_parts.query)),
|
||||
(history.method, history_uri_parts.scheme,
|
||||
history_uri_parts.netloc, history_uri_parts.path,
|
||||
history_uri_parts.params,
|
||||
urllib.parse.parse_qs(history_uri_parts.query)),
|
||||
('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)})
|
||||
(
|
||||
call['method'],
|
||||
call_uri_parts.scheme,
|
||||
call_uri_parts.netloc,
|
||||
call_uri_parts.path,
|
||||
call_uri_parts.params,
|
||||
urllib.parse.parse_qs(call_uri_parts.query),
|
||||
),
|
||||
(
|
||||
history.method,
|
||||
history_uri_parts.scheme,
|
||||
history_uri_parts.netloc,
|
||||
history_uri_parts.path,
|
||||
history_uri_parts.params,
|
||||
urllib.parse.parse_qs(history_uri_parts.query),
|
||||
),
|
||||
(
|
||||
'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:
|
||||
self.assertEqual(
|
||||
call['json'], history.json(),
|
||||
'json content mismatch in call {index}'.format(index=x))
|
||||
call['json'],
|
||||
history.json(),
|
||||
'json content mismatch in call {index}'.format(index=x),
|
||||
)
|
||||
# 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
|
||||
# only headers
|
||||
if 'headers' in call:
|
||||
for key, value in call['headers'].items():
|
||||
self.assertEqual(
|
||||
value, history.headers[key],
|
||||
'header mismatch in call {index}'.format(index=x))
|
||||
value,
|
||||
history.headers[key],
|
||||
'header mismatch in call {index}'.format(index=x),
|
||||
)
|
||||
if do_count:
|
||||
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):
|
||||
"""Helper for the assertEqual which compares Resource object against
|
||||
@ -756,7 +936,7 @@ class TestCase(base.TestCase):
|
||||
"""
|
||||
return self.assertEqual(
|
||||
resource_type(**expected).to_dict(computed=False),
|
||||
actual.to_dict(computed=False)
|
||||
actual.to_dict(computed=False),
|
||||
)
|
||||
|
||||
def assertResourceListEqual(self, actual, expected, resource_type):
|
||||
@ -771,12 +951,11 @@ class TestCase(base.TestCase):
|
||||
"""
|
||||
self.assertEqual(
|
||||
[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):
|
||||
|
||||
def setUp(self):
|
||||
super(IronicTestCase, self).setUp()
|
||||
self.use_ironic()
|
||||
|
@ -706,7 +706,9 @@ class TestCreateServer(base.TestCase):
|
||||
]
|
||||
)
|
||||
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,
|
||||
),
|
||||
|
||||
|
@ -23,7 +23,6 @@ IDENTIFIER = 'IDENTIFIER'
|
||||
|
||||
|
||||
class TestMetadata(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMetadata, self).setUp()
|
||||
|
||||
@ -95,8 +94,7 @@ class TestMetadata(base.TestCase):
|
||||
self.assertEqual(res, result)
|
||||
url = self.base_path + '/' + res.id + '/metadata'
|
||||
self.session.post.assert_called_once_with(
|
||||
url,
|
||||
json={'metadata': {'foo': 'bar'}}
|
||||
url, json={'metadata': {'foo': 'bar'}}
|
||||
)
|
||||
|
||||
def test_replace_metadata(self):
|
||||
@ -109,8 +107,7 @@ class TestMetadata(base.TestCase):
|
||||
self.assertEqual(res, result)
|
||||
url = self.base_path + '/' + res.id + '/metadata'
|
||||
self.session.put.assert_called_once_with(
|
||||
url,
|
||||
json={'metadata': {'foo': 'bar'}}
|
||||
url, json={'metadata': {'foo': 'bar'}}
|
||||
)
|
||||
|
||||
def test_delete_all_metadata(self):
|
||||
@ -125,9 +122,7 @@ class TestMetadata(base.TestCase):
|
||||
# Check passed resource is returned
|
||||
self.assertEqual(res, result)
|
||||
url = self.base_path + '/' + res.id + '/metadata'
|
||||
self.session.put.assert_called_once_with(
|
||||
url,
|
||||
json={'metadata': {}})
|
||||
self.session.put.assert_called_once_with(url, json={'metadata': {}})
|
||||
|
||||
def test_get_metadata_item(self):
|
||||
res = self.sot
|
||||
@ -198,5 +193,5 @@ class TestMetadata(base.TestCase):
|
||||
self.assertEqual(res, result)
|
||||
url = self.base_path + '/' + res.id + '/metadata/foo'
|
||||
self.session.put.assert_called_once_with(
|
||||
url,
|
||||
json={'meta': {'foo': 'black'}})
|
||||
url, json={'meta': {'foo': 'black'}}
|
||||
)
|
||||
|
@ -25,26 +25,13 @@ BASIC_EXAMPLE = {
|
||||
}
|
||||
|
||||
USAGE_EXAMPLE = {
|
||||
"backup_gigabytes": {
|
||||
"in_use": 0,
|
||||
"limit": 1000,
|
||||
"reserved": 0
|
||||
},
|
||||
"backups": {
|
||||
"in_use": 0,
|
||||
"limit": 10,
|
||||
"reserved": 0
|
||||
},
|
||||
"gigabytes___DEFAULT__": {
|
||||
"in_use": 0,
|
||||
"limit": -1,
|
||||
"reserved": 0
|
||||
}
|
||||
"backup_gigabytes": {"in_use": 0, "limit": 1000, "reserved": 0},
|
||||
"backups": {"in_use": 0, "limit": 10, "reserved": 0},
|
||||
"gigabytes___DEFAULT__": {"in_use": 0, "limit": -1, "reserved": 0},
|
||||
}
|
||||
|
||||
|
||||
class TestQuotaSet(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestQuotaSet, self).setUp()
|
||||
self.sess = mock.Mock(spec=adapter.Adapter)
|
||||
@ -64,10 +51,9 @@ class TestQuotaSet(base.TestCase):
|
||||
self.assertTrue(sot.allow_commit)
|
||||
|
||||
self.assertDictEqual(
|
||||
{"usage": "usage",
|
||||
"limit": "limit",
|
||||
"marker": "marker"},
|
||||
sot._query_mapping._mapping)
|
||||
{"usage": "usage", "limit": "limit", "marker": "marker"},
|
||||
sot._query_mapping._mapping,
|
||||
)
|
||||
|
||||
def test_make_basic(self):
|
||||
sot = _qs.QuotaSet(**BASIC_EXAMPLE)
|
||||
@ -87,10 +73,8 @@ class TestQuotaSet(base.TestCase):
|
||||
sot.fetch(self.sess)
|
||||
|
||||
self.sess.get.assert_called_with(
|
||||
'/os-quota-sets/proj',
|
||||
microversion=1,
|
||||
params={},
|
||||
skip_cache=False)
|
||||
'/os-quota-sets/proj', microversion=1, params={}, skip_cache=False
|
||||
)
|
||||
|
||||
self.assertEqual(BASIC_EXAMPLE['backups'], sot.backups)
|
||||
self.assertEqual({}, sot.reservation)
|
||||
@ -112,11 +96,10 @@ class TestQuotaSet(base.TestCase):
|
||||
'/os-quota-sets/proj',
|
||||
microversion=1,
|
||||
params={'usage': True},
|
||||
skip_cache=False)
|
||||
skip_cache=False,
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
USAGE_EXAMPLE['backups']['limit'],
|
||||
sot.backups)
|
||||
self.assertEqual(USAGE_EXAMPLE['backups']['limit'], sot.backups)
|
||||
|
||||
def test_update_quota(self):
|
||||
# Use QuotaSet as if it was returned by get(usage=True)
|
||||
@ -124,7 +107,8 @@ class TestQuotaSet(base.TestCase):
|
||||
project_id='proj',
|
||||
reservation={'a': 'b'},
|
||||
usage={'c': 'd'},
|
||||
foo='bar')
|
||||
foo='bar',
|
||||
)
|
||||
|
||||
resp = mock.Mock()
|
||||
resp.body = {'quota_set': copy.deepcopy(BASIC_EXAMPLE)}
|
||||
@ -133,10 +117,7 @@ class TestQuotaSet(base.TestCase):
|
||||
resp.headers = {}
|
||||
self.sess.put = mock.Mock(return_value=resp)
|
||||
|
||||
sot._update(
|
||||
reservation={'b': 'd'},
|
||||
backups=15,
|
||||
something_else=20)
|
||||
sot._update(reservation={'b': 'd'}, backups=15, something_else=20)
|
||||
|
||||
sot.commit(self.sess)
|
||||
|
||||
@ -144,12 +125,8 @@ class TestQuotaSet(base.TestCase):
|
||||
'/os-quota-sets/proj',
|
||||
microversion=1,
|
||||
headers={},
|
||||
json={
|
||||
'quota_set': {
|
||||
'backups': 15,
|
||||
'something_else': 20
|
||||
}
|
||||
})
|
||||
json={'quota_set': {'backups': 15, 'something_else': 20}},
|
||||
)
|
||||
|
||||
def test_delete_quota(self):
|
||||
# Use QuotaSet as if it was returned by get(usage=True)
|
||||
@ -157,7 +134,8 @@ class TestQuotaSet(base.TestCase):
|
||||
project_id='proj',
|
||||
reservation={'a': 'b'},
|
||||
usage={'c': 'd'},
|
||||
foo='bar')
|
||||
foo='bar',
|
||||
)
|
||||
|
||||
resp = mock.Mock()
|
||||
resp.body = None
|
||||
|
@ -21,7 +21,6 @@ from openstack.tests.unit.test_resource import FakeResponse
|
||||
|
||||
|
||||
class TestTagMixin(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestTagMixin, self).setUp()
|
||||
|
||||
@ -94,10 +93,7 @@ class TestTagMixin(base.TestCase):
|
||||
# Check the passed resource is returned
|
||||
self.assertEqual(res, result)
|
||||
url = self.base_path + '/' + res.id + '/tags'
|
||||
sess.put.assert_called_once_with(
|
||||
url,
|
||||
json={'tags': ['blue', 'green']}
|
||||
)
|
||||
sess.put.assert_called_once_with(url, json={'tags': ['blue', 'green']})
|
||||
|
||||
def test_remove_all_tags(self):
|
||||
res = self.sot
|
||||
|
@ -48,10 +48,7 @@ USER_CONF = {
|
||||
'force_ipv4': True,
|
||||
},
|
||||
'metrics': {
|
||||
'statsd': {
|
||||
'host': '127.0.0.1',
|
||||
'port': '1234'
|
||||
},
|
||||
'statsd': {'host': '127.0.0.1', 'port': '1234'},
|
||||
'influxdb': {
|
||||
'host': '127.0.0.1',
|
||||
'port': '1234',
|
||||
@ -61,7 +58,7 @@ USER_CONF = {
|
||||
'database': 'database',
|
||||
'measurement': 'measurement.name',
|
||||
'timeout': 10,
|
||||
}
|
||||
},
|
||||
},
|
||||
'clouds': {
|
||||
'_test-cloud_': {
|
||||
@ -112,30 +109,37 @@ USER_CONF = {
|
||||
'domain_id': '6789',
|
||||
'project_domain_id': '123456789',
|
||||
},
|
||||
'networks': [{
|
||||
'name': 'a-public',
|
||||
'routes_externally': True,
|
||||
'nat_source': True,
|
||||
}, {
|
||||
'name': 'another-public',
|
||||
'routes_externally': True,
|
||||
'default_interface': True,
|
||||
}, {
|
||||
'name': 'a-private',
|
||||
'routes_externally': False,
|
||||
}, {
|
||||
'name': 'another-private',
|
||||
'routes_externally': False,
|
||||
'nat_destination': True,
|
||||
}, {
|
||||
'name': 'split-default',
|
||||
'routes_externally': True,
|
||||
'routes_ipv4_externally': False,
|
||||
}, {
|
||||
'name': 'split-no-default',
|
||||
'routes_ipv6_externally': False,
|
||||
'routes_ipv4_externally': True,
|
||||
}],
|
||||
'networks': [
|
||||
{
|
||||
'name': 'a-public',
|
||||
'routes_externally': True,
|
||||
'nat_source': True,
|
||||
},
|
||||
{
|
||||
'name': 'another-public',
|
||||
'routes_externally': True,
|
||||
'default_interface': True,
|
||||
},
|
||||
{
|
||||
'name': 'a-private',
|
||||
'routes_externally': False,
|
||||
},
|
||||
{
|
||||
'name': 'another-private',
|
||||
'routes_externally': False,
|
||||
'nat_destination': True,
|
||||
},
|
||||
{
|
||||
'name': 'split-default',
|
||||
'routes_externally': True,
|
||||
'routes_ipv4_externally': False,
|
||||
},
|
||||
{
|
||||
'name': 'split-no-default',
|
||||
'routes_ipv6_externally': False,
|
||||
'routes_ipv4_externally': True,
|
||||
},
|
||||
],
|
||||
'region_name': 'test-region',
|
||||
},
|
||||
'_test_cloud_regions': {
|
||||
@ -150,13 +154,13 @@ USER_CONF = {
|
||||
'name': 'region1',
|
||||
'values': {
|
||||
'external_network': 'region1-network',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
'name': 'region2',
|
||||
'values': {
|
||||
'external_network': 'my-network',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
'name': 'region-no-value',
|
||||
@ -198,13 +202,13 @@ USER_CONF = {
|
||||
'statsd': {
|
||||
'host': '127.0.0.1',
|
||||
'port': 4321,
|
||||
'prefix': 'statsd.override.prefix'
|
||||
'prefix': 'statsd.override.prefix',
|
||||
},
|
||||
'influxdb': {
|
||||
'username': 'override-username',
|
||||
'password': 'override-password',
|
||||
'database': 'override-database',
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -40,7 +40,6 @@ fake_services_dict = {
|
||||
|
||||
|
||||
class TestCloudRegion(base.TestCase):
|
||||
|
||||
def test_arbitrary_attributes(self):
|
||||
cc = cloud_region.CloudRegion("test1", "region-al", fake_config_dict)
|
||||
self.assertEqual("test1", cc.name)
|
||||
@ -89,12 +88,10 @@ class TestCloudRegion(base.TestCase):
|
||||
self.assertIsNone(cc._get_config('nothing', None))
|
||||
# This is what is happening behind the scenes in get_default_interface.
|
||||
self.assertEqual(
|
||||
fake_services_dict['interface'],
|
||||
cc._get_config('interface', None))
|
||||
fake_services_dict['interface'], cc._get_config('interface', None)
|
||||
)
|
||||
# The same call as above, but from one step up the stack
|
||||
self.assertEqual(
|
||||
fake_services_dict['interface'],
|
||||
cc.get_interface())
|
||||
self.assertEqual(fake_services_dict['interface'], cc.get_interface())
|
||||
# Which finally is what is called to populate the below
|
||||
self.assertEqual('public', self.cloud.default_interface)
|
||||
|
||||
@ -150,16 +147,21 @@ class TestCloudRegion(base.TestCase):
|
||||
|
||||
def test_ipv6(self):
|
||||
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)
|
||||
|
||||
def test_getters(self):
|
||||
cc = cloud_region.CloudRegion("test1", "region-al", fake_services_dict)
|
||||
|
||||
self.assertEqual(['compute', 'identity', 'image', 'volume'],
|
||||
sorted(cc.get_services()))
|
||||
self.assertEqual({'password': 'hunter2', 'username': 'AzureDiamond'},
|
||||
cc.get_auth_args())
|
||||
self.assertEqual(
|
||||
['compute', 'identity', 'image', 'volume'],
|
||||
sorted(cc.get_services()),
|
||||
)
|
||||
self.assertEqual(
|
||||
{'password': 'hunter2', 'username': 'AzureDiamond'},
|
||||
cc.get_auth_args(),
|
||||
)
|
||||
self.assertEqual('public', cc.get_interface())
|
||||
self.assertEqual('public', cc.get_interface('compute'))
|
||||
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('1', cc.get_api_version('volume'))
|
||||
self.assertEqual('block-storage', cc.get_service_type('volume'))
|
||||
self.assertEqual('http://compute.example.com',
|
||||
cc.get_endpoint('compute'))
|
||||
self.assertEqual(
|
||||
'http://compute.example.com', cc.get_endpoint('compute')
|
||||
)
|
||||
self.assertIsNone(cc.get_endpoint('image'))
|
||||
self.assertIsNone(cc.get_service_name('compute'))
|
||||
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
|
||||
# parts from the rackspace profile. The thing we're testing
|
||||
# is that the project_id logic works.
|
||||
cc = cloud_region.CloudRegion("test1", "DFW", {
|
||||
'profile': 'rackspace',
|
||||
'region_name': 'DFW',
|
||||
'auth': {'project_id': '123456'},
|
||||
'block_storage_endpoint_override': 'https://example.com/v2/',
|
||||
})
|
||||
cc = cloud_region.CloudRegion(
|
||||
"test1",
|
||||
"DFW",
|
||||
{
|
||||
'profile': 'rackspace',
|
||||
'region_name': 'DFW',
|
||||
'auth': {'project_id': '123456'},
|
||||
'block_storage_endpoint_override': 'https://example.com/v2/',
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
'https://example.com/v2/123456',
|
||||
cc.get_endpoint('block-storage')
|
||||
'https://example.com/v2/123456', cc.get_endpoint('block-storage')
|
||||
)
|
||||
|
||||
def test_rackspace_workaround_only_rax(self):
|
||||
cc = cloud_region.CloudRegion("test1", "DFW", {
|
||||
'region_name': 'DFW',
|
||||
'auth': {'project_id': '123456'},
|
||||
'block_storage_endpoint_override': 'https://example.com/v2/',
|
||||
})
|
||||
cc = cloud_region.CloudRegion(
|
||||
"test1",
|
||||
"DFW",
|
||||
{
|
||||
'region_name': 'DFW',
|
||||
'auth': {'project_id': '123456'},
|
||||
'block_storage_endpoint_override': 'https://example.com/v2/',
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
'https://example.com/v2/',
|
||||
cc.get_endpoint('block-storage')
|
||||
'https://example.com/v2/', cc.get_endpoint('block-storage')
|
||||
)
|
||||
|
||||
def test_get_region_name(self):
|
||||
|
||||
def assert_region_name(default, compute):
|
||||
self.assertEqual(default, cc.region_name)
|
||||
self.assertEqual(default, cc.get_region_name())
|
||||
self.assertEqual(default, cc.get_region_name(service_type=None))
|
||||
self.assertEqual(
|
||||
compute, cc.get_region_name(service_type='compute'))
|
||||
compute, cc.get_region_name(service_type='compute')
|
||||
)
|
||||
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
|
||||
# (including the default).
|
||||
@ -224,14 +234,17 @@ class TestCloudRegion(base.TestCase):
|
||||
|
||||
# Only region_name kwarg; it's returned for everything
|
||||
cc = cloud_region.CloudRegion(
|
||||
region_name='foo', config=fake_services_dict)
|
||||
region_name='foo', config=fake_services_dict
|
||||
)
|
||||
assert_region_name('foo', 'foo')
|
||||
|
||||
# No region_name kwarg; values (including default) show through from
|
||||
# config dict
|
||||
services_dict = 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)
|
||||
assert_region_name('the-default', 'compute-region')
|
||||
|
||||
@ -239,9 +252,12 @@ class TestCloudRegion(base.TestCase):
|
||||
# compatibility), but service-specific region_name takes precedence.
|
||||
services_dict = dict(
|
||||
fake_services_dict,
|
||||
region_name='dict', compute_region_name='compute-region')
|
||||
region_name='dict',
|
||||
compute_region_name='compute-region',
|
||||
)
|
||||
cc = cloud_region.CloudRegion(
|
||||
region_name='kwarg', config=services_dict)
|
||||
region_name='kwarg', config=services_dict
|
||||
)
|
||||
assert_region_name('kwarg', 'compute-region')
|
||||
|
||||
def test_aliases(self):
|
||||
@ -265,9 +281,7 @@ class TestCloudRegion(base.TestCase):
|
||||
config_dict = defaults.get_defaults()
|
||||
config_dict.update(fake_services_dict)
|
||||
cc = cloud_region.CloudRegion("test1", "region-al", config_dict)
|
||||
self.assertRaises(
|
||||
exceptions.ConfigException,
|
||||
cc.get_session)
|
||||
self.assertRaises(exceptions.ConfigException, cc.get_session)
|
||||
|
||||
@mock.patch.object(ksa_session, 'Session')
|
||||
def test_get_session(self, mock_session):
|
||||
@ -277,15 +291,21 @@ class TestCloudRegion(base.TestCase):
|
||||
fake_session.additional_user_agent = []
|
||||
mock_session.return_value = fake_session
|
||||
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()
|
||||
mock_session.assert_called_with(
|
||||
auth=mock.ANY,
|
||||
verify=True, cert=None, timeout=None, collect_timing=None,
|
||||
discovery_cache=None)
|
||||
verify=True,
|
||||
cert=None,
|
||||
timeout=None,
|
||||
collect_timing=None,
|
||||
discovery_cache=None,
|
||||
)
|
||||
self.assertEqual(
|
||||
fake_session.additional_user_agent,
|
||||
[('openstacksdk', openstack_version.__version__)])
|
||||
[('openstacksdk', openstack_version.__version__)],
|
||||
)
|
||||
|
||||
@mock.patch.object(ksa_session, 'Session')
|
||||
def test_get_session_with_app_name(self, mock_session):
|
||||
@ -297,18 +317,28 @@ class TestCloudRegion(base.TestCase):
|
||||
fake_session.app_version = None
|
||||
mock_session.return_value = fake_session
|
||||
cc = cloud_region.CloudRegion(
|
||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock(),
|
||||
app_name="test_app", app_version="test_version")
|
||||
"test1",
|
||||
"region-al",
|
||||
config_dict,
|
||||
auth_plugin=mock.Mock(),
|
||||
app_name="test_app",
|
||||
app_version="test_version",
|
||||
)
|
||||
cc.get_session()
|
||||
mock_session.assert_called_with(
|
||||
auth=mock.ANY,
|
||||
verify=True, cert=None, timeout=None, collect_timing=None,
|
||||
discovery_cache=None)
|
||||
verify=True,
|
||||
cert=None,
|
||||
timeout=None,
|
||||
collect_timing=None,
|
||||
discovery_cache=None,
|
||||
)
|
||||
self.assertEqual(fake_session.app_name, "test_app")
|
||||
self.assertEqual(fake_session.app_version, "test_version")
|
||||
self.assertEqual(
|
||||
fake_session.additional_user_agent,
|
||||
[('openstacksdk', openstack_version.__version__)])
|
||||
[('openstacksdk', openstack_version.__version__)],
|
||||
)
|
||||
|
||||
@mock.patch.object(ksa_session, '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['api_timeout'] = 9
|
||||
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()
|
||||
mock_session.assert_called_with(
|
||||
auth=mock.ANY,
|
||||
verify=True, cert=None, timeout=9,
|
||||
collect_timing=None, discovery_cache=None)
|
||||
verify=True,
|
||||
cert=None,
|
||||
timeout=9,
|
||||
collect_timing=None,
|
||||
discovery_cache=None,
|
||||
)
|
||||
self.assertEqual(
|
||||
fake_session.additional_user_agent,
|
||||
[('openstacksdk', openstack_version.__version__)])
|
||||
[('openstacksdk', openstack_version.__version__)],
|
||||
)
|
||||
|
||||
@mock.patch.object(ksa_session, '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['timing'] = True
|
||||
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()
|
||||
mock_session.assert_called_with(
|
||||
auth=mock.ANY,
|
||||
verify=True, cert=None, timeout=None,
|
||||
collect_timing=True, discovery_cache=None)
|
||||
verify=True,
|
||||
cert=None,
|
||||
timeout=None,
|
||||
collect_timing=True,
|
||||
discovery_cache=None,
|
||||
)
|
||||
self.assertEqual(
|
||||
fake_session.additional_user_agent,
|
||||
[('openstacksdk', openstack_version.__version__)])
|
||||
[('openstacksdk', openstack_version.__version__)],
|
||||
)
|
||||
|
||||
@mock.patch.object(ksa_session, 'Session')
|
||||
def test_override_session_endpoint_override(self, mock_session):
|
||||
config_dict = defaults.get_defaults()
|
||||
config_dict.update(fake_services_dict)
|
||||
cc = cloud_region.CloudRegion(
|
||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock())
|
||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock()
|
||||
)
|
||||
self.assertEqual(
|
||||
cc.get_session_endpoint('compute'),
|
||||
fake_services_dict['compute_endpoint_override'])
|
||||
fake_services_dict['compute_endpoint_override'],
|
||||
)
|
||||
|
||||
@mock.patch.object(ksa_session, 'Session')
|
||||
def test_override_session_endpoint(self, mock_session):
|
||||
config_dict = defaults.get_defaults()
|
||||
config_dict.update(fake_services_dict)
|
||||
cc = cloud_region.CloudRegion(
|
||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock())
|
||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock()
|
||||
)
|
||||
self.assertEqual(
|
||||
cc.get_session_endpoint('telemetry'),
|
||||
fake_services_dict['telemetry_endpoint'])
|
||||
fake_services_dict['telemetry_endpoint'],
|
||||
)
|
||||
|
||||
@mock.patch.object(cloud_region.CloudRegion, '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.update(fake_services_dict)
|
||||
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')
|
||||
mock_session.get_endpoint.assert_called_with(
|
||||
interface='public',
|
||||
service_name=None,
|
||||
region_name='region-al',
|
||||
service_type='orchestration')
|
||||
service_type='orchestration',
|
||||
)
|
||||
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session')
|
||||
def test_session_endpoint_not_found(self, mock_get_session):
|
||||
exc_to_raise = ksa_exceptions.catalog.EndpointNotFound
|
||||
mock_get_session.return_value.get_endpoint.side_effect = exc_to_raise
|
||||
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'))
|
||||
|
||||
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.assertEqual(
|
||||
'https://compute.example.com/v2.1/',
|
||||
self.cloud.config.get_endpoint_from_catalog('compute'))
|
||||
self.cloud.config.get_endpoint_from_catalog('compute'),
|
||||
)
|
||||
self.assertEqual(
|
||||
'https://internal.compute.example.com/v2.1/',
|
||||
self.cloud.config.get_endpoint_from_catalog(
|
||||
'compute', interface='internal'))
|
||||
'compute', interface='internal'
|
||||
),
|
||||
)
|
||||
self.assertIsNone(
|
||||
self.cloud.config.get_endpoint_from_catalog(
|
||||
'compute', region_name='unknown-region'))
|
||||
'compute', region_name='unknown-region'
|
||||
)
|
||||
)
|
||||
self.assertEqual(
|
||||
'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):
|
||||
|
||||
def setUp(self):
|
||||
super(TestEnviron, self).setUp()
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_AUTH_URL', 'https://example.com'))
|
||||
fixtures.EnvironmentVariable('OS_AUTH_URL', 'https://example.com')
|
||||
)
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_USERNAME', 'testuser'))
|
||||
fixtures.EnvironmentVariable('OS_USERNAME', 'testuser')
|
||||
)
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_PASSWORD', 'testpass'))
|
||||
fixtures.EnvironmentVariable('OS_PASSWORD', 'testpass')
|
||||
)
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_PROJECT_NAME', 'testproject'))
|
||||
fixtures.EnvironmentVariable('OS_PROJECT_NAME', 'testproject')
|
||||
)
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('NOVA_PROJECT_ID', 'testnova'))
|
||||
fixtures.EnvironmentVariable('NOVA_PROJECT_ID', 'testnova')
|
||||
)
|
||||
|
||||
def test_get_one(self):
|
||||
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]
|
||||
)
|
||||
self.assertIsInstance(c.get_one(), cloud_region.CloudRegion)
|
||||
|
||||
def test_no_fallthrough(self):
|
||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml])
|
||||
self.assertRaises(
|
||||
exceptions.ConfigException, c.get_one, 'openstack')
|
||||
c = config.OpenStackConfig(
|
||||
config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]
|
||||
)
|
||||
self.assertRaises(exceptions.ConfigException, c.get_one, 'openstack')
|
||||
|
||||
def test_envvar_name_override(self):
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_CLOUD_NAME', 'override'))
|
||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml])
|
||||
fixtures.EnvironmentVariable('OS_CLOUD_NAME', 'override')
|
||||
)
|
||||
c = config.OpenStackConfig(
|
||||
config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]
|
||||
)
|
||||
cc = c.get_one('override')
|
||||
self._assert_cloud_details(cc)
|
||||
|
||||
def test_envvar_prefer_ipv6_override(self):
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_PREFER_IPV6', 'false'))
|
||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml],
|
||||
secure_files=[self.secure_yaml])
|
||||
fixtures.EnvironmentVariable('OS_PREFER_IPV6', 'false')
|
||||
)
|
||||
c = config.OpenStackConfig(
|
||||
config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml],
|
||||
secure_files=[self.secure_yaml],
|
||||
)
|
||||
cc = c.get_one('_test-cloud_')
|
||||
self.assertFalse(cc.prefer_ipv6)
|
||||
|
||||
def test_environ_exists(self):
|
||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml],
|
||||
secure_files=[self.secure_yaml])
|
||||
c = config.OpenStackConfig(
|
||||
config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml],
|
||||
secure_files=[self.secure_yaml],
|
||||
)
|
||||
cc = c.get_one('envvars')
|
||||
self._assert_cloud_details(cc)
|
||||
self.assertNotIn('auth_url', cc.config)
|
||||
@ -79,10 +91,12 @@ class TestEnviron(base.TestCase):
|
||||
self._assert_cloud_details(cc)
|
||||
|
||||
def test_environ_prefix(self):
|
||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml],
|
||||
envvar_prefix='NOVA_',
|
||||
secure_files=[self.secure_yaml])
|
||||
c = config.OpenStackConfig(
|
||||
config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml],
|
||||
envvar_prefix='NOVA_',
|
||||
secure_files=[self.secure_yaml],
|
||||
)
|
||||
cc = c.get_one('envvars')
|
||||
self._assert_cloud_details(cc)
|
||||
self.assertNotIn('auth_url', cc.config)
|
||||
@ -95,9 +109,11 @@ class TestEnviron(base.TestCase):
|
||||
self._assert_cloud_details(cc)
|
||||
|
||||
def test_get_one_with_config_files(self):
|
||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml],
|
||||
secure_files=[self.secure_yaml])
|
||||
c = config.OpenStackConfig(
|
||||
config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml],
|
||||
secure_files=[self.secure_yaml],
|
||||
)
|
||||
self.assertIsInstance(c.cloud_config, dict)
|
||||
self.assertIn('cache', c.cloud_config)
|
||||
self.assertIsInstance(c.cloud_config['cache'], dict)
|
||||
@ -111,40 +127,40 @@ class TestEnviron(base.TestCase):
|
||||
def test_config_file_override(self):
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable(
|
||||
'OS_CLIENT_CONFIG_FILE', self.cloud_yaml))
|
||||
c = config.OpenStackConfig(config_files=[],
|
||||
vendor_files=[self.vendor_yaml])
|
||||
'OS_CLIENT_CONFIG_FILE', self.cloud_yaml
|
||||
)
|
||||
)
|
||||
c = config.OpenStackConfig(
|
||||
config_files=[], vendor_files=[self.vendor_yaml]
|
||||
)
|
||||
cc = c.get_one('_test-cloud_')
|
||||
self._assert_cloud_details(cc)
|
||||
|
||||
|
||||
class TestEnvvars(base.TestCase):
|
||||
|
||||
def test_no_envvars(self):
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml])
|
||||
self.assertRaises(
|
||||
exceptions.ConfigException, c.get_one, 'envvars')
|
||||
self.useFixture(fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||
c = config.OpenStackConfig(
|
||||
config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]
|
||||
)
|
||||
self.assertRaises(exceptions.ConfigException, c.get_one, 'envvars')
|
||||
|
||||
def test_test_envvars(self):
|
||||
self.useFixture(fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_STDERR_CAPTURE', 'True'))
|
||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml])
|
||||
self.assertRaises(
|
||||
exceptions.ConfigException, c.get_one, 'envvars')
|
||||
fixtures.EnvironmentVariable('OS_STDERR_CAPTURE', 'True')
|
||||
)
|
||||
c = config.OpenStackConfig(
|
||||
config_files=[self.cloud_yaml], vendor_files=[self.vendor_yaml]
|
||||
)
|
||||
self.assertRaises(exceptions.ConfigException, c.get_one, 'envvars')
|
||||
|
||||
def test_incomplete_envvars(self):
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_USERNAME', 'user'))
|
||||
config.OpenStackConfig(config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml])
|
||||
self.useFixture(fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||
self.useFixture(fixtures.EnvironmentVariable('OS_USERNAME', 'user'))
|
||||
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
|
||||
# commenting it out in this patch to keep the patch size reasonable
|
||||
# self.assertRaises(
|
||||
@ -152,33 +168,38 @@ class TestEnvvars(base.TestCase):
|
||||
# c.get_one, 'envvars')
|
||||
|
||||
def test_have_envvars(self):
|
||||
self.useFixture(fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||
fixtures.EnvironmentVariable('OS_AUTH_URL', 'http://example.com')
|
||||
)
|
||||
self.useFixture(fixtures.EnvironmentVariable('OS_USERNAME', 'user'))
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_AUTH_URL', 'http://example.com'))
|
||||
fixtures.EnvironmentVariable('OS_PASSWORD', 'password')
|
||||
)
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_USERNAME', 'user'))
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_PASSWORD', 'password'))
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('OS_PROJECT_NAME', 'project'))
|
||||
c = config.OpenStackConfig(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')
|
||||
self.assertEqual(cc.config['auth']['username'], 'user')
|
||||
|
||||
def test_old_envvars(self):
|
||||
self.useFixture(fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('NOVA_USERNAME', 'nova'))
|
||||
fixtures.EnvironmentVariable('NOVA_AUTH_URL', 'http://example.com')
|
||||
)
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable(
|
||||
'NOVA_AUTH_URL', 'http://example.com'))
|
||||
fixtures.EnvironmentVariable('NOVA_PASSWORD', 'password')
|
||||
)
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('NOVA_PASSWORD', 'password'))
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('NOVA_PROJECT_NAME', 'project'))
|
||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml],
|
||||
envvar_prefix='NOVA_')
|
||||
fixtures.EnvironmentVariable('NOVA_PROJECT_NAME', 'project')
|
||||
)
|
||||
c = config.OpenStackConfig(
|
||||
config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml],
|
||||
envvar_prefix='NOVA_',
|
||||
)
|
||||
cc = c.get_one('envvars')
|
||||
self.assertEqual(cc.config['auth']['username'], 'nova')
|
||||
|
@ -23,13 +23,15 @@ from openstack.tests.unit import base
|
||||
|
||||
|
||||
class TestFromConf(base.TestCase):
|
||||
|
||||
def _get_conn(self, **from_conf_kwargs):
|
||||
oslocfg = self._load_ks_cfg_opts()
|
||||
# Throw name in here to prove **kwargs is working
|
||||
config = cloud_region.from_conf(
|
||||
oslocfg, session=self.cloud.session, name='from_conf.example.com',
|
||||
**from_conf_kwargs)
|
||||
oslocfg,
|
||||
session=self.cloud.session,
|
||||
name='from_conf.example.com',
|
||||
**from_conf_kwargs
|
||||
)
|
||||
self.assertEqual('from_conf.example.com', config.name)
|
||||
|
||||
return connection.Connection(config=config, strict_proxies=True)
|
||||
@ -41,33 +43,48 @@ class TestFromConf(base.TestCase):
|
||||
discovery = {
|
||||
"versions": {
|
||||
"values": [
|
||||
{"status": "stable",
|
||||
"updated": "2019-06-01T00:00:00Z",
|
||||
"media-types": [{
|
||||
"base": "application/json",
|
||||
"type": "application/vnd.openstack.heat-v2+json"}],
|
||||
"id": "v2.0",
|
||||
"links": [{
|
||||
"href": "https://example.org:8888/heat/v2",
|
||||
"rel": "self"}]
|
||||
}]
|
||||
{
|
||||
"status": "stable",
|
||||
"updated": "2019-06-01T00:00:00Z",
|
||||
"media-types": [
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/vnd.openstack.heat-v2+json", # noqa: E501
|
||||
}
|
||||
],
|
||||
"id": "v2.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://example.org:8888/heat/v2",
|
||||
"rel": "self",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri='https://example.org:8888/heat/v2',
|
||||
json=discovery),
|
||||
dict(method='GET',
|
||||
uri='https://example.org:8888/heat/v2/foo',
|
||||
json={'foo': {}}),
|
||||
])
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://example.org:8888/heat/v2',
|
||||
json=discovery,
|
||||
),
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://example.org:8888/heat/v2/foo',
|
||||
json={'foo': {}},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
adap = conn.orchestration
|
||||
self.assertEqual('SpecialRegion', adap.region_name)
|
||||
self.assertEqual('orchestration', adap.service_type)
|
||||
self.assertEqual('internal', adap.interface)
|
||||
self.assertEqual('https://example.org:8888/heat/v2',
|
||||
adap.endpoint_override)
|
||||
self.assertEqual(
|
||||
'https://example.org:8888/heat/v2', adap.endpoint_override
|
||||
)
|
||||
|
||||
adap.get('/foo')
|
||||
self.assert_calls()
|
||||
@ -80,13 +97,18 @@ class TestFromConf(base.TestCase):
|
||||
server_name = self.getUniqueString('name')
|
||||
fake_server = fakes.make_fake_server(server_id, server_name)
|
||||
|
||||
self.register_uris([
|
||||
self.get_nova_discovery_mock_dict(),
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'compute', 'public', append=['servers', 'detail']),
|
||||
json={'servers': [fake_server]}),
|
||||
])
|
||||
self.register_uris(
|
||||
[
|
||||
self.get_nova_discovery_mock_dict(),
|
||||
dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'compute', 'public', append=['servers', 'detail']
|
||||
),
|
||||
json={'servers': [fake_server]},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
# Nova has empty adapter config, so these default
|
||||
adap = conn.compute
|
||||
@ -108,20 +130,27 @@ class TestFromConf(base.TestCase):
|
||||
server_name = self.getUniqueString('name')
|
||||
fake_server = fakes.make_fake_server(server_id, server_name)
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri='https://compute.example.com/v2.1/',
|
||||
exc=requests.exceptions.ConnectionError),
|
||||
self.get_nova_discovery_mock_dict(),
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'compute', 'public', append=['servers', 'detail']),
|
||||
json={'servers': [fake_server]}),
|
||||
])
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://compute.example.com/v2.1/',
|
||||
exc=requests.exceptions.ConnectionError,
|
||||
),
|
||||
self.get_nova_discovery_mock_dict(),
|
||||
dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'compute', 'public', append=['servers', 'detail']
|
||||
),
|
||||
json={'servers': [fake_server]},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ServiceDiscoveryException,
|
||||
getattr, conn, 'compute')
|
||||
exceptions.ServiceDiscoveryException, getattr, conn, 'compute'
|
||||
)
|
||||
|
||||
# Nova has empty adapter config, so these default
|
||||
adap = conn.compute
|
||||
@ -141,31 +170,41 @@ class TestFromConf(base.TestCase):
|
||||
discovery = {
|
||||
"versions": {
|
||||
"values": [
|
||||
{"status": "stable",
|
||||
"id": "v1",
|
||||
"links": [{
|
||||
"href": "https://example.org:5050/v1",
|
||||
"rel": "self"}]
|
||||
}]
|
||||
{
|
||||
"status": "stable",
|
||||
"id": "v1",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://example.org:5050/v1",
|
||||
"rel": "self",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
status = {
|
||||
'finished': True,
|
||||
'error': None
|
||||
}
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri='https://example.org:5050',
|
||||
json=discovery),
|
||||
# strict-proxies means we're going to fetch the discovery
|
||||
# doc from the versioned endpoint to verify it works.
|
||||
dict(method='GET',
|
||||
uri='https://example.org:5050/v1',
|
||||
json=discovery),
|
||||
dict(method='GET',
|
||||
uri='https://example.org:5050/v1/introspection/abcd',
|
||||
json=status),
|
||||
])
|
||||
status = {'finished': True, 'error': None}
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://example.org:5050',
|
||||
json=discovery,
|
||||
),
|
||||
# strict-proxies means we're going to fetch the discovery
|
||||
# doc from the versioned endpoint to verify it works.
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://example.org:5050/v1',
|
||||
json=discovery,
|
||||
),
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://example.org:5050/v1/introspection/abcd',
|
||||
json=status,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
adap = conn.baremetal_introspection
|
||||
self.assertEqual('baremetal-introspection', adap.service_type)
|
||||
@ -180,38 +219,53 @@ class TestFromConf(base.TestCase):
|
||||
discovery = {
|
||||
"versions": {
|
||||
"values": [
|
||||
{"status": "stable",
|
||||
"id": "v1",
|
||||
"links": [{
|
||||
"href": "https://example.org:5050/v1",
|
||||
"rel": "self"}]
|
||||
}]
|
||||
{
|
||||
"status": "stable",
|
||||
"id": "v1",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://example.org:5050/v1",
|
||||
"rel": "self",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
status = {
|
||||
'finished': True,
|
||||
'error': None
|
||||
}
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri='https://example.org:5050',
|
||||
exc=requests.exceptions.ConnectTimeout),
|
||||
dict(method='GET',
|
||||
uri='https://example.org:5050',
|
||||
json=discovery),
|
||||
# strict-proxies means we're going to fetch the discovery
|
||||
# doc from the versioned endpoint to verify it works.
|
||||
dict(method='GET',
|
||||
uri='https://example.org:5050/v1',
|
||||
json=discovery),
|
||||
dict(method='GET',
|
||||
uri='https://example.org:5050/v1/introspection/abcd',
|
||||
json=status),
|
||||
])
|
||||
status = {'finished': True, 'error': None}
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://example.org:5050',
|
||||
exc=requests.exceptions.ConnectTimeout,
|
||||
),
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://example.org:5050',
|
||||
json=discovery,
|
||||
),
|
||||
# strict-proxies means we're going to fetch the discovery
|
||||
# doc from the versioned endpoint to verify it works.
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://example.org:5050/v1',
|
||||
json=discovery,
|
||||
),
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://example.org:5050/v1/introspection/abcd',
|
||||
json=status,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ServiceDiscoveryException,
|
||||
getattr, conn, 'baremetal_introspection')
|
||||
getattr,
|
||||
conn,
|
||||
'baremetal_introspection',
|
||||
)
|
||||
|
||||
adap = conn.baremetal_introspection
|
||||
self.assertEqual('baremetal-introspection', adap.service_type)
|
||||
@ -220,16 +274,21 @@ class TestFromConf(base.TestCase):
|
||||
|
||||
self.assertTrue(adap.get_introspection('abcd').is_finished)
|
||||
|
||||
def assert_service_disabled(self, service_type, expected_reason,
|
||||
**from_conf_kwargs):
|
||||
def assert_service_disabled(
|
||||
self, service_type, expected_reason, **from_conf_kwargs
|
||||
):
|
||||
conn = self._get_conn(**from_conf_kwargs)
|
||||
# The _ServiceDisabledProxyShim loads up okay...
|
||||
adap = getattr(conn, service_type)
|
||||
# ...but freaks out if you try to use it.
|
||||
ex = self.assertRaises(
|
||||
exceptions.ServiceDisabledException, getattr, adap, 'get')
|
||||
self.assertIn("Service '%s' is disabled because its configuration "
|
||||
"could not be loaded." % service_type, ex.message)
|
||||
exceptions.ServiceDisabledException, getattr, adap, 'get'
|
||||
)
|
||||
self.assertIn(
|
||||
"Service '%s' is disabled because its configuration "
|
||||
"could not be loaded." % service_type,
|
||||
ex.message,
|
||||
)
|
||||
self.assertIn(expected_reason, ex.message)
|
||||
|
||||
def test_no_such_conf_section(self):
|
||||
@ -238,15 +297,18 @@ class TestFromConf(base.TestCase):
|
||||
self.assert_service_disabled(
|
||||
'orchestration',
|
||||
"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):
|
||||
"""Ignore absent conf section if service type not requested."""
|
||||
del self.oslo_config_dict['heat']
|
||||
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
|
||||
service_types=['compute'])
|
||||
service_types=['compute'],
|
||||
)
|
||||
|
||||
def test_no_adapter_opts(self):
|
||||
"""Conf section present, but opts for service type not registered."""
|
||||
@ -254,15 +316,18 @@ class TestFromConf(base.TestCase):
|
||||
self.assert_service_disabled(
|
||||
'orchestration',
|
||||
"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):
|
||||
"""Ignore unregistered conf section if service type not requested."""
|
||||
self.oslo_config_dict['heat'] = None
|
||||
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
|
||||
service_types=['compute'])
|
||||
service_types=['compute'],
|
||||
)
|
||||
|
||||
def test_invalid_adapter_opts(self):
|
||||
"""Adapter opts are bogus, in exception-raising ways."""
|
||||
@ -274,24 +339,31 @@ class TestFromConf(base.TestCase):
|
||||
'orchestration',
|
||||
"Encountered an exception attempting to process config for "
|
||||
"project 'heat' (service type 'orchestration'): interface and "
|
||||
"valid_interfaces are mutually exclusive.")
|
||||
"valid_interfaces are mutually exclusive.",
|
||||
)
|
||||
|
||||
def test_no_session(self):
|
||||
# TODO(efried): Currently calling without a Session is not implemented.
|
||||
self.assertRaises(exceptions.ConfigException,
|
||||
cloud_region.from_conf, self._load_ks_cfg_opts())
|
||||
self.assertRaises(
|
||||
exceptions.ConfigException,
|
||||
cloud_region.from_conf,
|
||||
self._load_ks_cfg_opts(),
|
||||
)
|
||||
|
||||
def test_no_endpoint(self):
|
||||
"""Conf contains adapter opts, but service type not in catalog."""
|
||||
self.os_fixture.v3_token.remove_service('monitoring')
|
||||
conn = self._get_conn()
|
||||
# Monasca is not in the service catalog
|
||||
self.assertRaises(ks_exc.catalog.EndpointNotFound,
|
||||
getattr, conn, 'monitoring')
|
||||
self.assertRaises(
|
||||
ks_exc.catalog.EndpointNotFound, getattr, conn, 'monitoring'
|
||||
)
|
||||
|
||||
def test_no_endpoint_ignore_service_type(self):
|
||||
"""Bogus service type disabled if not in requested service_types."""
|
||||
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
|
||||
service_types={'compute', 'orchestration', 'bogus'})
|
||||
service_types={'compute', 'orchestration', 'bogus'},
|
||||
)
|
||||
|
@ -30,7 +30,8 @@ class TestFromSession(base.TestCase):
|
||||
|
||||
def test_from_session(self):
|
||||
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')
|
||||
if not self.test_region:
|
||||
self.assertIsNone(config.region_name)
|
||||
@ -40,13 +41,18 @@ class TestFromSession(base.TestCase):
|
||||
server_id = str(uuid.uuid4())
|
||||
server_name = self.getUniqueString('name')
|
||||
fake_server = fakes.make_fake_server(server_id, server_name)
|
||||
self.register_uris([
|
||||
self.get_nova_discovery_mock_dict(),
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'compute', 'public', append=['servers', 'detail']),
|
||||
json={'servers': [fake_server]}),
|
||||
])
|
||||
self.register_uris(
|
||||
[
|
||||
self.get_nova_discovery_mock_dict(),
|
||||
dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'compute', 'public', append=['servers', 'detail']
|
||||
),
|
||||
json={'servers': [fake_server]},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
conn = connection.Connection(config=config)
|
||||
s = next(conn.compute.servers())
|
||||
|
@ -19,17 +19,16 @@ from openstack.tests.unit.config import base
|
||||
class TestInit(base.TestCase):
|
||||
def test_get_cloud_region_without_arg_parser(self):
|
||||
cloud_region = openstack.config.get_cloud_region(
|
||||
options=None, validate=False)
|
||||
options=None, validate=False
|
||||
)
|
||||
self.assertIsInstance(
|
||||
cloud_region,
|
||||
openstack.config.cloud_region.CloudRegion
|
||||
cloud_region, openstack.config.cloud_region.CloudRegion
|
||||
)
|
||||
|
||||
def test_get_cloud_region_with_arg_parser(self):
|
||||
cloud_region = openstack.config.get_cloud_region(
|
||||
options=argparse.ArgumentParser(),
|
||||
validate=False)
|
||||
self.assertIsInstance(
|
||||
cloud_region,
|
||||
openstack.config.cloud_region.CloudRegion
|
||||
options=argparse.ArgumentParser(), validate=False
|
||||
)
|
||||
self.assertIsInstance(
|
||||
cloud_region, openstack.config.cloud_region.CloudRegion
|
||||
)
|
||||
|
@ -24,7 +24,6 @@ from openstack.tests.unit.config import base
|
||||
|
||||
|
||||
class TestConfig(base.TestCase):
|
||||
|
||||
def json_diagnostics(self, exc_info):
|
||||
self.addDetail('filename', content.text_content(self.filename))
|
||||
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):
|
||||
_schema_path = os.path.join(
|
||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
||||
'schema.json')
|
||||
os.path.dirname(os.path.realpath(defaults.__file__)), 'schema.json'
|
||||
)
|
||||
with open(_schema_path, 'r') as f:
|
||||
schema = json.load(f)
|
||||
self.validator = jsonschema.Draft4Validator(schema)
|
||||
@ -41,7 +40,8 @@ class TestConfig(base.TestCase):
|
||||
|
||||
self.filename = os.path.join(
|
||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
||||
'defaults.json')
|
||||
'defaults.json',
|
||||
)
|
||||
with open(self.filename, 'r') as f:
|
||||
self.json_data = json.load(f)
|
||||
|
||||
@ -50,7 +50,8 @@ class TestConfig(base.TestCase):
|
||||
def test_vendors_valid_json(self):
|
||||
_schema_path = os.path.join(
|
||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
||||
'vendor-schema.json')
|
||||
'vendor-schema.json',
|
||||
)
|
||||
with open(_schema_path, 'r') as f:
|
||||
schema = json.load(f)
|
||||
self.validator = jsonschema.Draft4Validator(schema)
|
||||
@ -58,8 +59,8 @@ class TestConfig(base.TestCase):
|
||||
self.addOnException(self.json_diagnostics)
|
||||
|
||||
_vendors_path = os.path.join(
|
||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
||||
'vendors')
|
||||
os.path.dirname(os.path.realpath(defaults.__file__)), 'vendors'
|
||||
)
|
||||
for self.filename in glob.glob(os.path.join(_vendors_path, '*.json')):
|
||||
with open(self.filename, 'r') as f:
|
||||
self.json_data = json.load(f)
|
||||
|
@ -21,14 +21,17 @@ from openstack import exceptions
|
||||
from openstack.tests.unit.config import base
|
||||
|
||||
FILES = {
|
||||
'yaml': textwrap.dedent('''
|
||||
'yaml': textwrap.dedent(
|
||||
'''
|
||||
foo: bar
|
||||
baz:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
'''),
|
||||
'json': textwrap.dedent('''
|
||||
'''
|
||||
),
|
||||
'json': textwrap.dedent(
|
||||
'''
|
||||
{
|
||||
"foo": "bar",
|
||||
"baz": [
|
||||
@ -37,18 +40,20 @@ FILES = {
|
||||
3
|
||||
]
|
||||
}
|
||||
'''),
|
||||
'txt': textwrap.dedent('''
|
||||
'''
|
||||
),
|
||||
'txt': textwrap.dedent(
|
||||
'''
|
||||
foo
|
||||
bar baz
|
||||
test
|
||||
one two
|
||||
'''),
|
||||
'''
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
class TestLoader(base.TestCase):
|
||||
|
||||
def test_base_load_yaml_json_file(self):
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
tested_files = []
|
||||
@ -59,7 +64,8 @@ class TestLoader(base.TestCase):
|
||||
tested_files.append(fn)
|
||||
|
||||
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
||||
tested_files)
|
||||
tested_files
|
||||
)
|
||||
# NOTE(hberaud): Prefer to test path rather than file because
|
||||
# our FILES var is a dict so results are appened
|
||||
# without keeping the initial order (python 3.5)
|
||||
@ -77,7 +83,8 @@ class TestLoader(base.TestCase):
|
||||
tested_files.append(fn)
|
||||
|
||||
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
||||
tested_files)
|
||||
tested_files
|
||||
)
|
||||
# NOTE(hberaud): Prefer to test path rather than file because
|
||||
# our FILES var is a dict so results are appened
|
||||
# without keeping the initial order (python 3.5)
|
||||
@ -92,7 +99,8 @@ class TestLoader(base.TestCase):
|
||||
tested_files.append(fn)
|
||||
|
||||
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
||||
tested_files)
|
||||
tested_files
|
||||
)
|
||||
self.assertEqual(fn, path)
|
||||
|
||||
def test__load_yaml_json_file_without_perm(self):
|
||||
@ -105,7 +113,8 @@ class TestLoader(base.TestCase):
|
||||
tested_files.append(fn)
|
||||
|
||||
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
||||
tested_files)
|
||||
tested_files
|
||||
)
|
||||
self.assertEqual(None, path)
|
||||
|
||||
def test__load_yaml_json_file_nonexisting(self):
|
||||
@ -114,28 +123,56 @@ class TestLoader(base.TestCase):
|
||||
tested_files.append(fn)
|
||||
|
||||
path, result = loader.OpenStackConfig()._load_yaml_json_file(
|
||||
tested_files)
|
||||
tested_files
|
||||
)
|
||||
self.assertEqual(None, path)
|
||||
|
||||
|
||||
class TestFixArgv(base.TestCase):
|
||||
def test_no_changes(self):
|
||||
argv = ['-a', '-b', '--long-arg', '--multi-value', 'key1=value1',
|
||||
'--multi-value', 'key2=value2']
|
||||
argv = [
|
||||
'-a',
|
||||
'-b',
|
||||
'--long-arg',
|
||||
'--multi-value',
|
||||
'key1=value1',
|
||||
'--multi-value',
|
||||
'key2=value2',
|
||||
]
|
||||
expected = argv[:]
|
||||
loader._fix_argv(argv)
|
||||
self.assertEqual(expected, argv)
|
||||
|
||||
def test_replace(self):
|
||||
argv = ['-a', '-b', '--long-arg', '--multi_value', 'key1=value1',
|
||||
'--multi_value', 'key2=value2']
|
||||
expected = ['-a', '-b', '--long-arg', '--multi-value', 'key1=value1',
|
||||
'--multi-value', 'key2=value2']
|
||||
argv = [
|
||||
'-a',
|
||||
'-b',
|
||||
'--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)
|
||||
self.assertEqual(expected, argv)
|
||||
|
||||
def test_mix(self):
|
||||
argv = ['-a', '-b', '--long-arg', '--multi_value', 'key1=value1',
|
||||
'--multi-value', 'key2=value2']
|
||||
self.assertRaises(exceptions.ConfigException,
|
||||
loader._fix_argv, argv)
|
||||
argv = [
|
||||
'-a',
|
||||
'-b',
|
||||
'--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}
|
||||
project_name: {project}
|
||||
cacert: {cacert}
|
||||
""".format(auth_url=CONFIG_AUTH_URL, username=CONFIG_USERNAME,
|
||||
password=CONFIG_PASSWORD, project=CONFIG_PROJECT,
|
||||
cacert=CONFIG_CACERT)
|
||||
""".format(
|
||||
auth_url=CONFIG_AUTH_URL,
|
||||
username=CONFIG_USERNAME,
|
||||
password=CONFIG_PASSWORD,
|
||||
project=CONFIG_PROJECT,
|
||||
cacert=CONFIG_CACERT,
|
||||
)
|
||||
|
||||
VENDOR_CONFIG = """
|
||||
{{
|
||||
@ -84,7 +88,9 @@ VENDOR_CONFIG = """
|
||||
"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:
|
||||
@ -92,11 +98,12 @@ public-clouds:
|
||||
auth:
|
||||
auth_url: {auth_url}
|
||||
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):
|
||||
|
||||
def setUp(self):
|
||||
super(_TestConnectionBase, self).setUp()
|
||||
# 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:
|
||||
conf.write(CLOUD_CONFIG)
|
||||
|
||||
self.useFixture(fixtures.EnvironmentVariable(
|
||||
"OS_CLIENT_CONFIG_FILE", config_path))
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable("OS_CLIENT_CONFIG_FILE", config_path)
|
||||
)
|
||||
self.use_keystone_v2()
|
||||
|
||||
|
||||
@ -152,104 +160,127 @@ class TestConnection(_TestConnectionBase):
|
||||
# conn.workflow.__class__.__module__)
|
||||
|
||||
def test_create_unknown_proxy(self):
|
||||
self.register_uris([
|
||||
self.get_placement_discovery_mock_dict(),
|
||||
])
|
||||
self.register_uris(
|
||||
[
|
||||
self.get_placement_discovery_mock_dict(),
|
||||
]
|
||||
)
|
||||
|
||||
def closure():
|
||||
return self.cloud.placement
|
||||
|
||||
self.assertThat(
|
||||
closure,
|
||||
matchers.Warnings(matchers.HasLength(0)))
|
||||
self.assertThat(closure, matchers.Warnings(matchers.HasLength(0)))
|
||||
|
||||
self.assertIsInstance(
|
||||
self.cloud.placement,
|
||||
proxy.Proxy)
|
||||
self.assertIsInstance(self.cloud.placement, proxy.Proxy)
|
||||
|
||||
self.assert_calls()
|
||||
|
||||
def test_create_connection_version_param_default(self):
|
||||
c1 = connection.Connection(cloud='sample-cloud')
|
||||
conn = connection.Connection(session=c1.session)
|
||||
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_string(self):
|
||||
c1 = connection.Connection(cloud='sample-cloud')
|
||||
conn = connection.Connection(
|
||||
session=c1.session, identity_api_version='2')
|
||||
self.assertEqual('openstack.identity.v2._proxy',
|
||||
conn.identity.__class__.__module__)
|
||||
session=c1.session, identity_api_version='2'
|
||||
)
|
||||
self.assertEqual(
|
||||
'openstack.identity.v2._proxy', conn.identity.__class__.__module__
|
||||
)
|
||||
|
||||
def test_create_connection_version_param_int(self):
|
||||
c1 = connection.Connection(cloud='sample-cloud')
|
||||
conn = connection.Connection(
|
||||
session=c1.session, identity_api_version=3)
|
||||
self.assertEqual('openstack.identity.v3._proxy',
|
||||
conn.identity.__class__.__module__)
|
||||
session=c1.session, identity_api_version=3
|
||||
)
|
||||
self.assertEqual(
|
||||
'openstack.identity.v3._proxy', conn.identity.__class__.__module__
|
||||
)
|
||||
|
||||
def test_create_connection_version_param_bogus(self):
|
||||
c1 = connection.Connection(cloud='sample-cloud')
|
||||
conn = connection.Connection(
|
||||
session=c1.session, identity_api_version='red')
|
||||
session=c1.session, identity_api_version='red'
|
||||
)
|
||||
# TODO(mordred) This is obviously silly behavior
|
||||
self.assertEqual('openstack.identity.v3._proxy',
|
||||
conn.identity.__class__.__module__)
|
||||
self.assertEqual(
|
||||
'openstack.identity.v3._proxy', conn.identity.__class__.__module__
|
||||
)
|
||||
|
||||
def test_from_config_given_config(self):
|
||||
cloud_region = (openstack.config.OpenStackConfig().
|
||||
get_one("sample-cloud"))
|
||||
cloud_region = openstack.config.OpenStackConfig().get_one(
|
||||
"sample-cloud"
|
||||
)
|
||||
|
||||
sot = connection.from_config(config=cloud_region)
|
||||
|
||||
self.assertEqual(CONFIG_USERNAME,
|
||||
sot.config.config['auth']['username'])
|
||||
self.assertEqual(CONFIG_PASSWORD,
|
||||
sot.config.config['auth']['password'])
|
||||
self.assertEqual(CONFIG_AUTH_URL,
|
||||
sot.config.config['auth']['auth_url'])
|
||||
self.assertEqual(CONFIG_PROJECT,
|
||||
sot.config.config['auth']['project_name'])
|
||||
self.assertEqual(
|
||||
CONFIG_USERNAME, sot.config.config['auth']['username']
|
||||
)
|
||||
self.assertEqual(
|
||||
CONFIG_PASSWORD, sot.config.config['auth']['password']
|
||||
)
|
||||
self.assertEqual(
|
||||
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):
|
||||
sot = connection.from_config(cloud="sample-cloud")
|
||||
|
||||
self.assertEqual(CONFIG_USERNAME,
|
||||
sot.config.config['auth']['username'])
|
||||
self.assertEqual(CONFIG_PASSWORD,
|
||||
sot.config.config['auth']['password'])
|
||||
self.assertEqual(CONFIG_AUTH_URL,
|
||||
sot.config.config['auth']['auth_url'])
|
||||
self.assertEqual(CONFIG_PROJECT,
|
||||
sot.config.config['auth']['project_name'])
|
||||
self.assertEqual(
|
||||
CONFIG_USERNAME, sot.config.config['auth']['username']
|
||||
)
|
||||
self.assertEqual(
|
||||
CONFIG_PASSWORD, sot.config.config['auth']['password']
|
||||
)
|
||||
self.assertEqual(
|
||||
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):
|
||||
cloud_region = (openstack.config.OpenStackConfig().
|
||||
get_one("sample-cloud"))
|
||||
cloud_region = openstack.config.OpenStackConfig().get_one(
|
||||
"sample-cloud"
|
||||
)
|
||||
|
||||
sot = connection.from_config(cloud_config=cloud_region)
|
||||
|
||||
self.assertEqual(CONFIG_USERNAME,
|
||||
sot.config.config['auth']['username'])
|
||||
self.assertEqual(CONFIG_PASSWORD,
|
||||
sot.config.config['auth']['password'])
|
||||
self.assertEqual(CONFIG_AUTH_URL,
|
||||
sot.config.config['auth']['auth_url'])
|
||||
self.assertEqual(CONFIG_PROJECT,
|
||||
sot.config.config['auth']['project_name'])
|
||||
self.assertEqual(
|
||||
CONFIG_USERNAME, sot.config.config['auth']['username']
|
||||
)
|
||||
self.assertEqual(
|
||||
CONFIG_PASSWORD, sot.config.config['auth']['password']
|
||||
)
|
||||
self.assertEqual(
|
||||
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):
|
||||
sot = connection.from_config(cloud_name="sample-cloud")
|
||||
|
||||
self.assertEqual(CONFIG_USERNAME,
|
||||
sot.config.config['auth']['username'])
|
||||
self.assertEqual(CONFIG_PASSWORD,
|
||||
sot.config.config['auth']['password'])
|
||||
self.assertEqual(CONFIG_AUTH_URL,
|
||||
sot.config.config['auth']['auth_url'])
|
||||
self.assertEqual(CONFIG_PROJECT,
|
||||
sot.config.config['auth']['project_name'])
|
||||
self.assertEqual(
|
||||
CONFIG_USERNAME, sot.config.config['auth']['username']
|
||||
)
|
||||
self.assertEqual(
|
||||
CONFIG_PASSWORD, sot.config.config['auth']['password']
|
||||
)
|
||||
self.assertEqual(
|
||||
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):
|
||||
sot = connection.from_config(cloud="insecure-cloud")
|
||||
@ -268,25 +299,32 @@ class TestOsloConfig(_TestConnectionBase):
|
||||
def test_from_conf(self):
|
||||
c1 = connection.Connection(cloud='sample-cloud')
|
||||
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
|
||||
self.assertIsInstance(
|
||||
conn.identity, service_description._ServiceDisabledProxyShim)
|
||||
conn.identity, service_description._ServiceDisabledProxyShim
|
||||
)
|
||||
# But nova was in there
|
||||
self.assertEqual('openstack.compute.v2._proxy',
|
||||
conn.compute.__class__.__module__)
|
||||
self.assertEqual(
|
||||
'openstack.compute.v2._proxy', conn.compute.__class__.__module__
|
||||
)
|
||||
|
||||
def test_from_conf_filter_service_types(self):
|
||||
c1 = connection.Connection(cloud='sample-cloud')
|
||||
conn = connection.Connection(
|
||||
session=c1.session, oslo_conf=self._load_ks_cfg_opts(),
|
||||
service_types={'orchestration', 'i-am-ignored'})
|
||||
session=c1.session,
|
||||
oslo_conf=self._load_ks_cfg_opts(),
|
||||
service_types={'orchestration', 'i-am-ignored'},
|
||||
)
|
||||
# There was no config for keystone
|
||||
self.assertIsInstance(
|
||||
conn.identity, service_description._ServiceDisabledProxyShim)
|
||||
conn.identity, service_description._ServiceDisabledProxyShim
|
||||
)
|
||||
# Nova was in there, but disabled because not requested
|
||||
self.assertIsInstance(
|
||||
conn.compute, service_description._ServiceDisabledProxyShim)
|
||||
conn.compute, service_description._ServiceDisabledProxyShim
|
||||
)
|
||||
|
||||
|
||||
class TestNetworkConnection(base.TestCase):
|
||||
@ -298,15 +336,18 @@ class TestNetworkConnection(base.TestCase):
|
||||
svc.add_endpoint(
|
||||
interface='public',
|
||||
url='https://network.example.com/v2.0',
|
||||
region='RegionOne')
|
||||
region='RegionOne',
|
||||
)
|
||||
self.use_keystone_v3()
|
||||
self.assertEqual(
|
||||
'openstack.network.v2._proxy',
|
||||
self.cloud.network.__class__.__module__)
|
||||
self.cloud.network.__class__.__module__,
|
||||
)
|
||||
self.assert_calls()
|
||||
self.assertEqual(
|
||||
"https://network.example.com/v2.0",
|
||||
self.cloud.network.get_endpoint())
|
||||
self.cloud.network.get_endpoint(),
|
||||
)
|
||||
|
||||
|
||||
class TestNetworkConnectionSuffix(base.TestCase):
|
||||
@ -316,15 +357,16 @@ class TestNetworkConnectionSuffix(base.TestCase):
|
||||
def test_network_proxy(self):
|
||||
self.assertEqual(
|
||||
'openstack.network.v2._proxy',
|
||||
self.cloud.network.__class__.__module__)
|
||||
self.cloud.network.__class__.__module__,
|
||||
)
|
||||
self.assert_calls()
|
||||
self.assertEqual(
|
||||
"https://network.example.com/v2.0",
|
||||
self.cloud.network.get_endpoint())
|
||||
self.cloud.network.get_endpoint(),
|
||||
)
|
||||
|
||||
|
||||
class TestAuthorize(base.TestCase):
|
||||
|
||||
def test_authorize_works(self):
|
||||
res = self.cloud.authorize()
|
||||
self.assertEqual('KeystoneToken-1', res)
|
||||
@ -332,12 +374,12 @@ class TestAuthorize(base.TestCase):
|
||||
def test_authorize_failure(self):
|
||||
self.use_broken_keystone()
|
||||
|
||||
self.assertRaises(openstack.exceptions.SDKException,
|
||||
self.cloud.authorize)
|
||||
self.assertRaises(
|
||||
openstack.exceptions.SDKException, self.cloud.authorize
|
||||
)
|
||||
|
||||
|
||||
class TestNewService(base.TestCase):
|
||||
|
||||
def test_add_service_v1(self):
|
||||
svc = self.os_fixture.v3_token.add_service('fake')
|
||||
svc.add_endpoint(
|
||||
@ -355,21 +397,30 @@ class TestNewService(base.TestCase):
|
||||
# Ensure no discovery calls made
|
||||
self.assertEqual(0, len(self.adapter.request_history))
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri='https://fake.example.com',
|
||||
status_code=404),
|
||||
dict(method='GET',
|
||||
uri='https://fake.example.com/v1/',
|
||||
status_code=404),
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url('fake'),
|
||||
status_code=404),
|
||||
])
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://fake.example.com',
|
||||
status_code=404,
|
||||
),
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://fake.example.com/v1/',
|
||||
status_code=404,
|
||||
),
|
||||
dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url('fake'),
|
||||
status_code=404,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
'openstack.tests.unit.fake.v1._proxy',
|
||||
conn.fake.__class__.__module__)
|
||||
conn.fake.__class__.__module__,
|
||||
)
|
||||
self.assertTrue(conn.fake.dummy())
|
||||
|
||||
def test_add_service_v2(self):
|
||||
@ -382,17 +433,25 @@ class TestNewService(base.TestCase):
|
||||
self.use_keystone_v3()
|
||||
conn = self.cloud
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri='https://fake.example.com',
|
||||
status_code=404),
|
||||
dict(method='GET',
|
||||
uri='https://fake.example.com/v2/',
|
||||
status_code=404),
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url('fake'),
|
||||
status_code=404),
|
||||
])
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://fake.example.com',
|
||||
status_code=404,
|
||||
),
|
||||
dict(
|
||||
method='GET',
|
||||
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')
|
||||
|
||||
@ -400,7 +459,8 @@ class TestNewService(base.TestCase):
|
||||
|
||||
self.assertEqual(
|
||||
'openstack.tests.unit.fake.v2._proxy',
|
||||
conn.fake.__class__.__module__)
|
||||
conn.fake.__class__.__module__,
|
||||
)
|
||||
self.assertFalse(conn.fake.dummy())
|
||||
|
||||
def test_replace_system_service(self):
|
||||
@ -416,17 +476,25 @@ class TestNewService(base.TestCase):
|
||||
# delete native dns service
|
||||
delattr(conn, 'dns')
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri='https://fake.example.com',
|
||||
status_code=404),
|
||||
dict(method='GET',
|
||||
uri='https://fake.example.com/v2/',
|
||||
status_code=404),
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url('fake'),
|
||||
status_code=404),
|
||||
])
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri='https://fake.example.com',
|
||||
status_code=404,
|
||||
),
|
||||
dict(
|
||||
method='GET',
|
||||
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'
|
||||
service = fake_service.FakeService('fake', aliases=['dns'])
|
||||
@ -441,7 +509,6 @@ def vendor_hook(conn):
|
||||
|
||||
|
||||
class TestVendorProfile(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestVendorProfile, self).setUp()
|
||||
# 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:
|
||||
conf.write(PUBLIC_CLOUDS_YAML)
|
||||
|
||||
self.useFixture(fixtures.EnvironmentVariable(
|
||||
"OS_CLIENT_CONFIG_FILE", config_path))
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable("OS_CLIENT_CONFIG_FILE", config_path)
|
||||
)
|
||||
self.use_keystone_v2()
|
||||
|
||||
self.config = openstack.config.loader.OpenStackConfig(
|
||||
vendor_files=[public_clouds])
|
||||
vendor_files=[public_clouds]
|
||||
)
|
||||
|
||||
def test_conn_from_profile(self):
|
||||
|
||||
@ -483,7 +552,7 @@ class TestVendorProfile(base.TestCase):
|
||||
|
||||
conn = connection.Connection(
|
||||
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)
|
||||
@ -492,7 +561,7 @@ class TestVendorProfile(base.TestCase):
|
||||
|
||||
conn = connection.Connection(
|
||||
cloud='sample-cloud',
|
||||
vendor_hook='openstack.tests.unit.test_connection:missing'
|
||||
vendor_hook='openstack.tests.unit.test_connection:missing',
|
||||
)
|
||||
|
||||
self.assertIsNotNone(conn)
|
||||
|
@ -23,13 +23,14 @@ from openstack.tests.unit import base
|
||||
class Test_Exception(base.TestCase):
|
||||
def test_method_not_supported(self):
|
||||
exc = exceptions.MethodNotSupported(self.__class__, 'list')
|
||||
expected = ('The list method is not supported for '
|
||||
+ 'openstack.tests.unit.test_exceptions.Test_Exception')
|
||||
expected = (
|
||||
'The list method is not supported for '
|
||||
+ 'openstack.tests.unit.test_exceptions.Test_Exception'
|
||||
)
|
||||
self.assertEqual(expected, str(exc))
|
||||
|
||||
|
||||
class Test_HttpException(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(Test_HttpException, self).setUp()
|
||||
self.message = "mayday"
|
||||
@ -38,32 +39,38 @@ class Test_HttpException(base.TestCase):
|
||||
raise exceptions.HttpException(*args, **kwargs)
|
||||
|
||||
def test_message(self):
|
||||
exc = self.assertRaises(exceptions.HttpException,
|
||||
self._do_raise, self.message)
|
||||
exc = self.assertRaises(
|
||||
exceptions.HttpException, self._do_raise, self.message
|
||||
)
|
||||
|
||||
self.assertEqual(self.message, exc.message)
|
||||
|
||||
def test_details(self):
|
||||
details = "some details"
|
||||
exc = self.assertRaises(exceptions.HttpException,
|
||||
self._do_raise, self.message,
|
||||
details=details)
|
||||
exc = self.assertRaises(
|
||||
exceptions.HttpException,
|
||||
self._do_raise,
|
||||
self.message,
|
||||
details=details,
|
||||
)
|
||||
|
||||
self.assertEqual(self.message, exc.message)
|
||||
self.assertEqual(details, exc.details)
|
||||
|
||||
def test_http_status(self):
|
||||
http_status = 123
|
||||
exc = self.assertRaises(exceptions.HttpException,
|
||||
self._do_raise, self.message,
|
||||
http_status=http_status)
|
||||
exc = self.assertRaises(
|
||||
exceptions.HttpException,
|
||||
self._do_raise,
|
||||
self.message,
|
||||
http_status=http_status,
|
||||
)
|
||||
|
||||
self.assertEqual(self.message, exc.message)
|
||||
self.assertEqual(http_status, exc.status_code)
|
||||
|
||||
|
||||
class TestRaiseFromResponse(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRaiseFromResponse, self).setUp()
|
||||
self.message = "Where is my kitty?"
|
||||
@ -83,14 +90,16 @@ class TestRaiseFromResponse(base.TestCase):
|
||||
'content-type': 'application/json',
|
||||
'x-openstack-request-id': uuid.uuid4().hex,
|
||||
}
|
||||
exc = self.assertRaises(exceptions.NotFoundException,
|
||||
self._do_raise, response,
|
||||
error_message=self.message)
|
||||
exc = self.assertRaises(
|
||||
exceptions.NotFoundException,
|
||||
self._do_raise,
|
||||
response,
|
||||
error_message=self.message,
|
||||
)
|
||||
self.assertEqual(self.message, exc.message)
|
||||
self.assertEqual(response.status_code, exc.status_code)
|
||||
self.assertEqual(
|
||||
response.headers.get('x-openstack-request-id'),
|
||||
exc.request_id
|
||||
response.headers.get('x-openstack-request-id'), exc.request_id
|
||||
)
|
||||
|
||||
def test_raise_bad_request_exception(self):
|
||||
@ -100,14 +109,16 @@ class TestRaiseFromResponse(base.TestCase):
|
||||
'content-type': 'application/json',
|
||||
'x-openstack-request-id': uuid.uuid4().hex,
|
||||
}
|
||||
exc = self.assertRaises(exceptions.BadRequestException,
|
||||
self._do_raise, response,
|
||||
error_message=self.message)
|
||||
exc = self.assertRaises(
|
||||
exceptions.BadRequestException,
|
||||
self._do_raise,
|
||||
response,
|
||||
error_message=self.message,
|
||||
)
|
||||
self.assertEqual(self.message, exc.message)
|
||||
self.assertEqual(response.status_code, exc.status_code)
|
||||
self.assertEqual(
|
||||
response.headers.get('x-openstack-request-id'),
|
||||
exc.request_id
|
||||
response.headers.get('x-openstack-request-id'), exc.request_id
|
||||
)
|
||||
|
||||
def test_raise_http_exception(self):
|
||||
@ -117,14 +128,16 @@ class TestRaiseFromResponse(base.TestCase):
|
||||
'content-type': 'application/json',
|
||||
'x-openstack-request-id': uuid.uuid4().hex,
|
||||
}
|
||||
exc = self.assertRaises(exceptions.HttpException,
|
||||
self._do_raise, response,
|
||||
error_message=self.message)
|
||||
exc = self.assertRaises(
|
||||
exceptions.HttpException,
|
||||
self._do_raise,
|
||||
response,
|
||||
error_message=self.message,
|
||||
)
|
||||
self.assertEqual(self.message, exc.message)
|
||||
self.assertEqual(response.status_code, exc.status_code)
|
||||
self.assertEqual(
|
||||
response.headers.get('x-openstack-request-id'),
|
||||
exc.request_id
|
||||
response.headers.get('x-openstack-request-id'), exc.request_id
|
||||
)
|
||||
|
||||
def test_raise_compute_format(self):
|
||||
@ -139,9 +152,12 @@ class TestRaiseFromResponse(base.TestCase):
|
||||
'code': 404,
|
||||
}
|
||||
}
|
||||
exc = self.assertRaises(exceptions.NotFoundException,
|
||||
self._do_raise, response,
|
||||
error_message=self.message)
|
||||
exc = self.assertRaises(
|
||||
exceptions.NotFoundException,
|
||||
self._do_raise,
|
||||
response,
|
||||
error_message=self.message,
|
||||
)
|
||||
self.assertEqual(response.status_code, exc.status_code)
|
||||
self.assertEqual(self.message, exc.details)
|
||||
self.assertIn(self.message, str(exc))
|
||||
@ -159,9 +175,12 @@ class TestRaiseFromResponse(base.TestCase):
|
||||
'detail': '',
|
||||
}
|
||||
}
|
||||
exc = self.assertRaises(exceptions.NotFoundException,
|
||||
self._do_raise, response,
|
||||
error_message=self.message)
|
||||
exc = self.assertRaises(
|
||||
exceptions.NotFoundException,
|
||||
self._do_raise,
|
||||
response,
|
||||
error_message=self.message,
|
||||
)
|
||||
self.assertEqual(response.status_code, exc.status_code)
|
||||
self.assertEqual(self.message, exc.details)
|
||||
self.assertIn(self.message, str(exc))
|
||||
@ -173,15 +192,20 @@ class TestRaiseFromResponse(base.TestCase):
|
||||
'content-type': 'application/json',
|
||||
}
|
||||
response.json.return_value = {
|
||||
'error_message': json.dumps({
|
||||
'faultstring': self.message,
|
||||
'faultcode': 'Client',
|
||||
'debuginfo': None,
|
||||
})
|
||||
'error_message': json.dumps(
|
||||
{
|
||||
'faultstring': self.message,
|
||||
'faultcode': 'Client',
|
||||
'debuginfo': None,
|
||||
}
|
||||
)
|
||||
}
|
||||
exc = self.assertRaises(exceptions.NotFoundException,
|
||||
self._do_raise, response,
|
||||
error_message=self.message)
|
||||
exc = self.assertRaises(
|
||||
exceptions.NotFoundException,
|
||||
self._do_raise,
|
||||
response,
|
||||
error_message=self.message,
|
||||
)
|
||||
self.assertEqual(response.status_code, exc.status_code)
|
||||
self.assertEqual(self.message, exc.details)
|
||||
self.assertIn(self.message, str(exc))
|
||||
@ -199,9 +223,12 @@ class TestRaiseFromResponse(base.TestCase):
|
||||
'debuginfo': None,
|
||||
}
|
||||
}
|
||||
exc = self.assertRaises(exceptions.NotFoundException,
|
||||
self._do_raise, response,
|
||||
error_message=self.message)
|
||||
exc = self.assertRaises(
|
||||
exceptions.NotFoundException,
|
||||
self._do_raise,
|
||||
response,
|
||||
error_message=self.message,
|
||||
)
|
||||
self.assertEqual(response.status_code, exc.status_code)
|
||||
self.assertEqual(self.message, exc.details)
|
||||
self.assertIn(self.message, str(exc))
|
||||
@ -217,9 +244,12 @@ class TestRaiseFromResponse(base.TestCase):
|
||||
'faultcode': 'Client',
|
||||
'debuginfo': None,
|
||||
}
|
||||
exc = self.assertRaises(exceptions.NotFoundException,
|
||||
self._do_raise, response,
|
||||
error_message=self.message)
|
||||
exc = self.assertRaises(
|
||||
exceptions.NotFoundException,
|
||||
self._do_raise,
|
||||
response,
|
||||
error_message=self.message,
|
||||
)
|
||||
self.assertEqual(response.status_code, exc.status_code)
|
||||
self.assertEqual(self.message, exc.details)
|
||||
self.assertIn(self.message, str(exc))
|
||||
|
@ -15,7 +15,6 @@ from openstack.tests.unit import base
|
||||
|
||||
|
||||
class TestBoolStrFormatter(base.TestCase):
|
||||
|
||||
def test_deserialize(self):
|
||||
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
|
||||
should pass.
|
||||
"""
|
||||
|
||||
def test_assert_no_setupclass(self):
|
||||
self.assertEqual(len(list(_hacking.assert_no_setupclass(
|
||||
"def setUpClass(cls)"))), 1)
|
||||
self.assertEqual(
|
||||
len(list(_hacking.assert_no_setupclass("def setUpClass(cls)"))), 1
|
||||
)
|
||||
|
||||
self.assertEqual(len(list(_hacking.assert_no_setupclass(
|
||||
"# setUpClass is evil"))), 0)
|
||||
self.assertEqual(
|
||||
len(list(_hacking.assert_no_setupclass("# setUpClass is evil"))), 0
|
||||
)
|
||||
|
||||
self.assertEqual(len(list(_hacking.assert_no_setupclass(
|
||||
"def setUpClassyDrinkingLocation(cls)"))), 0)
|
||||
self.assertEqual(
|
||||
len(
|
||||
list(
|
||||
_hacking.assert_no_setupclass(
|
||||
"def setUpClassyDrinkingLocation(cls)"
|
||||
)
|
||||
)
|
||||
),
|
||||
0,
|
||||
)
|
||||
|
@ -16,7 +16,6 @@ from openstack.tests.unit import base
|
||||
|
||||
|
||||
class TestMicroversions(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMicroversions, self).setUp()
|
||||
self.use_compute_discovery()
|
||||
@ -27,7 +26,8 @@ class TestMicroversions(base.TestCase):
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ConfigException,
|
||||
self.cloud.get_server, 'doesNotExist',
|
||||
self.cloud.get_server,
|
||||
'doesNotExist',
|
||||
)
|
||||
|
||||
self.assert_calls()
|
||||
@ -38,7 +38,8 @@ class TestMicroversions(base.TestCase):
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ConfigException,
|
||||
self.cloud.get_server, 'doesNotExist',
|
||||
self.cloud.get_server,
|
||||
'doesNotExist',
|
||||
)
|
||||
|
||||
self.assert_calls()
|
||||
@ -49,7 +50,8 @@ class TestMicroversions(base.TestCase):
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ConfigException,
|
||||
self.cloud.get_server, 'doesNotExist',
|
||||
self.cloud.get_server,
|
||||
'doesNotExist',
|
||||
)
|
||||
|
||||
self.assert_calls()
|
||||
@ -60,7 +62,8 @@ class TestMicroversions(base.TestCase):
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ConfigException,
|
||||
self.cloud.get_server, 'doesNotExist',
|
||||
self.cloud.get_server,
|
||||
'doesNotExist',
|
||||
)
|
||||
|
||||
self.assert_calls()
|
||||
@ -72,13 +75,18 @@ class TestMicroversions(base.TestCase):
|
||||
server1 = fakes.make_fake_server('123', 'mickey')
|
||||
server2 = fakes.make_fake_server('345', 'mouse')
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'compute', 'public', append=['servers', 'detail']),
|
||||
request_headers={'OpenStack-API-Version': 'compute 2.42'},
|
||||
json={'servers': [server1, server2]}),
|
||||
])
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'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)
|
||||
self.assertIsNotNone(r)
|
||||
@ -93,13 +101,18 @@ class TestMicroversions(base.TestCase):
|
||||
server1 = fakes.make_fake_server('123', 'mickey')
|
||||
server2 = fakes.make_fake_server('345', 'mouse')
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'compute', 'public', append=['servers', 'detail']),
|
||||
request_headers={'OpenStack-API-Version': 'compute 2.42'},
|
||||
json={'servers': [server1, server2]}),
|
||||
])
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'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)
|
||||
self.assertIsNotNone(r)
|
||||
|
@ -18,18 +18,20 @@ from openstack.tests.unit import base
|
||||
|
||||
|
||||
class TestMissingVersion(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMissingVersion, self).setUp()
|
||||
self.os_fixture.clear_tokens()
|
||||
svc = self.os_fixture.v3_token.add_service('image')
|
||||
svc.add_endpoint(
|
||||
url='https://example.com/image/',
|
||||
region='RegionOne', interface='public')
|
||||
region='RegionOne',
|
||||
interface='public',
|
||||
)
|
||||
self.use_keystone_v3()
|
||||
self.use_glance(
|
||||
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):
|
||||
|
||||
|
@ -20,7 +20,6 @@ from openstack.tests.unit import base
|
||||
|
||||
@ddt.ddt
|
||||
class TestPlacementRest(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestPlacementRest, self).setUp()
|
||||
self.use_placement()
|
||||
@ -29,8 +28,10 @@ class TestPlacementRest(base.TestCase):
|
||||
uri = dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'placement', 'public', append=['allocation_candidates']),
|
||||
json={})
|
||||
'placement', 'public', append=['allocation_candidates']
|
||||
),
|
||||
json={},
|
||||
)
|
||||
if status_code is not None:
|
||||
uri['status_code'] = status_code
|
||||
self.register_uris([uri])
|
||||
@ -38,8 +39,8 @@ class TestPlacementRest(base.TestCase):
|
||||
def _validate_resp(self, resp, status_code):
|
||||
self.assertEqual(status_code, resp.status_code)
|
||||
self.assertEqual(
|
||||
'https://placement.example.com/allocation_candidates',
|
||||
resp.url)
|
||||
'https://placement.example.com/allocation_candidates', resp.url
|
||||
)
|
||||
self.assert_calls()
|
||||
|
||||
@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
|
||||
ex = self.assertRaises(
|
||||
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)
|
||||
|
||||
def test_microversion_discovery(self):
|
||||
self.assertEqual(
|
||||
(1, 17),
|
||||
self.cloud.placement.get_endpoint_data().max_microversion)
|
||||
(1, 17), self.cloud.placement.get_endpoint_data().max_microversion
|
||||
)
|
||||
self.assert_calls()
|
||||
|
||||
|
||||
class TestBadPlacementRest(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.skipTest('Need to re-add support for broken placement versions')
|
||||
super(TestBadPlacementRest, self).setUp()
|
||||
@ -85,8 +88,10 @@ class TestBadPlacementRest(base.TestCase):
|
||||
uri = dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'placement', 'public', append=['allocation_candidates']),
|
||||
json={})
|
||||
'placement', 'public', append=['allocation_candidates']
|
||||
),
|
||||
json={},
|
||||
)
|
||||
if status_code is not None:
|
||||
uri['status_code'] = status_code
|
||||
self.register_uris([uri])
|
||||
@ -94,8 +99,8 @@ class TestBadPlacementRest(base.TestCase):
|
||||
def _validate_resp(self, resp, status_code):
|
||||
self.assertEqual(status_code, resp.status_code)
|
||||
self.assertEqual(
|
||||
'https://placement.example.com/allocation_candidates',
|
||||
resp.url)
|
||||
'https://placement.example.com/allocation_candidates', resp.url
|
||||
)
|
||||
self.assert_calls()
|
||||
|
||||
def test_discovery(self):
|
||||
|
@ -58,7 +58,6 @@ class HeadableResource(resource.Resource):
|
||||
|
||||
|
||||
class TestProxyPrivate(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestProxyPrivate, self).setUp()
|
||||
|
||||
@ -88,9 +87,14 @@ class TestProxyPrivate(base.TestCase):
|
||||
|
||||
def test__check_resource_strict_id(self):
|
||||
decorated = proxy._check_resource(strict=True)(self.sot.method)
|
||||
self.assertRaisesRegex(ValueError, "A Resource must be passed",
|
||||
decorated, self.sot, resource.Resource,
|
||||
"this-is-not-a-resource")
|
||||
self.assertRaisesRegex(
|
||||
ValueError,
|
||||
"A Resource must be passed",
|
||||
decorated,
|
||||
self.sot,
|
||||
resource.Resource,
|
||||
"this-is-not-a-resource",
|
||||
)
|
||||
|
||||
def test__check_resource_incorrect_resource(self):
|
||||
class OneType(resource.Resource):
|
||||
@ -101,9 +105,14 @@ class TestProxyPrivate(base.TestCase):
|
||||
|
||||
value = AnotherType()
|
||||
decorated = proxy._check_resource(strict=False)(self.sot.method)
|
||||
self.assertRaisesRegex(ValueError,
|
||||
"Expected OneType but received AnotherType",
|
||||
decorated, self.sot, OneType, value)
|
||||
self.assertRaisesRegex(
|
||||
ValueError,
|
||||
"Expected OneType but received AnotherType",
|
||||
decorated,
|
||||
self.sot,
|
||||
OneType,
|
||||
value,
|
||||
)
|
||||
|
||||
def test__get_uri_attribute_no_parent(self):
|
||||
class Child(resource.Resource):
|
||||
@ -161,7 +170,8 @@ class TestProxyPrivate(base.TestCase):
|
||||
result = self.fake_proxy._get_resource(Fake, id, **attrs)
|
||||
|
||||
self.assertDictEqual(
|
||||
dict(id=id, connection=mock.ANY, **attrs), Fake.call)
|
||||
dict(id=id, connection=mock.ANY, **attrs), Fake.call
|
||||
)
|
||||
self.assertEqual(value, result)
|
||||
|
||||
def test__get_resource_from_resource(self):
|
||||
@ -170,8 +180,7 @@ class TestProxyPrivate(base.TestCase):
|
||||
|
||||
attrs = {"first": "Brian", "last": "Curtin"}
|
||||
|
||||
result = self.fake_proxy._get_resource(resource.Resource,
|
||||
res, **attrs)
|
||||
result = self.fake_proxy._get_resource(resource.Resource, res, **attrs)
|
||||
|
||||
res._update.assert_called_once_with(**attrs)
|
||||
self.assertEqual(result, res)
|
||||
@ -193,7 +202,6 @@ class TestProxyPrivate(base.TestCase):
|
||||
|
||||
|
||||
class TestProxyDelete(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestProxyDelete, self).setUp()
|
||||
|
||||
@ -215,7 +223,8 @@ class TestProxyDelete(base.TestCase):
|
||||
|
||||
self.sot._delete(DeleteableResource, self.fake_id)
|
||||
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)
|
||||
|
||||
# Delete generally doesn't return anything, so we will normally
|
||||
@ -227,32 +236,42 @@ class TestProxyDelete(base.TestCase):
|
||||
|
||||
def test_delete_ignore_missing(self):
|
||||
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)
|
||||
self.assertIsNone(rv)
|
||||
|
||||
def test_delete_NotFound(self):
|
||||
self.res.delete.side_effect = exceptions.ResourceNotFound(
|
||||
message="test", http_status=404)
|
||||
message="test", http_status=404
|
||||
)
|
||||
|
||||
self.assertRaisesRegex(
|
||||
exceptions.ResourceNotFound,
|
||||
# TODO(shade) The mocks here are hiding the thing we want to test.
|
||||
"test",
|
||||
self.sot._delete, DeleteableResource, self.res,
|
||||
ignore_missing=False)
|
||||
self.sot._delete,
|
||||
DeleteableResource,
|
||||
self.res,
|
||||
ignore_missing=False,
|
||||
)
|
||||
|
||||
def test_delete_HttpException(self):
|
||||
self.res.delete.side_effect = exceptions.HttpException(
|
||||
message="test", http_status=500)
|
||||
message="test", http_status=500
|
||||
)
|
||||
|
||||
self.assertRaises(exceptions.HttpException, self.sot._delete,
|
||||
DeleteableResource, self.res, ignore_missing=False)
|
||||
self.assertRaises(
|
||||
exceptions.HttpException,
|
||||
self.sot._delete,
|
||||
DeleteableResource,
|
||||
self.res,
|
||||
ignore_missing=False,
|
||||
)
|
||||
|
||||
|
||||
class TestProxyUpdate(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestProxyUpdate, self).setUp()
|
||||
|
||||
@ -280,8 +299,9 @@ class TestProxyUpdate(base.TestCase):
|
||||
|
||||
def test_update_resource_override_base_path(self):
|
||||
base_path = 'dummy'
|
||||
rv = self.sot._update(UpdateableResource, self.res,
|
||||
base_path=base_path, **self.attrs)
|
||||
rv = self.sot._update(
|
||||
UpdateableResource, self.res, base_path=base_path, **self.attrs
|
||||
)
|
||||
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
self.res._update.assert_called_once_with(**self.attrs)
|
||||
@ -295,7 +315,6 @@ class TestProxyUpdate(base.TestCase):
|
||||
|
||||
|
||||
class TestProxyCreate(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestProxyCreate, self).setUp()
|
||||
|
||||
@ -317,7 +336,8 @@ class TestProxyCreate(base.TestCase):
|
||||
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
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)
|
||||
|
||||
def test_create_attributes_override_base_path(self):
|
||||
@ -329,12 +349,12 @@ class TestProxyCreate(base.TestCase):
|
||||
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
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)
|
||||
|
||||
|
||||
class TestProxyBulkCreate(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestProxyBulkCreate, self).setUp()
|
||||
|
||||
@ -353,8 +373,9 @@ class TestProxyBulkCreate(base.TestCase):
|
||||
rv = self.sot._bulk_create(self.cls, self.data)
|
||||
|
||||
self.assertEqual(rv, self.result)
|
||||
self.cls.bulk_create.assert_called_once_with(self.sot, self.data,
|
||||
base_path=None)
|
||||
self.cls.bulk_create.assert_called_once_with(
|
||||
self.sot, self.data, base_path=None
|
||||
)
|
||||
|
||||
def test_bulk_create_attributes_override_base_path(self):
|
||||
base_path = 'dummy'
|
||||
@ -362,12 +383,12 @@ class TestProxyBulkCreate(base.TestCase):
|
||||
rv = self.sot._bulk_create(self.cls, self.data, base_path=base_path)
|
||||
|
||||
self.assertEqual(rv, self.result)
|
||||
self.cls.bulk_create.assert_called_once_with(self.sot, self.data,
|
||||
base_path=base_path)
|
||||
self.cls.bulk_create.assert_called_once_with(
|
||||
self.sot, self.data, base_path=base_path
|
||||
)
|
||||
|
||||
|
||||
class TestProxyGet(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestProxyGet, self).setUp()
|
||||
|
||||
@ -389,10 +410,12 @@ class TestProxyGet(base.TestCase):
|
||||
rv = self.sot._get(RetrieveableResource, self.res)
|
||||
|
||||
self.res.fetch.assert_called_with(
|
||||
self.sot, requires_id=True,
|
||||
self.sot,
|
||||
requires_id=True,
|
||||
base_path=None,
|
||||
skip_cache=mock.ANY,
|
||||
error_message=mock.ANY)
|
||||
error_message=mock.ANY,
|
||||
)
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
|
||||
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.fetch.assert_called_with(
|
||||
self.sot, requires_id=True, base_path=None,
|
||||
self.sot,
|
||||
requires_id=True,
|
||||
base_path=None,
|
||||
skip_cache=mock.ANY,
|
||||
error_message=mock.ANY)
|
||||
error_message=mock.ANY,
|
||||
)
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
|
||||
def test_get_id(self):
|
||||
rv = self.sot._get(RetrieveableResource, self.fake_id)
|
||||
|
||||
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.sot, requires_id=True, base_path=None,
|
||||
self.sot,
|
||||
requires_id=True,
|
||||
base_path=None,
|
||||
skip_cache=mock.ANY,
|
||||
error_message=mock.ANY)
|
||||
error_message=mock.ANY,
|
||||
)
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
|
||||
def test_get_base_path(self):
|
||||
base_path = 'dummy'
|
||||
rv = self.sot._get(RetrieveableResource, self.fake_id,
|
||||
base_path=base_path)
|
||||
rv = self.sot._get(
|
||||
RetrieveableResource, self.fake_id, base_path=base_path
|
||||
)
|
||||
|
||||
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.sot, requires_id=True, base_path=base_path,
|
||||
self.sot,
|
||||
requires_id=True,
|
||||
base_path=base_path,
|
||||
skip_cache=mock.ANY,
|
||||
error_message=mock.ANY)
|
||||
error_message=mock.ANY,
|
||||
)
|
||||
self.assertEqual(rv, self.fake_result)
|
||||
|
||||
def test_get_not_found(self):
|
||||
self.res.fetch.side_effect = exceptions.ResourceNotFound(
|
||||
message="test", http_status=404)
|
||||
message="test", http_status=404
|
||||
)
|
||||
|
||||
self.assertRaisesRegex(
|
||||
exceptions.ResourceNotFound,
|
||||
"test", self.sot._get, RetrieveableResource, self.res)
|
||||
"test",
|
||||
self.sot._get,
|
||||
RetrieveableResource,
|
||||
self.res,
|
||||
)
|
||||
|
||||
|
||||
class TestProxyList(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestProxyList, self).setUp()
|
||||
|
||||
@ -455,12 +494,17 @@ class TestProxyList(base.TestCase):
|
||||
ListableResource.list.return_value = self.fake_response
|
||||
|
||||
def _test_list(self, paginated, base_path=None):
|
||||
rv = self.sot._list(ListableResource, paginated=paginated,
|
||||
base_path=base_path, **self.args)
|
||||
rv = self.sot._list(
|
||||
ListableResource,
|
||||
paginated=paginated,
|
||||
base_path=base_path,
|
||||
**self.args,
|
||||
)
|
||||
|
||||
self.assertEqual(self.fake_response, rv)
|
||||
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):
|
||||
self._test_list(True)
|
||||
@ -481,21 +525,24 @@ class TestProxyList(base.TestCase):
|
||||
FilterableResource.list.return_value = fake_response
|
||||
|
||||
rv = self.sot._list(
|
||||
FilterableResource, paginated=False,
|
||||
base_path=None, jmespath_filters="[?c=='c']"
|
||||
FilterableResource,
|
||||
paginated=False,
|
||||
base_path=None,
|
||||
jmespath_filters="[?c=='c']",
|
||||
)
|
||||
self.assertEqual(3, len(rv))
|
||||
|
||||
# Test filtering based on unknown attribute
|
||||
rv = self.sot._list(
|
||||
FilterableResource, paginated=False,
|
||||
base_path=None, jmespath_filters="[?d=='c']"
|
||||
FilterableResource,
|
||||
paginated=False,
|
||||
base_path=None,
|
||||
jmespath_filters="[?d=='c']",
|
||||
)
|
||||
self.assertEqual(0, len(rv))
|
||||
|
||||
|
||||
class TestProxyHead(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestProxyHead, self).setUp()
|
||||
|
||||
@ -530,7 +577,8 @@ class TestProxyHead(base.TestCase):
|
||||
rv = self.sot._head(HeadableResource, self.fake_id)
|
||||
|
||||
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.assertEqual(rv, self.fake_result)
|
||||
|
||||
@ -546,10 +594,14 @@ class TestExtractName(base.TestCase):
|
||||
('networks_arg', dict(url='/v2.0/networks/1', parts=['network'])),
|
||||
('tokens', dict(url='/v3/tokens', parts=['tokens'])),
|
||||
('discovery', dict(url='/', parts=['discovery'])),
|
||||
('secgroups', dict(
|
||||
url='/servers/1/os-security-groups',
|
||||
parts=['server', 'os-security-groups'])),
|
||||
('bm_chassis', dict(url='/v1/chassis/id', parts=['chassis']))
|
||||
(
|
||||
'secgroups',
|
||||
dict(
|
||||
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):
|
||||
@ -559,7 +611,6 @@ class TestExtractName(base.TestCase):
|
||||
|
||||
|
||||
class TestProxyCache(base.TestCase):
|
||||
|
||||
class Res(resource.Resource):
|
||||
base_path = 'fake'
|
||||
|
||||
@ -570,7 +621,8 @@ class TestProxyCache(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestProxyCache, self).setUp(
|
||||
cloud_config_fixture='clouds_cache.yaml')
|
||||
cloud_config_fixture='clouds_cache.yaml'
|
||||
)
|
||||
|
||||
self.session = mock.Mock()
|
||||
self.session._sdk_connection = self.cloud
|
||||
@ -581,19 +633,15 @@ class TestProxyCache(base.TestCase):
|
||||
self.response.history = []
|
||||
self.response.headers = {}
|
||||
self.response.body = {}
|
||||
self.response.json = mock.Mock(
|
||||
return_value=self.response.body)
|
||||
self.session.request = mock.Mock(
|
||||
return_value=self.response)
|
||||
self.response.json = mock.Mock(return_value=self.response.body)
|
||||
self.session.request = mock.Mock(return_value=self.response)
|
||||
|
||||
self.sot = proxy.Proxy(self.session)
|
||||
self.sot._connection = self.cloud
|
||||
self.sot.service_type = 'srv'
|
||||
|
||||
def _get_key(self, id):
|
||||
return (
|
||||
f"srv.fake.fake/{id}."
|
||||
"{'microversion': None, 'params': {}}")
|
||||
return f"srv.fake.fake/{id}." "{'microversion': None, 'params': {}}"
|
||||
|
||||
def test_get_not_in_cache(self):
|
||||
self.cloud._cache_expirations['srv.fake'] = 5
|
||||
@ -602,15 +650,15 @@ class TestProxyCache(base.TestCase):
|
||||
self.session.request.assert_called_with(
|
||||
'fake/1',
|
||||
'GET',
|
||||
connect_retries=mock.ANY, raise_exc=mock.ANY,
|
||||
connect_retries=mock.ANY,
|
||||
raise_exc=mock.ANY,
|
||||
global_request_id=mock.ANY,
|
||||
endpoint_filter=mock.ANY,
|
||||
headers=mock.ANY,
|
||||
microversion=mock.ANY, params=mock.ANY
|
||||
microversion=mock.ANY,
|
||||
params=mock.ANY,
|
||||
)
|
||||
self.assertIn(
|
||||
self._get_key(1),
|
||||
self.cloud._api_cache_keys)
|
||||
self.assertIn(self._get_key(1), self.cloud._api_cache_keys)
|
||||
|
||||
def test_get_from_cache(self):
|
||||
key = self._get_key(2)
|
||||
@ -639,9 +687,7 @@ class TestProxyCache(base.TestCase):
|
||||
|
||||
self.session.request.assert_called()
|
||||
self.assertIsNotNone(self.cloud._cache.get(key))
|
||||
self.assertEqual(
|
||||
'NoValue',
|
||||
type(self.cloud._cache.get(key)).__name__)
|
||||
self.assertEqual('NoValue', type(self.cloud._cache.get(key)).__name__)
|
||||
self.assertNotIn(key, self.cloud._api_cache_keys)
|
||||
|
||||
# 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
|
||||
self.assertEqual(dict(), self.response.body)
|
||||
self.assertNotIn(key, self.cloud._api_cache_keys)
|
||||
self.assertEqual(
|
||||
'NoValue',
|
||||
type(self.cloud._cache.get(key)).__name__)
|
||||
self.assertEqual('NoValue', type(self.cloud._cache.get(key)).__name__)
|
||||
|
||||
|
||||
class TestProxyCleanup(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestProxyCleanup, self).setUp()
|
||||
|
||||
@ -693,40 +736,28 @@ class TestProxyCleanup(base.TestCase):
|
||||
def test_filters_evaluation_created_at(self):
|
||||
self.assertTrue(
|
||||
self.sot._service_cleanup_resource_filters_evaluation(
|
||||
self.res,
|
||||
filters={
|
||||
'created_at': '2020-02-03T00:00:00'
|
||||
}
|
||||
self.res, filters={'created_at': '2020-02-03T00:00:00'}
|
||||
)
|
||||
)
|
||||
|
||||
def test_filters_evaluation_created_at_not(self):
|
||||
self.assertFalse(
|
||||
self.sot._service_cleanup_resource_filters_evaluation(
|
||||
self.res,
|
||||
filters={
|
||||
'created_at': '2020-01-01T00:00:00'
|
||||
}
|
||||
self.res, filters={'created_at': '2020-01-01T00:00:00'}
|
||||
)
|
||||
)
|
||||
|
||||
def test_filters_evaluation_updated_at(self):
|
||||
self.assertTrue(
|
||||
self.sot._service_cleanup_resource_filters_evaluation(
|
||||
self.res,
|
||||
filters={
|
||||
'updated_at': '2020-02-03T00:00:00'
|
||||
}
|
||||
self.res, filters={'updated_at': '2020-02-03T00:00:00'}
|
||||
)
|
||||
)
|
||||
|
||||
def test_filters_evaluation_updated_at_not(self):
|
||||
self.assertFalse(
|
||||
self.sot._service_cleanup_resource_filters_evaluation(
|
||||
self.res,
|
||||
filters={
|
||||
'updated_at': '2020-01-01T00:00:00'
|
||||
}
|
||||
self.res, filters={'updated_at': '2020-01-01T00:00:00'}
|
||||
)
|
||||
)
|
||||
|
||||
@ -734,9 +765,7 @@ class TestProxyCleanup(base.TestCase):
|
||||
self.assertFalse(
|
||||
self.sot._service_cleanup_resource_filters_evaluation(
|
||||
self.res_no_updated,
|
||||
filters={
|
||||
'updated_at': '2020-01-01T00:00:00'
|
||||
}
|
||||
filters={'updated_at': '2020-01-01T00:00:00'},
|
||||
)
|
||||
)
|
||||
|
||||
@ -750,19 +779,14 @@ class TestProxyCleanup(base.TestCase):
|
||||
def test_service_cleanup_dry_run(self):
|
||||
self.assertTrue(
|
||||
self.sot._service_cleanup_del_res(
|
||||
self.delete_mock,
|
||||
self.res,
|
||||
dry_run=True
|
||||
self.delete_mock, self.res, dry_run=True
|
||||
)
|
||||
)
|
||||
self.delete_mock.assert_not_called()
|
||||
|
||||
def test_service_cleanup_dry_run_default(self):
|
||||
self.assertTrue(
|
||||
self.sot._service_cleanup_del_res(
|
||||
self.delete_mock,
|
||||
self.res
|
||||
)
|
||||
self.sot._service_cleanup_del_res(self.delete_mock, self.res)
|
||||
)
|
||||
self.delete_mock.assert_not_called()
|
||||
|
||||
@ -783,7 +807,7 @@ class TestProxyCleanup(base.TestCase):
|
||||
self.delete_mock,
|
||||
self.res,
|
||||
dry_run=False,
|
||||
identified_resources=rd
|
||||
identified_resources=rd,
|
||||
)
|
||||
)
|
||||
self.delete_mock.assert_called_with(self.res)
|
||||
@ -795,7 +819,7 @@ class TestProxyCleanup(base.TestCase):
|
||||
self.delete_mock,
|
||||
self.res,
|
||||
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()
|
||||
@ -806,7 +830,7 @@ class TestProxyCleanup(base.TestCase):
|
||||
self.delete_mock,
|
||||
self.res,
|
||||
dry_run=False,
|
||||
resource_evaluation_fn=lambda x, y, z: True
|
||||
resource_evaluation_fn=lambda x, y, z: True,
|
||||
)
|
||||
)
|
||||
self.delete_mock.assert_called()
|
||||
@ -818,7 +842,7 @@ class TestProxyCleanup(base.TestCase):
|
||||
self.res,
|
||||
dry_run=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.res,
|
||||
dry_run=False,
|
||||
filters={'created_at': '2200-01-01'}
|
||||
filters={'created_at': '2200-01-01'},
|
||||
)
|
||||
)
|
||||
self.delete_mock.assert_called()
|
||||
@ -841,7 +865,7 @@ class TestProxyCleanup(base.TestCase):
|
||||
self.res,
|
||||
dry_run=False,
|
||||
client_status_queue=q,
|
||||
filters={'created_at': '2200-01-01'}
|
||||
filters={'created_at': '2200-01-01'},
|
||||
)
|
||||
)
|
||||
self.assertEqual(self.res, q.get_nowait())
|
||||
|
@ -21,18 +21,27 @@ class TestProxyBase(base.TestCase):
|
||||
self.session = mock.Mock()
|
||||
|
||||
def _verify(
|
||||
self, mock_method, test_method, *,
|
||||
method_args=None, method_kwargs=None, method_result=None,
|
||||
expected_args=None, expected_kwargs=None, expected_result=None,
|
||||
self,
|
||||
mock_method,
|
||||
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:
|
||||
mocked.return_value = expected_result
|
||||
if any([
|
||||
method_args,
|
||||
method_kwargs,
|
||||
expected_args,
|
||||
expected_kwargs,
|
||||
]):
|
||||
if any(
|
||||
[
|
||||
method_args,
|
||||
method_kwargs,
|
||||
expected_args,
|
||||
expected_kwargs,
|
||||
]
|
||||
):
|
||||
method_args = method_args or ()
|
||||
method_kwargs = method_kwargs or {}
|
||||
expected_args = expected_args or ()
|
||||
@ -77,9 +86,16 @@ class TestProxyBase(base.TestCase):
|
||||
mocked.assert_called_with(test_method.__self__)
|
||||
|
||||
def verify_create(
|
||||
self, test_method, resource_type, base_path=None, *,
|
||||
method_args=None, method_kwargs=None,
|
||||
expected_args=None, expected_kwargs=None, expected_result="result",
|
||||
self,
|
||||
test_method,
|
||||
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",
|
||||
):
|
||||
if method_args is None:
|
||||
@ -103,9 +119,15 @@ class TestProxyBase(base.TestCase):
|
||||
)
|
||||
|
||||
def verify_delete(
|
||||
self, test_method, resource_type, ignore_missing=True, *,
|
||||
method_args=None, method_kwargs=None,
|
||||
expected_args=None, expected_kwargs=None,
|
||||
self,
|
||||
test_method,
|
||||
resource_type,
|
||||
ignore_missing=True,
|
||||
*,
|
||||
method_args=None,
|
||||
method_kwargs=None,
|
||||
expected_args=None,
|
||||
expected_kwargs=None,
|
||||
mock_method="openstack.proxy.Proxy._delete",
|
||||
):
|
||||
if method_args is None:
|
||||
@ -128,9 +150,16 @@ class TestProxyBase(base.TestCase):
|
||||
)
|
||||
|
||||
def verify_get(
|
||||
self, test_method, resource_type, requires_id=False, base_path=None, *,
|
||||
method_args=None, method_kwargs=None,
|
||||
expected_args=None, expected_kwargs=None,
|
||||
self,
|
||||
test_method,
|
||||
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",
|
||||
):
|
||||
if method_args is None:
|
||||
@ -156,15 +185,23 @@ class TestProxyBase(base.TestCase):
|
||||
proxy._get_resource = mock.Mock(return_value=res)
|
||||
proxy._get(resource_type)
|
||||
res.fetch.assert_called_once_with(
|
||||
proxy, requires_id=True,
|
||||
proxy,
|
||||
requires_id=True,
|
||||
base_path=None,
|
||||
error_message=mock.ANY,
|
||||
skip_cache=False)
|
||||
skip_cache=False,
|
||||
)
|
||||
|
||||
def verify_head(
|
||||
self, test_method, resource_type, base_path=None, *,
|
||||
method_args=None, method_kwargs=None,
|
||||
expected_args=None, expected_kwargs=None,
|
||||
self,
|
||||
test_method,
|
||||
resource_type,
|
||||
base_path=None,
|
||||
*,
|
||||
method_args=None,
|
||||
method_kwargs=None,
|
||||
expected_args=None,
|
||||
expected_kwargs=None,
|
||||
mock_method="openstack.proxy.Proxy._head",
|
||||
):
|
||||
if method_args is None:
|
||||
@ -184,10 +221,16 @@ class TestProxyBase(base.TestCase):
|
||||
)
|
||||
|
||||
def verify_find(
|
||||
self, test_method, resource_type, name_or_id='resource_name',
|
||||
ignore_missing=True, *,
|
||||
method_args=None, method_kwargs=None,
|
||||
expected_args=None, expected_kwargs=None,
|
||||
self,
|
||||
test_method,
|
||||
resource_type,
|
||||
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",
|
||||
):
|
||||
method_args = [name_or_id] + (method_args or [])
|
||||
@ -206,9 +249,16 @@ class TestProxyBase(base.TestCase):
|
||||
)
|
||||
|
||||
def verify_list(
|
||||
self, test_method, resource_type, paginated=None, base_path=None, *,
|
||||
method_args=None, method_kwargs=None,
|
||||
expected_args=None, expected_kwargs=None,
|
||||
self,
|
||||
test_method,
|
||||
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",
|
||||
):
|
||||
if method_args is None:
|
||||
@ -234,9 +284,16 @@ class TestProxyBase(base.TestCase):
|
||||
)
|
||||
|
||||
def verify_update(
|
||||
self, test_method, resource_type, base_path=None, *,
|
||||
method_args=None, method_kwargs=None,
|
||||
expected_args=None, expected_kwargs=None, expected_result="result",
|
||||
self,
|
||||
test_method,
|
||||
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",
|
||||
):
|
||||
if method_args is None:
|
||||
@ -259,7 +316,8 @@ class TestProxyBase(base.TestCase):
|
||||
)
|
||||
|
||||
def verify_wait_for_status(
|
||||
self, test_method,
|
||||
self,
|
||||
test_method,
|
||||
mock_method="openstack.resource.wait_for_status",
|
||||
**kwargs,
|
||||
):
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -66,16 +66,17 @@ class StatsdFixture(fixtures.Fixture):
|
||||
|
||||
|
||||
class TestStats(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.statsd = StatsdFixture()
|
||||
self.useFixture(self.statsd)
|
||||
# note, use 127.0.0.1 rather than localhost to avoid getting ipv6
|
||||
# see: https://github.com/jsocol/pystatsd/issues/61
|
||||
self.useFixture(
|
||||
fixtures.EnvironmentVariable('STATSD_HOST', '127.0.0.1'))
|
||||
fixtures.EnvironmentVariable('STATSD_HOST', '127.0.0.1')
|
||||
)
|
||||
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)
|
||||
# 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)
|
||||
self.addDetail(
|
||||
'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):
|
||||
"""Check statsd output
|
||||
@ -127,7 +129,8 @@ class TestStats(base.TestCase):
|
||||
# newlines; thus we first flatten the stats out into
|
||||
# single entries.
|
||||
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:
|
||||
k, v = stat.split(':')
|
||||
if key == k:
|
||||
@ -166,127 +169,184 @@ class TestStats(base.TestCase):
|
||||
def test_list_projects(self):
|
||||
|
||||
mock_uri = self.get_mock_url(
|
||||
service_type='identity', resource='projects',
|
||||
base_url_append='v3')
|
||||
service_type='identity', resource='projects', base_url_append='v3'
|
||||
)
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET', uri=mock_uri, status_code=200,
|
||||
json={'projects': []})])
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri=mock_uri,
|
||||
status_code=200,
|
||||
json={'projects': []},
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
self.cloud.list_projects()
|
||||
self.assert_calls()
|
||||
|
||||
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(
|
||||
'openstack_http_requests_total', 1, dict(
|
||||
'openstack_http_requests_total',
|
||||
1,
|
||||
dict(
|
||||
service_type='identity',
|
||||
endpoint=mock_uri,
|
||||
method='GET',
|
||||
status_code='200'))
|
||||
status_code='200',
|
||||
),
|
||||
)
|
||||
|
||||
def test_projects(self):
|
||||
mock_uri = self.get_mock_url(
|
||||
service_type='identity', resource='projects',
|
||||
base_url_append='v3')
|
||||
service_type='identity', resource='projects', base_url_append='v3'
|
||||
)
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET', uri=mock_uri, status_code=200,
|
||||
json={'projects': []})])
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri=mock_uri,
|
||||
status_code=200,
|
||||
json={'projects': []},
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
list(self.cloud.identity.projects())
|
||||
self.assert_calls()
|
||||
|
||||
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(
|
||||
'openstack_http_requests_total', 1, dict(
|
||||
'openstack_http_requests_total',
|
||||
1,
|
||||
dict(
|
||||
service_type='identity',
|
||||
endpoint=mock_uri,
|
||||
method='GET',
|
||||
status_code='200'))
|
||||
status_code='200',
|
||||
),
|
||||
)
|
||||
|
||||
def test_servers(self):
|
||||
|
||||
mock_uri = 'https://compute.example.com/v2.1/servers/detail'
|
||||
|
||||
self.register_uris([
|
||||
self.get_nova_discovery_mock_dict(),
|
||||
dict(method='GET', uri=mock_uri, status_code=200,
|
||||
json={'servers': []})])
|
||||
self.register_uris(
|
||||
[
|
||||
self.get_nova_discovery_mock_dict(),
|
||||
dict(
|
||||
method='GET',
|
||||
uri=mock_uri,
|
||||
status_code=200,
|
||||
json={'servers': []},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
list(self.cloud.compute.servers())
|
||||
self.assert_calls()
|
||||
|
||||
self.assert_reported_stat(
|
||||
'openstack.api.compute.GET.servers_detail.200',
|
||||
value='1', kind='c')
|
||||
'openstack.api.compute.GET.servers_detail.200', value='1', kind='c'
|
||||
)
|
||||
self.assert_reported_stat(
|
||||
'openstack.api.compute.GET.servers_detail.200',
|
||||
value='0', kind='ms')
|
||||
value='0',
|
||||
kind='ms',
|
||||
)
|
||||
self.assert_prometheus_stat(
|
||||
'openstack_http_requests_total', 1, dict(
|
||||
'openstack_http_requests_total',
|
||||
1,
|
||||
dict(
|
||||
service_type='compute',
|
||||
endpoint=mock_uri,
|
||||
method='GET',
|
||||
status_code='200'))
|
||||
status_code='200',
|
||||
),
|
||||
)
|
||||
|
||||
def test_servers_no_detail(self):
|
||||
|
||||
mock_uri = 'https://compute.example.com/v2.1/servers'
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET', uri=mock_uri, status_code=200,
|
||||
json={'servers': []})])
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri=mock_uri,
|
||||
status_code=200,
|
||||
json={'servers': []},
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
self.cloud.compute.get('/servers')
|
||||
self.assert_calls()
|
||||
|
||||
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(
|
||||
'openstack.api.compute.GET.servers.200', value='0', kind='ms')
|
||||
'openstack.api.compute.GET.servers.200', value='0', kind='ms'
|
||||
)
|
||||
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(
|
||||
'openstack_http_requests_total', 1, dict(
|
||||
'openstack_http_requests_total',
|
||||
1,
|
||||
dict(
|
||||
service_type='compute',
|
||||
endpoint=mock_uri,
|
||||
method='GET',
|
||||
status_code='200'))
|
||||
status_code='200',
|
||||
),
|
||||
)
|
||||
|
||||
def test_servers_error(self):
|
||||
|
||||
mock_uri = 'https://compute.example.com/v2.1/servers'
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET', uri=mock_uri, status_code=500,
|
||||
json={})])
|
||||
self.register_uris(
|
||||
[dict(method='GET', uri=mock_uri, status_code=500, json={})]
|
||||
)
|
||||
|
||||
self.cloud.compute.get('/servers')
|
||||
self.assert_calls()
|
||||
|
||||
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(
|
||||
'openstack.api.compute.GET.servers.500', value='0', kind='ms')
|
||||
'openstack.api.compute.GET.servers.500', value='0', kind='ms'
|
||||
)
|
||||
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(
|
||||
'openstack_http_requests_total', 1, dict(
|
||||
'openstack_http_requests_total',
|
||||
1,
|
||||
dict(
|
||||
service_type='compute',
|
||||
endpoint=mock_uri,
|
||||
method='GET',
|
||||
status_code='500'))
|
||||
status_code='500',
|
||||
),
|
||||
)
|
||||
|
||||
def test_timeout(self):
|
||||
|
||||
mock_uri = 'https://compute.example.com/v2.1/servers'
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET', uri=mock_uri,
|
||||
exc=rexceptions.ConnectTimeout)
|
||||
])
|
||||
self.register_uris(
|
||||
[dict(method='GET', uri=mock_uri, exc=rexceptions.ConnectTimeout)]
|
||||
)
|
||||
|
||||
try:
|
||||
self.cloud.compute.get('/servers')
|
||||
@ -294,13 +354,14 @@ class TestStats(base.TestCase):
|
||||
pass
|
||||
|
||||
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(
|
||||
'openstack.api.compute.GET.servers.attempted', value='1', kind='c')
|
||||
'openstack.api.compute.GET.servers.attempted', value='1', kind='c'
|
||||
)
|
||||
|
||||
|
||||
class TestNoStats(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestNoStats, self).setUp()
|
||||
self.statsd = StatsdFixture()
|
||||
@ -309,12 +370,19 @@ class TestNoStats(base.TestCase):
|
||||
def test_no_stats(self):
|
||||
|
||||
mock_uri = self.get_mock_url(
|
||||
service_type='identity', resource='projects',
|
||||
base_url_append='v3')
|
||||
service_type='identity', resource='projects', base_url_append='v3'
|
||||
)
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET', uri=mock_uri, status_code=200,
|
||||
json={'projects': []})])
|
||||
self.register_uris(
|
||||
[
|
||||
dict(
|
||||
method='GET',
|
||||
uri=mock_uri,
|
||||
status_code=200,
|
||||
json={'projects': []},
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
self.cloud.identity._statsd_client = None
|
||||
list(self.cloud.identity.projects())
|
||||
|
@ -29,7 +29,6 @@ from openstack import utils
|
||||
|
||||
|
||||
class Test_enable_logging(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(Test_enable_logging, self).setUp()
|
||||
self.openstack_logger = mock.Mock()
|
||||
@ -54,10 +53,11 @@ class Test_enable_logging(base.TestCase):
|
||||
self.stevedore_logger,
|
||||
self.ksa_logger_1,
|
||||
self.ksa_logger_2,
|
||||
self.ksa_logger_3
|
||||
self.ksa_logger_3,
|
||||
]
|
||||
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):
|
||||
|
||||
@ -69,7 +69,8 @@ class Test_enable_logging(base.TestCase):
|
||||
def _file_tests(self, level, debug):
|
||||
file_handler = mock.Mock()
|
||||
self.useFixture(
|
||||
fixtures.MonkeyPatch('logging.FileHandler', file_handler))
|
||||
fixtures.MonkeyPatch('logging.FileHandler', file_handler)
|
||||
)
|
||||
fake_path = "fake/path.log"
|
||||
|
||||
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.assertIsInstance(
|
||||
self.openstack_logger.addHandler.call_args_list[0][0][0],
|
||||
logging.StreamHandler)
|
||||
logging.StreamHandler,
|
||||
)
|
||||
|
||||
def test_debug_console_stderr(self):
|
||||
self._console_tests(logging.DEBUG, True, sys.stderr)
|
||||
@ -107,7 +109,6 @@ class Test_enable_logging(base.TestCase):
|
||||
|
||||
|
||||
class Test_urljoin(base.TestCase):
|
||||
|
||||
def test_strings(self):
|
||||
root = "http://www.example.com"
|
||||
leaves = "foo", "bar"
|
||||
@ -138,21 +139,20 @@ class TestSupportsMicroversion(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestSupportsMicroversion, self).setUp()
|
||||
self.adapter = mock.Mock(spec=['get_endpoint_data'])
|
||||
self.endpoint_data = mock.Mock(spec=['min_microversion',
|
||||
'max_microversion'],
|
||||
min_microversion='1.1',
|
||||
max_microversion='1.99')
|
||||
self.endpoint_data = mock.Mock(
|
||||
spec=['min_microversion', 'max_microversion'],
|
||||
min_microversion='1.1',
|
||||
max_microversion='1.99',
|
||||
)
|
||||
self.adapter.get_endpoint_data.return_value = self.endpoint_data
|
||||
|
||||
def test_requested_supported_no_default(self):
|
||||
self.adapter.default_microversion = None
|
||||
self.assertTrue(
|
||||
utils.supports_microversion(self.adapter, '1.2'))
|
||||
self.assertTrue(utils.supports_microversion(self.adapter, '1.2'))
|
||||
|
||||
def test_requested_not_supported_no_default(self):
|
||||
self.adapter.default_microversion = None
|
||||
self.assertFalse(
|
||||
utils.supports_microversion(self.adapter, '2.2'))
|
||||
self.assertFalse(utils.supports_microversion(self.adapter, '2.2'))
|
||||
|
||||
def test_requested_not_supported_no_default_exception(self):
|
||||
self.adapter.default_microversion = None
|
||||
@ -161,22 +161,20 @@ class TestSupportsMicroversion(base.TestCase):
|
||||
utils.supports_microversion,
|
||||
self.adapter,
|
||||
'2.2',
|
||||
True)
|
||||
True,
|
||||
)
|
||||
|
||||
def test_requested_supported_higher_default(self):
|
||||
self.adapter.default_microversion = '1.8'
|
||||
self.assertTrue(
|
||||
utils.supports_microversion(self.adapter, '1.6'))
|
||||
self.assertTrue(utils.supports_microversion(self.adapter, '1.6'))
|
||||
|
||||
def test_requested_supported_equal_default(self):
|
||||
self.adapter.default_microversion = '1.8'
|
||||
self.assertTrue(
|
||||
utils.supports_microversion(self.adapter, '1.8'))
|
||||
self.assertTrue(utils.supports_microversion(self.adapter, '1.8'))
|
||||
|
||||
def test_requested_supported_lower_default(self):
|
||||
self.adapter.default_microversion = '1.2'
|
||||
self.assertFalse(
|
||||
utils.supports_microversion(self.adapter, '1.8'))
|
||||
self.assertFalse(utils.supports_microversion(self.adapter, '1.8'))
|
||||
|
||||
def test_requested_supported_lower_default_exception(self):
|
||||
self.adapter.default_microversion = '1.2'
|
||||
@ -185,54 +183,58 @@ class TestSupportsMicroversion(base.TestCase):
|
||||
utils.supports_microversion,
|
||||
self.adapter,
|
||||
'1.8',
|
||||
True)
|
||||
True,
|
||||
)
|
||||
|
||||
@mock.patch('openstack.utils.supports_microversion')
|
||||
def test_require_microversion(self, sm_mock):
|
||||
utils.require_microversion(self.adapter, '1.2')
|
||||
sm_mock.assert_called_with(self.adapter,
|
||||
'1.2',
|
||||
raise_exception=True)
|
||||
sm_mock.assert_called_with(self.adapter, '1.2', raise_exception=True)
|
||||
|
||||
|
||||
class TestMaximumSupportedMicroversion(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestMaximumSupportedMicroversion, self).setUp()
|
||||
self.adapter = mock.Mock(spec=['get_endpoint_data'])
|
||||
self.endpoint_data = mock.Mock(spec=['min_microversion',
|
||||
'max_microversion'],
|
||||
min_microversion=None,
|
||||
max_microversion='1.99')
|
||||
self.endpoint_data = mock.Mock(
|
||||
spec=['min_microversion', 'max_microversion'],
|
||||
min_microversion=None,
|
||||
max_microversion='1.99',
|
||||
)
|
||||
self.adapter.get_endpoint_data.return_value = self.endpoint_data
|
||||
|
||||
def test_with_none(self):
|
||||
self.assertIsNone(utils.maximum_supported_microversion(self.adapter,
|
||||
None))
|
||||
self.assertIsNone(
|
||||
utils.maximum_supported_microversion(self.adapter, None)
|
||||
)
|
||||
|
||||
def test_with_value(self):
|
||||
self.assertEqual('1.42',
|
||||
utils.maximum_supported_microversion(self.adapter,
|
||||
'1.42'))
|
||||
self.assertEqual(
|
||||
'1.42', utils.maximum_supported_microversion(self.adapter, '1.42')
|
||||
)
|
||||
|
||||
def test_value_more_than_max(self):
|
||||
self.assertEqual('1.99',
|
||||
utils.maximum_supported_microversion(self.adapter,
|
||||
'1.100'))
|
||||
self.assertEqual(
|
||||
'1.99', utils.maximum_supported_microversion(self.adapter, '1.100')
|
||||
)
|
||||
|
||||
def test_value_less_than_min(self):
|
||||
self.endpoint_data.min_microversion = '1.42'
|
||||
self.assertIsNone(utils.maximum_supported_microversion(self.adapter,
|
||||
'1.2'))
|
||||
self.assertIsNone(
|
||||
utils.maximum_supported_microversion(self.adapter, '1.2')
|
||||
)
|
||||
|
||||
|
||||
class TestOsServiceTypesVersion(base.TestCase):
|
||||
def test_ost_version(self):
|
||||
ost_version = '2019-05-01T19:53:21.498745'
|
||||
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 "
|
||||
"os-service-types. Please bump requirements.txt and "
|
||||
"lower-constraints.txt accordingly.")
|
||||
"lower-constraints.txt accordingly.",
|
||||
)
|
||||
|
||||
|
||||
class TestTinyDAG(base.TestCase):
|
||||
@ -243,7 +245,7 @@ class TestTinyDAG(base.TestCase):
|
||||
'd': ['e'],
|
||||
'e': [],
|
||||
'f': ['e'],
|
||||
'g': ['e']
|
||||
'g': ['e'],
|
||||
}
|
||||
|
||||
def _verify_order(self, test_graph, test_list):
|
||||
@ -306,13 +308,13 @@ def test_walker_fn(graph, node, lst):
|
||||
|
||||
|
||||
class Test_md5(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(Test_md5, self).setUp()
|
||||
self.md5_test_data = "Openstack forever".encode('utf-8')
|
||||
try:
|
||||
self.md5_digest = hashlib.md5( # nosec
|
||||
self.md5_test_data).hexdigest()
|
||||
self.md5_test_data
|
||||
).hexdigest()
|
||||
self.fips_enabled = False
|
||||
except ValueError:
|
||||
self.md5_digest = '0d6dc3c588ae71a04ce9a6beebbbba06'
|
||||
@ -327,15 +329,17 @@ class Test_md5(base.TestCase):
|
||||
# [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
|
||||
self.assertRaises(ValueError, utils.md5, self.md5_test_data)
|
||||
if not self.fips_enabled:
|
||||
digest = utils.md5(self.md5_test_data,
|
||||
usedforsecurity=True).hexdigest()
|
||||
digest = utils.md5(
|
||||
self.md5_test_data, usedforsecurity=True
|
||||
).hexdigest()
|
||||
self.assertEqual(digest, self.md5_digest)
|
||||
else:
|
||||
self.assertRaises(
|
||||
ValueError, utils.md5, self.md5_test_data,
|
||||
usedforsecurity=True)
|
||||
digest = utils.md5(self.md5_test_data,
|
||||
usedforsecurity=False).hexdigest()
|
||||
ValueError, utils.md5, self.md5_test_data, usedforsecurity=True
|
||||
)
|
||||
digest = utils.md5(
|
||||
self.md5_test_data, usedforsecurity=False
|
||||
).hexdigest()
|
||||
self.assertEqual(digest, self.md5_digest)
|
||||
|
||||
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, utils.md5, u'foo')
|
||||
self.assertRaises(
|
||||
TypeError, utils.md5, u'foo', usedforsecurity=True)
|
||||
TypeError, utils.md5, u'foo', usedforsecurity=True
|
||||
)
|
||||
else:
|
||||
self.assertRaises(ValueError, hashlib.md5, u'foo')
|
||||
self.assertRaises(ValueError, utils.md5, u'foo')
|
||||
self.assertRaises(
|
||||
ValueError, utils.md5, u'foo', usedforsecurity=True)
|
||||
self.assertRaises(
|
||||
TypeError, utils.md5, u'foo', usedforsecurity=False)
|
||||
ValueError, utils.md5, u'foo', usedforsecurity=True
|
||||
)
|
||||
self.assertRaises(TypeError, utils.md5, u'foo', usedforsecurity=False)
|
||||
|
||||
def test_none_data_raises_type_error(self):
|
||||
if not self.fips_enabled:
|
||||
self.assertRaises(TypeError, hashlib.md5, None)
|
||||
self.assertRaises(TypeError, utils.md5, None)
|
||||
self.assertRaises(
|
||||
TypeError, utils.md5, None, usedforsecurity=True)
|
||||
self.assertRaises(TypeError, utils.md5, None, usedforsecurity=True)
|
||||
else:
|
||||
self.assertRaises(ValueError, hashlib.md5, None)
|
||||
self.assertRaises(ValueError, utils.md5, None)
|
||||
self.assertRaises(
|
||||
ValueError, utils.md5, None, usedforsecurity=True)
|
||||
self.assertRaises(
|
||||
TypeError, utils.md5, None, usedforsecurity=False)
|
||||
ValueError, utils.md5, None, usedforsecurity=True
|
||||
)
|
||||
self.assertRaises(TypeError, utils.md5, None, usedforsecurity=False)
|
||||
|
@ -57,7 +57,8 @@ def iterate_timeout(timeout, message, wait=2):
|
||||
except ValueError:
|
||||
raise exceptions.SDKException(
|
||||
"Wait value must be an int or float value. {wait} given"
|
||||
" instead".format(wait=wait))
|
||||
" instead".format(wait=wait)
|
||||
)
|
||||
|
||||
start = time.time()
|
||||
count = 0
|
||||
@ -76,6 +77,7 @@ def get_string_format_keys(fmt_string, old_style=True):
|
||||
use the old style string formatting.
|
||||
"""
|
||||
if old_style:
|
||||
|
||||
class AccessSaver:
|
||||
def __init__(self):
|
||||
self.keys = []
|
||||
@ -115,25 +117,29 @@ def supports_microversion(adapter, microversion, raise_exception=False):
|
||||
"""
|
||||
|
||||
endpoint_data = adapter.get_endpoint_data()
|
||||
if (endpoint_data.min_microversion
|
||||
and endpoint_data.max_microversion
|
||||
and discover.version_between(
|
||||
endpoint_data.min_microversion,
|
||||
endpoint_data.max_microversion,
|
||||
microversion)):
|
||||
if (
|
||||
endpoint_data.min_microversion
|
||||
and endpoint_data.max_microversion
|
||||
and discover.version_between(
|
||||
endpoint_data.min_microversion,
|
||||
endpoint_data.max_microversion,
|
||||
microversion,
|
||||
)
|
||||
):
|
||||
if adapter.default_microversion is not None:
|
||||
# If default_microversion is set - evaluate
|
||||
# whether it match the expectation
|
||||
candidate = discover.normalize_version_number(
|
||||
adapter.default_microversion)
|
||||
adapter.default_microversion
|
||||
)
|
||||
required = discover.normalize_version_number(microversion)
|
||||
supports = discover.version_match(required, candidate)
|
||||
if raise_exception and not supports:
|
||||
raise exceptions.SDKException(
|
||||
'Required microversion {ver} is higher than currently '
|
||||
'selected {curr}'.format(
|
||||
ver=microversion,
|
||||
curr=adapter.default_microversion)
|
||||
ver=microversion, curr=adapter.default_microversion
|
||||
)
|
||||
)
|
||||
return supports
|
||||
return True
|
||||
@ -175,19 +181,24 @@ def pick_microversion(session, required):
|
||||
|
||||
if session.default_microversion is not None:
|
||||
default = discover.normalize_version_number(
|
||||
session.default_microversion)
|
||||
session.default_microversion
|
||||
)
|
||||
|
||||
if required is None:
|
||||
required = default
|
||||
else:
|
||||
required = (default if discover.version_match(required, default)
|
||||
else required)
|
||||
required = (
|
||||
default
|
||||
if discover.version_match(required, default)
|
||||
else required
|
||||
)
|
||||
|
||||
if required is not None:
|
||||
if not supports_microversion(session, required):
|
||||
raise exceptions.SDKException(
|
||||
'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)
|
||||
|
||||
|
||||
@ -212,8 +223,10 @@ def maximum_supported_microversion(adapter, client_maximum):
|
||||
|
||||
if endpoint_data is None:
|
||||
log = _log.setup_logging('openstack')
|
||||
log.warning('Cannot determine endpoint data for service %s',
|
||||
adapter.service_type or adapter.service_name)
|
||||
log.warning(
|
||||
'Cannot determine endpoint data for service %s',
|
||||
adapter.service_type or adapter.service_name,
|
||||
)
|
||||
return None
|
||||
|
||||
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)
|
||||
server_max = discover.normalize_version_number(
|
||||
endpoint_data.max_microversion)
|
||||
endpoint_data.max_microversion
|
||||
)
|
||||
|
||||
if endpoint_data.min_microversion:
|
||||
server_min = discover.normalize_version_number(
|
||||
endpoint_data.min_microversion)
|
||||
endpoint_data.min_microversion
|
||||
)
|
||||
if client_max < server_min:
|
||||
# NOTE(dtantsur): we may want to raise in this case, but this keeps
|
||||
# the current behavior intact.
|
||||
@ -265,6 +280,7 @@ try:
|
||||
# See https://docs.python.org/3.9/library/hashlib.html
|
||||
md5 = hashlib.md5
|
||||
except TypeError:
|
||||
|
||||
def md5(string=b'', usedforsecurity=True):
|
||||
"""Return an md5 hashlib object without usedforsecurity parameter
|
||||
For python distributions that do not yet support this keyword
|
||||
@ -314,8 +330,7 @@ class TinyDAG:
|
||||
|
||||
@property
|
||||
def graph(self):
|
||||
"""Get graph as adjacency dict
|
||||
"""
|
||||
"""Get graph as adjacency dict"""
|
||||
return self._graph
|
||||
|
||||
def add_node(self, node):
|
||||
@ -332,8 +347,7 @@ class TinyDAG:
|
||||
self.add_edge(k, dep)
|
||||
|
||||
def walk(self, timeout=None):
|
||||
"""Start the walking from the beginning.
|
||||
"""
|
||||
"""Start the walking from the beginning."""
|
||||
if timeout:
|
||||
self._wait_timeout = timeout
|
||||
return self
|
||||
@ -345,17 +359,16 @@ class TinyDAG:
|
||||
def __next__(self):
|
||||
# Start waiting if it is expected to get something
|
||||
# (counting down from graph length to 0).
|
||||
if (self._it_cnt > 0):
|
||||
if self._it_cnt > 0:
|
||||
self._it_cnt -= 1
|
||||
try:
|
||||
res = self._queue.get(
|
||||
block=True,
|
||||
timeout=self._wait_timeout)
|
||||
res = self._queue.get(block=True, timeout=self._wait_timeout)
|
||||
return res
|
||||
|
||||
except queue.Empty:
|
||||
raise exceptions.SDKException('Timeout waiting for '
|
||||
'cleanup task to complete')
|
||||
raise exceptions.SDKException(
|
||||
'Timeout waiting for ' 'cleanup task to complete'
|
||||
)
|
||||
else:
|
||||
raise StopIteration
|
||||
|
||||
@ -410,13 +423,13 @@ class TinyDAG:
|
||||
# it we can have a reduced version.
|
||||
class Munch(dict):
|
||||
"""A slightly stripped version of munch.Munch class"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.update(*args, **kwargs)
|
||||
|
||||
# only called if k not found in normal places
|
||||
def __getattr__(self, k):
|
||||
"""Gets key if it exists, otherwise throws AttributeError.
|
||||
"""
|
||||
"""Gets key if it exists, otherwise throws AttributeError."""
|
||||
try:
|
||||
return object.__getattribute__(self, k)
|
||||
except AttributeError:
|
||||
@ -427,8 +440,8 @@ class Munch(dict):
|
||||
|
||||
def __setattr__(self, k, v):
|
||||
"""Sets attribute k if it exists, otherwise sets key k. A KeyError
|
||||
raised by set-item (only likely if you subclass Munch) will
|
||||
propagate as an AttributeError instead.
|
||||
raised by set-item (only likely if you subclass Munch) will
|
||||
propagate as an AttributeError instead.
|
||||
"""
|
||||
try:
|
||||
# Throws exception if not in prototype chain
|
||||
@ -459,8 +472,7 @@ class Munch(dict):
|
||||
object.__delattr__(self, k)
|
||||
|
||||
def toDict(self):
|
||||
"""Recursively converts a munch back into a dictionary.
|
||||
"""
|
||||
"""Recursively converts a munch back into a dictionary."""
|
||||
return unmunchify(self)
|
||||
|
||||
@property
|
||||
@ -468,7 +480,7 @@ class Munch(dict):
|
||||
return self.toDict()
|
||||
|
||||
def __repr__(self):
|
||||
"""Invertible* string-form of a Munch. """
|
||||
"""Invertible* string-form of a Munch."""
|
||||
return f'{self.__class__.__name__}({dict.__repr__(self)})'
|
||||
|
||||
def __dir__(self):
|
||||
|
@ -197,9 +197,13 @@ htmlhelp_basename = 'shadeReleaseNotesdoc'
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'shadeReleaseNotes.tex',
|
||||
'Shade Release Notes Documentation',
|
||||
'Shade Developers', 'manual'),
|
||||
(
|
||||
'index',
|
||||
'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
|
||||
@ -228,9 +232,13 @@ latex_documents = [
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'shadereleasenotes',
|
||||
'shade Release Notes Documentation',
|
||||
['shade Developers'], 1)
|
||||
(
|
||||
'index',
|
||||
'shadereleasenotes',
|
||||
'shade Release Notes Documentation',
|
||||
['shade Developers'],
|
||||
1,
|
||||
)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
@ -243,11 +251,15 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'shadeReleaseNotes',
|
||||
'shade Release Notes Documentation',
|
||||
'shade Developers', 'shadeReleaseNotes',
|
||||
'A client library for interacting with OpenStack clouds',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
'index',
|
||||
'shadeReleaseNotes',
|
||||
'shade Release Notes Documentation',
|
||||
'shade Developers',
|
||||
'shadeReleaseNotes',
|
||||
'A client library for interacting with OpenStack clouds',
|
||||
'Miscellaneous',
|
||||
),
|
||||
]
|
||||
|
||||
# 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
|
||||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['pbr>=2.0.0'],
|
||||
pbr=True)
|
||||
setuptools.setup(setup_requires=['pbr>=2.0.0'], pbr=True)
|
||||
|
@ -36,8 +36,9 @@ def print_version(version):
|
||||
if version['status'] in ('CURRENT', 'stable'):
|
||||
print(
|
||||
"\tVersion ID: {id} updated {updated}".format(
|
||||
id=version.get('id'),
|
||||
updated=version.get('updated')))
|
||||
id=version.get('id'), updated=version.get('updated')
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
verbose = '-v' in sys.argv
|
||||
@ -71,7 +72,8 @@ for cloud in openstack.config.OpenStackConfig().get_all_clouds():
|
||||
if port:
|
||||
stripped = '{stripped}:{port}'.format(stripped=stripped, port=port)
|
||||
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))
|
||||
try:
|
||||
r = c.get(endpoint).json()
|
||||
|
@ -35,22 +35,27 @@ for cloud in openstack.config.OpenStackConfig().get_all_clouds():
|
||||
have_current = True
|
||||
print(
|
||||
"\tVersion ID: {id} updated {updated}".format(
|
||||
id=version.get('id'),
|
||||
updated=version.get('updated')))
|
||||
id=version.get('id'), updated=version.get('updated')
|
||||
)
|
||||
)
|
||||
print("\tVersion Max: {max}".format(max=version.get('version')))
|
||||
print(
|
||||
"\tVersion Max: {max}".format(max=version.get('version')))
|
||||
print(
|
||||
"\tVersion Min: {min}".format(min=version.get('min_version')))
|
||||
"\tVersion Min: {min}".format(min=version.get('min_version'))
|
||||
)
|
||||
if not have_current:
|
||||
for version in r['versions']:
|
||||
if version['status'] == 'SUPPORTED':
|
||||
have_current = True
|
||||
print(
|
||||
"\tVersion ID: {id} updated {updated}".format(
|
||||
id=version.get('id'),
|
||||
updated=version.get('updated')))
|
||||
id=version.get('id'), updated=version.get('updated')
|
||||
)
|
||||
)
|
||||
print(
|
||||
"\tVersion Max: {max}".format(max=version.get('version')))
|
||||
"\tVersion Max: {max}".format(max=version.get('version'))
|
||||
)
|
||||
print(
|
||||
"\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':
|
||||
base_mod, dm = desc_class.__module__.rsplit('.', 1)
|
||||
imports.append(
|
||||
'from {base_mod} import {dm}'.format(
|
||||
base_mod=base_mod,
|
||||
dm=dm))
|
||||
'from {base_mod} import {dm}'.format(base_mod=base_mod, dm=dm)
|
||||
)
|
||||
else:
|
||||
dm = 'service_description'
|
||||
|
||||
dc = desc_class.__name__
|
||||
services.append(
|
||||
"{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
|
||||
@ -63,9 +63,8 @@ def make_names():
|
||||
if alias_name[-1].isdigit():
|
||||
continue
|
||||
services.append(
|
||||
'{alias_name} = {st}'.format(
|
||||
alias_name=alias_name,
|
||||
st=st))
|
||||
'{alias_name} = {st}'.format(alias_name=alias_name, st=st)
|
||||
)
|
||||
services.append('')
|
||||
print("# Generated file, to change, run tools/print-services.py")
|
||||
for imp in sorted(imports):
|
||||
|
Loading…
Reference in New Issue
Block a user