1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2026-04-13 15:35:08 +00:00

Initial commit

This commit is contained in:
Ansible Core Team 2020-03-09 09:11:07 +00:00
commit aebc1b03fd
4861 changed files with 812621 additions and 0 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,497 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 Huawei
# GNU General Public License v3.0+ (see COPYING or
# https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
###############################################################################
# Documentation
###############################################################################
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ["preview"],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: hwc_network_vpc
description:
- Represents an vpc resource.
short_description: Creates a Huawei Cloud VPC
author: Huawei Inc. (@huaweicloud)
requirements:
- requests >= 2.18.4
- keystoneauth1 >= 3.6.0
options:
state:
description:
- Whether the given object should exist in vpc.
type: str
choices: ['present', 'absent']
default: 'present'
timeouts:
description:
- The timeouts for each operations.
type: dict
suboptions:
create:
description:
- The timeout for create operation.
type: str
default: '15m'
update:
description:
- The timeout for update operation.
type: str
default: '15m'
delete:
description:
- The timeout for delete operation.
type: str
default: '15m'
name:
description:
- The name of vpc.
type: str
required: true
cidr:
description:
- The range of available subnets in the vpc.
type: str
required: true
extends_documentation_fragment:
- community.general.hwc
'''
EXAMPLES = '''
- name: create a vpc
hwc_network_vpc:
identity_endpoint: "{{ identity_endpoint }}"
user: "{{ user }}"
password: "{{ password }}"
domain: "{{ domain }}"
project: "{{ project }}"
region: "{{ region }}"
name: "vpc_1"
cidr: "192.168.100.0/24"
state: present
'''
RETURN = '''
id:
description:
- the id of vpc.
type: str
returned: success
name:
description:
- the name of vpc.
type: str
returned: success
cidr:
description:
- the range of available subnets in the vpc.
type: str
returned: success
status:
description:
- the status of vpc.
type: str
returned: success
routes:
description:
- the route information.
type: complex
returned: success
contains:
destination:
description:
- the destination network segment of a route.
type: str
returned: success
next_hop:
description:
- the next hop of a route. If the route type is peering,
it will provide VPC peering connection ID.
type: str
returned: success
enable_shared_snat:
description:
- show whether the shared snat is enabled.
type: bool
returned: success
'''
###############################################################################
# Imports
###############################################################################
from ansible_collections.community.general.plugins.module_utils.hwc_utils import (Config, HwcClientException,
HwcClientException404, HwcModule,
are_different_dicts, is_empty_value,
wait_to_finish, get_region,
build_path, navigate_value)
import re
###############################################################################
# Main
###############################################################################
def main():
"""Main function"""
module = HwcModule(
argument_spec=dict(
state=dict(
default='present', choices=['present', 'absent'], type='str'),
timeouts=dict(type='dict', options=dict(
create=dict(default='15m', type='str'),
update=dict(default='15m', type='str'),
delete=dict(default='15m', type='str'),
), default=dict()),
name=dict(required=True, type='str'),
cidr=dict(required=True, type='str')
),
supports_check_mode=True,
)
config = Config(module, 'vpc')
state = module.params['state']
if (not module.params.get("id")) and module.params.get("name"):
module.params['id'] = get_id_by_name(config)
fetch = None
link = self_link(module)
# the link will include Nones if required format parameters are missed
if not re.search('/None/|/None$', link):
client = config.client(get_region(module), "vpc", "project")
fetch = fetch_resource(module, client, link)
if fetch:
fetch = fetch.get('vpc')
changed = False
if fetch:
if state == 'present':
expect = _get_editable_properties(module)
current_state = response_to_hash(module, fetch)
current = {"cidr": current_state["cidr"]}
if are_different_dicts(expect, current):
if not module.check_mode:
fetch = update(config, self_link(module))
fetch = response_to_hash(module, fetch.get('vpc'))
changed = True
else:
fetch = current_state
else:
if not module.check_mode:
delete(config, self_link(module))
fetch = {}
changed = True
else:
if state == 'present':
if not module.check_mode:
fetch = create(config, "vpcs")
fetch = response_to_hash(module, fetch.get('vpc'))
changed = True
else:
fetch = {}
fetch.update({'changed': changed})
module.exit_json(**fetch)
def create(config, link):
module = config.module
client = config.client(get_region(module), "vpc", "project")
r = None
try:
r = client.post(link, resource_to_create(module))
except HwcClientException as ex:
msg = ("module(hwc_network_vpc): error creating "
"resource, error: %s" % str(ex))
module.fail_json(msg=msg)
wait_done = wait_for_operation(config, 'create', r)
v = ""
try:
v = navigate_value(wait_done, ['vpc', 'id'])
except Exception as ex:
module.fail_json(msg=str(ex))
url = build_path(module, 'vpcs/{op_id}', {'op_id': v})
return fetch_resource(module, client, url)
def update(config, link):
module = config.module
client = config.client(get_region(module), "vpc", "project")
r = None
try:
r = client.put(link, resource_to_update(module))
except HwcClientException as ex:
msg = ("module(hwc_network_vpc): error updating "
"resource, error: %s" % str(ex))
module.fail_json(msg=msg)
wait_for_operation(config, 'update', r)
return fetch_resource(module, client, link)
def delete(config, link):
module = config.module
client = config.client(get_region(module), "vpc", "project")
try:
client.delete(link)
except HwcClientException as ex:
msg = ("module(hwc_network_vpc): error deleting "
"resource, error: %s" % str(ex))
module.fail_json(msg=msg)
wait_for_delete(module, client, link)
def fetch_resource(module, client, link):
try:
return client.get(link)
except HwcClientException as ex:
msg = ("module(hwc_network_vpc): error fetching "
"resource, error: %s" % str(ex))
module.fail_json(msg=msg)
def get_id_by_name(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
name = module.params.get("name")
link = "vpcs"
query_link = "?marker={marker}&limit=10"
link += query_link
not_format_keys = re.findall("={marker}", link)
none_values = re.findall("=None", link)
if not (not_format_keys or none_values):
r = None
try:
r = client.get(link)
except Exception:
pass
if r is None:
return None
r = r.get('vpcs', [])
ids = [
i.get('id') for i in r if i.get('name', '') == name
]
if not ids:
return None
elif len(ids) == 1:
return ids[0]
else:
module.fail_json(
msg="Multiple resources with same name are found.")
elif none_values:
module.fail_json(
msg="Can not find id by name because url includes None.")
else:
p = {'marker': ''}
ids = set()
while True:
r = None
try:
r = client.get(link.format(**p))
except Exception:
pass
if r is None:
break
r = r.get('vpcs', [])
if r == []:
break
for i in r:
if i.get('name') == name:
ids.add(i.get('id'))
if len(ids) >= 2:
module.fail_json(
msg="Multiple resources with same name are found.")
p['marker'] = r[-1].get('id')
return ids.pop() if ids else None
def self_link(module):
return build_path(module, "vpcs/{id}")
def resource_to_create(module):
params = dict()
v = module.params.get('cidr')
if not is_empty_value(v):
params["cidr"] = v
v = module.params.get('name')
if not is_empty_value(v):
params["name"] = v
if not params:
return params
params = {"vpc": params}
return params
def resource_to_update(module):
params = dict()
v = module.params.get('cidr')
if not is_empty_value(v):
params["cidr"] = v
if not params:
return params
params = {"vpc": params}
return params
def _get_editable_properties(module):
return {
"cidr": module.params.get("cidr"),
}
def response_to_hash(module, response):
""" Remove unnecessary properties from the response.
This is for doing comparisons with Ansible's current parameters.
"""
return {
u'id': response.get(u'id'),
u'name': response.get(u'name'),
u'cidr': response.get(u'cidr'),
u'status': response.get(u'status'),
u'routes': VpcRoutesArray(
response.get(u'routes', []), module).from_response(),
u'enable_shared_snat': response.get(u'enable_shared_snat')
}
def wait_for_operation(config, op_type, op_result):
module = config.module
op_id = ""
try:
op_id = navigate_value(op_result, ['vpc', 'id'])
except Exception as ex:
module.fail_json(msg=str(ex))
url = build_path(module, "vpcs/{op_id}", {'op_id': op_id})
timeout = 60 * int(module.params['timeouts'][op_type].rstrip('m'))
states = {
'create': {
'allowed': ['CREATING', 'DONW', 'OK'],
'complete': ['OK'],
},
'update': {
'allowed': ['PENDING_UPDATE', 'DONW', 'OK'],
'complete': ['OK'],
}
}
return wait_for_completion(url, timeout, states[op_type]['allowed'],
states[op_type]['complete'], config)
def wait_for_completion(op_uri, timeout, allowed_states,
complete_states, config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
def _refresh_status():
r = None
try:
r = fetch_resource(module, client, op_uri)
except Exception:
return None, ""
status = ""
try:
status = navigate_value(r, ['vpc', 'status'])
except Exception:
return None, ""
return r, status
try:
return wait_to_finish(complete_states, allowed_states,
_refresh_status, timeout)
except Exception as ex:
module.fail_json(msg=str(ex))
def wait_for_delete(module, client, link):
def _refresh_status():
try:
client.get(link)
except HwcClientException404:
return True, "Done"
except Exception:
return None, ""
return True, "Pending"
timeout = 60 * int(module.params['timeouts']['delete'].rstrip('m'))
try:
return wait_to_finish(["Done"], ["Pending"], _refresh_status, timeout)
except Exception as ex:
module.fail_json(msg=str(ex))
class VpcRoutesArray(object):
def __init__(self, request, module):
self.module = module
if request:
self.request = request
else:
self.request = []
def to_request(self):
items = []
for item in self.request:
items.append(self._request_for_item(item))
return items
def from_response(self):
items = []
for item in self.request:
items.append(self._response_from_item(item))
return items
def _request_for_item(self, item):
return {
u'destination': item.get('destination'),
u'nexthop': item.get('next_hop')
}
def _response_from_item(self, item):
return {
u'destination': item.get(u'destination'),
u'next_hop': item.get(u'nexthop')
}
if __name__ == '__main__':
main()

View file

@ -0,0 +1,342 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Huawei
# GNU General Public License v3.0+ (see COPYING or
# https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
###############################################################################
# Documentation
###############################################################################
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ["preview"],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: hwc_smn_topic
description:
- Represents a SMN notification topic resource.
short_description: Creates a resource of SMNTopic in Huaweicloud Cloud
author: Huawei Inc. (@huaweicloud)
requirements:
- requests >= 2.18.4
- keystoneauth1 >= 3.6.0
options:
state:
description:
- Whether the given object should exist in Huaweicloud Cloud.
type: str
choices: ['present', 'absent']
default: 'present'
display_name:
description:
- Topic display name, which is presented as the name of the email
sender in an email message. The topic display name contains a
maximum of 192 bytes.
type: str
required: false
name:
description:
- Name of the topic to be created. The topic name is a string of 1
to 256 characters. It must contain upper- or lower-case letters,
digits, hyphens (-), and underscores C(_), and must start with a
letter or digit.
type: str
required: true
extends_documentation_fragment:
- community.general.hwc
'''
EXAMPLES = '''
- name: create a smn topic
hwc_smn_topic:
identity_endpoint: "{{ identity_endpoint }}"
user_name: "{{ user_name }}"
password: "{{ password }}"
domain_name: "{{ domain_name }}"
project_name: "{{ project_name }}"
region: "{{ region }}"
name: "ansible_smn_topic_test"
state: present
'''
RETURN = '''
create_time:
description:
- Time when the topic was created.
returned: success
type: str
display_name:
description:
- Topic display name, which is presented as the name of the email
sender in an email message. The topic display name contains a
maximum of 192 bytes.
returned: success
type: str
name:
description:
- Name of the topic to be created. The topic name is a string of 1
to 256 characters. It must contain upper- or lower-case letters,
digits, hyphens (-), and underscores C(_), and must start with a
letter or digit.
returned: success
type: str
push_policy:
description:
- Message pushing policy. 0 indicates that the message sending
fails and the message is cached in the queue. 1 indicates that
the failed message is discarded.
returned: success
type: int
topic_urn:
description:
- Resource identifier of a topic, which is unique.
returned: success
type: str
update_time:
description:
- Time when the topic was updated.
returned: success
type: str
'''
###############################################################################
# Imports
###############################################################################
from ansible_collections.community.general.plugins.module_utils.hwc_utils import (Config, HwcClientException,
HwcModule, navigate_value,
are_different_dicts, is_empty_value,
build_path, get_region)
import re
###############################################################################
# Main
###############################################################################
def main():
"""Main function"""
module = HwcModule(
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'],
type='str'),
display_name=dict(type='str'),
name=dict(required=True, type='str')
),
supports_check_mode=True,
)
config = Config(module, "smn")
state = module.params['state']
if not module.params.get("id"):
module.params['id'] = get_resource_id(config)
fetch = None
link = self_link(module)
# the link will include Nones if required format parameters are missed
if not re.search('/None/|/None$', link):
client = config.client(get_region(module), "smn", "project")
fetch = fetch_resource(module, client, link)
changed = False
if fetch:
if state == 'present':
expect = _get_resource_editable_properties(module)
current_state = response_to_hash(module, fetch)
current = {'display_name': current_state['display_name']}
if are_different_dicts(expect, current):
if not module.check_mode:
fetch = update(config)
fetch = response_to_hash(module, fetch)
changed = True
else:
fetch = current_state
else:
if not module.check_mode:
delete(config)
fetch = {}
changed = True
else:
if state == 'present':
if not module.check_mode:
fetch = create(config)
fetch = response_to_hash(module, fetch)
changed = True
else:
fetch = {}
fetch.update({'changed': changed})
module.exit_json(**fetch)
def create(config):
module = config.module
client = config.client(get_region(module), "smn", "project")
link = "notifications/topics"
r = None
try:
r = client.post(link, create_resource_opts(module))
except HwcClientException as ex:
msg = ("module(hwc_smn_topic): error creating "
"resource, error: %s" % str(ex))
module.fail_json(msg=msg)
return get_resource(config, r)
def update(config):
module = config.module
client = config.client(get_region(module), "smn", "project")
link = self_link(module)
try:
client.put(link, update_resource_opts(module))
except HwcClientException as ex:
msg = ("module(hwc_smn_topic): error updating "
"resource, error: %s" % str(ex))
module.fail_json(msg=msg)
return fetch_resource(module, client, link)
def delete(config):
module = config.module
client = config.client(get_region(module), "smn", "project")
link = self_link(module)
try:
client.delete(link)
except HwcClientException as ex:
msg = ("module(hwc_smn_topic): error deleting "
"resource, error: %s" % str(ex))
module.fail_json(msg=msg)
def fetch_resource(module, client, link):
try:
return client.get(link)
except HwcClientException as ex:
msg = ("module(hwc_smn_topic): error fetching "
"resource, error: %s" % str(ex))
module.fail_json(msg=msg)
def get_resource(config, result):
module = config.module
client = config.client(get_region(module), "smn", "project")
v = ""
try:
v = navigate_value(result, ['topic_urn'])
except Exception as ex:
module.fail_json(msg=str(ex))
d = {'topic_urn': v}
url = build_path(module, 'notifications/topics/{topic_urn}', d)
return fetch_resource(module, client, url)
def get_resource_id(config):
module = config.module
client = config.client(get_region(module), "smn", "project")
link = "notifications/topics"
query_link = "?offset={offset}&limit=10"
link += query_link
p = {'offset': 0}
v = module.params.get('name')
ids = set()
while True:
r = None
try:
r = client.get(link.format(**p))
except Exception:
pass
if r is None:
break
r = r.get('topics', [])
if r == []:
break
for i in r:
if i.get('name') == v:
ids.add(i.get('topic_urn'))
if len(ids) >= 2:
module.fail_json(msg="Multiple resources are found")
p['offset'] += 1
return ids.pop() if ids else None
def self_link(module):
return build_path(module, "notifications/topics/{id}")
def create_resource_opts(module):
params = dict()
v = module.params.get('display_name')
if not is_empty_value(v):
params["display_name"] = v
v = module.params.get('name')
if not is_empty_value(v):
params["name"] = v
return params
def update_resource_opts(module):
params = dict()
v = module.params.get('display_name')
if not is_empty_value(v):
params["display_name"] = v
return params
def _get_resource_editable_properties(module):
return {
"display_name": module.params.get("display_name"),
}
def response_to_hash(module, response):
"""Remove unnecessary properties from the response.
This is for doing comparisons with Ansible's current parameters.
"""
return {
u'create_time': response.get(u'create_time'),
u'display_name': response.get(u'display_name'),
u'name': response.get(u'name'),
u'push_policy': _push_policy_convert_from_response(
response.get('push_policy')),
u'topic_urn': response.get(u'topic_urn'),
u'update_time': response.get(u'update_time')
}
def _push_policy_convert_from_response(value):
return {
0: "the message sending fails and is cached in the queue",
1: "the failed message is discarded",
}.get(int(value))
if __name__ == '__main__':
main()

