572fe85894
It's not required for collections, for more details: https://github.com/ansible-collections/overview/issues/57 Change-Id: I954eef25bb9837c9282665ad5586dbe37f4f4424
277 lines
9.5 KiB
Python
277 lines
9.5 KiB
Python
#!/usr/bin/python
|
|
# coding: utf-8 -*-
|
|
|
|
# (c) 2016, Mathieu Bultel <mbultel@redhat.com>
|
|
# (c) 2016, Steve Baker <sbaker@redhat.com>
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
|
|
DOCUMENTATION = '''
|
|
---
|
|
module: stack
|
|
short_description: Add/Remove Heat Stack
|
|
author:
|
|
- "Mathieu Bultel (@matbu)"
|
|
- "Steve Baker (@steveb)"
|
|
description:
|
|
- Add or Remove a Stack to an OpenStack Heat
|
|
options:
|
|
state:
|
|
description:
|
|
- Indicate desired state of the resource
|
|
choices: ['present', 'absent']
|
|
default: present
|
|
type: str
|
|
name:
|
|
description:
|
|
- Name of the stack that should be created, name could be char and digit, no space
|
|
required: true
|
|
type: str
|
|
tag:
|
|
description:
|
|
- Tag for the stack that should be created, name could be char and digit, no space
|
|
type: str
|
|
template:
|
|
description:
|
|
- Path of the template file to use for the stack creation
|
|
type: str
|
|
environment:
|
|
description:
|
|
- List of environment files that should be used for the stack creation
|
|
type: list
|
|
elements: str
|
|
parameters:
|
|
description:
|
|
- Dictionary of parameters for the stack creation
|
|
type: dict
|
|
rollback:
|
|
description:
|
|
- Rollback stack creation
|
|
type: bool
|
|
default: false
|
|
timeout:
|
|
description:
|
|
- Maximum number of seconds to wait for the stack creation
|
|
default: 3600
|
|
type: int
|
|
requirements:
|
|
- "python >= 3.6"
|
|
- "openstacksdk"
|
|
|
|
extends_documentation_fragment:
|
|
- openstack.cloud.openstack
|
|
'''
|
|
EXAMPLES = '''
|
|
---
|
|
- name: create stack
|
|
ignore_errors: True
|
|
register: stack_create
|
|
openstack.cloud.stack:
|
|
name: "{{ stack_name }}"
|
|
tag: "{{ tag_name }}"
|
|
state: present
|
|
template: "/path/to/my_stack.yaml"
|
|
environment:
|
|
- /path/to/resource-registry.yaml
|
|
- /path/to/environment.yaml
|
|
parameters:
|
|
bmc_flavor: m1.medium
|
|
bmc_image: CentOS
|
|
key_name: default
|
|
private_net: "{{ private_net_param }}"
|
|
node_count: 2
|
|
name: undercloud
|
|
image: CentOS
|
|
my_flavor: m1.large
|
|
external_net: "{{ external_net_param }}"
|
|
'''
|
|
|
|
RETURN = '''
|
|
id:
|
|
description: Stack ID.
|
|
type: str
|
|
sample: "97a3f543-8136-4570-920e-fd7605c989d6"
|
|
returned: always
|
|
|
|
stack:
|
|
description: stack info
|
|
type: complex
|
|
returned: always
|
|
contains:
|
|
action:
|
|
description: Action, could be Create or Update.
|
|
type: str
|
|
sample: "CREATE"
|
|
creation_time:
|
|
description: Time when the action has been made.
|
|
type: str
|
|
sample: "2016-07-05T17:38:12Z"
|
|
description:
|
|
description: Description of the Stack provided in the heat template.
|
|
type: str
|
|
sample: "HOT template to create a new instance and networks"
|
|
id:
|
|
description: Stack ID.
|
|
type: str
|
|
sample: "97a3f543-8136-4570-920e-fd7605c989d6"
|
|
name:
|
|
description: Name of the Stack
|
|
type: str
|
|
sample: "test-stack"
|
|
identifier:
|
|
description: Identifier of the current Stack action.
|
|
type: str
|
|
sample: "test-stack/97a3f543-8136-4570-920e-fd7605c989d6"
|
|
links:
|
|
description: Links to the current Stack.
|
|
type: list
|
|
elements: dict
|
|
sample: "[{'href': 'http://foo:8004/v1/7f6a/stacks/test-stack/97a3f543-8136-4570-920e-fd7605c989d6']"
|
|
outputs:
|
|
description: Output returned by the Stack.
|
|
type: list
|
|
elements: dict
|
|
sample: "{'description': 'IP address of server1 in private network',
|
|
'output_key': 'server1_private_ip',
|
|
'output_value': '10.1.10.103'}"
|
|
parameters:
|
|
description: Parameters of the current Stack
|
|
type: dict
|
|
sample: "{'OS::project_id': '7f6a3a3e01164a4eb4eecb2ab7742101',
|
|
'OS::stack_id': '97a3f543-8136-4570-920e-fd7605c989d6',
|
|
'OS::stack_name': 'test-stack',
|
|
'stack_status': 'CREATE_COMPLETE',
|
|
'stack_status_reason': 'Stack CREATE completed successfully',
|
|
'status': 'COMPLETE',
|
|
'template_description': 'HOT template to create a new instance and networks',
|
|
'timeout_mins': 60,
|
|
'updated_time': null}"
|
|
'''
|
|
|
|
from ansible.module_utils.basic import AnsibleModule
|
|
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
|
openstack_module_kwargs,
|
|
openstack_cloud_from_module)
|
|
from ansible.module_utils._text import to_native
|
|
from distutils.version import StrictVersion
|
|
|
|
|
|
def _create_stack(module, stack, cloud, sdk, parameters):
|
|
try:
|
|
stack = cloud.create_stack(module.params['name'],
|
|
template_file=module.params['template'],
|
|
environment_files=module.params['environment'],
|
|
timeout=module.params['timeout'],
|
|
wait=True,
|
|
rollback=module.params['rollback'],
|
|
**parameters)
|
|
|
|
stack = cloud.get_stack(stack.id, None)
|
|
if stack.stack_status == 'CREATE_COMPLETE':
|
|
return stack
|
|
else:
|
|
module.fail_json(msg="Failure in creating stack: {0}".format(stack))
|
|
except sdk.exceptions.OpenStackCloudException as e:
|
|
if hasattr(e, 'response'):
|
|
module.fail_json(msg=to_native(e), response=e.response.json())
|
|
else:
|
|
module.fail_json(msg=to_native(e))
|
|
|
|
|
|
def _update_stack(module, stack, cloud, sdk, parameters):
|
|
try:
|
|
stack = cloud.update_stack(
|
|
module.params['name'],
|
|
template_file=module.params['template'],
|
|
environment_files=module.params['environment'],
|
|
timeout=module.params['timeout'],
|
|
rollback=module.params['rollback'],
|
|
wait=module.params['wait'],
|
|
**parameters)
|
|
|
|
if stack['stack_status'] == 'UPDATE_COMPLETE':
|
|
return stack
|
|
else:
|
|
module.fail_json(msg="Failure in updating stack: %s" %
|
|
stack['stack_status_reason'])
|
|
except sdk.exceptions.OpenStackCloudException as e:
|
|
if hasattr(e, 'response'):
|
|
module.fail_json(msg=to_native(e), response=e.response.json())
|
|
else:
|
|
module.fail_json(msg=to_native(e))
|
|
|
|
|
|
def _system_state_change(module, stack, cloud):
|
|
state = module.params['state']
|
|
if state == 'present':
|
|
if not stack:
|
|
return True
|
|
if state == 'absent' and stack:
|
|
return True
|
|
return False
|
|
|
|
|
|
def main():
|
|
|
|
argument_spec = openstack_full_argument_spec(
|
|
name=dict(required=True),
|
|
tag=dict(required=False, default=None),
|
|
template=dict(default=None),
|
|
environment=dict(default=None, type='list', elements='str'),
|
|
parameters=dict(default={}, type='dict'),
|
|
rollback=dict(default=False, type='bool'),
|
|
timeout=dict(default=3600, type='int'),
|
|
state=dict(default='present', choices=['absent', 'present']),
|
|
)
|
|
|
|
module_kwargs = openstack_module_kwargs()
|
|
module = AnsibleModule(argument_spec,
|
|
supports_check_mode=True,
|
|
**module_kwargs)
|
|
|
|
state = module.params['state']
|
|
name = module.params['name']
|
|
# Check for required parameters when state == 'present'
|
|
if state == 'present':
|
|
for p in ['template']:
|
|
if not module.params[p]:
|
|
module.fail_json(msg='%s required with present state' % p)
|
|
|
|
sdk, cloud = openstack_cloud_from_module(module)
|
|
try:
|
|
stack = cloud.get_stack(name)
|
|
|
|
if module.check_mode:
|
|
module.exit_json(changed=_system_state_change(module, stack, cloud))
|
|
|
|
if state == 'present':
|
|
parameters = module.params['parameters']
|
|
if module.params['tag']:
|
|
parameters['tags'] = module.params['tag']
|
|
min_version = '0.28.0'
|
|
if StrictVersion(sdk.version.__version__) < StrictVersion(min_version) and stack:
|
|
module.warn("To update tags using openstack.cloud.stack module, the"
|
|
"installed version of the openstacksdk"
|
|
"library MUST be >={min_version}"
|
|
"".format(min_version=min_version))
|
|
if not stack:
|
|
stack = _create_stack(module, stack, cloud, sdk, parameters)
|
|
else:
|
|
stack = _update_stack(module, stack, cloud, sdk, parameters)
|
|
module.exit_json(changed=True,
|
|
stack=stack,
|
|
id=stack.id)
|
|
elif state == 'absent':
|
|
if not stack:
|
|
changed = False
|
|
else:
|
|
changed = True
|
|
if not cloud.delete_stack(name, wait=module.params['wait']):
|
|
module.fail_json(msg='delete stack failed for stack: %s' % name)
|
|
module.exit_json(changed=changed)
|
|
except sdk.exceptions.OpenStackCloudException as e:
|
|
module.fail_json(msg=to_native(e))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|