diff --git a/lib/ansible/modules/cloud/google/gcp_compute_disk.py b/lib/ansible/modules/cloud/google/gcp_compute_disk.py index 31fac0a5d9e481..be4f5bf18177e4 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_disk.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_disk.py @@ -193,6 +193,12 @@ ''' RETURN = ''' + label_fingerprint: + description: + - The fingerprint used for optimistic locking of this resource. Used internally during + updates. + returned: success + type: str creation_timestamp: description: - Creation timestamp in RFC3339 text format. @@ -427,7 +433,7 @@ def main(): if fetch: if state == 'present': if is_different(module, fetch): - fetch = update(module, self_link(module), kind) + fetch = update(module, self_link(module), kind, fetch) changed = True else: delete(module, self_link(module), kind) @@ -450,8 +456,44 @@ def create(module, link, kind): return wait_for_operation(module, auth.post(link, resource_to_request(module))) -def update(module, link, kind): - module.fail_json(msg="Disk cannot be edited") +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('labels') != request.get('labels'): + label_fingerprint_update(module, request, response) + if response.get('sizeGb') != request.get('sizeGb'): + size_gb_update(module, request, response) + + +def label_fingerprint_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/zones/{zone}/disks/{name}/setLabels" + ]).format(**module.params), + { + u'labelFingerprint': response.get('labelFingerprint'), + u'labels': module.params.get('labels') + } + ) + + +def size_gb_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/zones/{zone}/disks/{name}/resize" + ]).format(**module.params), + { + u'sizeGb': module.params.get('size_gb') + } + ) def delete(module, link, kind): @@ -539,6 +581,7 @@ def is_different(module, response): # This is for doing comparisons with Ansible's current parameters. def response_to_hash(module, response): return { + u'labelFingerprint': response.get(u'labelFingerprint'), u'creationTimestamp': response.get(u'creationTimestamp'), u'description': response.get(u'description'), u'id': response.get(u'id'), diff --git a/lib/ansible/modules/cloud/google/gcp_compute_disk_facts.py b/lib/ansible/modules/cloud/google/gcp_compute_disk_facts.py index 13f01c8d88f375..4366852ae112c7 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_disk_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_disk_facts.py @@ -71,6 +71,12 @@ returned: always type: complex contains: + label_fingerprint: + description: + - The fingerprint used for optimistic locking of this resource. Used internally during + updates. + returned: success + type: str creation_timestamp: description: - Creation timestamp in RFC3339 text format. diff --git a/lib/ansible/modules/cloud/google/gcp_compute_forwarding_rule.py b/lib/ansible/modules/cloud/google/gcp_compute_forwarding_rule.py index 7b33e640c6fd02..a499ec5ff5c87c 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_forwarding_rule.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_forwarding_rule.py @@ -331,6 +331,12 @@ - This field is not used for internal load balancing. returned: success type: dict + label_fingerprint: + description: + - The fingerprint used for optimistic locking of this resource. Used internally during + updates. + returned: success + type: str region: description: - A reference to the region where the regional forwarding rule resides. @@ -386,7 +392,7 @@ def main(): if fetch: if state == 'present': if is_different(module, fetch): - fetch = update(module, self_link(module), kind) + fetch = update(module, self_link(module), kind, fetch) changed = True else: delete(module, self_link(module), kind) @@ -409,8 +415,41 @@ def create(module, link, kind): return wait_for_operation(module, auth.post(link, resource_to_request(module))) -def update(module, link, kind): - module.fail_json(msg="ForwardingRule cannot be edited") +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('target') != request.get('target'): + target_update(module, request, response) + + +def target_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/regions/{region}/forwardingRules/{name}/setTarget" + ]).format(**module.params), + { + u'target': replace_resource_dict(module.params.get(u'target', {}), 'selfLink') + } + ) + + +def label_fingerprint_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/regions/{region}/forwardingRules/{name}/setLabels" + ]).format(**module.params), + { + u'labelFingerprint': response.get('labelFingerprint') + } + ) def delete(module, link, kind): @@ -513,7 +552,8 @@ def response_to_hash(module, response): u'portRange': response.get(u'portRange'), u'ports': response.get(u'ports'), u'subnetwork': response.get(u'subnetwork'), - u'target': response.get(u'target') + u'target': response.get(u'target'), + u'labelFingerprint': response.get(u'labelFingerprint') } diff --git a/lib/ansible/modules/cloud/google/gcp_compute_forwarding_rule_facts.py b/lib/ansible/modules/cloud/google/gcp_compute_forwarding_rule_facts.py index 2be21b9ec54fc4..38936246c196f0 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_forwarding_rule_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_forwarding_rule_facts.py @@ -199,6 +199,12 @@ - This field is not used for internal load balancing. returned: success type: dict + label_fingerprint: + description: + - The fingerprint used for optimistic locking of this resource. Used internally during + updates. + returned: success + type: str region: description: - A reference to the region where the regional forwarding rule resides. diff --git a/lib/ansible/modules/cloud/google/gcp_compute_global_address.py b/lib/ansible/modules/cloud/google/gcp_compute_global_address.py index d313db81b4f5c1..3981dd058c8d1e 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_global_address.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_global_address.py @@ -115,6 +115,12 @@ be a dash. returned: success type: str + label_fingerprint: + description: + - The fingerprint used for optimistic locking of this resource. Used internally during + updates. + returned: success + type: str ip_version: description: - The IP Version that will be used by this address. Valid options are IPV4 or IPV6. @@ -166,7 +172,7 @@ def main(): if fetch: if state == 'present': if is_different(module, fetch): - fetch = update(module, self_link(module), kind) + fetch = update(module, self_link(module), kind, fetch) changed = True else: delete(module, self_link(module), kind) @@ -189,8 +195,27 @@ def create(module, link, kind): return wait_for_operation(module, auth.post(link, resource_to_request(module))) -def update(module, link, kind): - module.fail_json(msg="GlobalAddress cannot be edited") +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): + pass + + +def label_fingerprint_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/global/addresses/{name}/setLabels" + ]).format(**module.params), + { + u'labelFingerprint': response.get('labelFingerprint') + } + ) def delete(module, link, kind): @@ -276,6 +301,7 @@ def response_to_hash(module, response): u'description': response.get(u'description'), u'id': response.get(u'id'), u'name': response.get(u'name'), + u'labelFingerprint': response.get(u'labelFingerprint'), u'ipVersion': response.get(u'ipVersion'), u'region': response.get(u'region') } diff --git a/lib/ansible/modules/cloud/google/gcp_compute_global_address_facts.py b/lib/ansible/modules/cloud/google/gcp_compute_global_address_facts.py index 69cdab4f81387c..d141ffc3f78745 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_global_address_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_global_address_facts.py @@ -97,6 +97,12 @@ be a dash. returned: success type: str + label_fingerprint: + description: + - The fingerprint used for optimistic locking of this resource. Used internally during + updates. + returned: success + type: str ip_version: description: - The IP Version that will be used by this address. Valid options are IPV4 or IPV6. diff --git a/lib/ansible/modules/cloud/google/gcp_compute_subnetwork.py b/lib/ansible/modules/cloud/google/gcp_compute_subnetwork.py index 183ea3761fab53..326f9a769151e0 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_subnetwork.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_subnetwork.py @@ -228,7 +228,7 @@ def main(): if fetch: if state == 'present': if is_different(module, fetch): - fetch = update(module, self_link(module), kind) + fetch = update(module, self_link(module), kind, fetch) changed = True else: delete(module, self_link(module), kind) @@ -251,8 +251,43 @@ def create(module, link, kind): return wait_for_operation(module, auth.post(link, resource_to_request(module))) -def update(module, link, kind): - module.fail_json(msg="Subnetwork cannot be edited") +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('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 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): diff --git a/lib/ansible/modules/cloud/google/gcp_compute_target_http_proxy.py b/lib/ansible/modules/cloud/google/gcp_compute_target_http_proxy.py index 99d963e25c4c10..0097aad02bf710 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_target_http_proxy.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_target_http_proxy.py @@ -198,7 +198,7 @@ def main(): if fetch: if state == 'present': if is_different(module, fetch): - fetch = update(module, self_link(module), kind) + fetch = update(module, self_link(module), kind, fetch) changed = True else: delete(module, self_link(module), kind) @@ -221,8 +221,28 @@ def create(module, link, kind): return wait_for_operation(module, auth.post(link, resource_to_request(module))) -def update(module, link, kind): - module.fail_json(msg="TargetHttpProxy cannot be edited") +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('urlMap') != request.get('urlMap'): + url_map_update(module, request, response) + + +def url_map_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/targetHttpProxies/{name}/setUrlMap" + ]).format(**module.params), + { + u'urlMap': replace_resource_dict(module.params.get(u'url_map', {}), 'selfLink') + } + ) def delete(module, link, kind): diff --git a/lib/ansible/modules/cloud/google/gcp_compute_target_https_proxy.py b/lib/ansible/modules/cloud/google/gcp_compute_target_https_proxy.py index cef23873e65e7e..08a175c8215d48 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_target_https_proxy.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_target_https_proxy.py @@ -266,7 +266,7 @@ def main(): if fetch: if state == 'present': if is_different(module, fetch): - fetch = update(module, self_link(module), kind) + fetch = update(module, self_link(module), kind, fetch) changed = True else: delete(module, self_link(module), kind) @@ -289,8 +289,58 @@ def create(module, link, kind): return wait_for_operation(module, auth.post(link, resource_to_request(module))) -def update(module, link, kind): - module.fail_json(msg="TargetHttpsProxy cannot be edited") +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('quicOverride') != request.get('quicOverride'): + quic_override_update(module, request, response) + if response.get('sslCertificates') != request.get('sslCertificates'): + ssl_certificates_update(module, request, response) + if response.get('urlMap') != request.get('urlMap'): + url_map_update(module, request, response) + + +def quic_override_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/global/targetHttpsProxies/{name}/setQuicOverride" + ]).format(**module.params), + { + u'quicOverride': module.params.get('quic_override') + } + ) + + +def ssl_certificates_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/targetHttpsProxies/{name}/setSslCertificates" + ]).format(**module.params), + { + u'sslCertificates': replace_resource_dict(module.params.get('ssl_certificates', []), 'selfLink') + } + ) + + +def url_map_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/targetHttpsProxies/{name}/setUrlMap" + ]).format(**module.params), + { + u'urlMap': replace_resource_dict(module.params.get(u'url_map', {}), 'selfLink') + } + ) def delete(module, link, kind): diff --git a/lib/ansible/modules/cloud/google/gcp_compute_target_ssl_proxy.py b/lib/ansible/modules/cloud/google/gcp_compute_target_ssl_proxy.py index ac115a4e525227..af131c27e1b49a 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_target_ssl_proxy.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_target_ssl_proxy.py @@ -253,7 +253,7 @@ def main(): if fetch: if state == 'present': if is_different(module, fetch): - fetch = update(module, self_link(module), kind) + fetch = update(module, self_link(module), kind, fetch) changed = True else: delete(module, self_link(module), kind) @@ -276,8 +276,58 @@ def create(module, link, kind): return wait_for_operation(module, auth.post(link, resource_to_request(module))) -def update(module, link, kind): - module.fail_json(msg="TargetSslProxy cannot be edited") +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('proxyHeader') != request.get('proxyHeader'): + proxy_header_update(module, request, response) + if response.get('service') != request.get('service'): + service_update(module, request, response) + if response.get('sslCertificates') != request.get('sslCertificates'): + ssl_certificates_update(module, request, response) + + +def proxy_header_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/global/targetSslProxies/{name}/setProxyHeader" + ]).format(**module.params), + { + u'proxyHeader': module.params.get('proxy_header') + } + ) + + +def service_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/global/targetSslProxies/{name}/setBackendService" + ]).format(**module.params), + { + u'service': replace_resource_dict(module.params.get(u'service', {}), 'selfLink') + } + ) + + +def ssl_certificates_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/global/targetSslProxies/{name}/setSslCertificates" + ]).format(**module.params), + { + u'sslCertificates': replace_resource_dict(module.params.get('ssl_certificates', []), 'selfLink') + } + ) def delete(module, link, kind): diff --git a/lib/ansible/modules/cloud/google/gcp_compute_target_tcp_proxy.py b/lib/ansible/modules/cloud/google/gcp_compute_target_tcp_proxy.py index 1c5459e2c57ce1..56887a40e2cdca 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_target_tcp_proxy.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_target_tcp_proxy.py @@ -206,7 +206,7 @@ def main(): if fetch: if state == 'present': if is_different(module, fetch): - fetch = update(module, self_link(module), kind) + fetch = update(module, self_link(module), kind, fetch) changed = True else: delete(module, self_link(module), kind) @@ -229,8 +229,43 @@ def create(module, link, kind): return wait_for_operation(module, auth.post(link, resource_to_request(module))) -def update(module, link, kind): - module.fail_json(msg="TargetTcpProxy cannot be edited") +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('proxyHeader') != request.get('proxyHeader'): + proxy_header_update(module, request, response) + if response.get('service') != request.get('service'): + service_update(module, request, response) + + +def proxy_header_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/global/targetTcpProxies/{name}/setProxyHeader" + ]).format(**module.params), + { + u'proxyHeader': module.params.get('proxy_header') + } + ) + + +def service_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/global/targetTcpProxies/{name}/setBackendService" + ]).format(**module.params), + { + u'service': replace_resource_dict(module.params.get(u'service', {}), 'selfLink') + } + ) def delete(module, link, kind): diff --git a/lib/ansible/modules/cloud/google/gcp_compute_vpn_tunnel.py b/lib/ansible/modules/cloud/google/gcp_compute_vpn_tunnel.py index 06502428239bad..91fddc74e5ba00 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_vpn_tunnel.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_vpn_tunnel.py @@ -236,6 +236,12 @@ - Labels to apply to this VpnTunnel. returned: success type: dict + label_fingerprint: + description: + - The fingerprint used for optimistic locking of this resource. Used internally during + updates. + returned: success + type: str region: description: - The region where the tunnel is located. @@ -288,7 +294,7 @@ def main(): if fetch: if state == 'present': if is_different(module, fetch): - fetch = update(module, self_link(module), kind) + fetch = update(module, self_link(module), kind, fetch) changed = True else: delete(module, self_link(module), kind) @@ -297,6 +303,7 @@ def main(): else: if state == 'present': fetch = create(module, collection(module), kind) + labels_update(module, module.params, fetch) changed = True else: fetch = {} @@ -311,8 +318,29 @@ def create(module, link, kind): return wait_for_operation(module, auth.post(link, resource_to_request(module))) -def update(module, link, kind): - module.fail_json(msg="VpnTunnel cannot be edited") +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('labels') != request.get('labels'): + labels_update(module, request, response) + + +def labels_update(module, request, response): + auth = GcpSession(module, 'compute') + auth.post( + ''.join([ + "https://www.googleapis.com/compute/v1/", + "projects/{project}/regions/{region}/vpnTunnels/{name}/setLabels" + ]).format(**module.params), + { + u'labels': module.params.get('labels'), + u'labelFingerprint': response.get('labelFingerprint') + } + ) def delete(module, link, kind): @@ -411,7 +439,8 @@ def response_to_hash(module, response): u'ikeVersion': response.get(u'ikeVersion'), u'localTrafficSelector': response.get(u'localTrafficSelector'), u'remoteTrafficSelector': response.get(u'remoteTrafficSelector'), - u'labels': response.get(u'labels') + u'labels': response.get(u'labels'), + u'labelFingerprint': response.get(u'labelFingerprint') } diff --git a/lib/ansible/modules/cloud/google/gcp_compute_vpn_tunnel_facts.py b/lib/ansible/modules/cloud/google/gcp_compute_vpn_tunnel_facts.py index 24a0142a24efe7..275b6665c3777c 100644 --- a/lib/ansible/modules/cloud/google/gcp_compute_vpn_tunnel_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_compute_vpn_tunnel_facts.py @@ -143,6 +143,12 @@ - Labels to apply to this VpnTunnel. returned: success type: dict + label_fingerprint: + description: + - The fingerprint used for optimistic locking of this resource. Used internally during + updates. + returned: success + type: str region: description: - The region where the tunnel is located.