View file

@ -0,0 +1,880 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Huawei
# GNU General Public License v3.0+ (see COPYING or
# https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
###############################################################################
# Documentation
###############################################################################
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ["preview"],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: hwc_vpc_eip
description:
- elastic ip management.
short_description: Creates a resource of Vpc/EIP in Huawei Cloud
author: Huawei Inc. (@huaweicloud)
requirements:
- keystoneauth1 >= 3.6.0
options:
state:
description:
- Whether the given object should exist in Huawei Cloud.
type: str
choices: ['present', 'absent']
default: 'present'
timeouts:
description:
- The timeouts for each operations.
type: dict
suboptions:
create:
description:
- The timeouts for create operation.
type: str
default: '5m'
update:
description:
- The timeouts for update operation.
type: str
default: '5m'
type:
description:
- Specifies the EIP type.
type: str
required: true
dedicated_bandwidth:
description:
- Specifies the dedicated bandwidth object.
type: dict
required: false
suboptions:
charge_mode:
description:
- Specifies whether the bandwidth is billed by traffic or
by bandwidth size. The value can be bandwidth or traffic.
If this parameter is left blank or is null character
string, default value bandwidth is used. For IPv6
addresses, the default parameter value is bandwidth
outside China and is traffic in China.
type: str
required: true
name:
description:
- Specifies the bandwidth name. The value is a string of 1
to 64 characters that can contain letters, digits,
underscores C(_), hyphens (-), and periods (.).
type: str
required: true
size:
description:
- Specifies the bandwidth size. The value ranges from 1
Mbit/s to 2000 Mbit/s by default. (The specific range may
vary depending on the configuration in each region. You
can see the bandwidth range of each region on the
management console.) The minimum unit for bandwidth
adjustment varies depending on the bandwidth range. The
details are as follows.
- The minimum unit is 1 Mbit/s if the allowed bandwidth
size ranges from 0 to 300 Mbit/s (with 300 Mbit/s
included).
- The minimum unit is 50 Mbit/s if the allowed bandwidth
size ranges 300 Mbit/s to 1000 Mbit/s (with 1000 Mbit/s
included).
- The minimum unit is 500 Mbit/s if the allowed bandwidth
size is greater than 1000 Mbit/s.
type: int
required: true
enterprise_project_id:
description:
- Specifies the enterprise project ID.
type: str
required: false
ip_version:
description:
- The value can be 4 (IPv4 address) or 6 (IPv6 address). If this
parameter is left blank, an IPv4 address will be assigned.
type: int
required: false
ipv4_address:
description:
- Specifies the obtained IPv4 EIP. The system automatically assigns
an EIP if you do not specify it.
type: str
required: false
port_id:
description:
- Specifies the port ID. This parameter is returned only when a
private IP address is bound with the EIP.
type: str
required: false
shared_bandwidth_id:
description:
- Specifies the ID of shared bandwidth.
type: str
required: false
extends_documentation_fragment:
- community.general.hwc
'''
EXAMPLES = '''
# create an eip and bind it to a port
- name: create vpc
hwc_network_vpc:
cidr: "192.168.100.0/24"
name: "ansible_network_vpc_test"
register: vpc
- name: create subnet
hwc_vpc_subnet:
gateway_ip: "192.168.100.32"
name: "ansible_network_subnet_test"
dhcp_enable: True
vpc_id: "{{ vpc.id }}"
cidr: "192.168.100.0/26"
register: subnet
- name: create a port
hwc_vpc_port:
subnet_id: "{{ subnet.id }}"
ip_address: "192.168.100.33"
register: port
- name: create an eip and bind it to a port
hwc_vpc_eip:
type: "5_bgp"
dedicated_bandwidth:
charge_mode: "traffic"
name: "ansible_test_dedicated_bandwidth"
size: 1
port_id: "{{ port.id }}"
'''
RETURN = '''
type:
description:
- Specifies the EIP type.
type: str
returned: success
dedicated_bandwidth:
description:
- Specifies the dedicated bandwidth object.
type: dict
returned: success
contains:
charge_mode:
description:
- Specifies whether the bandwidth is billed by traffic or
by bandwidth size. The value can be bandwidth or traffic.
If this parameter is left blank or is null character
string, default value bandwidth is used. For IPv6
addresses, the default parameter value is bandwidth
outside China and is traffic in China.
type: str
returned: success
name:
description:
- Specifies the bandwidth name. The value is a string of 1
to 64 characters that can contain letters, digits,
underscores C(_), hyphens (-), and periods (.).
type: str
returned: success
size:
description:
- Specifies the bandwidth size. The value ranges from 1
Mbit/s to 2000 Mbit/s by default. (The specific range may
vary depending on the configuration in each region. You
can see the bandwidth range of each region on the
management console.) The minimum unit for bandwidth
adjustment varies depending on the bandwidth range. The
details are as follows:.
- The minimum unit is 1 Mbit/s if the allowed bandwidth
size ranges from 0 to 300 Mbit/s (with 300 Mbit/s
included).
- The minimum unit is 50 Mbit/s if the allowed bandwidth
size ranges 300 Mbit/s to 1000 Mbit/s (with 1000 Mbit/s
included).
- The minimum unit is 500 Mbit/s if the allowed bandwidth
size is greater than 1000 Mbit/s.
type: int
returned: success
id:
description:
- Specifies the ID of dedicated bandwidth.
type: str
returned: success
enterprise_project_id:
description:
- Specifies the enterprise project ID.
type: str
returned: success
ip_version:
description:
- The value can be 4 (IPv4 address) or 6 (IPv6 address). If this
parameter is left blank, an IPv4 address will be assigned.
type: int
returned: success
ipv4_address:
description:
- Specifies the obtained IPv4 EIP. The system automatically assigns
an EIP if you do not specify it.
type: str
returned: success
port_id:
description:
- Specifies the port ID. This parameter is returned only when a
private IP address is bound with the EIP.
type: str
returned: success
shared_bandwidth_id:
description:
- Specifies the ID of shared bandwidth.
type: str
returned: success
create_time:
description:
- Specifies the time (UTC time) when the EIP was assigned.
type: str
returned: success
ipv6_address:
description:
- Specifies the obtained IPv6 EIP.
type: str
returned: success
private_ip_address:
description:
- Specifies the private IP address bound with the EIP. This
parameter is returned only when a private IP address is bound
with the EIP.
type: str
returned: success
'''
from ansible_collections.community.general.plugins.module_utils.hwc_utils import (
Config, HwcClientException, HwcClientException404, HwcModule,
are_different_dicts, build_path, get_region, is_empty_value,
navigate_value, wait_to_finish)
def build_module():
return HwcModule(
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'],
type='str'),
timeouts=dict(type='dict', options=dict(
create=dict(default='5m', type='str'),
update=dict(default='5m', type='str'),
), default=dict()),
type=dict(type='str', required=True),
dedicated_bandwidth=dict(type='dict', options=dict(
charge_mode=dict(type='str', required=True),
name=dict(type='str', required=True),
size=dict(type='int', required=True)
)),
enterprise_project_id=dict(type='str'),
ip_version=dict(type='int'),
ipv4_address=dict(type='str'),
port_id=dict(type='str'),
shared_bandwidth_id=dict(type='str')
),
supports_check_mode=True,
)
def main():
"""Main function"""
module = build_module()
config = Config(module, "vpc")
try:
resource = None
if module.params['id']:
resource = True
else:
v = search_resource(config)
if len(v) > 1:
raise Exception("Found more than one resource(%s)" % ", ".join([
navigate_value(i, ["id"]) for i in v]))
if len(v) == 1:
resource = v[0]
module.params['id'] = navigate_value(resource, ["id"])
result = {}
changed = False
if module.params['state'] == 'present':
if resource is None:
if not module.check_mode:
create(config)
changed = True
current = read_resource(config, exclude_output=True)
expect = user_input_parameters(module)
if are_different_dicts(expect, current):
if not module.check_mode:
update(config)
changed = True
result = read_resource(config)
result['id'] = module.params.get('id')
else:
if resource:
if not module.check_mode:
delete(config)
changed = True
except Exception as ex:
module.fail_json(msg=str(ex))
else:
result['changed'] = changed
module.exit_json(**result)
def user_input_parameters(module):
return {
"dedicated_bandwidth": module.params.get("dedicated_bandwidth"),
"enterprise_project_id": module.params.get("enterprise_project_id"),
"ip_version": module.params.get("ip_version"),
"ipv4_address": module.params.get("ipv4_address"),
"port_id": module.params.get("port_id"),
"shared_bandwidth_id": module.params.get("shared_bandwidth_id"),
"type": module.params.get("type"),
}
def create(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
timeout = 60 * int(module.params['timeouts']['create'].rstrip('m'))
opts = user_input_parameters(module)
params = build_create_parameters(opts)
r = send_create_request(module, params, client)
obj = async_wait_create(config, r, client, timeout)
module.params['id'] = navigate_value(obj, ["publicip", "id"])
def update(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
timeout = 60 * int(module.params['timeouts']['update'].rstrip('m'))
opts = user_input_parameters(module)
params = build_update_parameters(opts)
if params:
r = send_update_request(module, params, client)
async_wait_update(config, r, client, timeout)
def delete(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
if module.params["port_id"]:
module.params["port_id"] = ""
update(config)
send_delete_request(module, None, client)
url = build_path(module, "publicips/{id}")
def _refresh_status():
try:
client.get(url)
except HwcClientException404:
return True, "Done"
except Exception:
return None, ""
return True, "Pending"
timeout = 60 * int(module.params['timeouts']['create'].rstrip('m'))
try:
wait_to_finish(["Done"], ["Pending"], _refresh_status, timeout)
except Exception as ex:
module.fail_json(msg="module(hwc_vpc_eip): error "
"waiting for api(delete) to "
"be done, error= %s" % str(ex))
def read_resource(config, exclude_output=False):
module = config.module
client = config.client(get_region(module), "vpc", "project")
res = {}
r = send_read_request(module, client)
res["read"] = fill_read_resp_body(r)
return update_properties(module, res, None, exclude_output)
def _build_query_link(opts):
query_params = []
v = navigate_value(opts, ["ip_version"])
if v:
query_params.append("ip_version=" + str(v))
v = navigate_value(opts, ["enterprise_project_id"])
if v:
query_params.append("enterprise_project_id=" + str(v))
query_link = "?marker={marker}&limit=10"
if query_params:
query_link += "&" + "&".join(query_params)
return query_link
def search_resource(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
opts = user_input_parameters(module)
identity_obj = _build_identity_object(opts)
query_link = _build_query_link(opts)
link = "publicips" + query_link
result = []
p = {'marker': ''}
while True:
url = link.format(**p)
r = send_list_request(module, client, url)
if not r:
break
for item in r:
item = fill_list_resp_body(item)
if not are_different_dicts(identity_obj, item):
result.append(item)
if len(result) > 1:
break
p['marker'] = r[-1].get('id')
return result
def build_create_parameters(opts):
params = dict()
v = expand_create_bandwidth(opts, None)
if not is_empty_value(v):
params["bandwidth"] = v
v = navigate_value(opts, ["enterprise_project_id"], None)
if not is_empty_value(v):
params["enterprise_project_id"] = v
v = expand_create_publicip(opts, None)
if not is_empty_value(v):
params["publicip"] = v
return params
def expand_create_bandwidth(d, array_index):
v = navigate_value(d, ["dedicated_bandwidth"], array_index)
sbwid = navigate_value(d, ["shared_bandwidth_id"], array_index)
if v and sbwid:
raise Exception("don't input shared_bandwidth_id and "
"dedicated_bandwidth at same time")
if not (v or sbwid):
raise Exception("must input shared_bandwidth_id or "
"dedicated_bandwidth")
if sbwid:
return {
"id": sbwid,
"share_type": "WHOLE"}
return {
"charge_mode": v["charge_mode"],
"name": v["name"],
"share_type": "PER",
"size": v["size"]}
def expand_create_publicip(d, array_index):
r = dict()
v = navigate_value(d, ["ipv4_address"], array_index)
if not is_empty_value(v):
r["ip_address"] = v
v = navigate_value(d, ["ip_version"], array_index)
if not is_empty_value(v):
r["ip_version"] = v
v = navigate_value(d, ["type"], array_index)
if not is_empty_value(v):
r["type"] = v
return r
def send_create_request(module, params, client):
url = "publicips"
try:
r = client.post(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_eip): error running "
"api(create), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def async_wait_create(config, result, client, timeout):
module = config.module
path_parameters = {
"publicip_id": ["publicip", "id"],
}
data = dict((key, navigate_value(result, path))
for key, path in path_parameters.items())
url = build_path(module, "publicips/{publicip_id}", data)
def _query_status():
r = None
try:
r = client.get(url, timeout=timeout)
except HwcClientException:
return None, ""
try:
s = navigate_value(r, ["publicip", "status"])
return r, s
except Exception:
return None, ""
try:
return wait_to_finish(
["ACTIVE", "DOWN"],
None,
_query_status, timeout)
except Exception as ex:
module.fail_json(msg="module(hwc_vpc_eip): error "
"waiting for api(create) to "
"be done, error= %s" % str(ex))
def build_update_parameters(opts):
params = dict()
v = navigate_value(opts, ["ip_version"], None)
if not is_empty_value(v):
params["ip_version"] = v
v = navigate_value(opts, ["port_id"], None)
if v is not None:
params["port_id"] = v
if not params:
return params
params = {"publicip": params}
return params
def send_update_request(module, params, client):
url = build_path(module, "publicips/{id}")
try:
r = client.put(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_eip): error running "
"api(update), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def async_wait_update(config, result, client, timeout):
module = config.module
url = build_path(module, "publicips/{id}")
def _query_status():
r = None
try:
r = client.get(url, timeout=timeout)
except HwcClientException:
return None, ""
try:
s = navigate_value(r, ["publicip", "status"])
return r, s
except Exception:
return None, ""
try:
return wait_to_finish(
["ACTIVE", "DOWN"],
None,
_query_status, timeout)
except Exception as ex:
module.fail_json(msg="module(hwc_vpc_eip): error "
"waiting for api(update) to "
"be done, error= %s" % str(ex))
def send_delete_request(module, params, client):
url = build_path(module, "publicips/{id}")
try:
r = client.delete(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_eip): error running "
"api(delete), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_read_request(module, client):
url = build_path(module, "publicips/{id}")
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_eip): error running "
"api(read), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["publicip"], None)
def fill_read_resp_body(body):
result = dict()
result["bandwidth_id"] = body.get("bandwidth_id")
result["bandwidth_name"] = body.get("bandwidth_name")
result["bandwidth_share_type"] = body.get("bandwidth_share_type")
result["bandwidth_size"] = body.get("bandwidth_size")
result["create_time"] = body.get("create_time")
result["enterprise_project_id"] = body.get("enterprise_project_id")
result["id"] = body.get("id")
result["ip_version"] = body.get("ip_version")
result["port_id"] = body.get("port_id")
result["private_ip_address"] = body.get("private_ip_address")
result["public_ip_address"] = body.get("public_ip_address")
result["public_ipv6_address"] = body.get("public_ipv6_address")
result["status"] = body.get("status")
result["tenant_id"] = body.get("tenant_id")
result["type"] = body.get("type")
return result
def update_properties(module, response, array_index, exclude_output=False):
r = user_input_parameters(module)
if not exclude_output:
v = navigate_value(response, ["read", "create_time"], array_index)
r["create_time"] = v
v = r.get("dedicated_bandwidth")
v = flatten_dedicated_bandwidth(response, array_index, v, exclude_output)
r["dedicated_bandwidth"] = v
v = navigate_value(response, ["read", "enterprise_project_id"],
array_index)
r["enterprise_project_id"] = v
v = navigate_value(response, ["read", "ip_version"], array_index)
r["ip_version"] = v
v = navigate_value(response, ["read", "public_ip_address"], array_index)
r["ipv4_address"] = v
if not exclude_output:
v = navigate_value(response, ["read", "public_ipv6_address"],
array_index)
r["ipv6_address"] = v
v = navigate_value(response, ["read", "port_id"], array_index)
r["port_id"] = v
if not exclude_output:
v = navigate_value(response, ["read", "private_ip_address"],
array_index)
r["private_ip_address"] = v
v = r.get("shared_bandwidth_id")
v = flatten_shared_bandwidth_id(response, array_index, v, exclude_output)
r["shared_bandwidth_id"] = v
v = navigate_value(response, ["read", "type"], array_index)
r["type"] = v
return r
def flatten_dedicated_bandwidth(d, array_index, current_value, exclude_output):
v = navigate_value(d, ["read", "bandwidth_share_type"], array_index)
if not (v and v == "PER"):
return current_value
result = current_value
if not result:
result = dict()
if not exclude_output:
v = navigate_value(d, ["read", "bandwidth_id"], array_index)
if v is not None:
result["id"] = v
v = navigate_value(d, ["read", "bandwidth_name"], array_index)
if v is not None:
result["name"] = v
v = navigate_value(d, ["read", "bandwidth_size"], array_index)
if v is not None:
result["size"] = v
return result if result else current_value
def flatten_shared_bandwidth_id(d, array_index, current_value, exclude_output):
v = navigate_value(d, ["read", "bandwidth_id"], array_index)
v1 = navigate_value(d, ["read", "bandwidth_share_type"], array_index)
return v if (v1 and v1 == "WHOLE") else current_value
def send_list_request(module, client, url):
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_eip): error running "
"api(list), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["publicips"], None)
def _build_identity_object(all_opts):
result = dict()
v = expand_list_bandwidth_id(all_opts, None)
result["bandwidth_id"] = v
v = navigate_value(all_opts, ["dedicated_bandwidth", "name"], None)
result["bandwidth_name"] = v
result["bandwidth_share_type"] = None
v = navigate_value(all_opts, ["dedicated_bandwidth", "size"], None)
result["bandwidth_size"] = v
result["create_time"] = None
v = navigate_value(all_opts, ["enterprise_project_id"], None)
result["enterprise_project_id"] = v
result["id"] = None
v = navigate_value(all_opts, ["ip_version"], None)
result["ip_version"] = v
v = navigate_value(all_opts, ["port_id"], None)
result["port_id"] = v
result["private_ip_address"] = None
v = navigate_value(all_opts, ["ipv4_address"], None)
result["public_ip_address"] = v
result["public_ipv6_address"] = None
result["status"] = None
result["tenant_id"] = None
v = navigate_value(all_opts, ["type"], None)
result["type"] = v
return result
def expand_list_bandwidth_id(d, array_index):
v = navigate_value(d, ["dedicated_bandwidth"], array_index)
sbwid = navigate_value(d, ["shared_bandwidth_id"], array_index)
if v and sbwid:
raise Exception("don't input shared_bandwidth_id and "
"dedicated_bandwidth at same time")
return sbwid
def fill_list_resp_body(body):
result = dict()
result["bandwidth_id"] = body.get("bandwidth_id")
result["bandwidth_name"] = body.get("bandwidth_name")
result["bandwidth_share_type"] = body.get("bandwidth_share_type")
result["bandwidth_size"] = body.get("bandwidth_size")
result["create_time"] = body.get("create_time")
result["enterprise_project_id"] = body.get("enterprise_project_id")
result["id"] = body.get("id")
result["ip_version"] = body.get("ip_version")
result["port_id"] = body.get("port_id")
result["private_ip_address"] = body.get("private_ip_address")
result["public_ip_address"] = body.get("public_ip_address")
result["public_ipv6_address"] = body.get("public_ipv6_address")
result["status"] = body.get("status")
result["tenant_id"] = body.get("tenant_id")
result["type"] = body.get("type")
return result
if __name__ == '__main__':
main()

View file

@ -0,0 +1,694 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Huawei
# GNU General Public License v3.0+ (see COPYING or
# https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
###############################################################################
# Documentation
###############################################################################
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ["preview"],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: hwc_vpc_peering_connect
description:
- vpc peering management.
short_description: Creates a resource of Vpc/PeeringConnect in Huawei Cloud
author: Huawei Inc. (@huaweicloud)
requirements:
- keystoneauth1 >= 3.6.0
options:
state:
description:
- Whether the given object should exist in Huawei Cloud.
type: str
choices: ['present', 'absent']
default: 'present'
timeouts:
description:
- The timeouts for each operations.
type: dict
suboptions:
create:
description:
- The timeouts for create operation.
type: str
default: '15m'
local_vpc_id:
description:
- Specifies the ID of local VPC.
type: str
required: true
name:
description:
- Specifies the name of the VPC peering connection. The value can
contain 1 to 64 characters.
type: str
required: true
peering_vpc:
description:
- Specifies information about the peering VPC.
type: dict
required: true
suboptions:
vpc_id:
description:
- Specifies the ID of peering VPC.
type: str
required: true
project_id:
description:
- Specifies the ID of the project which the peering vpc
belongs to.
type: str
required: false
description:
description:
- The description of vpc peering connection.
type: str
required: false
extends_documentation_fragment:
- community.general.hwc
'''
EXAMPLES = '''
# create a peering connect
- name: create a local vpc
hwc_network_vpc:
cidr: "192.168.0.0/16"
name: "ansible_network_vpc_test_local"
register: vpc1
- name: create a peering vpc
hwc_network_vpc:
cidr: "192.168.0.0/16"
name: "ansible_network_vpc_test_peering"
register: vpc2
- name: create a peering connect
hwc_vpc_peering_connect:
local_vpc_id: "{{ vpc1.id }}"
name: "ansible_network_peering_test"
peering_vpc:
vpc_id: "{{ vpc2.id }}"
'''
RETURN = '''
local_vpc_id:
description:
- Specifies the ID of local VPC.
type: str
returned: success
name:
description:
- Specifies the name of the VPC peering connection. The value can
contain 1 to 64 characters.
type: str
returned: success
peering_vpc:
description:
- Specifies information about the peering VPC.
type: dict
returned: success
contains:
vpc_id:
description:
- Specifies the ID of peering VPC.
type: str
returned: success
project_id:
description:
- Specifies the ID of the project which the peering vpc
belongs to.
type: str
returned: success
description:
description:
- The description of vpc peering connection.
type: str
returned: success
'''
from ansible_collections.community.general.plugins.module_utils.hwc_utils import (
Config, HwcClientException, HwcClientException404, HwcModule,
are_different_dicts, build_path, get_region, is_empty_value,
navigate_value, wait_to_finish)
def build_module():
return HwcModule(
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'],
type='str'),
timeouts=dict(type='dict', options=dict(
create=dict(default='15m', type='str'),
), default=dict()),
local_vpc_id=dict(type='str', required=True),
name=dict(type='str', required=True),
peering_vpc=dict(type='dict', required=True, options=dict(
vpc_id=dict(type='str', required=True),
project_id=dict(type='str')
)),
description=dict(type='str')
),
supports_check_mode=True,
)
def main():
"""Main function"""
module = build_module()
config = Config(module, "vpc")
try:
resource = None
if module.params['id']:
resource = True
else:
v = search_resource(config)
if len(v) > 1:
raise Exception("Found more than one resource(%s)" % ", ".join([
navigate_value(i, ["id"]) for i in v]))
if len(v) == 1:
resource = v[0]
module.params['id'] = navigate_value(resource, ["id"])
result = {}
changed = False
if module.params['state'] == 'present':
if resource is None:
if not module.check_mode:
create(config)
changed = True
current = read_resource(config, exclude_output=True)
expect = user_input_parameters(module)
if are_different_dicts(expect, current):
if not module.check_mode:
update(config)
changed = True
result = read_resource(config)
result['id'] = module.params.get('id')
else:
if resource:
if not module.check_mode:
delete(config)
changed = True
except Exception as ex:
module.fail_json(msg=str(ex))
else:
result['changed'] = changed
module.exit_json(**result)
def user_input_parameters(module):
return {
"description": module.params.get("description"),
"local_vpc_id": module.params.get("local_vpc_id"),
"name": module.params.get("name"),
"peering_vpc": module.params.get("peering_vpc"),
}
def create(config):
module = config.module
client = config.client(get_region(module), "network", "project")
timeout = 60 * int(module.params['timeouts']['create'].rstrip('m'))
opts = user_input_parameters(module)
params = build_create_parameters(opts)
r = send_create_request(module, params, client)
obj = async_wait_create(config, r, client, timeout)
module.params['id'] = navigate_value(obj, ["peering", "id"])
def update(config):
module = config.module
client = config.client(get_region(module), "network", "project")
opts = user_input_parameters(module)
params = build_update_parameters(opts)
if params:
send_update_request(module, params, client)
def delete(config):
module = config.module
client = config.client(get_region(module), "network", "project")
send_delete_request(module, None, client)
url = build_path(module, "v2.0/vpc/peerings/{id}")
def _refresh_status():
try:
client.get(url)
except HwcClientException404:
return True, "Done"
except Exception:
return None, ""
return True, "Pending"
timeout = 60 * int(module.params['timeouts']['create'].rstrip('m'))
try:
wait_to_finish(["Done"], ["Pending"], _refresh_status, timeout)
except Exception as ex:
module.fail_json(msg="module(hwc_vpc_peering_connect): error "
"waiting for api(delete) to "
"be done, error= %s" % str(ex))
def read_resource(config, exclude_output=False):
module = config.module
client = config.client(get_region(module), "network", "project")
res = {}
r = send_read_request(module, client)
res["read"] = fill_read_resp_body(r)
return update_properties(module, res, None, exclude_output)
def _build_query_link(opts):
query_params = []
v = navigate_value(opts, ["local_vpc_id"])
if v:
query_params.append("vpc_id=" + str(v))
v = navigate_value(opts, ["name"])
if v:
query_params.append("name=" + str(v))
query_link = "?marker={marker}&limit=10"
if query_params:
query_link += "&" + "&".join(query_params)
return query_link
def search_resource(config):
module = config.module
client = config.client(get_region(module), "network", "project")
opts = user_input_parameters(module)
identity_obj = _build_identity_object(opts)
query_link = _build_query_link(opts)
link = "v2.0/vpc/peerings" + query_link
result = []
p = {'marker': ''}
while True:
url = link.format(**p)
r = send_list_request(module, client, url)
if not r:
break
for item in r:
item = fill_list_resp_body(item)
if not are_different_dicts(identity_obj, item):
result.append(item)
if len(result) > 1:
break
p['marker'] = r[-1].get('id')
return result
def build_create_parameters(opts):
params = dict()
v = expand_create_accept_vpc_info(opts, None)
if not is_empty_value(v):
params["accept_vpc_info"] = v
v = navigate_value(opts, ["description"], None)
if not is_empty_value(v):
params["description"] = v
v = navigate_value(opts, ["name"], None)
if not is_empty_value(v):
params["name"] = v
v = expand_create_request_vpc_info(opts, None)
if not is_empty_value(v):
params["request_vpc_info"] = v
if not params:
return params
params = {"peering": params}
return params
def expand_create_accept_vpc_info(d, array_index):
r = dict()
v = navigate_value(d, ["peering_vpc", "project_id"], array_index)
if not is_empty_value(v):
r["tenant_id"] = v
v = navigate_value(d, ["peering_vpc", "vpc_id"], array_index)
if not is_empty_value(v):
r["vpc_id"] = v
return r
def expand_create_request_vpc_info(d, array_index):
r = dict()
r["tenant_id"] = ""
v = navigate_value(d, ["local_vpc_id"], array_index)
if not is_empty_value(v):
r["vpc_id"] = v
return r
def send_create_request(module, params, client):
url = "v2.0/vpc/peerings"
try:
r = client.post(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_peering_connect): error running "
"api(create), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def async_wait_create(config, result, client, timeout):
module = config.module
path_parameters = {
"peering_id": ["peering", "id"],
}
data = dict((key, navigate_value(result, path))
for key, path in path_parameters.items())
url = build_path(module, "v2.0/vpc/peerings/{peering_id}", data)
def _query_status():
r = None
try:
r = client.get(url, timeout=timeout)
except HwcClientException:
return None, ""
try:
s = navigate_value(r, ["peering", "status"])
return r, s
except Exception:
return None, ""
try:
return wait_to_finish(
["ACTIVE"],
["PENDING_ACCEPTANCE"],
_query_status, timeout)
except Exception as ex:
module.fail_json(msg="module(hwc_vpc_peering_connect): error "
"waiting for api(create) to "
"be done, error= %s" % str(ex))
def build_update_parameters(opts):
params = dict()
v = navigate_value(opts, ["description"], None)
if not is_empty_value(v):
params["description"] = v
v = navigate_value(opts, ["name"], None)
if not is_empty_value(v):
params["name"] = v
if not params:
return params
params = {"peering": params}
return params
def send_update_request(module, params, client):
url = build_path(module, "v2.0/vpc/peerings/{id}")
try:
r = client.put(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_peering_connect): error running "
"api(update), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_delete_request(module, params, client):
url = build_path(module, "v2.0/vpc/peerings/{id}")
try:
r = client.delete(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_peering_connect): error running "
"api(delete), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_read_request(module, client):
url = build_path(module, "v2.0/vpc/peerings/{id}")
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_peering_connect): error running "
"api(read), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["peering"], None)
def fill_read_resp_body(body):
result = dict()
v = fill_read_resp_accept_vpc_info(body.get("accept_vpc_info"))
result["accept_vpc_info"] = v
result["description"] = body.get("description")
result["id"] = body.get("id")
result["name"] = body.get("name")
v = fill_read_resp_request_vpc_info(body.get("request_vpc_info"))
result["request_vpc_info"] = v
result["status"] = body.get("status")
return result
def fill_read_resp_accept_vpc_info(value):
if not value:
return None
result = dict()
result["tenant_id"] = value.get("tenant_id")
result["vpc_id"] = value.get("vpc_id")
return result
def fill_read_resp_request_vpc_info(value):
if not value:
return None
result = dict()
result["tenant_id"] = value.get("tenant_id")
result["vpc_id"] = value.get("vpc_id")
return result
def update_properties(module, response, array_index, exclude_output=False):
r = user_input_parameters(module)
v = navigate_value(response, ["read", "description"], array_index)
r["description"] = v
v = navigate_value(response, ["read", "request_vpc_info", "vpc_id"],
array_index)
r["local_vpc_id"] = v
v = navigate_value(response, ["read", "name"], array_index)
r["name"] = v
v = r.get("peering_vpc")
v = flatten_peering_vpc(response, array_index, v, exclude_output)
r["peering_vpc"] = v
return r
def flatten_peering_vpc(d, array_index, current_value, exclude_output):
result = current_value
has_init_value = True
if not result:
result = dict()
has_init_value = False
v = navigate_value(d, ["read", "accept_vpc_info", "tenant_id"],
array_index)
result["project_id"] = v
v = navigate_value(d, ["read", "accept_vpc_info", "vpc_id"], array_index)
result["vpc_id"] = v
if has_init_value:
return result
for v in result.values():
if v is not None:
return result
return current_value
def send_list_request(module, client, url):
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_peering_connect): error running "
"api(list), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["peerings"], None)
def _build_identity_object(all_opts):
result = dict()
v = expand_list_accept_vpc_info(all_opts, None)
result["accept_vpc_info"] = v
v = navigate_value(all_opts, ["description"], None)
result["description"] = v
result["id"] = None
v = navigate_value(all_opts, ["name"], None)
result["name"] = v
v = expand_list_request_vpc_info(all_opts, None)
result["request_vpc_info"] = v
result["status"] = None
return result
def expand_list_accept_vpc_info(d, array_index):
r = dict()
v = navigate_value(d, ["peering_vpc", "project_id"], array_index)
r["tenant_id"] = v
v = navigate_value(d, ["peering_vpc", "vpc_id"], array_index)
r["vpc_id"] = v
for v in r.values():
if v is not None:
return r
return None
def expand_list_request_vpc_info(d, array_index):
r = dict()
r["tenant_id"] = None
v = navigate_value(d, ["local_vpc_id"], array_index)
r["vpc_id"] = v
for v in r.values():
if v is not None:
return r
return None
def fill_list_resp_body(body):
result = dict()
v = fill_list_resp_accept_vpc_info(body.get("accept_vpc_info"))
result["accept_vpc_info"] = v
result["description"] = body.get("description")
result["id"] = body.get("id")
result["name"] = body.get("name")
v = fill_list_resp_request_vpc_info(body.get("request_vpc_info"))
result["request_vpc_info"] = v
result["status"] = body.get("status")
return result
def fill_list_resp_accept_vpc_info(value):
if not value:
return None
result = dict()
result["tenant_id"] = value.get("tenant_id")
result["vpc_id"] = value.get("vpc_id")
return result
def fill_list_resp_request_vpc_info(value):
if not value:
return None
result = dict()
result["tenant_id"] = value.get("tenant_id")
result["vpc_id"] = value.get("vpc_id")
return result
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,357 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Huawei
# GNU General Public License v3.0+ (see COPYING or
# https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
###############################################################################
# Documentation
###############################################################################
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ["preview"],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: hwc_vpc_private_ip
description:
- vpc private ip management.
short_description: Creates a resource of Vpc/PrivateIP in Huawei Cloud
notes:
- If I(id) option is provided, it takes precedence over I(subnet_id), I(ip_address) for private ip selection.
- I(subnet_id), I(ip_address) are used for private ip selection. If more than one private ip with this options exists, execution is aborted.
- No parameter support updating. If one of option is changed, the module will create a new resource.
author: Huawei Inc. (@huaweicloud)
requirements:
- keystoneauth1 >= 3.6.0
options:
state:
description:
- Whether the given object should exist in Huawei Cloud.
type: str
choices: ['present', 'absent']
default: 'present'
subnet_id:
description:
- Specifies the ID of the subnet from which IP addresses are
assigned. Cannot be changed after creating the private ip.
type: str
required: true
ip_address:
description:
- Specifies the target IP address. The value can be an available IP
address in the subnet. If it is not specified, the system
automatically assigns an IP address. Cannot be changed after
creating the private ip.
type: str
required: false
extends_documentation_fragment:
- community.general.hwc
'''
EXAMPLES = '''
# create a private ip
- name: create vpc
hwc_network_vpc:
cidr: "192.168.100.0/24"
name: "ansible_network_vpc_test"
register: vpc
- name: create subnet
hwc_vpc_subnet:
gateway_ip: "192.168.100.32"
name: "ansible_network_subnet_test"
dhcp_enable: True
vpc_id: "{{ vpc.id }}"
cidr: "192.168.100.0/26"
register: subnet
- name: create a private ip
hwc_vpc_private_ip:
subnet_id: "{{ subnet.id }}"
ip_address: "192.168.100.33"
'''
RETURN = '''
subnet_id:
description:
- Specifies the ID of the subnet from which IP addresses are
assigned.
type: str
returned: success
ip_address:
description:
- Specifies the target IP address. The value can be an available IP
address in the subnet. If it is not specified, the system
automatically assigns an IP address.
type: str
returned: success
'''
from ansible_collections.community.general.plugins.module_utils.hwc_utils import (
Config, HwcClientException, HwcModule, are_different_dicts, build_path,
get_region, is_empty_value, navigate_value)
def build_module():
return HwcModule(
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'],
type='str'),
subnet_id=dict(type='str', required=True),
ip_address=dict(type='str')
),
supports_check_mode=True,
)
def main():
"""Main function"""
module = build_module()
config = Config(module, "vpc")
try:
resource = None
if module.params['id']:
resource = True
else:
v = search_resource(config)
if len(v) > 1:
raise Exception("Found more than one resource(%s)" % ", ".join([
navigate_value(i, ["id"]) for i in v]))
if len(v) == 1:
resource = v[0]
module.params['id'] = navigate_value(resource, ["id"])
result = {}
changed = False
if module.params['state'] == 'present':
if resource is None:
if not module.check_mode:
create(config)
changed = True
current = read_resource(config, exclude_output=True)
expect = user_input_parameters(module)
if are_different_dicts(expect, current):
raise Exception(
"Cannot change option from (%s) to (%s)of an"
" existing resource.(%s)" % (current, expect, module.params.get('id')))
result = read_resource(config)
result['id'] = module.params.get('id')
else:
if resource:
if not module.check_mode:
delete(config)
changed = True
except Exception as ex:
module.fail_json(msg=str(ex))
else:
result['changed'] = changed
module.exit_json(**result)
def user_input_parameters(module):
return {
"ip_address": module.params.get("ip_address"),
"subnet_id": module.params.get("subnet_id"),
}
def create(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
opts = user_input_parameters(module)
params = build_create_parameters(opts)
r = send_create_request(module, params, client)
module.params['id'] = navigate_value(r, ["privateips", "id"],
{"privateips": 0})
def delete(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
send_delete_request(module, None, client)
def read_resource(config, exclude_output=False):
module = config.module
client = config.client(get_region(module), "vpc", "project")
res = {}
r = send_read_request(module, client)
res["read"] = fill_read_resp_body(r)
return update_properties(module, res, None, exclude_output)
def _build_query_link(opts):
query_link = "?marker={marker}&limit=10"
return query_link
def search_resource(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
opts = user_input_parameters(module)
identity_obj = _build_identity_object(opts)
query_link = _build_query_link(opts)
link = build_path(module, "subnets/{subnet_id}/privateips") + query_link
result = []
p = {'marker': ''}
while True:
url = link.format(**p)
r = send_list_request(module, client, url)
if not r:
break
for item in r:
item = fill_list_resp_body(item)
if not are_different_dicts(identity_obj, item):
result.append(item)
if len(result) > 1:
break
p['marker'] = r[-1].get('id')
return result
def build_create_parameters(opts):
params = dict()
v = navigate_value(opts, ["ip_address"], None)
if not is_empty_value(v):
params["ip_address"] = v
v = navigate_value(opts, ["subnet_id"], None)
if not is_empty_value(v):
params["subnet_id"] = v
if not params:
return params
params = {"privateips": [params]}
return params
def send_create_request(module, params, client):
url = "privateips"
try:
r = client.post(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_private_ip): error running "
"api(create), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_delete_request(module, params, client):
url = build_path(module, "privateips/{id}")
try:
r = client.delete(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_private_ip): error running "
"api(delete), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_read_request(module, client):
url = build_path(module, "privateips/{id}")
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_private_ip): error running "
"api(read), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["privateip"], None)
def fill_read_resp_body(body):
result = dict()
result["id"] = body.get("id")
result["ip_address"] = body.get("ip_address")
result["subnet_id"] = body.get("subnet_id")
return result
def update_properties(module, response, array_index, exclude_output=False):
r = user_input_parameters(module)
v = navigate_value(response, ["read", "ip_address"], array_index)
r["ip_address"] = v
v = navigate_value(response, ["read", "subnet_id"], array_index)
r["subnet_id"] = v
return r
def send_list_request(module, client, url):
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_private_ip): error running "
"api(list), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["privateips"], None)
def _build_identity_object(all_opts):
result = dict()
result["id"] = None
v = navigate_value(all_opts, ["ip_address"], None)
result["ip_address"] = v
v = navigate_value(all_opts, ["subnet_id"], None)
result["subnet_id"] = v
return result
def fill_list_resp_body(body):
result = dict()
result["id"] = body.get("id")
result["ip_address"] = body.get("ip_address")
result["subnet_id"] = body.get("subnet_id")
return result
if __name__ == '__main__':
main()

View file

@ -0,0 +1,440 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Huawei
# GNU General Public License v3.0+ (see COPYING or
# https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
###############################################################################
# Documentation
###############################################################################
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ["preview"],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: hwc_vpc_route
description:
- vpc route management.
short_description: Creates a resource of Vpc/Route in Huawei Cloud
notes:
- If I(id) option is provided, it takes precedence over I(destination), I(vpc_id), I(type) and I(next_hop) for route selection.
- I(destination), I(vpc_id), I(type) and I(next_hop) are used for route selection. If more than one route with this options exists, execution is aborted.
- No parameter support updating. If one of option is changed, the module will create a new resource.
author: Huawei Inc. (@huaweicloud)
requirements:
- keystoneauth1 >= 3.6.0
options:
state:
description:
- Whether the given object should exist in Huawei Cloud.
type: str
choices: ['present', 'absent']
default: 'present'
destination:
description:
- Specifies the destination IP address or CIDR block.
type: str
required: true
next_hop:
description:
- Specifies the next hop. The value is VPC peering connection ID.
type: str
required: true
vpc_id:
description:
- Specifies the VPC ID to which route is added.
type: str
required: true
type:
description:
- Specifies the type of route.
type: str
required: false
default: 'peering'
extends_documentation_fragment:
- community.general.hwc
'''
EXAMPLES = '''
# create a peering connect
- name: create a local vpc
hwc_network_vpc:
cidr: "192.168.0.0/16"
name: "ansible_network_vpc_test_local"
register: vpc1
- name: create a peering vpc
hwc_network_vpc:
cidr: "192.168.0.0/16"
name: "ansible_network_vpc_test_peering"
register: vpc2
- name: create a peering connect
hwc_vpc_peering_connect:
local_vpc_id: "{{ vpc1.id }}"
name: "ansible_network_peering_test"
filters:
- "name"
peering_vpc:
vpc_id: "{{ vpc2.id }}"
register: connect
- name: create a route
hwc_vpc_route:
vpc_id: "{{ vpc1.id }}"
destination: "192.168.0.0/16"
next_hop: "{{ connect.id }}"
'''
RETURN = '''
id:
description:
- UUID of the route.
type: str
returned: success
destination:
description:
- Specifies the destination IP address or CIDR block.
type: str
returned: success
next_hop:
description:
- Specifies the next hop. The value is VPC peering connection ID.
type: str
returned: success
vpc_id:
description:
- Specifies the VPC ID to which route is added.
type: str
returned: success
type:
description:
- Specifies the type of route.
type: str
returned: success
'''
from ansible_collections.community.general.plugins.module_utils.hwc_utils import (
Config, HwcClientException, HwcModule, are_different_dicts, build_path,
get_region, is_empty_value, navigate_value)
def build_module():
return HwcModule(
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'],
type='str'),
destination=dict(type='str', required=True),
next_hop=dict(type='str', required=True),
vpc_id=dict(type='str', required=True),
type=dict(type='str', default='peering'),
id=dict(type='str')
),
supports_check_mode=True,
)
def main():
"""Main function"""
module = build_module()
config = Config(module, "vpc")
try:
resource = None
if module.params.get("id"):
resource = get_resource_by_id(config)
if module.params['state'] == 'present':
opts = user_input_parameters(module)
if are_different_dicts(resource, opts):
raise Exception(
"Cannot change option from (%s) to (%s) for an"
" existing route.(%s)" % (resource, opts,
config.module.params.get(
'id')))
else:
v = search_resource(config)
if len(v) > 1:
raise Exception("Found more than one resource(%s)" % ", ".join([
navigate_value(i, ["id"]) for i in v]))
if len(v) == 1:
resource = update_properties(module, {"read": v[0]}, None)
module.params['id'] = navigate_value(resource, ["id"])
result = {}
changed = False
if module.params['state'] == 'present':
if resource is None:
if not module.check_mode:
resource = create(config)
changed = True
result = resource
else:
if resource:
if not module.check_mode:
delete(config)
changed = True
except Exception as ex:
module.fail_json(msg=str(ex))
else:
result['changed'] = changed
module.exit_json(**result)
def user_input_parameters(module):
return {
"destination": module.params.get("destination"),
"next_hop": module.params.get("next_hop"),
"type": module.params.get("type"),
"vpc_id": module.params.get("vpc_id"),
"id": module.params.get("id"),
}
def create(config):
module = config.module
client = config.client(get_region(module), "network", "project")
opts = user_input_parameters(module)
params = build_create_parameters(opts)
r = send_create_request(module, params, client)
module.params['id'] = navigate_value(r, ["route", "id"])
result = update_properties(module, {"read": fill_resp_body(r)}, None)
return result
def delete(config):
module = config.module
client = config.client(get_region(module), "network", "project")
send_delete_request(module, None, client)
def get_resource_by_id(config, exclude_output=False):
module = config.module
client = config.client(get_region(module), "network", "project")
res = {}
r = send_read_request(module, client)
res["read"] = fill_resp_body(r)
result = update_properties(module, res, None, exclude_output)
return result
def _build_query_link(opts):
query_params = []
v = navigate_value(opts, ["type"])
if v:
query_params.append("type=" + str(v))
v = navigate_value(opts, ["destination"])
if v:
query_params.append("destination=" + str(v))
v = navigate_value(opts, ["vpc_id"])
if v:
query_params.append("vpc_id=" + str(v))
query_link = "?marker={marker}&limit=10"
if query_params:
query_link += "&" + "&".join(query_params)
return query_link
def search_resource(config):
module = config.module
client = config.client(get_region(module), "network", "project")
opts = user_input_parameters(module)
identity_obj = _build_identity_object(opts)
query_link = _build_query_link(opts)
link = "v2.0/vpc/routes" + query_link
result = []
p = {'marker': ''}
while True:
url = link.format(**p)
r = send_list_request(module, client, url)
if not r:
break
for item in r:
item = fill_list_resp_body(item)
if not are_different_dicts(identity_obj, item):
result.append(item)
if len(result) > 1:
break
p['marker'] = r[-1].get('id')
return result
def build_create_parameters(opts):
params = dict()
v = navigate_value(opts, ["destination"], None)
if not is_empty_value(v):
params["destination"] = v
v = navigate_value(opts, ["next_hop"], None)
if not is_empty_value(v):
params["nexthop"] = v
v = navigate_value(opts, ["type"], None)
if not is_empty_value(v):
params["type"] = v
v = navigate_value(opts, ["vpc_id"], None)
if not is_empty_value(v):
params["vpc_id"] = v
if not params:
return params
params = {"route": params}
return params
def send_create_request(module, params, client):
url = "v2.0/vpc/routes"
try:
r = client.post(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_route): error running "
"api(create), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_delete_request(module, params, client):
url = build_path(module, "v2.0/vpc/routes/{id}")
try:
r = client.delete(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_route): error running "
"api(delete), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_read_request(module, client):
url = build_path(module, "v2.0/vpc/routes/{id}")
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_route): error running "
"api(read), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["route"], None)
def fill_resp_body(body):
result = dict()
result["destination"] = body.get("destination")
result["id"] = body.get("id")
result["nexthop"] = body.get("nexthop")
result["type"] = body.get("type")
result["vpc_id"] = body.get("vpc_id")
return result
def update_properties(module, response, array_index, exclude_output=False):
r = user_input_parameters(module)
v = navigate_value(response, ["read", "destination"], array_index)
r["destination"] = v
v = navigate_value(response, ["read", "nexthop"], array_index)
r["next_hop"] = v
v = navigate_value(response, ["read", "type"], array_index)
r["type"] = v
v = navigate_value(response, ["read", "vpc_id"], array_index)
r["vpc_id"] = v
v = navigate_value(response, ["read", "id"], array_index)
r["id"] = v
return r
def send_list_request(module, client, url):
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_route): error running "
"api(list), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["routes"], None)
def _build_identity_object(all_opts):
result = dict()
v = navigate_value(all_opts, ["destination"], None)
result["destination"] = v
v = navigate_value(all_opts, ["id"], None)
result["id"] = v
v = navigate_value(all_opts, ["next_hop"], None)
result["nexthop"] = v
v = navigate_value(all_opts, ["type"], None)
result["type"] = v
v = navigate_value(all_opts, ["vpc_id"], None)
result["vpc_id"] = v
return result
def fill_list_resp_body(body):
result = dict()
result["destination"] = body.get("destination")
result["id"] = body.get("id")
result["nexthop"] = body.get("nexthop")
result["type"] = body.get("type")
result["vpc_id"] = body.get("vpc_id")
return result
if __name__ == '__main__':
main()

