Jakob Meng 1b38b7c500 Properly documented openstacksdk version requirements
With "extends_documentation_fragment: ['openstack.cloud.openstack']"
it is not necessary to list required Python libraries in section
'requirements' of DOCUMENTATION docstring in modules. Ansible will
merge requirements from doc fragments and DOCUMENTATION docstring
which previously resulted in duplicates such as in server module [0]:

* openstacksdk
* openstacksdk >= 0.36, < 0.99.0
* python >= 3.6

When removing the 'requirements' section from server module, then
Ansible will list openstacksdk once only:

* openstacksdk >= 0.36, < 0.99.0
* python >= 3.6

To see what documentation Ansible will produce for server module run:

  ansible-doc --type module openstack.cloud.server

[0] https://docs.ansible.com/ansible/latest/collections/openstack/\
    cloud/server_module.html

Change-Id: I727ed95ee480bb644b5a533f6a9526973677064c
2023-01-16 13:51:01 +01:00

203 lines
6.0 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) 2021 by Uemit Seren <uemit.seren@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
DOCUMENTATION = '''
---
module: address_scope
short_description: Create or delete address scopes from OpenStack
author: OpenStack Ansible SIG
description:
- Create or Delete address scopes from OpenStack.
options:
state:
description:
- Indicate desired state of the resource
choices: ['present', 'absent']
default: present
type: str
name:
description:
- Name to be give to the address scope
- This option cannot be updated.
required: true
type: str
project:
description:
- Unique name or ID of the project.
- This option cannot be updated.
type: str
ip_version:
description:
- The IP version of the subnet 4 or 6.
- This option cannot be updated.
default: '4'
type: str
choices: ['4', '6']
is_shared:
description:
- Whether this address scope is shared or not.
type: bool
default: 'no'
aliases: ['shared']
extra_specs:
description:
- Dictionary with extra key/value pairs passed to the API
default: {}
type: dict
extends_documentation_fragment:
- openstack.cloud.openstack
'''
EXAMPLES = '''
# Create an IPv4 address scope.
- openstack.cloud.address_scope:
cloud: mycloud
state: present
name: my_adress_scope
# Create a shared IPv6 address scope for a given project.
- openstack.cloud.address_scope:
cloud: mycloud
state: present
ip_version: 6
name: ipv6_address_scope
project: myproj
# Delete address scope.
- openstack.cloud.address_scope:
cloud: mycloud
state: absent
name: my_adress_scope
'''
RETURN = '''
address_scope:
description: Dictionary describing the address scope.
returned: On success when I(state) is 'present'
type: dict
contains:
id:
description: Address Scope ID.
type: str
sample: "474acfe5-be34-494c-b339-50f06aa143e4"
ip_version:
description: The IP version of the subnet 4 or 6.
type: str
sample: "4"
is_shared:
description: Indicates whether this address scope is shared across
all tenants.
type: bool
sample: false
name:
description: Address Scope name.
type: str
sample: "my_address_scope"
project_id:
description: The project ID
type: str
sample: "474acfe5-be34-494c-b339-50f06aa143e4"
tenant_id:
description: The tenant ID.
type: str
sample: "861174b82b43463c9edc5202aadc60ef"
'''
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
class AddressScopeModule(OpenStackModule):
argument_spec = dict(
state=dict(default='present', choices=['absent', 'present']),
name=dict(required=True),
is_shared=dict(default=False, type='bool', aliases=['shared']),
ip_version=dict(default='4', choices=['4', '6']),
project=dict(),
extra_specs=dict(type='dict', default=dict())
)
def _needs_update(self, address_scope):
"""Decide if the given address_scope needs an update.
"""
if address_scope['is_shared'] != self.params['is_shared']:
return True
return False
def _system_state_change(self, address_scope):
"""Check if the system state would be changed."""
state = self.params['state']
if state == 'absent' and address_scope:
return True
if state == 'present':
if not address_scope:
return True
return self._needs_update(address_scope)
return False
def run(self):
state = self.params['state']
name = self.params['name']
is_shared = self.params['is_shared']
ip_version = self.params['ip_version']
project_name_or_id = self.params['project']
extra_specs = self.params['extra_specs']
if project_name_or_id is not None:
project_id = self.conn.identity.find_project(
project_name_or_id, ignore_missing=False)['id']
else:
project_id = self.conn.session.get_project_id()
address_scope = self.conn.network.find_address_scope(
name_or_id=name, project_id=project_id)
if self.ansible.check_mode:
self.exit_json(
changed=self._system_state_change(address_scope)
)
if state == 'present':
changed = False
if not address_scope:
kwargs = dict(
name=name,
ip_version=ip_version,
is_shared=is_shared,
project_id=project_id)
dup_args = set(kwargs.keys()) & set(extra_specs.keys())
if dup_args:
raise ValueError('Duplicate key(s) {0} in extra_specs'
.format(list(dup_args)))
kwargs = dict(kwargs, **extra_specs)
address_scope = \
self.conn.network.create_address_scope(**kwargs)
changed = True
elif self._needs_update(address_scope):
address_scope = self.conn.network.update_address_scope(
address_scope['id'], is_shared=is_shared)
changed = True
self.exit_json(changed=changed,
address_scope=address_scope.to_dict(computed=False))
elif state == 'absent':
if not address_scope:
self.exit_json(changed=False)
else:
self.conn.network.delete_address_scope(address_scope['id'])
self.exit_json(changed=True)
def main():
module = AddressScopeModule()
module()
if __name__ == '__main__':
main()