summaryrefslogtreecommitdiff
path: root/lib/ansible/modules/cloud/google/gcp_compute_subnetwork.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/modules/cloud/google/gcp_compute_subnetwork.py')
-rw-r--r--lib/ansible/modules/cloud/google/gcp_compute_subnetwork.py189
1 files changed, 174 insertions, 15 deletions
diff --git a/lib/ansible/modules/cloud/google/gcp_compute_subnetwork.py b/lib/ansible/modules/cloud/google/gcp_compute_subnetwork.py
index e2cca99239..9348fb6293 100644
--- a/lib/ansible/modules/cloud/google/gcp_compute_subnetwork.py
+++ b/lib/ansible/modules/cloud/google/gcp_compute_subnetwork.py
@@ -87,7 +87,39 @@ options:
description:
- The network this subnet belongs to.
- Only networks that are in the distributed mode can have subnetworks.
+ - 'This field represents a link to a Network resource in GCP. It can be specified
+ in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
+ and then set this network field to "{{ name-of-resource }}" Alternatively, you can
+ set this network to a dictionary with the selfLink key where the value is the selfLink
+ of your Network.'
required: true
+ enable_flow_logs:
+ description:
+ - Whether to enable flow logging for this subnetwork.
+ required: false
+ type: bool
+ version_added: 2.8
+ secondary_ip_ranges:
+ description:
+ - An array of configurations for secondary IP ranges for VM instances contained in
+ this subnetwork. The primary IP of such VM must belong to the primary ipCidrRange
+ of the subnetwork. The alias IPs may belong to either primary or secondary ranges.
+ required: false
+ version_added: 2.8
+ suboptions:
+ range_name:
+ description:
+ - The name associated with this subnetwork secondary range, used when adding an alias
+ IP range to a VM instance. The name must be 1-63 characters long, and comply with
+ RFC1035. The name must be unique within the subnetwork.
+ required: true
+ ip_cidr_range:
+ description:
+ - The range of IP addresses belonging to this subnetwork secondary range. Provide
+ this property when you create the subnetwork.
+ - Ranges must be unique and non-overlapping with all primary and secondary IP ranges
+ within a network. Only IPv4 is supported.
+ required: true
private_ip_google_access:
description:
- Whether the VMs in this subnet can access Google services without assigned external
@@ -123,13 +155,13 @@ EXAMPLES = '''
network: "{{ network }}"
ip_cidr_range: 172.16.0.0/16
project: "test_project"
- auth_kind: "service_account"
+ auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
- creation_timestamp:
+ creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@@ -140,7 +172,7 @@ RETURN = '''
the resource. This field can be set only at resource creation time.
returned: success
type: str
- gateway_address:
+ gatewayAddress:
description:
- The gateway address for default routes to reach destination addresses outside this
subnetwork.
@@ -151,7 +183,7 @@ RETURN = '''
- The unique identifier for the resource.
returned: success
type: int
- ip_cidr_range:
+ ipCidrRange:
description:
- The range of internal addresses that are owned by this subnetwork.
- Provide this property when you create the subnetwork. For example, 10.0.0.0/8 or
@@ -175,7 +207,41 @@ RETURN = '''
- Only networks that are in the distributed mode can have subnetworks.
returned: success
type: dict
- private_ip_google_access:
+ enableFlowLogs:
+ description:
+ - Whether to enable flow logging for this subnetwork.
+ returned: success
+ type: bool
+ fingerprint:
+ description:
+ - Fingerprint of this resource. This field is used internally during updates of this
+ resource.
+ returned: success
+ type: str
+ secondaryIpRanges:
+ description:
+ - An array of configurations for secondary IP ranges for VM instances contained in
+ this subnetwork. The primary IP of such VM must belong to the primary ipCidrRange
+ of the subnetwork. The alias IPs may belong to either primary or secondary ranges.
+ returned: success
+ type: complex
+ contains:
+ rangeName:
+ description:
+ - The name associated with this subnetwork secondary range, used when adding an alias
+ IP range to a VM instance. The name must be 1-63 characters long, and comply with
+ RFC1035. The name must be unique within the subnetwork.
+ returned: success
+ type: str
+ ipCidrRange:
+ description:
+ - The range of IP addresses belonging to this subnetwork secondary range. Provide
+ this property when you create the subnetwork.
+ - Ranges must be unique and non-overlapping with all primary and secondary IP ranges
+ within a network. Only IPv4 is supported.
+ returned: success
+ type: str
+ privateIpGoogleAccess:
description:
- Whether the VMs in this subnet can access Google services without assigned external
IP addresses.
@@ -192,7 +258,7 @@ RETURN = '''
# Imports
################################################################################
-from ansible.module_utils.gcp_utils import navigate_hash, GcpSession, GcpModule, GcpRequest, replace_resource_dict
+from ansible.module_utils.gcp_utils import navigate_hash, GcpSession, GcpModule, GcpRequest, remove_nones_from_dict, replace_resource_dict
import json
import time
@@ -211,6 +277,11 @@ def main():
ip_cidr_range=dict(required=True, type='str'),
name=dict(required=True, type='str'),
network=dict(required=True, type='dict'),
+ enable_flow_logs=dict(type='bool'),
+ secondary_ip_ranges=dict(type='list', elements='dict', options=dict(
+ range_name=dict(required=True, type='str'),
+ ip_cidr_range=dict(required=True, type='str')
+ )),
private_ip_google_access=dict(type='bool'),
region=dict(required=True, type='str')
)
@@ -228,7 +299,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
- fetch = update(module, self_link(module), kind)
+ update(module, self_link(module), kind, fetch)
+ fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@@ -251,9 +323,60 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module)))
-def update(module, link, kind):
+def update(module, link, kind, fetch):
+ update_fields(module, resource_to_request(module),
+ response_to_hash(module, fetch))
+ return fetch_resource(module, self_link(module), kind)
+
+
+def update_fields(module, request, response):
+ if response.get('ipCidrRange') != request.get('ipCidrRange'):
+ ip_cidr_range_update(module, request, response)
+ if response.get('enableFlowLogs') != request.get('enableFlowLogs') or response.get('secondaryIpRanges') != request.get('secondaryIpRanges'):
+ enable_flow_logs_update(module, request, response)
+ if response.get('privateIpGoogleAccess') != request.get('privateIpGoogleAccess'):
+ private_ip_google_access_update(module, request, response)
+
+
+def ip_cidr_range_update(module, request, response):
+ auth = GcpSession(module, 'compute')
+ auth.post(
+ ''.join([
+ "https://www.googleapis.com/compute/v1/",
+ "projects/{project}/regions/{region}/subnetworks/{name}/expandIpCidrRange"
+ ]).format(**module.params),
+ {
+ u'ipCidrRange': module.params.get('ip_cidr_range')
+ }
+ )
+
+
+def enable_flow_logs_update(module, request, response):
auth = GcpSession(module, 'compute')
- return wait_for_operation(module, auth.put(link, resource_to_request(module)))
+ auth.patch(
+ ''.join([
+ "https://www.googleapis.com/compute/v1/",
+ "projects/{project}/regions/{region}/subnetworks/{name}"
+ ]).format(**module.params),
+ {
+ u'enableFlowLogs': module.params.get('enable_flow_logs'),
+ u'fingerprint': response.get('fingerprint'),
+ u'secondaryIpRanges': SubnetworkSecondaryIpRangesArray(module.params.get('secondary_ip_ranges', []), module).to_request()
+ }
+ )
+
+
+def private_ip_google_access_update(module, request, response):
+ auth = GcpSession(module, 'compute')
+ auth.post(
+ ''.join([
+ "https://www.googleapis.com/compute/v1/",
+ "projects/{project}/regions/{region}/subnetworks/{name}/setPrivateIpGoogleAccess"
+ ]).format(**module.params),
+ {
+ u'privateIpGoogleAccess': module.params.get('private_ip_google_access')
+ }
+ )
def delete(module, link, kind):
@@ -268,6 +391,8 @@ def resource_to_request(module):
u'ipCidrRange': module.params.get('ip_cidr_range'),
u'name': module.params.get('name'),
u'network': replace_resource_dict(module.params.get(u'network', {}), 'selfLink'),
+ u'enableFlowLogs': module.params.get('enable_flow_logs'),
+ u'secondaryIpRanges': SubnetworkSecondaryIpRangesArray(module.params.get('secondary_ip_ranges', []), module).to_request(),
u'privateIpGoogleAccess': module.params.get('private_ip_google_access'),
u'region': module.params.get('region')
}
@@ -279,9 +404,9 @@ def resource_to_request(module):
return return_vals
-def fetch_resource(module, link, kind):
+def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
- return return_if_object(module, auth.get(link), kind)
+ return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@@ -292,9 +417,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/regions/{region}/subnetworks".format(**module.params)
-def return_if_object(module, response, kind):
+def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
- if response.status_code == 404:
+ if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@@ -309,8 +434,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
- if result['kind'] != kind:
- module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@@ -344,6 +467,9 @@ def response_to_hash(module, response):
u'ipCidrRange': response.get(u'ipCidrRange'),
u'name': response.get(u'name'),
u'network': replace_resource_dict(module.params.get(u'network', {}), 'selfLink'),
+ u'enableFlowLogs': response.get(u'enableFlowLogs'),
+ u'fingerprint': response.get(u'fingerprint'),
+ u'secondaryIpRanges': SubnetworkSecondaryIpRangesArray(response.get(u'secondaryIpRanges', []), module).from_response(),
u'privateIpGoogleAccess': response.get(u'privateIpGoogleAccess'),
u'region': module.params.get('region')
}
@@ -386,5 +512,38 @@ def raise_if_errors(response, err_path, module):
module.fail_json(msg=errors)
+class SubnetworkSecondaryIpRangesArray(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 remove_nones_from_dict({
+ u'rangeName': item.get('range_name'),
+ u'ipCidrRange': item.get('ip_cidr_range')
+ })
+
+ def _response_from_item(self, item):
+ return remove_nones_from_dict({
+ u'rangeName': item.get(u'rangeName'),
+ u'ipCidrRange': item.get(u'ipCidrRange')
+ })
+
+
if __name__ == '__main__':
main()