Blackify openstack.orchestration

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: I77ee83b03379efbec18ba61166fd74ce5ee0e84b
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2023-05-05 11:01:48 +01:00
parent 409f648ce5
commit 874ea74103
22 changed files with 575 additions and 378 deletions

View File

@ -16,13 +16,19 @@ from openstack.orchestration.util import template_format
SECTIONS = ( SECTIONS = (
PARAMETER_DEFAULTS, PARAMETERS, RESOURCE_REGISTRY, PARAMETER_DEFAULTS,
ENCRYPTED_PARAM_NAMES, EVENT_SINKS, PARAMETERS,
PARAMETER_MERGE_STRATEGIES RESOURCE_REGISTRY,
ENCRYPTED_PARAM_NAMES,
EVENT_SINKS,
PARAMETER_MERGE_STRATEGIES,
) = ( ) = (
'parameter_defaults', 'parameters', 'resource_registry', 'parameter_defaults',
'encrypted_param_names', 'event_sinks', 'parameters',
'parameter_merge_strategies' 'resource_registry',
'encrypted_param_names',
'event_sinks',
'parameter_merge_strategies',
) )
@ -47,7 +53,8 @@ def parse(env_str):
env = {} env = {}
elif not isinstance(env, dict): elif not isinstance(env, dict):
raise ValueError( raise ValueError(
'The environment is not a valid YAML mapping data type.') 'The environment is not a valid YAML mapping data type.'
)
for param in env: for param in env:
if param not in SECTIONS: if param not in SECTIONS:

View File