View file

@ -0,0 +1,648 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Huawei
# GNU General Public License v3.0+ (see COPYING or
# https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
###############################################################################
# Documentation
###############################################################################
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ["preview"],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: hwc_vpc_security_group
description:
- vpc security group management.
short_description: Creates a resource of Vpc/SecurityGroup in Huawei Cloud
notes:
- If I(id) option is provided, it takes precedence over I(name),
I(enterprise_project_id) and I(vpc_id) for security group selection.
- I(name), I(enterprise_project_id) and I(vpc_id) are used for security
group selection. If more than one security group with this options exists,
execution is aborted.
- No parameter support updating. If one of option is changed, the module
will create a new resource.
author: Huawei Inc. (@huaweicloud)
requirements:
- keystoneauth1 >= 3.6.0
options:
state:
description:
- Whether the given object should exist in Huawei Cloud.
type: str
choices: ['present', 'absent']
default: 'present'
name:
description:
- Specifies the security group name. The value is a string of 1 to
64 characters that can contain letters, digits, underscores C(_),
hyphens (-), and periods (.).
type: str
required: true
enterprise_project_id:
description:
- Specifies the enterprise project ID. When creating a security
group, associate the enterprise project ID with the security
group.s
type: str
required: false
default: 0
vpc_id:
description:
- Specifies the resource ID of the VPC to which the security group
belongs.
type: str
required: false
extends_documentation_fragment:
- community.general.hwc
'''
EXAMPLES = '''
# create a security group
- name: create a security group
hwc_vpc_security_group:
name: "ansible_network_security_group_test"
'''
RETURN = '''
name:
description:
- Specifies the security group name. The value is a string of 1 to
64 characters that can contain letters, digits, underscores C(_),
hyphens (-), and periods (.).
type: str
returned: success
enterprise_project_id:
description:
- Specifies the enterprise project ID. When creating a security
group, associate the enterprise project ID with the security
group.
type: str
returned: success
vpc_id:
description:
- Specifies the resource ID of the VPC to which the security group
belongs.
type: str
returned: success
rules:
description:
- Specifies the security group rule, which ensures that resources
in the security group can communicate with one another.
type: complex
returned: success
contains:
description:
description:
- Provides supplementary information about the security
group rule.
type: str
returned: success
direction:
description:
- Specifies the direction of access control. The value can
be egress or ingress.
type: str
returned: success
ethertype:
description:
- Specifies the IP protocol version. The value can be IPv4
or IPv6.
type: str
returned: success
id:
description:
- Specifies the security group rule ID.
type: str
returned: success
port_range_max:
description:
- Specifies the end port number. The value ranges from 1 to
65535. If the protocol is not icmp, the value cannot be
smaller than the port_range_min value. An empty value
indicates all ports.
type: int
returned: success
port_range_min:
description:
- Specifies the start port number. The value ranges from 1
to 65535. The value cannot be greater than the
port_range_max value. An empty value indicates all ports.
type: int
returned: success
protocol:
description:
- Specifies the protocol type. The value can be icmp, tcp,
udp, or others. If the parameter is left blank, the
security group supports all protocols.
type: str
returned: success
remote_address_group_id:
description:
- Specifies the ID of remote IP address group.
type: str
returned: success
remote_group_id:
description:
- Specifies the ID of the peer security group.
type: str
returned: success
remote_ip_prefix:
description:
- Specifies the remote IP address. If the access control
direction is set to egress, the parameter specifies the
source IP address. If the access control direction is set
to ingress, the parameter specifies the destination IP
address.
type: str
returned: success
'''
from ansible_collections.community.general.plugins.module_utils.hwc_utils import (
Config, HwcClientException, HwcModule, are_different_dicts, build_path,
get_region, is_empty_value, navigate_value)
def build_module():
return HwcModule(
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'],
type='str'),
name=dict(type='str', required=True),
enterprise_project_id=dict(type='str'),
vpc_id=dict(type='str')
),
supports_check_mode=True,
)
def main():
"""Main function"""
module = build_module()
config = Config(module, "vpc")
try:
resource = None
if module.params.get("id"):
resource = read_resource(config)
if module.params['state'] == 'present':
check_resource_option(resource, module)
else:
v = search_resource(config)
if len(v) > 1:
raise Exception("Found more than one resource(%s)" % ", ".join([
navigate_value(i, ["id"]) for i in v]))
if len(v) == 1:
resource = update_properties(module, {"read": v[0]}, None)
module.params['id'] = navigate_value(resource, ["id"])
result = {}
changed = False
if module.params['state'] == 'present':
if resource is None:
if not module.check_mode:
resource = create(config)
changed = True
result = resource
else:
if resource:
if not module.check_mode:
delete(config)
changed = True
except Exception as ex:
module.fail_json(msg=str(ex))
else:
result['changed'] = changed
module.exit_json(**result)
def user_input_parameters(module):
return {
"enterprise_project_id": module.params.get("enterprise_project_id"),
"name": module.params.get("name"),
"vpc_id": module.params.get("vpc_id"),
"id": module.params.get("id"),
}
def check_resource_option(resource, module):
opts = user_input_parameters(module)
resource = {
"enterprise_project_id": resource.get("enterprise_project_id"),
"name": resource.get("name"),
"vpc_id": resource.get("vpc_id"),
"id": resource.get("id"),
}
if are_different_dicts(resource, opts):
raise Exception(
"Cannot change option from (%s) to (%s) for an"
" existing security group(%s)." % (resource, opts,
module.params.get('id')))
def create(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
opts = user_input_parameters(module)
params = build_create_parameters(opts)
r = send_create_request(module, params, client)
module.params['id'] = navigate_value(r, ["security_group", "id"])
result = update_properties(module, {"read": fill_read_resp_body(r)}, None)
return result
def delete(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
send_delete_request(module, None, client)
def read_resource(config, exclude_output=False):
module = config.module
client = config.client(get_region(module), "vpc", "project")
res = {}
r = send_read_request(module, client)
res["read"] = fill_read_resp_body(r)
return update_properties(module, res, None, exclude_output)
def _build_query_link(opts):
query_params = []
v = navigate_value(opts, ["enterprise_project_id"])
if v:
query_params.append("enterprise_project_id=" + str(v))
v = navigate_value(opts, ["vpc_id"])
if v:
query_params.append("vpc_id=" + str(v))
query_link = "?marker={marker}&limit=10"
if query_params:
query_link += "&" + "&".join(query_params)
return query_link
def search_resource(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
opts = user_input_parameters(module)
identity_obj = _build_identity_object(opts)
query_link = _build_query_link(opts)
link = "security-groups" + query_link
result = []
p = {'marker': ''}
while True:
url = link.format(**p)
r = send_list_request(module, client, url)
if not r:
break
for item in r:
item = fill_list_resp_body(item)
if not are_different_dicts(identity_obj, item):
result.append(item)
if len(result) > 1:
break
p['marker'] = r[-1].get('id')
return result
def build_create_parameters(opts):
params = dict()
v = navigate_value(opts, ["enterprise_project_id"], None)
if not is_empty_value(v):
params["enterprise_project_id"] = v
v = navigate_value(opts, ["name"], None)
if not is_empty_value(v):
params["name"] = v
v = navigate_value(opts, ["vpc_id"], None)
if not is_empty_value(v):
params["vpc_id"] = v
if not params:
return params
params = {"security_group": params}
return params
def send_create_request(module, params, client):
url = "security-groups"
try:
r = client.post(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_security_group): error running "
"api(create), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_delete_request(module, params, client):
url = build_path(module, "security-groups/{id}")
try:
r = client.delete(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_security_group): error running "
"api(delete), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_read_request(module, client):
url = build_path(module, "security-groups/{id}")
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_security_group): error running "
"api(read), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["security_group"], None)
def fill_read_resp_body(body):
result = dict()
result["enterprise_project_id"] = body.get("enterprise_project_id")
result["id"] = body.get("id")
result["name"] = body.get("name")
v = fill_read_resp_security_group_rules(body.get("security_group_rules"))
result["security_group_rules"] = v
result["vpc_id"] = body.get("vpc_id")
return result
def fill_read_resp_security_group_rules(value):
if not value:
return None
result = []
for item in value:
val = dict()
val["description"] = item.get("description")
val["direction"] = item.get("direction")
val["ethertype"] = item.get("ethertype")
val["id"] = item.get("id")
val["port_range_max"] = item.get("port_range_max")
val["port_range_min"] = item.get("port_range_min")
val["protocol"] = item.get("protocol")
val["remote_address_group_id"] = item.get("remote_address_group_id")
val["remote_group_id"] = item.get("remote_group_id")
val["remote_ip_prefix"] = item.get("remote_ip_prefix")
val["security_group_id"] = item.get("security_group_id")
result.append(val)
return result
def update_properties(module, response, array_index, exclude_output=False):
r = user_input_parameters(module)
v = navigate_value(response, ["read", "enterprise_project_id"],
array_index)
r["enterprise_project_id"] = v
v = navigate_value(response, ["read", "name"], array_index)
r["name"] = v
if not exclude_output:
v = r.get("rules")
v = flatten_rules(response, array_index, v, exclude_output)
r["rules"] = v
v = navigate_value(response, ["read", "vpc_id"], array_index)
r["vpc_id"] = v
v = navigate_value(response, ["read", "id"], array_index)
r["id"] = v
return r
def flatten_rules(d, array_index, current_value, exclude_output):
n = 0
result = current_value
has_init_value = True
if result:
n = len(result)
else:
has_init_value = False
result = []
v = navigate_value(d, ["read", "security_group_rules"],
array_index)
if not v:
return current_value
n = len(v)
new_array_index = dict()
if array_index:
new_array_index.update(array_index)
for i in range(n):
new_array_index["read.security_group_rules"] = i
val = dict()
if len(result) >= (i + 1) and result[i]:
val = result[i]
if not exclude_output:
v = navigate_value(d, ["read", "security_group_rules", "description"],
new_array_index)
val["description"] = v
if not exclude_output:
v = navigate_value(d, ["read", "security_group_rules", "direction"],
new_array_index)
val["direction"] = v
if not exclude_output:
v = navigate_value(d, ["read", "security_group_rules", "ethertype"],
new_array_index)
val["ethertype"] = v
if not exclude_output:
v = navigate_value(d, ["read", "security_group_rules", "id"],
new_array_index)
val["id"] = v
if not exclude_output:
v = navigate_value(d, ["read", "security_group_rules", "port_range_max"],
new_array_index)
val["port_range_max"] = v
if not exclude_output:
v = navigate_value(d, ["read", "security_group_rules", "port_range_min"],
new_array_index)
val["port_range_min"] = v
if not exclude_output:
v = navigate_value(d, ["read", "security_group_rules", "protocol"],
new_array_index)
val["protocol"] = v
if not exclude_output:
v = navigate_value(d, ["read", "security_group_rules", "remote_address_group_id"],
new_array_index)
val["remote_address_group_id"] = v
if not exclude_output:
v = navigate_value(d, ["read", "security_group_rules", "remote_group_id"],
new_array_index)
val["remote_group_id"] = v
if not exclude_output:
v = navigate_value(d, ["read", "security_group_rules", "remote_ip_prefix"],
new_array_index)
val["remote_ip_prefix"] = v
if len(result) >= (i + 1):
result[i] = val
else:
for v in val.values():
if v is not None:
result.append(val)
break
return result if (has_init_value or result) else current_value
def send_list_request(module, client, url):
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_security_group): error running "
"api(list), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["security_groups"], None)
def _build_identity_object(all_opts):
result = dict()
v = navigate_value(all_opts, ["enterprise_project_id"], None)
result["enterprise_project_id"] = v
result["id"] = None
v = navigate_value(all_opts, ["name"], None)
result["name"] = v
result["security_group_rules"] = None
v = navigate_value(all_opts, ["vpc_id"], None)
result["vpc_id"] = v
return result
def fill_list_resp_body(body):
result = dict()
result["enterprise_project_id"] = body.get("enterprise_project_id")
result["id"] = body.get("id")
result["name"] = body.get("name")
v = fill_list_resp_security_group_rules(body.get("security_group_rules"))
result["security_group_rules"] = v
result["vpc_id"] = body.get("vpc_id")
return result
def fill_list_resp_security_group_rules(value):
if not value:
return None
result = []
for item in value:
val = dict()
val["description"] = item.get("description")
val["direction"] = item.get("direction")
val["ethertype"] = item.get("ethertype")
val["id"] = item.get("id")
val["port_range_max"] = item.get("port_range_max")
val["port_range_min"] = item.get("port_range_min")
val["protocol"] = item.get("protocol")
val["remote_address_group_id"] = item.get("remote_address_group_id")
val["remote_group_id"] = item.get("remote_group_id")
val["remote_ip_prefix"] = item.get("remote_ip_prefix")
val["security_group_id"] = item.get("security_group_id")
result.append(val)
return result
if __name__ == '__main__':
main()

View file

@ -0,0 +1,573 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Huawei
# GNU General Public License v3.0+ (see COPYING or
# https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
###############################################################################
# Documentation
###############################################################################
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ["preview"],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: hwc_vpc_security_group_rule
description:
- vpc security group management.
short_description: Creates a resource of Vpc/SecurityGroupRule in Huawei Cloud
notes:
- If I(id) option is provided, it takes precedence over
I(enterprise_project_id) for security group rule selection.
- I(security_group_id) is used for security group rule selection. If more
than one security group rule with this options exists, execution is
aborted.
- No parameter support updating. If one of option is changed, the module
will create a new resource.
author: Huawei Inc. (@huaweicloud)
requirements:
- keystoneauth1 >= 3.6.0
options:
state:
description:
- Whether the given object should exist in Huawei Cloud.
type: str
choices: ['present', 'absent']
default: 'present'
direction:
description:
- Specifies the direction of access control. The value can be
egress or ingress.
type: str
required: true
security_group_id:
description:
- Specifies the security group rule ID, which uniquely identifies
the security group rule.
type: str
required: true
description:
description:
- Provides supplementary information about the security group rule.
The value is a string of no more than 255 characters that can
contain letters and digits.
type: str
required: false
ethertype:
description:
- Specifies the IP protocol version. The value can be IPv4 or IPv6.
If you do not set this parameter, IPv4 is used by default.
type: str
required: false
port_range_max:
description:
- Specifies the end port number. The value ranges from 1 to 65535.
If the protocol is not icmp, the value cannot be smaller than the
port_range_min value. An empty value indicates all ports.
type: int
required: false
port_range_min:
description:
- Specifies the start port number. The value ranges from 1 to
65535. The value cannot be greater than the port_range_max value.
An empty value indicates all ports.
type: int
required: false
protocol:
description:
- Specifies the protocol type. The value can be icmp, tcp, or udp.
If the parameter is left blank, the security group supports all
protocols.
type: str
required: false
remote_group_id:
description:
- Specifies the ID of the peer security group. The value is
exclusive with parameter remote_ip_prefix.
type: str
required: false
remote_ip_prefix:
description:
- Specifies the remote IP address. If the access control direction
is set to egress, the parameter specifies the source IP address.
If the access control direction is set to ingress, the parameter
specifies the destination IP address. The value can be in the
CIDR format or IP addresses. The parameter is exclusive with
parameter remote_group_id.
type: str
required: false
extends_documentation_fragment:
- community.general.hwc
'''
EXAMPLES = '''
# create a security group rule
- name: create a security group
hwc_vpc_security_group:
name: "ansible_network_security_group_test"
register: sg
- name: create a security group rule
hwc_vpc_security_group_rule:
direction: "ingress"
protocol: "tcp"
ethertype: "IPv4"
port_range_max: 22
security_group_id: "{{ sg.id }}"
port_range_min: 22
remote_ip_prefix: "0.0.0.0/0"
'''
RETURN = '''
direction:
description:
- Specifies the direction of access control. The value can be
egress or ingress.
type: str
returned: success
security_group_id:
description:
- Specifies the security group rule ID, which uniquely identifies
the security group rule.
type: str
returned: success
description:
description:
- Provides supplementary information about the security group rule.
The value is a string of no more than 255 characters that can
contain letters and digits.
type: str
returned: success
ethertype:
description:
- Specifies the IP protocol version. The value can be IPv4 or IPv6.
If you do not set this parameter, IPv4 is used by default.
type: str
returned: success
port_range_max:
description:
- Specifies the end port number. The value ranges from 1 to 65535.
If the protocol is not icmp, the value cannot be smaller than the
port_range_min value. An empty value indicates all ports.
type: int
returned: success
port_range_min:
description:
- Specifies the start port number. The value ranges from 1 to
65535. The value cannot be greater than the port_range_max value.
An empty value indicates all ports.
type: int
returned: success
protocol:
description:
- Specifies the protocol type. The value can be icmp, tcp, or udp.
If the parameter is left blank, the security group supports all
protocols.
type: str
returned: success
remote_group_id:
description:
- Specifies the ID of the peer security group. The value is
exclusive with parameter remote_ip_prefix.
type: str
returned: success
remote_ip_prefix:
description:
- Specifies the remote IP address. If the access control direction
is set to egress, the parameter specifies the source IP address.
If the access control direction is set to ingress, the parameter
specifies the destination IP address. The value can be in the
CIDR format or IP addresses. The parameter is exclusive with
parameter remote_group_id.
type: str
returned: success
'''
from ansible_collections.community.general.plugins.module_utils.hwc_utils import (
Config, HwcClientException, HwcModule, are_different_dicts, build_path,
get_region, is_empty_value, navigate_value)
def build_module():
return HwcModule(
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'],
type='str'),
direction=dict(type='str', required=True),
security_group_id=dict(type='str', required=True),
description=dict(type='str'),
ethertype=dict(type='str'),
port_range_max=dict(type='int'),
port_range_min=dict(type='int'),
protocol=dict(type='str'),
remote_group_id=dict(type='str'),
remote_ip_prefix=dict(type='str')
),
supports_check_mode=True,
)
def main():
"""Main function"""
module = build_module()
config = Config(module, "vpc")
try:
resource = None
if module.params['id']:
resource = True
else:
v = search_resource(config)
if len(v) > 1:
raise Exception("Found more than one resource(%s)" % ", ".join([
navigate_value(i, ["id"]) for i in v]))
if len(v) == 1:
resource = v[0]
module.params['id'] = navigate_value(resource, ["id"])
result = {}
changed = False
if module.params['state'] == 'present':
if resource is None:
if not module.check_mode:
create(config)
changed = True
current = read_resource(config, exclude_output=True)
expect = user_input_parameters(module)
if are_different_dicts(expect, current):
raise Exception(
"Cannot change option from (%s) to (%s) for an"
" existing security group(%s)." % (current, expect, module.params.get('id')))
result = read_resource(config)
result['id'] = module.params.get('id')
else:
if resource:
if not module.check_mode:
delete(config)
changed = True
except Exception as ex:
module.fail_json(msg=str(ex))
else:
result['changed'] = changed
module.exit_json(**result)
def user_input_parameters(module):
return {
"description": module.params.get("description"),
"direction": module.params.get("direction"),
"ethertype": module.params.get("ethertype"),
"port_range_max": module.params.get("port_range_max"),
"port_range_min": module.params.get("port_range_min"),
"protocol": module.params.get("protocol"),
"remote_group_id": module.params.get("remote_group_id"),
"remote_ip_prefix": module.params.get("remote_ip_prefix"),
"security_group_id": module.params.get("security_group_id"),
}
def create(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
opts = user_input_parameters(module)
params = build_create_parameters(opts)
r = send_create_request(module, params, client)
module.params['id'] = navigate_value(r, ["security_group_rule", "id"])
def delete(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
send_delete_request(module, None, client)
def read_resource(config, exclude_output=False):
module = config.module
client = config.client(get_region(module), "vpc", "project")
res = {}
r = send_read_request(module, client)
res["read"] = fill_read_resp_body(r)
return update_properties(module, res, None, exclude_output)
def _build_query_link(opts):
query_link = "?marker={marker}&limit=10"
v = navigate_value(opts, ["security_group_id"])
if v:
query_link += "&security_group_id=" + str(v)
return query_link
def search_resource(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
opts = user_input_parameters(module)
identity_obj = _build_identity_object(opts)
query_link = _build_query_link(opts)
link = "security-group-rules" + query_link
result = []
p = {'marker': ''}
while True:
url = link.format(**p)
r = send_list_request(module, client, url)
if not r:
break
for item in r:
item = fill_list_resp_body(item)
if not are_different_dicts(identity_obj, item):
result.append(item)
if len(result) > 1:
break
p['marker'] = r[-1].get('id')
return result
def build_create_parameters(opts):
params = dict()
v = navigate_value(opts, ["description"], None)
if not is_empty_value(v):
params["description"] = v
v = navigate_value(opts, ["direction"], None)
if not is_empty_value(v):
params["direction"] = v
v = navigate_value(opts, ["ethertype"], None)
if not is_empty_value(v):
params["ethertype"] = v
v = navigate_value(opts, ["port_range_max"], None)
if not is_empty_value(v):
params["port_range_max"] = v
v = navigate_value(opts, ["port_range_min"], None)
if not is_empty_value(v):
params["port_range_min"] = v
v = navigate_value(opts, ["protocol"], None)
if not is_empty_value(v):
params["protocol"] = v
v = navigate_value(opts, ["remote_group_id"], None)
if not is_empty_value(v):
params["remote_group_id"] = v
v = navigate_value(opts, ["remote_ip_prefix"], None)
if not is_empty_value(v):
params["remote_ip_prefix"] = v
v = navigate_value(opts, ["security_group_id"], None)
if not is_empty_value(v):
params["security_group_id"] = v
if not params:
return params
params = {"security_group_rule": params}
return params
def send_create_request(module, params, client):
url = "security-group-rules"
try:
r = client.post(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_security_group_rule): error running "
"api(create), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_delete_request(module, params, client):
url = build_path(module, "security-group-rules/{id}")
try:
r = client.delete(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_security_group_rule): error running "
"api(delete), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_read_request(module, client):
url = build_path(module, "security-group-rules/{id}")
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_security_group_rule): error running "
"api(read), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["security_group_rule"], None)
def fill_read_resp_body(body):
result = dict()
result["description"] = body.get("description")
result["direction"] = body.get("direction")
result["ethertype"] = body.get("ethertype")
result["id"] = body.get("id")
result["port_range_max"] = body.get("port_range_max")
result["port_range_min"] = body.get("port_range_min")
result["protocol"] = body.get("protocol")
result["remote_address_group_id"] = body.get("remote_address_group_id")
result["remote_group_id"] = body.get("remote_group_id")
result["remote_ip_prefix"] = body.get("remote_ip_prefix")
result["security_group_id"] = body.get("security_group_id")
return result
def update_properties(module, response, array_index, exclude_output=False):
r = user_input_parameters(module)
v = navigate_value(response, ["read", "description"], array_index)
r["description"] = v
v = navigate_value(response, ["read", "direction"], array_index)
r["direction"] = v
v = navigate_value(response, ["read", "ethertype"], array_index)
r["ethertype"] = v
v = navigate_value(response, ["read", "port_range_max"], array_index)
r["port_range_max"] = v
v = navigate_value(response, ["read", "port_range_min"], array_index)
r["port_range_min"] = v
v = navigate_value(response, ["read", "protocol"], array_index)
r["protocol"] = v
v = navigate_value(response, ["read", "remote_group_id"], array_index)
r["remote_group_id"] = v
v = navigate_value(response, ["read", "remote_ip_prefix"], array_index)
r["remote_ip_prefix"] = v
v = navigate_value(response, ["read", "security_group_id"], array_index)
r["security_group_id"] = v
return r
def send_list_request(module, client, url):
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_security_group_rule): error running "
"api(list), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["security_group_rules"], None)
def _build_identity_object(all_opts):
result = dict()
v = navigate_value(all_opts, ["description"], None)
result["description"] = v
v = navigate_value(all_opts, ["direction"], None)
result["direction"] = v
v = navigate_value(all_opts, ["ethertype"], None)
result["ethertype"] = v
result["id"] = None
v = navigate_value(all_opts, ["port_range_max"], None)
result["port_range_max"] = v
v = navigate_value(all_opts, ["port_range_min"], None)
result["port_range_min"] = v
v = navigate_value(all_opts, ["protocol"], None)
result["protocol"] = v
result["remote_address_group_id"] = None
v = navigate_value(all_opts, ["remote_group_id"], None)
result["remote_group_id"] = v
v = navigate_value(all_opts, ["remote_ip_prefix"], None)
result["remote_ip_prefix"] = v
v = navigate_value(all_opts, ["security_group_id"], None)
result["security_group_id"] = v
return result
def fill_list_resp_body(body):
result = dict()
result["description"] = body.get("description")
result["direction"] = body.get("direction")
result["ethertype"] = body.get("ethertype")
result["id"] = body.get("id")
result["port_range_max"] = body.get("port_range_max")
result["port_range_min"] = body.get("port_range_min")
result["protocol"] = body.get("protocol")
result["remote_address_group_id"] = body.get("remote_address_group_id")
result["remote_group_id"] = body.get("remote_group_id")
result["remote_ip_prefix"] = body.get("remote_ip_prefix")
result["security_group_id"] = body.get("security_group_id")
return result
if __name__ == '__main__':
main()

View file

@ -0,0 +1,736 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Huawei
# GNU General Public License v3.0+ (see COPYING or
# https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
###############################################################################
# Documentation
###############################################################################
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ["preview"],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: hwc_vpc_subnet
description:
- subnet management.
short_description: Creates a resource of Vpc/Subnet in Huawei Cloud
author: Huawei Inc. (@huaweicloud)
requirements:
- keystoneauth1 >= 3.6.0
options:
state:
description:
- Whether the given object should exist in Huawei Cloud.
type: str
choices: ['present', 'absent']
default: 'present'
timeouts:
description:
- The timeouts for each operations.
type: dict
suboptions:
create:
description:
- The timeouts for create operation.
type: str
default: '15m'
update:
description:
- The timeouts for update operation.
type: str
default: '15m'
cidr:
description:
- Specifies the subnet CIDR block. The value must be within the VPC
CIDR block and be in CIDR format. The subnet mask cannot be
greater than 28. Cannot be changed after creating the subnet.
type: str
required: true
gateway_ip:
description:
- Specifies the gateway of the subnet. The value must be an IP
address in the subnet. Cannot be changed after creating the subnet.
type: str
required: true
name:
description:
- Specifies the subnet name. The value is a string of 1 to 64
characters that can contain letters, digits, underscores C(_),
hyphens (-), and periods (.).
type: str
required: true
vpc_id:
description:
- Specifies the ID of the VPC to which the subnet belongs. Cannot
be changed after creating the subnet.
type: str
required: true
availability_zone:
description:
- Specifies the AZ to which the subnet belongs. Cannot be changed
after creating the subnet.
type: str
required: false
dhcp_enable:
description:
- Specifies whether DHCP is enabled for the subnet. The value can
be true (enabled) or false(disabled), and default value is true.
If this parameter is set to false, newly created ECSs cannot
obtain IP addresses, and usernames and passwords cannot be
injected using Cloud-init.
type: bool
required: false
dns_address:
description:
- Specifies the DNS server addresses for subnet. The address
in the head will be used first.
type: list
required: false
extends_documentation_fragment:
- community.general.hwc
'''
EXAMPLES = '''
# create subnet
- name: create vpc
hwc_network_vpc:
cidr: "192.168.100.0/24"
name: "ansible_network_vpc_test"
register: vpc
- name: create subnet
hwc_vpc_subnet:
vpc_id: "{{ vpc.id }}"
cidr: "192.168.100.0/26"
gateway_ip: "192.168.100.32"
name: "ansible_network_subnet_test"
dhcp_enable: True
'''
RETURN = '''
cidr:
description:
- Specifies the subnet CIDR block. The value must be within the VPC
CIDR block and be in CIDR format. The subnet mask cannot be
greater than 28.
type: str
returned: success
gateway_ip:
description:
- Specifies the gateway of the subnet. The value must be an IP
address in the subnet.
type: str
returned: success
name:
description:
- Specifies the subnet name. The value is a string of 1 to 64
characters that can contain letters, digits, underscores C(_),
hyphens (-), and periods (.).
type: str
returned: success
vpc_id:
description:
- Specifies the ID of the VPC to which the subnet belongs.
type: str
returned: success
availability_zone:
description:
- Specifies the AZ to which the subnet belongs.
type: str
returned: success
dhcp_enable:
description:
- Specifies whether DHCP is enabled for the subnet. The value can
be true (enabled) or false(disabled), and default value is true.
If this parameter is set to false, newly created ECSs cannot
obtain IP addresses, and usernames and passwords cannot be
injected using Cloud-init.
type: bool
returned: success
dns_address:
description:
- Specifies the DNS server addresses for subnet. The address
in the head will be used first.
type: list
returned: success
'''
from ansible_collections.community.general.plugins.module_utils.hwc_utils import (
Config, HwcClientException, HwcClientException404, HwcModule,
are_different_dicts, build_path, get_region, is_empty_value,
navigate_value, wait_to_finish)
def build_module():
return HwcModule(
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'],
type='str'),
timeouts=dict(type='dict', options=dict(
create=dict(default='15m', type='str'),
update=dict(default='15m', type='str'),
), default=dict()),
cidr=dict(type='str', required=True),
gateway_ip=dict(type='str', required=True),
name=dict(type='str', required=True),
vpc_id=dict(type='str', required=True),
availability_zone=dict(type='str'),
dhcp_enable=dict(type='bool'),
dns_address=dict(type='list', elements='str')
),
supports_check_mode=True,
)
def main():
"""Main function"""
module = build_module()
config = Config(module, "vpc")
try:
resource = None
if module.params.get('id'):
resource = True
else:
v = search_resource(config)
if len(v) > 1:
raise Exception("Found more than one resource(%s)" % ", ".join([
navigate_value(i, ["id"]) for i in v]))
if len(v) == 1:
resource = v[0]
module.params['id'] = navigate_value(resource, ["id"])
result = {}
changed = False
if module.params['state'] == 'present':
if resource is None:
if not module.check_mode:
create(config)
changed = True
current = read_resource(config, exclude_output=True)
expect = user_input_parameters(module)
if are_different_dicts(expect, current):
if not module.check_mode:
update(config)
changed = True
result = read_resource(config)
result['id'] = module.params.get('id')
else:
if resource:
if not module.check_mode:
delete(config)
changed = True
except Exception as ex:
module.fail_json(msg=str(ex))
else:
result['changed'] = changed
module.exit_json(**result)
def user_input_parameters(module):
return {
"availability_zone": module.params.get("availability_zone"),
"cidr": module.params.get("cidr"),
"dhcp_enable": module.params.get("dhcp_enable"),
"dns_address": module.params.get("dns_address"),
"gateway_ip": module.params.get("gateway_ip"),
"name": module.params.get("name"),
"vpc_id": module.params.get("vpc_id"),
}
def create(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
timeout = 60 * int(module.params['timeouts']['create'].rstrip('m'))
opts = user_input_parameters(module)
params = build_create_parameters(opts)
r = send_create_request(module, params, client)
obj = async_wait_create(config, r, client, timeout)
module.params['id'] = navigate_value(obj, ["subnet", "id"])
def update(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
timeout = 60 * int(module.params['timeouts']['update'].rstrip('m'))
opts = user_input_parameters(module)
params = build_update_parameters(opts)
if params:
r = send_update_request(module, params, client)
async_wait_update(config, r, client, timeout)
def delete(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
send_delete_request(module, None, client)
url = build_path(module, "subnets/{id}")
def _refresh_status():
try:
client.get(url)
except HwcClientException404:
return True, "Done"
except Exception:
return None, ""
return True, "Pending"
timeout = 60 * int(module.params['timeouts']['create'].rstrip('m'))
try:
wait_to_finish(["Done"], ["Pending"], _refresh_status, timeout)
except Exception as ex:
module.fail_json(msg="module(hwc_vpc_subnet): error "
"waiting for api(delete) to "
"be done, error= %s" % str(ex))
def read_resource(config, exclude_output=False):
module = config.module
client = config.client(get_region(module), "vpc", "project")
res = {}
r = send_read_request(module, client)
res["read"] = fill_read_resp_body(r)
return update_properties(module, res, None, exclude_output)
def _build_query_link(opts):
query_link = "?marker={marker}&limit=10"
v = navigate_value(opts, ["vpc_id"])
if v:
query_link += "&vpc_id=" + str(v)
return query_link
def search_resource(config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
opts = user_input_parameters(module)
identity_obj = _build_identity_object(opts)
query_link = _build_query_link(opts)
link = "subnets" + query_link
result = []
p = {'marker': ''}
while True:
url = link.format(**p)
r = send_list_request(module, client, url)
if not r:
break
for item in r:
item = fill_list_resp_body(item)
if not are_different_dicts(identity_obj, item):
result.append(item)
if len(result) > 1:
break
p['marker'] = r[-1].get('id')
return result
def build_create_parameters(opts):
params = dict()
v = navigate_value(opts, ["availability_zone"], None)
if not is_empty_value(v):
params["availability_zone"] = v
v = navigate_value(opts, ["cidr"], None)
if not is_empty_value(v):
params["cidr"] = v
v = navigate_value(opts, ["dhcp_enable"], None)
if v is not None:
params["dhcp_enable"] = v
v = expand_create_dns_list(opts, None)
if not is_empty_value(v):
params["dnsList"] = v
v = navigate_value(opts, ["gateway_ip"], None)
if not is_empty_value(v):
params["gateway_ip"] = v
v = navigate_value(opts, ["name"], None)
if not is_empty_value(v):
params["name"] = v
v = expand_create_primary_dns(opts, None)
if not is_empty_value(v):
params["primary_dns"] = v
v = expand_create_secondary_dns(opts, None)
if not is_empty_value(v):
params["secondary_dns"] = v
v = navigate_value(opts, ["vpc_id"], None)
if not is_empty_value(v):
params["vpc_id"] = v
if not params:
return params
params = {"subnet": params}
return params
def expand_create_dns_list(d, array_index):
v = navigate_value(d, ["dns_address"], array_index)
return v if (v and len(v) > 2) else []
def expand_create_primary_dns(d, array_index):
v = navigate_value(d, ["dns_address"], array_index)
return v[0] if v else ""
def expand_create_secondary_dns(d, array_index):
v = navigate_value(d, ["dns_address"], array_index)
return v[1] if (v and len(v) > 1) else ""
def send_create_request(module, params, client):
url = "subnets"
try:
r = client.post(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_subnet): error running "
"api(create), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def async_wait_create(config, result, client, timeout):
module = config.module
path_parameters = {
"subnet_id": ["subnet", "id"],
}
data = dict((key, navigate_value(result, path))
for key, path in path_parameters.items())
url = build_path(module, "subnets/{subnet_id}", data)
def _query_status():
r = None
try:
r = client.get(url, timeout=timeout)
except HwcClientException:
return None, ""
try:
s = navigate_value(r, ["subnet", "status"])
return r, s
except Exception:
return None, ""
try:
return wait_to_finish(
["ACTIVE"],
["UNKNOWN"],
_query_status, timeout)
except Exception as ex:
module.fail_json(msg="module(hwc_vpc_subnet): error "
"waiting for api(create) to "
"be done, error= %s" % str(ex))
def build_update_parameters(opts):
params = dict()
v = navigate_value(opts, ["dhcp_enable"], None)
if v is not None:
params["dhcp_enable"] = v
v = expand_update_dns_list(opts, None)
if v is not None:
params["dnsList"] = v
v = navigate_value(opts, ["name"], None)
if not is_empty_value(v):
params["name"] = v
v = expand_update_primary_dns(opts, None)
if v is not None:
params["primary_dns"] = v
v = expand_update_secondary_dns(opts, None)
if v is not None:
params["secondary_dns"] = v
if not params:
return params
params = {"subnet": params}
return params
def expand_update_dns_list(d, array_index):
v = navigate_value(d, ["dns_address"], array_index)
if v:
if len(v) > 2:
return v
return None
return []
def expand_update_primary_dns(d, array_index):
v = navigate_value(d, ["dns_address"], array_index)
return v[0] if v else ""
def expand_update_secondary_dns(d, array_index):
v = navigate_value(d, ["dns_address"], array_index)
return v[1] if (v and len(v) > 1) else ""
def send_update_request(module, params, client):
url = build_path(module, "vpcs/{vpc_id}/subnets/{id}")
try:
r = client.put(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_subnet): error running "
"api(update), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def async_wait_update(config, result, client, timeout):
module = config.module
path_parameters = {
"subnet_id": ["subnet", "id"],
}
data = dict((key, navigate_value(result, path))
for key, path in path_parameters.items())
url = build_path(module, "subnets/{subnet_id}", data)
def _query_status():
r = None
try:
r = client.get(url, timeout=timeout)
except HwcClientException:
return None, ""
try:
s = navigate_value(r, ["subnet", "status"])
return r, s
except Exception:
return None, ""
try:
return wait_to_finish(
["ACTIVE"],
["UNKNOWN"],
_query_status, timeout)
except Exception as ex:
module.fail_json(msg="module(hwc_vpc_subnet): error "
"waiting for api(update) to "
"be done, error= %s" % str(ex))
def send_delete_request(module, params, client):
url = build_path(module, "vpcs/{vpc_id}/subnets/{id}")
try:
r = client.delete(url, params)
except HwcClientException as ex:
msg = ("module(hwc_vpc_subnet): error running "
"api(delete), error: %s" % str(ex))
module.fail_json(msg=msg)
return r
def send_read_request(module, client):
url = build_path(module, "subnets/{id}")
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_subnet): error running "
"api(read), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["subnet"], None)
def fill_read_resp_body(body):
result = dict()
result["availability_zone"] = body.get("availability_zone")
result["cidr"] = body.get("cidr")
result["dhcp_enable"] = body.get("dhcp_enable")
result["dnsList"] = body.get("dnsList")
result["gateway_ip"] = body.get("gateway_ip")
result["id"] = body.get("id")
result["name"] = body.get("name")
result["neutron_network_id"] = body.get("neutron_network_id")
result["neutron_subnet_id"] = body.get("neutron_subnet_id")
result["primary_dns"] = body.get("primary_dns")
result["secondary_dns"] = body.get("secondary_dns")
result["status"] = body.get("status")
result["vpc_id"] = body.get("vpc_id")
return result
def update_properties(module, response, array_index, exclude_output=False):
r = user_input_parameters(module)
v = navigate_value(response, ["read", "availability_zone"], array_index)
r["availability_zone"] = v
v = navigate_value(response, ["read", "cidr"], array_index)
r["cidr"] = v
v = navigate_value(response, ["read", "dhcp_enable"], array_index)
r["dhcp_enable"] = v
v = navigate_value(response, ["read", "dnsList"], array_index)
r["dns_address"] = v
v = navigate_value(response, ["read", "gateway_ip"], array_index)
r["gateway_ip"] = v
v = navigate_value(response, ["read", "name"], array_index)
r["name"] = v
v = navigate_value(response, ["read", "vpc_id"], array_index)
r["vpc_id"] = v
return r
def send_list_request(module, client, url):
r = None
try:
r = client.get(url)
except HwcClientException as ex:
msg = ("module(hwc_vpc_subnet): error running "
"api(list), error: %s" % str(ex))
module.fail_json(msg=msg)
return navigate_value(r, ["subnets"], None)
def _build_identity_object(all_opts):
result = dict()
v = navigate_value(all_opts, ["availability_zone"], None)
result["availability_zone"] = v
v = navigate_value(all_opts, ["cidr"], None)
result["cidr"] = v
v = navigate_value(all_opts, ["dhcp_enable"], None)
result["dhcp_enable"] = v
v = navigate_value(all_opts, ["dns_address"], None)
result["dnsList"] = v
v = navigate_value(all_opts, ["gateway_ip"], None)
result["gateway_ip"] = v
result["id"] = None
v = navigate_value(all_opts, ["name"], None)
result["name"] = v
result["neutron_network_id"] = None
result["neutron_subnet_id"] = None
result["primary_dns"] = None
result["secondary_dns"] = None
result["status"] = None
v = navigate_value(all_opts, ["vpc_id"], None)
result["vpc_id"] = v
return result
def fill_list_resp_body(body):
result = dict()
result["availability_zone"] = body.get("availability_zone")
result["cidr"] = body.get("cidr")
result["dhcp_enable"] = body.get("dhcp_enable")
result["dnsList"] = body.get("dnsList")
result["gateway_ip"] = body.get("gateway_ip")
result["id"] = body.get("id")
result["name"] = body.get("name")
result["neutron_network_id"] = body.get("neutron_network_id")
result["neutron_subnet_id"] = body.get("neutron_subnet_id")
result["primary_dns"] = body.get("primary_dns")
result["secondary_dns"] = body.get("secondary_dns")
result["status"] = body.get("status")
result["vpc_id"] = body.get("vpc_id")
return result
if __name__ == '__main__':
main()