@ -30,8 +30,8 @@ def get_events(cloud, stack_id, event_args, marker=None, limit=None):
event_args['limit'] = limit event_args['limit'] = limit
data = cloud._orchestration_client.get( data = cloud._orchestration_client.get(
'/stacks/{id}/events'.format(id=stack_id), '/stacks/{id}/events'.format(id=stack_id), params=params
params=params) )
events = meta.get_and_munchify('events', data) events = meta.get_and_munchify('events', data)
# Show which stack the event comes from (for nested events) # Show which stack the event comes from (for nested events)
@ -41,7 +41,8 @@ def get_events(cloud, stack_id, event_args, marker=None, limit=None):
def poll_for_events( def poll_for_events(
cloud, stack_name, action=None, poll_period=5, marker=None): cloud, stack_name, action=None, poll_period=5, marker=None
):
"""Continuously poll events and logs for performed action on stack.""" """Continuously poll events and logs for performed action on stack."""
def stop_check_action(a): def stop_check_action(a):
@ -60,20 +61,26 @@ def poll_for_events(
msg_template = "\n Stack %(name)s %(status)s \n" msg_template = "\n Stack %(name)s %(status)s \n"
def is_stack_event(event): def is_stack_event(event):
if (event.get('resource_name', '') != stack_name if (
and event.get('physical_resource_id', '') != stack_name): event.get('resource_name', '') != stack_name
and event.get('physical_resource_id', '') != stack_name
):
return False return False
phys_id = event.get('physical_resource_id', '') phys_id = event.get('physical_resource_id', '')
links = dict((link.get('rel'), links = dict(
link.get('href')) for link in event.get('links', [])) (link.get('rel'), link.get('href'))
for link in event.get('links', [])
)
stack_id = links.get('stack', phys_id).rsplit('/', 1)[-1] stack_id = links.get('stack', phys_id).rsplit('/', 1)[-1]
return stack_id == phys_id return stack_id == phys_id
while True: while True:
events = get_events( events = get_events(
cloud, stack_id=stack_name, cloud,
event_args={'sort_dir': 'asc', 'marker': marker}) stack_id=stack_name,
event_args={'sort_dir': 'asc', 'marker': marker},
)
if len(events) == 0: if len(events) == 0:
no_event_polls += 1 no_event_polls += 1
@ -87,7 +94,8 @@ def poll_for_events(
if is_stack_event(event): if is_stack_event(event):
stack_status = getattr(event, 'resource_status', '') stack_status = getattr(event, 'resource_status', '')
msg = msg_template % dict( msg = msg_template % dict(
name=stack_name, status=stack_status) name=stack_name, status=stack_status
)
if stop_check(stack_status): if stop_check(stack_status):
return stack_status, msg return stack_status, msg
@ -95,8 +103,7 @@ def poll_for_events(
# after 2 polls with no events, fall back to a stack get # after 2 polls with no events, fall back to a stack get
stack = cloud.get_stack(stack_name, resolve_outputs=False) stack = cloud.get_stack(stack_name, resolve_outputs=False)
stack_status = stack['stack_status'] stack_status = stack['stack_status']
msg = msg_template % dict( msg = msg_template % dict(name=stack_name, status=stack_status)
name=stack_name, status=stack_status)
if stop_check(stack_status): if stop_check(stack_status):
return stack_status, msg return stack_status, msg
# go back to event polling again # go back to event polling again

View File

@ -36,7 +36,8 @@ HeatYamlLoader.add_constructor(u'tag:yaml.org,2002:str', _construct_yaml_str)
# openstack.common.jsonutils. Therefore, make unicode string out of timestamps # openstack.common.jsonutils. Therefore, make unicode string out of timestamps
# until jsonutils can handle dates. # until jsonutils can handle dates.
HeatYamlLoader.add_constructor( HeatYamlLoader.add_constructor(
u'tag:yaml.org,2002:timestamp', _construct_yaml_str) u'tag:yaml.org,2002:timestamp', _construct_yaml_str
)
def parse(tmpl_str): def parse(tmpl_str):
@ -64,8 +65,10 @@ def parse(tmpl_str):
if tpl is None: if tpl is None:
tpl = {} tpl = {}
# Looking for supported version keys in the loaded template # Looking for supported version keys in the loaded template
if not ('HeatTemplateFormatVersion' in tpl if not (
or 'heat_template_version' in tpl 'HeatTemplateFormatVersion' in tpl
or 'AWSTemplateFormatVersion' in tpl): or 'heat_template_version' in tpl
or 'AWSTemplateFormatVersion' in tpl
):
raise ValueError("Template format version not found.") raise ValueError("Template format version not found.")
return tpl return tpl

View File

@ -23,9 +23,14 @@ from openstack.orchestration.util import template_format
from openstack.orchestration.util import utils from openstack.orchestration.util import utils
def get_template_contents(template_file=None, template_url=None, def get_template_contents(
template_object=None, object_request=None, template_file=None,
files=None, existing=False): template_url=None,
template_object=None,
object_request=None,
files=None,
existing=False,
):
is_object = False is_object = False
tpl = None tpl = None
@ -46,11 +51,13 @@ def get_template_contents(template_file=None, template_url=None,
else: else:
raise exceptions.SDKException( raise exceptions.SDKException(
'Must provide one of template_file,' 'Must provide one of template_file,'
' template_url or template_object') ' template_url or template_object'
)
if not tpl: if not tpl:
raise exceptions.SDKException( raise exceptions.SDKException(
'Could not fetch template from %s' % template_url) 'Could not fetch template from %s' % template_url
)
try: try:
if isinstance(tpl, bytes): if isinstance(tpl, bytes):
@ -58,35 +65,43 @@ def get_template_contents(template_file=None, template_url=None,
template = template_format.parse(tpl) template = template_format.parse(tpl)
except ValueError as e: except ValueError as e:
raise exceptions.SDKException( raise exceptions.SDKException(
'Error parsing template %(url)s %(error)s' % 'Error parsing template %(url)s %(error)s'
{'url': template_url, 'error': e}) % {'url': template_url, 'error': e}
)
tmpl_base_url = utils.base_url_for_url(template_url) tmpl_base_url = utils.base_url_for_url(template_url)
if files is None: if files is None:
files = {} files = {}
resolve_template_get_files(template, files, tmpl_base_url, is_object, resolve_template_get_files(
object_request) template, files, tmpl_base_url, is_object, object_request
)
return files, template return files, template
def resolve_template_get_files(template, files, template_base_url, def resolve_template_get_files(
is_object=False, object_request=None): template, files, template_base_url, is_object=False, object_request=None
):
def ignore_if(key, value): def ignore_if(key, value):
if key != 'get_file' and key != 'type': if key != 'get_file' and key != 'type':
return True return True
if not isinstance(value, str): if not isinstance(value, str):
return True return True
if (key == 'type' if key == 'type' and not value.endswith(('.yaml', '.template')):
and not value.endswith(('.yaml', '.template'))):
return True return True
return False return False
def recurse_if(value): def recurse_if(value):
return isinstance(value, (dict, list)) return isinstance(value, (dict, list))
get_file_contents(template, files, template_base_url, get_file_contents(
ignore_if, recurse_if, is_object, object_request) template,
files,
template_base_url,
ignore_if,
recurse_if,
is_object,
object_request,
)
def is_template(file_content): def is_template(file_content):
@ -99,9 +114,15 @@ def is_template(file_content):
return True return True
def get_file_contents(from_data, files, base_url=None, def get_file_contents(
ignore_if=None, recurse_if=None, from_data,
is_object=False, object_request=None): files,
base_url=None,
ignore_if=None,
recurse_if=None,
is_object=False,
object_request=None,
):
if recurse_if and recurse_if(from_data): if recurse_if and recurse_if(from_data):
if isinstance(from_data, dict): if isinstance(from_data, dict):
@ -109,8 +130,15 @@ def get_file_contents(from_data, files, base_url=None,
else: else:
recurse_data = from_data recurse_data = from_data
for value in recurse_data: for value in recurse_data:
get_file_contents(value, files, base_url, ignore_if, recurse_if, get_file_contents(
is_object, object_request) value,
files,
base_url,
ignore_if,
recurse_if,
is_object,
object_request,
)
if isinstance(from_data, dict): if isinstance(from_data, dict):
for key, value in from_data.items(): for key, value in from_data.items():
@ -129,11 +157,14 @@ def get_file_contents(from_data, files, base_url=None,
if is_template(file_content): if is_template(file_content):
if is_object: if is_object:
template = get_template_contents( template = get_template_contents(
template_object=str_url, files=files, template_object=str_url,
object_request=object_request)[1] files=files,
object_request=object_request,
)[1]
else: else:
template = get_template_contents( template = get_template_contents(
template_url=str_url, files=files)[1] template_url=str_url, files=files
)[1]
file_content = json.dumps(template) file_content = json.dumps(template)
files[str_url] = file_content files[str_url] = file_content
# replace the data value with the normalised absolute URL # replace the data value with the normalised absolute URL
@ -157,11 +188,14 @@ def deep_update(old, new):
return old return old
def process_multiple_environments_and_files(env_paths=None, template=None, def process_multiple_environments_and_files(
template_url=None, env_paths=None,
env_path_is_object=None, template=None,
object_request=None, template_url=None,
env_list_tracker=None): env_path_is_object=None,
object_request=None,
env_list_tracker=None,
):
"""Reads one or more environment files. """Reads one or more environment files.
Reads in each specified environment file and returns a dictionary Reads in each specified environment file and returns a dictionary
@ -204,7 +238,8 @@ def process_multiple_environments_and_files(env_paths=None, template=None,
template_url=template_url, template_url=template_url,
env_path_is_object=env_path_is_object, env_path_is_object=env_path_is_object,
object_request=object_request, object_request=object_request,
include_env_in_files=include_env_in_files) include_env_in_files=include_env_in_files,
)
# 'files' looks like {"filename1": contents, "filename2": contents} # 'files' looks like {"filename1": contents, "filename2": contents}
# so a simple update is enough for merging # so a simple update is enough for merging
@ -221,12 +256,14 @@ def process_multiple_environments_and_files(env_paths=None, template=None,
return merged_files, merged_env return merged_files, merged_env
def process_environment_and_files(env_path=None, def process_environment_and_files(
template=None, env_path=None,
template_url=None, template=None,
env_path_is_object=None, template_url=None,
object_request=None, env_path_is_object=None,
include_env_in_files=False): object_request=None,
include_env_in_files=False,
):
"""Loads a single environment file. """Loads a single environment file.
Returns an entry suitable for the files dict which maps the environment Returns an entry suitable for the files dict which maps the environment
@ -253,7 +290,10 @@ def process_environment_and_files(env_path=None,
resolve_environment_urls( resolve_environment_urls(
env.get('resource_registry'), env.get('resource_registry'),
files, files,
env_base_url, is_object=True, object_request=object_request) env_base_url,
is_object=True,
object_request=object_request,
)
elif env_path: elif env_path:
env_url = utils.normalise_file_path_to_url(env_path) env_url = utils.normalise_file_path_to_url(env_path)
@ -263,9 +303,8 @@ def process_environment_and_files(env_path=None,
env = environment_format.parse(raw_env) env = environment_format.parse(raw_env)
resolve_environment_urls( resolve_environment_urls(
env.get('resource_registry'), env.get('resource_registry'), files, env_base_url
files, )
env_base_url)
if include_env_in_files: if include_env_in_files:
files[env_url] = json.dumps(env) files[env_url] = json.dumps(env)
@ -273,8 +312,13 @@ def process_environment_and_files(env_path=None,
return files, env return files, env
def resolve_environment_urls(resource_registry, files, env_base_url, def resolve_environment_urls(
is_object=False, object_request=None): resource_registry,
files,
env_base_url,
is_object=False,
object_request=None,
):
"""Handles any resource URLs specified in an environment. """Handles any resource URLs specified in an environment.
:param resource_registry: mapping of type name to template filename :param resource_registry: mapping of type name to template filename
@ -302,11 +346,22 @@ def resolve_environment_urls(resource_registry, files, env_base_url,
if key in ['hooks', 'restricted_actions']: if key in ['hooks', 'restricted_actions']:
return True return True
get_file_contents(rr, files, base_url, ignore_if, get_file_contents(
is_object=is_object, object_request=object_request) rr,
files,
base_url,
ignore_if,
is_object=is_object,
object_request=object_request,
)
for res_name, res_dict in rr.get('resources', {}).items(): for res_name, res_dict in rr.get('resources', {}).items():
res_base_url = res_dict.get('base_url', base_url) res_base_url = res_dict.get('base_url', base_url)
get_file_contents( get_file_contents(
res_dict, files, res_base_url, ignore_if, res_dict,
is_object=is_object, object_request=object_request) files,
res_base_url,
ignore_if,
is_object=is_object,
object_request=object_request,
)

View File

@ -40,8 +40,7 @@ def read_url_content(url):
# TODO(mordred) Use requests # TODO(mordred) Use requests
content = request.urlopen(url).read() content = request.urlopen(url).read()
except error.URLError: except error.URLError:
raise exceptions.SDKException( raise exceptions.SDKException('Could not fetch contents for %s' % url)
'Could not fetch contents for %s' % url)
if content: if content:
try: try:
@ -52,8 +51,9 @@ def read_url_content(url):
def resource_nested_identifier(rsrc): def resource_nested_identifier(rsrc):
nested_link = [link for link in rsrc.links or [] nested_link = [
if link.get('rel') == 'nested'] link for link in rsrc.links or [] if link.get('rel') == 'nested'
]
if nested_link: if nested_link:
nested_href = nested_link[0].get('href') nested_href = nested_link[0].get('href')
nested_identifier = nested_href.split("/")[-2:] nested_identifier = nested_href.split("/")[-2:]

View File

@ -36,23 +36,34 @@ class Proxy(proxy.Proxy):
} }
def _extract_name_consume_url_parts(self, url_parts): def _extract_name_consume_url_parts(self, url_parts):
if (len(url_parts) == 3 and url_parts[0] == 'software_deployments' if (
and url_parts[1] == 'metadata'): len(url_parts) == 3
and url_parts[0] == 'software_deployments'
and url_parts[1] == 'metadata'
):
# Another nice example of totally different URL naming scheme, # Another nice example of totally different URL naming scheme,
# which we need to repair /software_deployment/metadata/server_id - # which we need to repair /software_deployment/metadata/server_id -
# just replace server_id with metadata to keep further logic # just replace server_id with metadata to keep further logic
return ['software_deployment', 'metadata'] return ['software_deployment', 'metadata']
if (url_parts[0] == 'stacks' and len(url_parts) > 2 if (
and not url_parts[2] in ['preview', 'resources']): url_parts[0] == 'stacks'
and len(url_parts) > 2
and not url_parts[2] in ['preview', 'resources']
):
# orchestrate introduce having stack name and id part of the URL # orchestrate introduce having stack name and id part of the URL
# (/stacks/name/id/everything_else), so if on third position we # (/stacks/name/id/everything_else), so if on third position we
# have not a known part - discard it, not to brake further logic # have not a known part - discard it, not to brake further logic
del url_parts[2] del url_parts[2]
return super(Proxy, self)._extract_name_consume_url_parts(url_parts) return super(Proxy, self)._extract_name_consume_url_parts(url_parts)
def read_env_and_templates(self, template_file=None, template_url=None, def read_env_and_templates(
template_object=None, files=None, self,
environment_files=None): template_file=None,
template_url=None,
template_object=None,
files=None,
environment_files=None,
):
"""Read templates and environment content and prepares """Read templates and environment content and prepares
corresponding stack attributes corresponding stack attributes
@ -70,16 +81,20 @@ class Proxy(proxy.Proxy):
envfiles = dict() envfiles = dict()
tpl_files = None tpl_files = None
if environment_files: if environment_files:
envfiles, env = \ (
template_utils.process_multiple_environments_and_files( envfiles,
env_paths=environment_files) env,
) = template_utils.process_multiple_environments_and_files(
env_paths=environment_files
)
stack_attrs['environment'] = env stack_attrs['environment'] = env
if template_file or template_url or template_object: if template_file or template_url or template_object:
tpl_files, template = template_utils.get_template_contents( tpl_files, template = template_utils.get_template_contents(
template_file=template_file, template_file=template_file,
template_url=template_url, template_url=template_url,
template_object=template_object, template_object=template_object,
files=files) files=files,
)
stack_attrs['template'] = template stack_attrs['template'] = template
if tpl_files or envfiles: if tpl_files or envfiles:
stack_attrs['files'] = dict( stack_attrs['files'] = dict(
@ -104,8 +119,9 @@ class Proxy(proxy.Proxy):
base_path = None if not preview else '/stacks/preview' base_path = None if not preview else '/stacks/preview'
return self._create(_stack.Stack, base_path=base_path, **attrs) return self._create(_stack.Stack, base_path=base_path, **attrs)
def find_stack(self, name_or_id, def find_stack(
ignore_missing=True, resolve_outputs=True): self, name_or_id, ignore_missing=True, resolve_outputs=True
):
"""Find a single stack """Find a single stack
:param name_or_id: The name or ID of a stack. :param name_or_id: The name or ID of a stack.
@ -116,9 +132,12 @@ class Proxy(proxy.Proxy):
attempting to find a nonexistent resource. attempting to find a nonexistent resource.
:returns: One :class:`~openstack.orchestration.v1.stack.Stack` or None :returns: One :class:`~openstack.orchestration.v1.stack.Stack` or None
""" """
return self._find(_stack.Stack, name_or_id, return self._find(
ignore_missing=ignore_missing, _stack.Stack,
resolve_outputs=resolve_outputs) name_or_id,
ignore_missing=ignore_missing,
resolve_outputs=resolve_outputs,
)
def stacks(self, **query): def stacks(self, **query):
"""Return a generator of stacks """Return a generator of stacks
@ -219,8 +238,12 @@ class Proxy(proxy.Proxy):
else: else:
obj = self._find(_stack.Stack, stack, ignore_missing=False) obj = self._find(_stack.Stack, stack, ignore_missing=False)
return self._get(_stack_template.StackTemplate, requires_id=False, return self._get(
stack_name=obj.name, stack_id=obj.id) _stack_template.StackTemplate,
requires_id=False,
stack_name=obj.name,
stack_id=obj.id,
)
def get_stack_environment(self, stack): def get_stack_environment(self, stack):
"""Get environment used by a stack """Get environment used by a stack
@ -238,9 +261,12 @@ class Proxy(proxy.Proxy):
else: else:
obj = self._find(_stack.Stack, stack, ignore_missing=False) obj = self._find(_stack.Stack, stack, ignore_missing=False)
return self._get(_stack_environment.StackEnvironment, return self._get(
requires_id=False, stack_name=obj.name, _stack_environment.StackEnvironment,
stack_id=obj.id) requires_id=False,
stack_name=obj.name,
stack_id=obj.id,
)
def get_stack_files(self, stack): def get_stack_files(self, stack):
"""Get files used by a stack """Get files used by a stack
@ -283,8 +309,9 @@ class Proxy(proxy.Proxy):
else: else:
obj = self._find(_stack.Stack, stack, ignore_missing=False) obj = self._find(_stack.Stack, stack, ignore_missing=False)
return self._list(_resource.Resource, stack_name=obj.name, return self._list(
stack_id=obj.id, **query) _resource.Resource, stack_name=obj.name, stack_id=obj.id, **query
)
def create_software_config(self, **attrs): def create_software_config(self, **attrs):
"""Create a new software config from attributes """Create a new software config from attributes
@ -335,8 +362,9 @@ class Proxy(proxy.Proxy):
attempting to delete a nonexistent software config. attempting to delete a nonexistent software config.
:returns: ``None`` :returns: ``None``
""" """
self._delete(_sc.SoftwareConfig, software_config, self._delete(
ignore_missing=ignore_missing) _sc.SoftwareConfig, software_config, ignore_missing=ignore_missing
)
def create_software_deployment(self, **attrs): def create_software_deployment(self, **attrs):
"""Create a new software deployment from attributes """Create a new software deployment from attributes
@ -374,8 +402,9 @@ class Proxy(proxy.Proxy):
""" """
return self._get(_sd.SoftwareDeployment, software_deployment) return self._get(_sd.SoftwareDeployment, software_deployment)
def delete_software_deployment(self, software_deployment, def delete_software_deployment(
ignore_missing=True): self, software_deployment, ignore_missing=True
):
"""Delete a software deployment """Delete a software deployment
:param software_deployment: The value can be either the ID of a :param software_deployment: The value can be either the ID of a
@ -388,8 +417,11 @@ class Proxy(proxy.Proxy):
attempting to delete a nonexistent software deployment. attempting to delete a nonexistent software deployment.
:returns: ``None`` :returns: ``None``
""" """
self._delete(_sd.SoftwareDeployment, software_deployment, self._delete(
ignore_missing=ignore_missing) _sd.SoftwareDeployment,
software_deployment,
ignore_missing=ignore_missing,
)
def update_software_deployment(self, software_deployment, **attrs): def update_software_deployment(self, software_deployment, **attrs):
"""Update a software deployment """Update a software deployment
@ -403,11 +435,13 @@ class Proxy(proxy.Proxy):
:rtype: :rtype:
:class:`~openstack.orchestration.v1.software_deployment.SoftwareDeployment` :class:`~openstack.orchestration.v1.software_deployment.SoftwareDeployment`
""" """
return self._update(_sd.SoftwareDeployment, software_deployment, return self._update(
**attrs) _sd.SoftwareDeployment, software_deployment, **attrs
)
def validate_template(self, template, environment=None, template_url=None, def validate_template(
ignore_errors=None): self, template, environment=None, template_url=None, ignore_errors=None
):
"""Validates a template. """Validates a template.
:param template: The stack template on which the validation is :param template: The stack template on which the validation is
@ -429,15 +463,21 @@ class Proxy(proxy.Proxy):
""" """
if template is None and template_url is None: if template is None and template_url is None:
raise exceptions.InvalidRequest( raise exceptions.InvalidRequest(
"'template_url' must be specified when template is None") "'template_url' must be specified when template is None"
)
tmpl = _template.Template.new() tmpl = _template.Template.new()
return tmpl.validate(self, template, environment=environment, return tmpl.validate(
template_url=template_url, self,
ignore_errors=ignore_errors) template,
environment=environment,
template_url=template_url,
ignore_errors=ignore_errors,
)
def wait_for_status(self, res, status='ACTIVE', failures=None, def wait_for_status(
interval=2, wait=120): self, res, status='ACTIVE', failures=None, interval=2, wait=120
):
"""Wait for a resource to be in a particular status. """Wait for a resource to be in a particular status.
:param res: The resource to wait on to reach the specified status. :param res: The resource to wait on to reach the specified status.
@ -460,7 +500,8 @@ class Proxy(proxy.Proxy):
""" """
failures = [] if failures is None else failures failures = [] if failures is None else failures
return resource.wait_for_status( return resource.wait_for_status(
self, res, status, failures, interval, wait) self, res, status, failures, interval, wait
)
def wait_for_delete(self, res, interval=2, wait=120): def wait_for_delete(self, res, interval=2, wait=120):
"""Wait for a resource to be deleted. """Wait for a resource to be deleted.
@ -478,26 +519,37 @@ class Proxy(proxy.Proxy):
return resource.wait_for_delete(self, res, interval, wait) return resource.wait_for_delete(self, res, interval, wait)
def get_template_contents( def get_template_contents(
self, template_file=None, template_url=None, self,
template_object=None, files=None): template_file=None,
template_url=None,
template_object=None,
files=None,
):
try: try:
return template_utils.get_template_contents( return template_utils.get_template_contents(
template_file=template_file, template_url=template_url, template_file=template_file,
template_object=template_object, files=files) template_url=template_url,
template_object=template_object,
files=files,
)
except Exception as e: except Exception as e:
raise exceptions.SDKException( raise exceptions.SDKException(
"Error in processing template files: %s" % str(e)) "Error in processing template files: %s" % str(e)
)
def _get_cleanup_dependencies(self): def _get_cleanup_dependencies(self):
return { return {
'orchestration': { 'orchestration': {'before': ['compute', 'network', 'identity']}
'before': ['compute', 'network', 'identity']
}
} }
def _service_cleanup(self, dry_run=True, client_status_queue=None, def _service_cleanup(
identified_resources=None, self,
filters=None, resource_evaluation_fn=None): dry_run=True,
client_status_queue=None,
identified_resources=None,
filters=None,
resource_evaluation_fn=None,
):
stacks = [] stacks = []
for obj in self.stacks(): for obj in self.stacks():
need_delete = self._service_cleanup_del_res( need_delete = self._service_cleanup_del_res(
@ -507,7 +559,8 @@ class Proxy(proxy.Proxy):
client_status_queue=client_status_queue, client_status_queue=client_status_queue,
identified_resources=identified_resources, identified_resources=identified_resources,
filters=filters, filters=filters,
resource_evaluation_fn=resource_evaluation_fn) resource_evaluation_fn=resource_evaluation_fn,
)
if not dry_run and need_delete: if not dry_run and need_delete:
stacks.append(obj) stacks.append(obj)

View File

@ -31,8 +31,9 @@ class Resource(resource.Resource):
links = resource.Body('links') links = resource.Body('links')
#: ID of the logical resource, usually the literal name of the resource #: ID of the logical resource, usually the literal name of the resource
#: as it appears in the stack template. #: as it appears in the stack template.
logical_resource_id = resource.Body('logical_resource_id', logical_resource_id = resource.Body(
alternate_id=True) 'logical_resource_id', alternate_id=True
)
#: Name of the resource. #: Name of the resource.
name = resource.Body('resource_name') name = resource.Body('resource_name')
#: ID of the physical resource (if any) that backs up the resource. For #: ID of the physical resource (if any) that backs up the resource. For

View File

@ -48,5 +48,6 @@ class SoftwareConfig(resource.Resource):
def create(self, session, base_path=None): def create(self, session, base_path=None):
# This overrides the default behavior of resource creation because # This overrides the default behavior of resource creation because
# heat doesn't accept resource_key in its request. # heat doesn't accept resource_key in its request.
return super(SoftwareConfig, self).create(session, prepend_key=False, return super(SoftwareConfig, self).create(
base_path=base_path) session, prepend_key=False, base_path=base_path
)

View File

@ -53,10 +53,12 @@ class SoftwareDeployment(resource.Resource):
# This overrides the default behavior of resource creation because # This overrides the default behavior of resource creation because
# heat doesn't accept resource_key in its request. # heat doesn't accept resource_key in its request.
return super(SoftwareDeployment, self).create( return super(SoftwareDeployment, self).create(
session, prepend_key=False, base_path=base_path) session, prepend_key=False, base_path=base_path
)
def commit(self, session, base_path=None): def commit(self, session, base_path=None):
# This overrides the default behavior of resource creation because # This overrides the default behavior of resource creation because
# heat doesn't accept resource_key in its request. # heat doesn't accept resource_key in its request.
return super(SoftwareDeployment, self).commit( return super(SoftwareDeployment, self).commit(
session, prepend_key=False, base_path=base_path) session, prepend_key=False, base_path=base_path
)

View File

@ -29,8 +29,12 @@ class Stack(resource.Resource):
allow_delete = True allow_delete = True
_query_mapping = resource.QueryParameters( _query_mapping = resource.QueryParameters(
'action', 'name', 'status', 'action',
'project_id', 'owner_id', 'username', 'name',
'status',
'project_id',
'owner_id',
'username',
project_id='tenant_id', project_id='tenant_id',
**tag.TagMixin._tag_query_parameters **tag.TagMixin._tag_query_parameters
) )
@ -111,14 +115,16 @@ class Stack(resource.Resource):
def create(self, session, base_path=None): def create(self, session, base_path=None):
# This overrides the default behavior of resource creation because # This overrides the default behavior of resource creation because
# heat doesn't accept resource_key in its request. # heat doesn't accept resource_key in its request.
return super(Stack, self).create(session, prepend_key=False, return super(Stack, self).create(
base_path=base_path) session, prepend_key=False, base_path=base_path
)
def commit(self, session, base_path=None): def commit(self, session, base_path=None):
# This overrides the default behavior of resource creation because # This overrides the default behavior of resource creation because
# heat doesn't accept resource_key in its request. # heat doesn't accept resource_key in its request.
return super(Stack, self).commit(session, prepend_key=False, return super(Stack, self).commit(
has_body=False, base_path=None) session, prepend_key=False, has_body=False, base_path=None
)
def update(self, session, preview=False): def update(self, session, preview=False):
# This overrides the default behavior of resource update because # This overrides the default behavior of resource update because
@ -127,16 +133,17 @@ class Stack(resource.Resource):
if self.name and self.id: if self.name and self.id:
base_path = '/stacks/%(stack_name)s/%(stack_id)s' % { base_path = '/stacks/%(stack_name)s/%(stack_id)s' % {
'stack_name': self.name, 'stack_name': self.name,
'stack_id': self.id} 'stack_id': self.id,
}
elif self.name or self.id: elif self.name or self.id:
# We have only one of name/id. Do not try to build a stacks/NAME/ID # We have only one of name/id. Do not try to build a stacks/NAME/ID
# path # path
base_path = '/stacks/%(stack_identity)s' % { base_path = '/stacks/%(stack_identity)s' % {
'stack_identity': self.name or self.id} 'stack_identity': self.name or self.id
}
request = self._prepare_request( request = self._prepare_request(
prepend_key=False, prepend_key=False, requires_id=False, base_path=base_path
requires_id=False, )
base_path=base_path)
microversion = self._get_microversion(session, action='commit') microversion = self._get_microversion(session, action='commit')
@ -145,8 +152,11 @@ class Stack(resource.Resource):
request_url = utils.urljoin(request_url, 'preview') request_url = utils.urljoin(request_url, 'preview')
response = session.put( response = session.put(
request_url, json=request.body, headers=request.headers, request_url,
microversion=microversion) json=request.body,
headers=request.headers,
microversion=microversion,
)
self.microversion = microversion self.microversion = microversion
self._translate_response(response, has_body=True) self._translate_response(response, has_body=True)
@ -162,20 +172,28 @@ class Stack(resource.Resource):
return self._action(session, {'check': ''}) return self._action(session, {'check': ''})
def abandon(self, session): def abandon(self, session):
url = utils.urljoin(self.base_path, self.name, url = utils.urljoin(
self._get_id(self), 'abandon') self.base_path, self.name, self._get_id(self), 'abandon'
)
resp = session.delete(url) resp = session.delete(url)
return resp.json() return resp.json()
def fetch(self, session, requires_id=True, def fetch(
base_path=None, error_message=None, self,
skip_cache=False, resolve_outputs=True): session,
requires_id=True,
base_path=None,
error_message=None,
skip_cache=False,
resolve_outputs=True,
):
if not self.allow_fetch: if not self.allow_fetch:
raise exceptions.MethodNotSupported(self, "fetch") raise exceptions.MethodNotSupported(self, "fetch")
request = self._prepare_request(requires_id=requires_id, request = self._prepare_request(
base_path=base_path) requires_id=requires_id, base_path=base_path
)
# session = self._get_session(session) # session = self._get_session(session)
microversion = self._get_microversion(session, action='fetch') microversion = self._get_microversion(session, action='fetch')
@ -185,7 +203,8 @@ class Stack(resource.Resource):
if not resolve_outputs: if not resolve_outputs:
request.url = request.url + '?resolve_outputs=False' request.url = request.url + '?resolve_outputs=False'
response = session.get( response = session.get(
request.url, microversion=microversion, skip_cache=skip_cache) request.url, microversion=microversion, skip_cache=skip_cache
)
kwargs = {} kwargs = {}
if error_message: if error_message:
kwargs['error_message'] = error_message kwargs['error_message'] = error_message
@ -195,7 +214,8 @@ class Stack(resource.Resource):
if self and self.status in ['DELETE_COMPLETE', 'ADOPT_COMPLETE']: if self and self.status in ['DELETE_COMPLETE', 'ADOPT_COMPLETE']:
raise exceptions.ResourceNotFound( raise exceptions.ResourceNotFound(
"No stack found for %s" % self.id) "No stack found for %s" % self.id
)
return self return self
@classmethod @classmethod
@ -227,9 +247,8 @@ class Stack(resource.Resource):
# Try to short-circuit by looking directly for a matching ID. # Try to short-circuit by looking directly for a matching ID.
try: try:
match = cls.existing( match = cls.existing(
id=name_or_id, id=name_or_id, connection=session._get_connection(), **params
connection=session._get_connection(), )
**params)
return match.fetch(session, **params) return match.fetch(session, **params)
except exceptions.NotFoundException: except exceptions.NotFoundException:
pass pass
@ -240,7 +259,8 @@ class Stack(resource.Resource):
if ignore_missing: if ignore_missing:
return None return None
raise exceptions.ResourceNotFound( raise exceptions.ResourceNotFound(
"No %s found for %s" % (cls.__name__, name_or_id)) "No %s found for %s" % (cls.__name__, name_or_id)
)
StackPreview = Stack StackPreview = Stack

View File

@ -32,8 +32,14 @@ class Template(resource.Resource):
#: A list of parameter groups each contains a lsit of parameter names. #: A list of parameter groups each contains a lsit of parameter names.
parameter_groups = resource.Body('ParameterGroups', type=list) parameter_groups = resource.Body('ParameterGroups', type=list)
def validate(self, session, template, environment=None, template_url=None, def validate(
ignore_errors=None): self,
session,
template,
environment=None,
template_url=None,
ignore_errors=None,
):
url = '/validate' url = '/validate'
body = {'template': template} body = {'template': template}

View File

@ -42,9 +42,8 @@ class TestStack(base.BaseFunctionalTest):
# the shade layer. # the shade layer.
template['heat_template_version'] = '2013-05-23' template['heat_template_version'] = '2013-05-23'
self.network, self.subnet = test_network.create_network( self.network, self.subnet = test_network.create_network(
self.conn, self.conn, self.NAME, self.cidr
self.NAME, )
self.cidr)
parameters = { parameters = {
'image': image.id, 'image': image.id,
'key_name': self.NAME, 'key_name': self.NAME,
@ -60,8 +59,11 @@ class TestStack(base.BaseFunctionalTest):
self.stack = sot self.stack = sot
self.assertEqual(self.NAME, sot.name) self.assertEqual(self.NAME, sot.name)
self.conn.orchestration.wait_for_status( self.conn.orchestration.wait_for_status(
sot, status='CREATE_COMPLETE', failures=['CREATE_FAILED'], sot,
wait=self._wait_for_timeout) status='CREATE_COMPLETE',
failures=['CREATE_FAILED'],
wait=self._wait_for_timeout,
)
def tearDown(self): def tearDown(self):
self.conn.orchestration.delete_stack(self.stack, ignore_missing=False) self.conn.orchestration.delete_stack(self.stack, ignore_missing=False)
@ -69,7 +71,8 @@ class TestStack(base.BaseFunctionalTest):
# Need to wait for the stack to go away before network delete # Need to wait for the stack to go away before network delete
try: try:
self.conn.orchestration.wait_for_status( self.conn.orchestration.wait_for_status(
self.stack, 'DELETE_COMPLETE', wait=self._wait_for_timeout) self.stack, 'DELETE_COMPLETE', wait=self._wait_for_timeout
)
except exceptions.ResourceNotFound: except exceptions.ResourceNotFound:
pass pass
test_network.delete_network(self.conn, self.network, self.subnet) test_network.delete_network(self.conn, self.network, self.subnet)

View File

@ -23,7 +23,6 @@ EXAMPLE = {
class TestVersion(base.TestCase): class TestVersion(base.TestCase):
def test_basic(self): def test_basic(self):
sot = version.Version() sot = version.Version()
self.assertEqual('version', sot.resource_key) self.assertEqual('version', sot.resource_key)

View File

@ -42,11 +42,15 @@ class TestOrchestrationStack(TestOrchestrationProxy):
self.proxy.create_stack, self.proxy.create_stack,
stack.Stack, stack.Stack,
method_kwargs={"preview": True, "x": 1, "y": 2, "z": 3}, method_kwargs={"preview": True, "x": 1, "y": 2, "z": 3},
expected_kwargs={"x": 1, "y": 2, "z": 3}) expected_kwargs={"x": 1, "y": 2, "z": 3},
)
def test_find_stack(self): def test_find_stack(self):
self.verify_find(self.proxy.find_stack, stack.Stack, self.verify_find(
expected_kwargs={'resolve_outputs': True}) self.proxy.find_stack,
stack.Stack,
expected_kwargs={'resolve_outputs': True},
)
# mock_method="openstack.proxy.Proxy._find" # mock_method="openstack.proxy.Proxy._find"
# test_method=self.proxy.find_stack # test_method=self.proxy.find_stack
# method_kwargs = { # method_kwargs = {
@ -78,12 +82,15 @@ class TestOrchestrationStack(TestOrchestrationProxy):
self.verify_list(self.proxy.stacks, stack.Stack) self.verify_list(self.proxy.stacks, stack.Stack)
def test_get_stack(self): def test_get_stack(self):
self.verify_get(self.proxy.get_stack, stack.Stack, self.verify_get(
method_kwargs={'resolve_outputs': False}, self.proxy.get_stack,
expected_kwargs={'resolve_outputs': False}) stack.Stack,
method_kwargs={'resolve_outputs': False},
expected_kwargs={'resolve_outputs': False},
)
self.verify_get_overrided( self.verify_get_overrided(
self.proxy, stack.Stack, self.proxy, stack.Stack, 'openstack.orchestration.v1.stack.Stack'
'openstack.orchestration.v1.stack.Stack') )
def test_update_stack(self): def test_update_stack(self):
self._verify( self._verify(
@ -92,7 +99,8 @@ class TestOrchestrationStack(TestOrchestrationProxy):
expected_result='result', expected_result='result',
method_args=['stack'], method_args=['stack'],
method_kwargs={'preview': False}, method_kwargs={'preview': False},
expected_args=[self.proxy, False]) expected_args=[self.proxy, False],
)
def test_update_stack_preview(self): def test_update_stack_preview(self):
self._verify( self._verify(
@ -101,7 +109,8 @@ class TestOrchestrationStack(TestOrchestrationProxy):
expected_result='result', expected_result='result',
method_args=['stack'], method_args=['stack'],
method_kwargs={'preview': True}, method_kwargs={'preview': True},
expected_args=[self.proxy, True]) expected_args=[self.proxy, True],
)
def test_abandon_stack(self): def test_abandon_stack(self):
self._verify( self._verify(
@ -109,7 +118,8 @@ class TestOrchestrationStack(TestOrchestrationProxy):
self.proxy.abandon_stack, self.proxy.abandon_stack,
expected_result='result', expected_result='result',
method_args=['stack'], method_args=['stack'],
expected_args=[self.proxy]) expected_args=[self.proxy],
)
def test_delete_stack(self): def test_delete_stack(self):
self.verify_delete(self.proxy.delete_stack, stack.Stack, False) self.verify_delete(self.proxy.delete_stack, stack.Stack, False)
@ -154,9 +164,12 @@ class TestOrchestrationStackEnvironment(TestOrchestrationProxy):
expected_kwargs={ expected_kwargs={
'requires_id': False, 'requires_id': False,
'stack_name': stack_name, 'stack_name': stack_name,
'stack_id': stack_id}) 'stack_id': stack_id,
mock_find.assert_called_once_with(mock.ANY, 'IDENTITY', },
ignore_missing=False) )
mock_find.assert_called_once_with(
mock.ANY, 'IDENTITY', ignore_missing=False
)
def test_get_stack_environment_with_stack_object(self): def test_get_stack_environment_with_stack_object(self):
stack_id = '1234' stack_id = '1234'
@ -171,7 +184,9 @@ class TestOrchestrationStackEnvironment(TestOrchestrationProxy):
expected_kwargs={ expected_kwargs={
'requires_id': False, 'requires_id': False,
'stack_name': stack_name, 'stack_name': stack_name,
'stack_id': stack_id}) 'stack_id': stack_id,
},
)
class TestOrchestrationStackFiles(TestOrchestrationProxy): class TestOrchestrationStackFiles(TestOrchestrationProxy):
@ -187,8 +202,9 @@ class TestOrchestrationStackFiles(TestOrchestrationProxy):
res = self.proxy.get_stack_files('IDENTITY') res = self.proxy.get_stack_files('IDENTITY')
self.assertEqual({'file': 'content'}, res) self.assertEqual({'file': 'content'}, res)
mock_find.assert_called_once_with(mock.ANY, 'IDENTITY', mock_find.assert_called_once_with(
ignore_missing=False) mock.ANY, 'IDENTITY', ignore_missing=False
)
mock_fetch.assert_called_once_with(self.proxy) mock_fetch.assert_called_once_with(self.proxy)
@mock.patch.object(stack_files.StackFiles, 'fetch') @mock.patch.object(stack_files.StackFiles, 'fetch')
@ -220,9 +236,12 @@ class TestOrchestrationStackTemplate(TestOrchestrationProxy):
expected_kwargs={ expected_kwargs={
'requires_id': False, 'requires_id': False,
'stack_name': stack_name, 'stack_name': stack_name,
'stack_id': stack_id}) 'stack_id': stack_id,
mock_find.assert_called_once_with(mock.ANY, 'IDENTITY', },
ignore_missing=False) )
mock_find.assert_called_once_with(
mock.ANY, 'IDENTITY', ignore_missing=False
)
def test_get_stack_template_with_stack_object(self): def test_get_stack_template_with_stack_object(self):
stack_id = '1234' stack_id = '1234'
@ -237,7 +256,9 @@ class TestOrchestrationStackTemplate(TestOrchestrationProxy):
expected_kwargs={ expected_kwargs={
'requires_id': False, 'requires_id': False,
'stack_name': stack_name, 'stack_name': stack_name,
'stack_id': stack_id}) 'stack_id': stack_id,
},
)
class TestOrchestrationResource(TestOrchestrationProxy): class TestOrchestrationResource(TestOrchestrationProxy):
@ -247,11 +268,13 @@ class TestOrchestrationResource(TestOrchestrationProxy):
stack_name = 'test_stack' stack_name = 'test_stack'
stk = stack.Stack(id=stack_id, name=stack_name) stk = stack.Stack(id=stack_id, name=stack_name)
self.verify_list(self.proxy.resources, resource.Resource, self.verify_list(
method_args=[stk], self.proxy.resources,
expected_args=[], resource.Resource,
expected_kwargs={'stack_name': stack_name, method_args=[stk],
'stack_id': stack_id}) expected_args=[],
expected_kwargs={'stack_name': stack_name, 'stack_id': stack_id},
)
self.assertEqual(0, mock_find.call_count) self.assertEqual(0, mock_find.call_count)
@ -262,31 +285,37 @@ class TestOrchestrationResource(TestOrchestrationProxy):
stk = stack.Stack(id=stack_id, name=stack_name) stk = stack.Stack(id=stack_id, name=stack_name)
mock_find.return_value = stk mock_find.return_value = stk
self.verify_list(self.proxy.resources, resource.Resource, self.verify_list(
method_args=[stack_id], self.proxy.resources,
expected_args=[], resource.Resource,
expected_kwargs={'stack_name': stack_name, method_args=[stack_id],
'stack_id': stack_id}) expected_args=[],
expected_kwargs={'stack_name': stack_name, 'stack_id': stack_id},
)
mock_find.assert_called_once_with(mock.ANY, stack_id, mock_find.assert_called_once_with(
ignore_missing=False) mock.ANY, stack_id, ignore_missing=False
)
@mock.patch.object(stack.Stack, 'find') @mock.patch.object(stack.Stack, 'find')
@mock.patch.object(resource.Resource, 'list') @mock.patch.object(resource.Resource, 'list')
def test_resources_stack_not_found(self, mock_list, mock_find): def test_resources_stack_not_found(self, mock_list, mock_find):
stack_name = 'test_stack' stack_name = 'test_stack'
mock_find.side_effect = exceptions.ResourceNotFound( mock_find.side_effect = exceptions.ResourceNotFound(
'No stack found for test_stack') 'No stack found for test_stack'
)
ex = self.assertRaises(exceptions.ResourceNotFound, ex = self.assertRaises(
self.proxy.resources, stack_name) exceptions.ResourceNotFound, self.proxy.resources, stack_name
)
self.assertEqual('No stack found for test_stack', str(ex)) self.assertEqual('No stack found for test_stack', str(ex))
class TestOrchestrationSoftwareConfig(TestOrchestrationProxy): class TestOrchestrationSoftwareConfig(TestOrchestrationProxy):
def test_create_software_config(self): def test_create_software_config(self):
self.verify_create(self.proxy.create_software_config, self.verify_create(
sc.SoftwareConfig) self.proxy.create_software_config, sc.SoftwareConfig
)
def test_software_configs(self): def test_software_configs(self):
self.verify_list(self.proxy.software_configs, sc.SoftwareConfig) self.verify_list(self.proxy.software_configs, sc.SoftwareConfig)
@ -295,34 +324,42 @@ class TestOrchestrationSoftwareConfig(TestOrchestrationProxy):
self.verify_get(self.proxy.get_software_config, sc.SoftwareConfig) self.verify_get(self.proxy.get_software_config, sc.SoftwareConfig)
def test_delete_software_config(self): def test_delete_software_config(self):
self.verify_delete(self.proxy.delete_software_config, self.verify_delete(
sc.SoftwareConfig, True) self.proxy.delete_software_config, sc.SoftwareConfig, True
self.verify_delete(self.proxy.delete_software_config, )
sc.SoftwareConfig, False) self.verify_delete(
self.proxy.delete_software_config, sc.SoftwareConfig, False
)
class TestOrchestrationSoftwareDeployment(TestOrchestrationProxy): class TestOrchestrationSoftwareDeployment(TestOrchestrationProxy):
def test_create_software_deployment(self): def test_create_software_deployment(self):
self.verify_create(self.proxy.create_software_deployment, self.verify_create(
sd.SoftwareDeployment) self.proxy.create_software_deployment, sd.SoftwareDeployment
)
def test_software_deployments(self): def test_software_deployments(self):
self.verify_list(self.proxy.software_deployments, self.verify_list(
sd.SoftwareDeployment) self.proxy.software_deployments, sd.SoftwareDeployment
)
def test_get_software_deployment(self): def test_get_software_deployment(self):
self.verify_get(self.proxy.get_software_deployment, self.verify_get(
sd.SoftwareDeployment) self.proxy.get_software_deployment, sd.SoftwareDeployment
)
def test_update_software_deployment(self): def test_update_software_deployment(self):
self.verify_update(self.proxy.update_software_deployment, self.verify_update(
sd.SoftwareDeployment) self.proxy.update_software_deployment, sd.SoftwareDeployment
)
def test_delete_software_deployment(self): def test_delete_software_deployment(self):
self.verify_delete(self.proxy.delete_software_deployment, self.verify_delete(
sd.SoftwareDeployment, True) self.proxy.delete_software_deployment, sd.SoftwareDeployment, True
self.verify_delete(self.proxy.delete_software_deployment, )
sd.SoftwareDeployment, False) self.verify_delete(
self.proxy.delete_software_deployment, sd.SoftwareDeployment, False
)
class TestOrchestrationTemplate(TestOrchestrationProxy): class TestOrchestrationTemplate(TestOrchestrationProxy):
@ -336,8 +373,12 @@ class TestOrchestrationTemplate(TestOrchestrationProxy):
res = self.proxy.validate_template(tmpl, env, tmpl_url, ignore_errors) res = self.proxy.validate_template(tmpl, env, tmpl_url, ignore_errors)
mock_validate.assert_called_once_with( mock_validate.assert_called_once_with(
self.proxy, tmpl, environment=env, template_url=tmpl_url, self.proxy,
ignore_errors=ignore_errors) tmpl,
environment=env,
template_url=tmpl_url,
ignore_errors=ignore_errors,
)
self.assertEqual(mock_validate.return_value, res) self.assertEqual(mock_validate.return_value, res)
def test_validate_template_no_env(self): def test_validate_template_no_env(self):
@ -349,11 +390,16 @@ class TestOrchestrationTemplate(TestOrchestrationProxy):
self.assertIsInstance(res["files"], dict) self.assertIsInstance(res["files"], dict)
def test_validate_template_invalid_request(self): def test_validate_template_invalid_request(self):
err = self.assertRaises(exceptions.InvalidRequest, err = self.assertRaises(
self.proxy.validate_template, exceptions.InvalidRequest,
None, template_url=None) self.proxy.validate_template,
self.assertEqual("'template_url' must be specified when template is " None,
"None", str(err)) template_url=None,
)
self.assertEqual(
"'template_url' must be specified when template is " "None",
str(err),
)
class TestExtractName(TestOrchestrationProxy): class TestExtractName(TestOrchestrationProxy):
@ -362,22 +408,47 @@ class TestExtractName(TestOrchestrationProxy):
('stacks', dict(url='/stacks', parts=['stacks'])), ('stacks', dict(url='/stacks', parts=['stacks'])),
('name_id', dict(url='/stacks/name/id', parts=['stack'])), ('name_id', dict(url='/stacks/name/id', parts=['stack'])),
('identity', dict(url='/stacks/id', parts=['stack'])), ('identity', dict(url='/stacks/id', parts=['stack'])),
('preview', dict(url='/stacks/name/preview', (
parts=['stack', 'preview'])), 'preview',
('stack_act', dict(url='/stacks/name/id/preview', dict(url='/stacks/name/preview', parts=['stack', 'preview']),
parts=['stack', 'preview'])), ),
('stack_subres', dict(url='/stacks/name/id/resources', (
parts=['stack', 'resources'])), 'stack_act',
('stack_subres_id', dict(url='/stacks/name/id/resources/id', dict(url='/stacks/name/id/preview', parts=['stack', 'preview']),
parts=['stack', 'resource'])), ),
('stack_subres_id_act', (
dict(url='/stacks/name/id/resources/id/action', 'stack_subres',
parts=['stack', 'resource', 'action'])), dict(
('event', url='/stacks/name/id/resources', parts=['stack', 'resources']
dict(url='/stacks/ignore/ignore/resources/ignore/events/id', ),
parts=['stack', 'resource', 'event'])), ),
('sd_metadata', dict(url='/software_deployments/metadata/ignore', (
parts=['software_deployment', 'metadata'])) 'stack_subres_id',
dict(
url='/stacks/name/id/resources/id', parts=['stack', 'resource']
),
),
(
'stack_subres_id_act',
dict(
url='/stacks/name/id/resources/id/action',
parts=['stack', 'resource', 'action'],
),
),
(
'event',
dict(
url='/stacks/ignore/ignore/resources/ignore/events/id',
parts=['stack', 'resource', 'event'],
),
),
(
'sd_metadata',
dict(
url='/software_deployments/metadata/ignore',
parts=['software_deployment', 'metadata'],
),
),
] ]
def test_extract_name(self): def test_extract_name(self):

View File

@ -17,13 +17,10 @@ from openstack.tests.unit import base
FAKE_ID = '32e39358-2422-4ad0-a1b5-dd60696bf564' FAKE_ID = '32e39358-2422-4ad0-a1b5-dd60696bf564'
FAKE_NAME = 'test_stack' FAKE_NAME = 'test_stack'
FAKE = { FAKE = {
'links': [{ 'links': [
'href': 'http://res_link', {'href': 'http://res_link', 'rel': 'self'},
'rel': 'self' {'href': 'http://stack_link', 'rel': 'stack'},
}, { ],
'href': 'http://stack_link',
'rel': 'stack'
}],
'logical_resource_id': 'the_resource', 'logical_resource_id': 'the_resource',
'name': 'the_resource', 'name': 'the_resource',
'physical_resource_id': '9f38ab5a-37c8-4e40-9702-ce27fc5f6954', 'physical_resource_id': '9f38ab5a-37c8-4e40-9702-ce27fc5f6954',
@ -36,13 +33,13 @@ FAKE = {
class TestResource(base.TestCase): class TestResource(base.TestCase):
def test_basic(self): def test_basic(self):
sot = resource.Resource() sot = resource.Resource()
self.assertEqual('resource', sot.resource_key) self.assertEqual('resource', sot.resource_key)
self.assertEqual('resources', sot.resources_key) self.assertEqual('resources', sot.resources_key)
self.assertEqual('/stacks/%(stack_name)s/%(stack_id)s/resources', self.assertEqual(
sot.base_path) '/stacks/%(stack_name)s/%(stack_id)s/resources', sot.base_path
)
self.assertFalse(sot.allow_create) self.assertFalse(sot.allow_create)
self.assertFalse(sot.allow_retrieve) self.assertFalse(sot.allow_retrieve)
self.assertFalse(sot.allow_commit) self.assertFalse(sot.allow_commit)
@ -54,8 +51,9 @@ class TestResource(base.TestCase):
self.assertEqual(FAKE['links'], sot.links) self.assertEqual(FAKE['links'], sot.links)
self.assertEqual(FAKE['logical_resource_id'], sot.logical_resource_id) self.assertEqual(FAKE['logical_resource_id'], sot.logical_resource_id)
self.assertEqual(FAKE['name'], sot.name) self.assertEqual(FAKE['name'], sot.name)
self.assertEqual(FAKE['physical_resource_id'], self.assertEqual(
sot.physical_resource_id) FAKE['physical_resource_id'], sot.physical_resource_id
)
self.assertEqual(FAKE['required_by'], sot.required_by) self.assertEqual(FAKE['required_by'], sot.required_by)
self.assertEqual(FAKE['resource_type'], sot.resource_type) self.assertEqual(FAKE['resource_type'], sot.resource_type)
self.assertEqual(FAKE['status'], sot.status) self.assertEqual(FAKE['status'], sot.status)

View File

@ -29,7 +29,6 @@ FAKE = {
class TestSoftwareConfig(base.TestCase): class TestSoftwareConfig(base.TestCase):
def test_basic(self): def test_basic(self):
sot = software_config.SoftwareConfig() sot = software_config.SoftwareConfig()
self.assertEqual('software_config', sot.resource_key) self.assertEqual('software_config', sot.resource_key)

View File

@ -30,7 +30,6 @@ FAKE = {
class TestSoftwareDeployment(base.TestCase): class TestSoftwareDeployment(base.TestCase):
def test_basic(self): def test_basic(self):
sot = software_deployment.SoftwareDeployment() sot = software_deployment.SoftwareDeployment()
self.assertEqual('software_deployment', sot.resource_key) self.assertEqual('software_deployment', sot.resource_key)
@ -49,8 +48,9 @@ class TestSoftwareDeployment(base.TestCase):
self.assertEqual(FAKE['config_id'], sot.config_id) self.assertEqual(FAKE['config_id'], sot.config_id)
self.assertEqual(FAKE['creation_time'], sot.created_at) self.assertEqual(FAKE['creation_time'], sot.created_at)
self.assertEqual(FAKE['server_id'], sot.server_id) self.assertEqual(FAKE['server_id'], sot.server_id)
self.assertEqual(FAKE['stack_user_project_id'], self.assertEqual(
sot.stack_user_project_id) FAKE['stack_user_project_id'], sot.stack_user_project_id
)
self.assertEqual(FAKE['input_values'], sot.input_values) self.assertEqual(FAKE['input_values'], sot.input_values)
self.assertEqual(FAKE['output_values'], sot.output_values) self.assertEqual(FAKE['output_values'], sot.output_values)
self.assertEqual(FAKE['status'], sot.status) self.assertEqual(FAKE['status'], sot.status)

View File

@ -31,9 +31,7 @@ FAKE = {
'files': {'file1': 'content'}, 'files': {'file1': 'content'},
'files_container': 'dummy_container', 'files_container': 'dummy_container',
'id': FAKE_ID, 'id': FAKE_ID,
'links': [{ 'links': [{'href': 'stacks/%s/%s' % (FAKE_NAME, FAKE_ID), 'rel': 'self'}],
'href': 'stacks/%s/%s' % (FAKE_NAME, FAKE_ID),
'rel': 'self'}],
'notification_topics': '7', 'notification_topics': '7',
'outputs': '8', 'outputs': '8',
'parameters': {'OS::stack_id': '9'}, 'parameters': {'OS::stack_id': '9'},
@ -49,81 +47,81 @@ FAKE = {
FAKE_CREATE_RESPONSE = { FAKE_CREATE_RESPONSE = {
'stack': { 'stack': {
'id': FAKE_ID, 'id': FAKE_ID,
'links': [{ 'links': [
'href': 'stacks/%s/%s' % (FAKE_NAME, FAKE_ID), {'href': 'stacks/%s/%s' % (FAKE_NAME, FAKE_ID), 'rel': 'self'}
'rel': 'self'}]} ],
}
} }
FAKE_UPDATE_PREVIEW_RESPONSE = { FAKE_UPDATE_PREVIEW_RESPONSE = {
'unchanged': [ 'unchanged': [
{ {
'updated_time': 'datetime', 'updated_time': 'datetime',
'resource_name': '', 'resource_name': '',
'physical_resource_id': '{resource id or ''}', 'physical_resource_id': '{resource id or ' '}',
'resource_action': 'CREATE', 'resource_action': 'CREATE',
'resource_status': 'COMPLETE', 'resource_status': 'COMPLETE',
'resource_status_reason': '', 'resource_status_reason': '',
'resource_type': 'restype', 'resource_type': 'restype',
'stack_identity': '{stack_id}', 'stack_identity': '{stack_id}',
'stack_name': '{stack_name}' 'stack_name': '{stack_name}',
} }
], ],
'updated': [ 'updated': [
{ {
'updated_time': 'datetime', 'updated_time': 'datetime',
'resource_name': '', 'resource_name': '',
'physical_resource_id': '{resource id or ''}', 'physical_resource_id': '{resource id or ' '}',
'resource_action': 'CREATE', 'resource_action': 'CREATE',
'resource_status': 'COMPLETE', 'resource_status': 'COMPLETE',
'resource_status_reason': '', 'resource_status_reason': '',
'resource_type': 'restype', 'resource_type': 'restype',
'stack_identity': '{stack_id}', 'stack_identity': '{stack_id}',
'stack_name': '{stack_name}' 'stack_name': '{stack_name}',
} }
], ],
'replaced': [ 'replaced': [
{ {
'updated_time': 'datetime', 'updated_time': 'datetime',
'resource_name': '', 'resource_name': '',
'physical_resource_id': '{resource id or ''}', 'physical_resource_id': '{resource id or ' '}',
'resource_action': 'CREATE', 'resource_action': 'CREATE',
'resource_status': 'COMPLETE', 'resource_status': 'COMPLETE',
'resource_status_reason': '', 'resource_status_reason': '',
'resource_type': 'restype', 'resource_type': 'restype',
'stack_identity': '{stack_id}', 'stack_identity': '{stack_id}',
'stack_name': '{stack_name}' 'stack_name': '{stack_name}',
} }
], ],
'added': [ 'added': [
{ {
'updated_time': 'datetime', 'updated_time': 'datetime',
'resource_name': '', 'resource_name': '',
'physical_resource_id': '{resource id or ''}', 'physical_resource_id': '{resource id or ' '}',
'resource_action': 'CREATE', 'resource_action': 'CREATE',
'resource_status': 'COMPLETE', 'resource_status': 'COMPLETE',
'resource_status_reason': '', 'resource_status_reason': '',
'resource_type': 'restype', 'resource_type': 'restype',
'stack_identity': '{stack_id}', 'stack_identity': '{stack_id}',
'stack_name': '{stack_name}' 'stack_name': '{stack_name}',
} }
], ],
'deleted': [ 'deleted': [
{ {
'updated_time': 'datetime', 'updated_time': 'datetime',
'resource_name': '', 'resource_name': '',
'physical_resource_id': '{resource id or ''}', 'physical_resource_id': '{resource id or ' '}',
'resource_action': 'CREATE', 'resource_action': 'CREATE',
'resource_status': 'COMPLETE', 'resource_status': 'COMPLETE',
'resource_status_reason': '', 'resource_status_reason': '',
'resource_type': 'restype', 'resource_type': 'restype',
'stack_identity': '{stack_id}', 'stack_identity': '{stack_id}',
'stack_name': '{stack_name}' 'stack_name': '{stack_name}',
} }
] ],
} }
class TestStack(base.TestCase): class TestStack(base.TestCase):
def test_basic(self): def test_basic(self):
sot = stack.Stack() sot = stack.Stack()
self.assertEqual('stack', sot.resource_key) self.assertEqual('stack', sot.resource_key)
@ -150,7 +148,8 @@ class TestStack(base.TestCase):
'tags': 'tags', 'tags': 'tags',
'username': 'username', 'username': 'username',
}, },
sot._query_mapping._mapping) sot._query_mapping._mapping,
)
def test_make_it(self): def test_make_it(self):
sot = stack.Stack(**FAKE) sot = stack.Stack(**FAKE)
@ -165,16 +164,16 @@ class TestStack(base.TestCase):
self.assertTrue(sot.is_rollback_disabled) self.assertTrue(sot.is_rollback_disabled)
self.assertEqual(FAKE['id'], sot.id) self.assertEqual(FAKE['id'], sot.id)
self.assertEqual(FAKE['links'], sot.links) self.assertEqual(FAKE['links'], sot.links)
self.assertEqual(FAKE['notification_topics'], self.assertEqual(FAKE['notification_topics'], sot.notification_topics)
sot.notification_topics)
self.assertEqual(FAKE['outputs'], sot.outputs) self.assertEqual(FAKE['outputs'], sot.outputs)
self.assertEqual(FAKE['parameters'], sot.parameters) self.assertEqual(FAKE['parameters'], sot.parameters)
self.assertEqual(FAKE['name'], sot.name) self.assertEqual(FAKE['name'], sot.name)
self.assertEqual(FAKE['status'], sot.status) self.assertEqual(FAKE['status'], sot.status)
self.assertEqual(FAKE['status_reason'], sot.status_reason) self.assertEqual(FAKE['status_reason'], sot.status_reason)
self.assertEqual(FAKE['tags'], sot.tags) self.assertEqual(FAKE['tags'], sot.tags)
self.assertEqual(FAKE['template_description'], self.assertEqual(
sot.template_description) FAKE['template_description'], sot.template_description
)
self.assertEqual(FAKE['template_url'], sot.template_url) self.assertEqual(FAKE['template_url'], sot.template_url)
self.assertEqual(FAKE['timeout_mins'], sot.timeout_mins) self.assertEqual(FAKE['timeout_mins'], sot.timeout_mins)
self.assertEqual(FAKE['updated_time'], sot.updated_at) self.assertEqual(FAKE['updated_time'], sot.updated_at)
@ -186,8 +185,9 @@ class TestStack(base.TestCase):
res = sot.create(sess) res = sot.create(sess)
mock_create.assert_called_once_with(sess, prepend_key=False, mock_create.assert_called_once_with(
base_path=None) sess, prepend_key=False, base_path=None
)
self.assertEqual(mock_create.return_value, res) self.assertEqual(mock_create.return_value, res)
@mock.patch.object(resource.Resource, 'commit') @mock.patch.object(resource.Resource, 'commit')
@ -197,9 +197,9 @@ class TestStack(base.TestCase):
res = sot.commit(sess) res = sot.commit(sess)
mock_commit.assert_called_once_with(sess, prepend_key=False, mock_commit.assert_called_once_with(
has_body=False, sess, prepend_key=False, has_body=False, base_path=None
base_path=None) )
self.assertEqual(mock_commit.return_value, res) self.assertEqual(mock_commit.return_value, res)
def test_check(self): def test_check(self):
@ -221,29 +221,33 @@ class TestStack(base.TestCase):
sess.get = mock.Mock() sess.get = mock.Mock()
sess.get.side_effect = [ sess.get.side_effect = [
test_resource.FakeResponse( test_resource.FakeResponse(
{'stack': {'stack_status': 'CREATE_COMPLETE'}}, 200), {'stack': {'stack_status': 'CREATE_COMPLETE'}}, 200
),
test_resource.FakeResponse( test_resource.FakeResponse(
{'stack': {'stack_status': 'CREATE_COMPLETE'}}, 200), {'stack': {'stack_status': 'CREATE_COMPLETE'}}, 200
),
exceptions.ResourceNotFound(message='oops'), exceptions.ResourceNotFound(message='oops'),
test_resource.FakeResponse( test_resource.FakeResponse(
{'stack': {'stack_status': 'DELETE_COMPLETE'}}, 200) {'stack': {'stack_status': 'DELETE_COMPLETE'}}, 200
),
] ]
self.assertEqual(sot, sot.fetch(sess)) self.assertEqual(sot, sot.fetch(sess))
sess.get.assert_called_with( sess.get.assert_called_with(
'stacks/{id}'.format(id=sot.id), 'stacks/{id}'.format(id=sot.id),
microversion=None, microversion=None,
skip_cache=False) skip_cache=False,
)
sot.fetch(sess, resolve_outputs=False) sot.fetch(sess, resolve_outputs=False)
sess.get.assert_called_with( sess.get.assert_called_with(
'stacks/{id}?resolve_outputs=False'.format(id=sot.id), 'stacks/{id}?resolve_outputs=False'.format(id=sot.id),
microversion=None, microversion=None,
skip_cache=False) skip_cache=False,
)
ex = self.assertRaises(exceptions.ResourceNotFound, sot.fetch, sess) ex = self.assertRaises(exceptions.ResourceNotFound, sot.fetch, sess)
self.assertEqual('oops', str(ex)) self.assertEqual('oops', str(ex))
ex = self.assertRaises(exceptions.ResourceNotFound, sot.fetch, sess) ex = self.assertRaises(exceptions.ResourceNotFound, sot.fetch, sess)
self.assertEqual('No stack found for %s' % FAKE_ID, self.assertEqual('No stack found for %s' % FAKE_ID, str(ex))
str(ex))
def test_abandon(self): def test_abandon(self):
sess = mock.Mock() sess = mock.Mock()
@ -260,7 +264,6 @@ class TestStack(base.TestCase):
sess.delete.assert_called_with( sess.delete.assert_called_with(
'stacks/%s/%s/abandon' % (FAKE_NAME, FAKE_ID), 'stacks/%s/%s/abandon' % (FAKE_NAME, FAKE_ID),
) )
def test_update(self): def test_update(self):
@ -281,7 +284,7 @@ class TestStack(base.TestCase):
'/stacks/%s/%s' % (FAKE_NAME, FAKE_ID), '/stacks/%s/%s' % (FAKE_NAME, FAKE_ID),
headers={}, headers={},
microversion=None, microversion=None,
json=body json=body,
) )
def test_update_preview(self): def test_update_preview(self):
@ -302,21 +305,15 @@ class TestStack(base.TestCase):
'stacks/%s/%s/preview' % (FAKE_NAME, FAKE_ID), 'stacks/%s/%s/preview' % (FAKE_NAME, FAKE_ID),
headers={}, headers={},
microversion=None, microversion=None,
json=body json=body,
) )
self.assertEqual(FAKE_UPDATE_PREVIEW_RESPONSE['added'], ret.added)
self.assertEqual(FAKE_UPDATE_PREVIEW_RESPONSE['deleted'], ret.deleted)
self.assertEqual( self.assertEqual(
FAKE_UPDATE_PREVIEW_RESPONSE['added'], FAKE_UPDATE_PREVIEW_RESPONSE['replaced'], ret.replaced
ret.added) )
self.assertEqual( self.assertEqual(
FAKE_UPDATE_PREVIEW_RESPONSE['deleted'], FAKE_UPDATE_PREVIEW_RESPONSE['unchanged'], ret.unchanged
ret.deleted) )
self.assertEqual( self.assertEqual(FAKE_UPDATE_PREVIEW_RESPONSE['updated'], ret.updated)
FAKE_UPDATE_PREVIEW_RESPONSE['replaced'],
ret.replaced)
self.assertEqual(
FAKE_UPDATE_PREVIEW_RESPONSE['unchanged'],
ret.unchanged)
self.assertEqual(
FAKE_UPDATE_PREVIEW_RESPONSE['updated'],
ret.updated)

View File

@ -16,27 +16,14 @@ from openstack.tests.unit import base
FAKE = { FAKE = {
'encrypted_param_names': ['n1', 'n2'], 'encrypted_param_names': ['n1', 'n2'],
'event_sinks': { 'event_sinks': {'s1': 'v1'},
's1': 'v1' 'parameters': {'key_name': {'type': 'string'}},
}, 'parameter_defaults': {'p1': 'def1'},
'parameters': { 'resource_registry': {'resources': {'type1': 'type2'}},
'key_name': {
'type': 'string'
}
},
'parameter_defaults': {
'p1': 'def1'
},
'resource_registry': {
'resources': {
'type1': 'type2'
}
},
} }
class TestStackTemplate(base.TestCase): class TestStackTemplate(base.TestCase):
def test_basic(self): def test_basic(self):
sot = se.StackEnvironment() sot = se.StackEnvironment()
self.assertFalse(sot.allow_create) self.assertFalse(sot.allow_create)
@ -47,8 +34,9 @@ class TestStackTemplate(base.TestCase):
def test_make_it(self): def test_make_it(self):
sot = se.StackEnvironment(**FAKE) sot = se.StackEnvironment(**FAKE)
self.assertEqual(FAKE['encrypted_param_names'], self.assertEqual(
sot.encrypted_param_names) FAKE['encrypted_param_names'], sot.encrypted_param_names
)
self.assertEqual(FAKE['event_sinks'], sot.event_sinks) self.assertEqual(FAKE['event_sinks'], sot.event_sinks)
self.assertEqual(FAKE['parameters'], sot.parameters) self.assertEqual(FAKE['parameters'], sot.parameters)
self.assertEqual(FAKE['parameter_defaults'], sot.parameter_defaults) self.assertEqual(FAKE['parameter_defaults'], sot.parameter_defaults)

View File

@ -16,14 +16,10 @@ from openstack.orchestration.v1 import stack_files as sf
from openstack import resource from openstack import resource
from openstack.tests.unit import base from openstack.tests.unit import base
FAKE = { FAKE = {'stack_id': 'ID', 'stack_name': 'NAME'}
'stack_id': 'ID',
'stack_name': 'NAME'
}
class TestStackFiles(base.TestCase): class TestStackFiles(base.TestCase):
def test_basic(self): def test_basic(self):
sot = sf.StackFiles() sot = sf.StackFiles()
self.assertFalse(sot.allow_create) self.assertFalse(sot.allow_create)
@ -48,9 +44,10 @@ class TestStackFiles(base.TestCase):
sot = sf.StackFiles(**FAKE) sot = sf.StackFiles(**FAKE)
req = mock.MagicMock() req = mock.MagicMock()
req.url = ('/stacks/%(stack_name)s/%(stack_id)s/files' % req.url = '/stacks/%(stack_name)s/%(stack_id)s/files' % {
{'stack_name': FAKE['stack_name'], 'stack_name': FAKE['stack_name'],
'stack_id': FAKE['stack_id']}) 'stack_id': FAKE['stack_id'],
}
mock_prepare_request.return_value = req mock_prepare_request.return_value = req
files = sot.fetch(sess) files = sot.fetch(sess)

View File

@ -19,25 +19,14 @@ from openstack.tests.unit import base
FAKE = { FAKE = {
'description': 'template description', 'description': 'template description',
'heat_template_version': '2014-10-16', 'heat_template_version': '2014-10-16',
'parameters': { 'parameters': {'key_name': {'type': 'string'}},
'key_name': { 'resources': {'resource1': {'type': 'ResourceType'}},
'type': 'string'
}
},
'resources': {
'resource1': {
'type': 'ResourceType'
}
},
'conditions': {'cd1': True}, 'conditions': {'cd1': True},
'outputs': { 'outputs': {'key1': 'value1'},
'key1': 'value1'
}
} }
class TestStackTemplate(base.TestCase): class TestStackTemplate(base.TestCase):
def test_basic(self): def test_basic(self):
sot = stack_template.StackTemplate() sot = stack_template.StackTemplate()
self.assertFalse(sot.allow_create) self.assertFalse(sot.allow_create)
@ -49,8 +38,9 @@ class TestStackTemplate(base.TestCase):
def test_make_it(self): def test_make_it(self):
sot = stack_template.StackTemplate(**FAKE) sot = stack_template.StackTemplate(**FAKE)
self.assertEqual(FAKE['description'], sot.description) self.assertEqual(FAKE['description'], sot.description)
self.assertEqual(FAKE['heat_template_version'], self.assertEqual(
sot.heat_template_version) FAKE['heat_template_version'], sot.heat_template_version
)
self.assertEqual(FAKE['outputs'], sot.outputs) self.assertEqual(FAKE['outputs'], sot.outputs)
self.assertEqual(FAKE['parameters'], sot.parameters) self.assertEqual(FAKE['parameters'], sot.parameters)
self.assertEqual(FAKE['resources'], sot.resources) self.assertEqual(FAKE['resources'], sot.resources)
@ -58,17 +48,28 @@ class TestStackTemplate(base.TestCase):
def test_to_dict(self): def test_to_dict(self):
fake_sot = copy.deepcopy(FAKE) fake_sot = copy.deepcopy(FAKE)
fake_sot['parameter_groups'] = [{ fake_sot['parameter_groups'] = [
"description": "server parameters", {
"parameters": ["key_name", "image_id"], "description": "server parameters",
"label": "server_parameters"}] "parameters": ["key_name", "image_id"],
"label": "server_parameters",
}
]
fake_sot['location'] = None fake_sot['location'] = None
fake_sot['id'] = None fake_sot['id'] = None
fake_sot['name'] = None fake_sot['name'] = None
for temp_version in ['2016-10-14', '2017-02-24', '2017-02-24', for temp_version in [
'2017-09-01', '2018-03-02', 'newton', '2016-10-14',
'ocata', 'pike', 'queens']: '2017-02-24',
'2017-02-24',
'2017-09-01',
'2018-03-02',
'newton',
'ocata',
'pike',
'queens',
]:
fake_sot['heat_template_version'] = temp_version fake_sot['heat_template_version'] = temp_version
sot = stack_template.StackTemplate(**fake_sot) sot = stack_template.StackTemplate(**fake_sot)
self.assertEqual(fake_sot, sot.to_dict()) self.assertEqual(fake_sot, sot.to_dict())

View File

@ -18,20 +18,12 @@ from openstack.tests.unit import base
FAKE = { FAKE = {
'Description': 'Blah blah', 'Description': 'Blah blah',
'Parameters': { 'Parameters': {'key_name': {'type': 'string'}},
'key_name': { 'ParameterGroups': [{'label': 'Group 1', 'parameters': ['key_name']}],
'type': 'string'
}
},
'ParameterGroups': [{
'label': 'Group 1',
'parameters': ['key_name']
}]
} }
class TestTemplate(base.TestCase): class TestTemplate(base.TestCase):
def test_basic(self): def test_basic(self):
sot = template.Template() sot = template.Template()
self.assertFalse(sot.allow_create) self.assertFalse(sot.allow_create)
@ -55,8 +47,7 @@ class TestTemplate(base.TestCase):
sot.validate(sess, tmpl) sot.validate(sess, tmpl)
sess.post.assert_called_once_with( sess.post.assert_called_once_with('/validate', json=body)
'/validate', json=body)
mock_translate.assert_called_once_with(sess.post.return_value) mock_translate.assert_called_once_with(sess.post.return_value)
@mock.patch.object(resource.Resource, '_translate_response') @mock.patch.object(resource.Resource, '_translate_response')
@ -69,8 +60,7 @@ class TestTemplate(base.TestCase):
sot.validate(sess, tmpl, environment=env) sot.validate(sess, tmpl, environment=env)
sess.post.assert_called_once_with( sess.post.assert_called_once_with('/validate', json=body)
'/validate', json=body)
mock_translate.assert_called_once_with(sess.post.return_value) mock_translate.assert_called_once_with(sess.post.return_value)
@mock.patch.object(resource.Resource, '_translate_response') @mock.patch.object(resource.Resource, '_translate_response')
@ -82,8 +72,7 @@ class TestTemplate(base.TestCase):
sot.validate(sess, None, template_url=template_url) sot.validate(sess, None, template_url=template_url)
sess.post.assert_called_once_with( sess.post.assert_called_once_with('/validate', json=body)
'/validate', json=body)
mock_translate.assert_called_once_with(sess.post.return_value) mock_translate.assert_called_once_with(sess.post.return_value)
@mock.patch.object(resource.Resource, '_translate_response') @mock.patch.object(resource.Resource, '_translate_response')
@ -96,6 +85,6 @@ class TestTemplate(base.TestCase):
sot.validate(sess, tmpl, ignore_errors='123,456') sot.validate(sess, tmpl, ignore_errors='123,456')
sess.post.assert_called_once_with( sess.post.assert_called_once_with(
'/validate?ignore_errors=123%2C456', '/validate?ignore_errors=123%2C456', json=body
json=body) )
mock_translate.assert_called_once_with(sess.post.return_value) mock_translate.assert_called_once_with(sess.post.return_value)