From a837cc569498d94d1dcf70d99748357922bd74d5 Mon Sep 17 00:00:00 2001 From: The Magician Date: Tue, 28 May 2019 10:43:19 -0700 Subject: [PATCH] Bug fixes for GCP modules (#55976) --- .../google/gcp_compute_vpn_tunnel_facts.py | 8 +- .../cloud/google/gcp_container_cluster.py | 12 +- .../google/gcp_container_cluster_facts.py | 6 +- .../google/gcp_container_node_pool_facts.py | 6 +- .../cloud/google/gcp_dns_managed_zone.py | 188 +++++++++++++++++- .../google/gcp_dns_managed_zone_facts.py | 60 +++++- .../google/gcp_dns_resource_record_set.py | 22 +- .../gcp_dns_resource_record_set_facts.py | 8 +- .../modules/cloud/google/gcp_iam_role.py | 11 +- .../cloud/google/gcp_iam_role_facts.py | 6 +- .../google/gcp_iam_service_account_facts.py | 6 +- .../google/gcp_iam_service_account_key.py | 14 +- .../cloud/google/gcp_pubsub_subscription.py | 65 +++++- .../google/gcp_pubsub_subscription_facts.py | 31 ++- .../cloud/google/gcp_pubsub_topic_facts.py | 6 +- .../cloud/google/gcp_redis_instance.py | 16 +- .../cloud/google/gcp_redis_instance_facts.py | 8 +- .../gcp_resourcemanager_project_facts.py | 6 +- .../gcp_dns_managed_zone/tasks/main.yml | 4 +- .../targets/gcp_iam_role/tasks/main.yml | 4 +- .../gcp_iam_service_account/tasks/main.yml | 4 +- .../targets/gcp_redis_instance/tasks/main.yml | 4 +- .../tasks/main.yml | 4 +- .../gcp_sourcerepo_repository/tasks/main.yml | 4 +- 24 files changed, 398 insertions(+), 105 deletions(-) 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 e67c1b4e040..62cfe4a357f 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 @@ -42,7 +42,7 @@ requirements: options: filters: description: - - A list of filter value pairs. Available filters are listed here U(https://cloud.google.com/sdk/gcloud/reference/topic/filters.) + - A list of filter value pairs. Available filters are listed here U(https://cloud.google.com/sdk/gcloud/reference/topic/filters). - Each additional filter in the list will act be added as an AND condition (filter1 and filter2) . region: @@ -65,8 +65,8 @@ EXAMPLES = ''' ''' RETURN = ''' -items: - description: List of items +resources: + description: List of resources returned: always type: complex contains: @@ -167,7 +167,7 @@ def main(): items = items.get('items') else: items = [] - return_value = {'items': items} + return_value = {'resources': items} module.exit_json(**return_value) diff --git a/lib/ansible/modules/cloud/google/gcp_container_cluster.py b/lib/ansible/modules/cloud/google/gcp_container_cluster.py index aca85eb58b9..b8110cbe2a5 100644 --- a/lib/ansible/modules/cloud/google/gcp_container_cluster.py +++ b/lib/ansible/modules/cloud/google/gcp_container_cluster.py @@ -176,10 +176,8 @@ options: options: logging.googleapis.com - the Google Cloud Logging service.' - none - no logs will be exported from the cluster. - if left as an empty string,logging.googleapis.com will be used. + - 'Some valid choices include: "logging.googleapis.com", "none"' required: false - choices: - - logging.googleapis.com - - none monitoring_service: description: - The monitoring service the cluster should use to write metrics. @@ -187,10 +185,8 @@ options: service.' - none - no metrics will be exported from the cluster. - if left as an empty string, monitoring.googleapis.com will be used. + - 'Some valid choices include: "monitoring.googleapis.com", "none"' required: false - choices: - - monitoring.googleapis.com - - none network: description: - The name of the Google Compute Engine network to which the cluster is connected. @@ -651,8 +647,8 @@ def main(): ), ), master_auth=dict(type='dict', options=dict(username=dict(type='str'), password=dict(type='str'))), - logging_service=dict(type='str', choices=['logging.googleapis.com', 'none']), - monitoring_service=dict(type='str', choices=['monitoring.googleapis.com', 'none']), + logging_service=dict(type='str'), + monitoring_service=dict(type='str'), network=dict(type='str'), private_cluster_config=dict( type='dict', diff --git a/lib/ansible/modules/cloud/google/gcp_container_cluster_facts.py b/lib/ansible/modules/cloud/google/gcp_container_cluster_facts.py index a19f87428cc..d3db9b8e96b 100644 --- a/lib/ansible/modules/cloud/google/gcp_container_cluster_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_container_cluster_facts.py @@ -62,8 +62,8 @@ EXAMPLES = ''' ''' RETURN = ''' -items: - description: List of items +resources: + description: List of resources returned: always type: complex contains: @@ -411,7 +411,7 @@ def main(): items = items.get('clusters') else: items = [] - return_value = {'items': items} + return_value = {'resources': items} module.exit_json(**return_value) diff --git a/lib/ansible/modules/cloud/google/gcp_container_node_pool_facts.py b/lib/ansible/modules/cloud/google/gcp_container_node_pool_facts.py index aae03244997..f526c05818c 100644 --- a/lib/ansible/modules/cloud/google/gcp_container_node_pool_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_container_node_pool_facts.py @@ -72,8 +72,8 @@ EXAMPLES = ''' ''' RETURN = ''' -items: - description: List of items +resources: + description: List of resources returned: always type: complex contains: @@ -283,7 +283,7 @@ def main(): items = items.get('nodePools') else: items = [] - return_value = {'items': items} + return_value = {'resources': items} module.exit_json(**return_value) diff --git a/lib/ansible/modules/cloud/google/gcp_dns_managed_zone.py b/lib/ansible/modules/cloud/google/gcp_dns_managed_zone.py index 5a548124af4..e75e79df1fe 100644 --- a/lib/ansible/modules/cloud/google/gcp_dns_managed_zone.py +++ b/lib/ansible/modules/cloud/google/gcp_dns_managed_zone.py @@ -57,6 +57,58 @@ options: description: - The DNS name of this managed zone, for instance "example.com.". required: true + dnssec_config: + description: + - DNSSEC configuration. + required: false + version_added: 2.9 + suboptions: + kind: + description: + - Identifies what kind of resource this is. + required: false + default: dns#managedZoneDnsSecConfig + non_existence: + description: + - Specifies the mechanism used to provide authenticated denial-of-existence + responses. Output only while state is not OFF. . + - 'Some valid choices include: "nsec", "nsec3"' + required: false + state: + description: + - Specifies whether DNSSEC is enabled, and what mode it is in. + - 'Some valid choices include: "off", "on", "transfer"' + required: false + default_key_specs: + description: + - Specifies parameters that will be used for generating initial DnsKeys for + this ManagedZone. Output only while state is not OFF . + required: false + suboptions: + algorithm: + description: + - String mnemonic specifying the DNSSEC algorithm of this key. + - 'Some valid choices include: "ecdsap256sha256", "ecdsap384sha384", "rsasha1", + "rsasha256", "rsasha512"' + required: false + key_length: + description: + - Length of the keys in bits. + required: false + key_type: + description: + - Specifies whether this is a key signing key (KSK) or a zone signing + key (ZSK). Key signing keys have the Secure Entry Point flag set and, + when active, will only be used to sign resource record sets of type + DNSKEY. Zone signing keys do not have the Secure Entry Point flag set + and will be used to sign all other types of resource record sets. . + - 'Some valid choices include: "keySigning", "zoneSigning"' + required: false + kind: + description: + - Identifies what kind of resource this is. + required: false + default: dns#dnsKeySpec name: description: - User assigned name for this resource. @@ -78,12 +130,10 @@ options: - 'The zone''s visibility: public zones are exposed to the Internet, while private zones are visible only to Virtual Private Cloud resources.' - 'Must be one of: `public`, `private`.' + - 'Some valid choices include: "private", "public"' required: false default: public version_added: 2.8 - choices: - - private - - public private_visibility_config: description: - For privately visible zones, the set of Virtual Private Cloud resources that @@ -132,6 +182,59 @@ dnsName: - The DNS name of this managed zone, for instance "example.com.". returned: success type: str +dnssecConfig: + description: + - DNSSEC configuration. + returned: success + type: complex + contains: + kind: + description: + - Identifies what kind of resource this is. + returned: success + type: str + nonExistence: + description: + - Specifies the mechanism used to provide authenticated denial-of-existence + responses. Output only while state is not OFF. . + returned: success + type: str + state: + description: + - Specifies whether DNSSEC is enabled, and what mode it is in. + returned: success + type: str + defaultKeySpecs: + description: + - Specifies parameters that will be used for generating initial DnsKeys for + this ManagedZone. Output only while state is not OFF . + returned: success + type: complex + contains: + algorithm: + description: + - String mnemonic specifying the DNSSEC algorithm of this key. + returned: success + type: str + keyLength: + description: + - Length of the keys in bits. + returned: success + type: int + keyType: + description: + - Specifies whether this is a key signing key (KSK) or a zone signing key + (ZSK). Key signing keys have the Secure Entry Point flag set and, when + active, will only be used to sign resource record sets of type DNSKEY. + Zone signing keys do not have the Secure Entry Point flag set and will + be used to sign all other types of resource record sets. . + returned: success + type: str + kind: + description: + - Identifies what kind of resource this is. + returned: success + type: str id: description: - Unique identifier for the resource; defined by the server. @@ -216,10 +319,25 @@ def main(): state=dict(default='present', choices=['present', 'absent'], type='str'), description=dict(required=True, type='str'), dns_name=dict(required=True, type='str'), + dnssec_config=dict( + type='dict', + options=dict( + kind=dict(default='dns#managedZoneDnsSecConfig', type='str'), + non_existence=dict(type='str'), + state=dict(type='str'), + default_key_specs=dict( + type='list', + elements='dict', + options=dict( + algorithm=dict(type='str'), key_length=dict(type='int'), key_type=dict(type='str'), kind=dict(default='dns#dnsKeySpec', type='str') + ), + ), + ), + ), name=dict(required=True, type='str'), name_server_set=dict(type='str'), labels=dict(type='dict'), - visibility=dict(default='public', type='str', choices=['private', 'public']), + visibility=dict(default='public', type='str'), private_visibility_config=dict(type='dict', options=dict(networks=dict(type='list', elements='dict', options=dict(network_url=dict(type='str'))))), ) ) @@ -296,6 +414,7 @@ def resource_to_request(module): u'kind': 'dns#managedZone', u'description': module.params.get('description'), u'dnsName': module.params.get('dns_name'), + u'dnssecConfig': ManagedZoneDnssecconfig(module.params.get('dnssec_config', {}), module).to_request(), u'name': module.params.get('name'), u'nameServerSet': module.params.get('name_server_set'), u'labels': module.params.get('labels'), @@ -368,6 +487,7 @@ def response_to_hash(module, response): return { u'description': response.get(u'description'), u'dnsName': response.get(u'dnsName'), + u'dnssecConfig': ManagedZoneDnssecconfig(response.get(u'dnssecConfig', {}), module).from_response(), u'id': response.get(u'id'), u'name': response.get(u'name'), u'nameServers': response.get(u'nameServers'), @@ -379,6 +499,66 @@ def response_to_hash(module, response): } +class ManagedZoneDnssecconfig(object): + def __init__(self, request, module): + self.module = module + if request: + self.request = request + else: + self.request = {} + + def to_request(self): + return remove_nones_from_dict( + { + u'kind': self.request.get('kind'), + u'nonExistence': self.request.get('non_existence'), + u'state': self.request.get('state'), + u'defaultKeySpecs': ManagedZoneDefaultkeyspecsArray(self.request.get('default_key_specs', []), self.module).to_request(), + } + ) + + def from_response(self): + return remove_nones_from_dict( + { + u'kind': self.request.get(u'kind'), + u'nonExistence': self.request.get(u'nonExistence'), + u'state': self.request.get(u'state'), + u'defaultKeySpecs': ManagedZoneDefaultkeyspecsArray(self.request.get(u'defaultKeySpecs', []), self.module).from_response(), + } + ) + + +class ManagedZoneDefaultkeyspecsArray(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'algorithm': item.get('algorithm'), u'keyLength': item.get('key_length'), u'keyType': item.get('key_type'), u'kind': item.get('kind')} + ) + + def _response_from_item(self, item): + return remove_nones_from_dict( + {u'algorithm': item.get(u'algorithm'), u'keyLength': item.get(u'keyLength'), u'keyType': item.get(u'keyType'), u'kind': item.get(u'kind')} + ) + + class ManagedZonePrivatevisibilityconfig(object): def __init__(self, request, module): self.module = module diff --git a/lib/ansible/modules/cloud/google/gcp_dns_managed_zone_facts.py b/lib/ansible/modules/cloud/google/gcp_dns_managed_zone_facts.py index 6e729dac736..1952058c0ee 100644 --- a/lib/ansible/modules/cloud/google/gcp_dns_managed_zone_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_dns_managed_zone_facts.py @@ -57,8 +57,8 @@ EXAMPLES = ''' ''' RETURN = ''' -items: - description: List of items +resources: + description: List of resources returned: always type: complex contains: @@ -73,6 +73,60 @@ items: - The DNS name of this managed zone, for instance "example.com.". returned: success type: str + dnssecConfig: + description: + - DNSSEC configuration. + returned: success + type: complex + contains: + kind: + description: + - Identifies what kind of resource this is. + returned: success + type: str + nonExistence: + description: + - Specifies the mechanism used to provide authenticated denial-of-existence + responses. Output only while state is not OFF. . + returned: success + type: str + state: + description: + - Specifies whether DNSSEC is enabled, and what mode it is in. + returned: success + type: str + defaultKeySpecs: + description: + - Specifies parameters that will be used for generating initial DnsKeys + for this ManagedZone. Output only while state is not OFF . + returned: success + type: complex + contains: + algorithm: + description: + - String mnemonic specifying the DNSSEC algorithm of this key. + returned: success + type: str + keyLength: + description: + - Length of the keys in bits. + returned: success + type: int + keyType: + description: + - Specifies whether this is a key signing key (KSK) or a zone signing + key (ZSK). Key signing keys have the Secure Entry Point flag set and, + when active, will only be used to sign resource record sets of type + DNSKEY. Zone signing keys do not have the Secure Entry Point flag + set and will be used to sign all other types of resource record sets. + . + returned: success + type: str + kind: + description: + - Identifies what kind of resource this is. + returned: success + type: str id: description: - Unique identifier for the resource; defined by the server. @@ -159,7 +213,7 @@ def main(): items = items.get('managedZones') else: items = [] - return_value = {'items': items} + return_value = {'resources': items} module.exit_json(**return_value) diff --git a/lib/ansible/modules/cloud/google/gcp_dns_resource_record_set.py b/lib/ansible/modules/cloud/google/gcp_dns_resource_record_set.py index 6acd1957a71..e23f4273ed1 100644 --- a/lib/ansible/modules/cloud/google/gcp_dns_resource_record_set.py +++ b/lib/ansible/modules/cloud/google/gcp_dns_resource_record_set.py @@ -53,26 +53,14 @@ options: default: present name: description: - - For example, U(www.example.com.) + - For example, U(www.example.com). required: true type: description: - One of valid DNS resource types. + - 'Some valid choices include: "A", "AAAA", "CAA", "CNAME", "MX", "NAPTR", "NS", + "PTR", "SOA", "SPF", "SRV", "TLSA", "TXT"' required: true - choices: - - A - - AAAA - - CAA - - CNAME - - MX - - NAPTR - - NS - - PTR - - SOA - - SPF - - SRV - - TLSA - - TXT ttl: description: - Number of seconds that this ResourceRecordSet can be cached by resolvers. @@ -123,7 +111,7 @@ EXAMPLES = ''' RETURN = ''' name: description: - - For example, U(www.example.com.) + - For example, U(www.example.com). returned: success type: str type: @@ -170,7 +158,7 @@ def main(): argument_spec=dict( state=dict(default='present', choices=['present', 'absent'], type='str'), name=dict(required=True, type='str'), - type=dict(required=True, type='str', choices=['A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SOA', 'SPF', 'SRV', 'TLSA', 'TXT']), + type=dict(required=True, type='str'), ttl=dict(type='int'), target=dict(type='list', elements='str'), managed_zone=dict(required=True, type='dict'), diff --git a/lib/ansible/modules/cloud/google/gcp_dns_resource_record_set_facts.py b/lib/ansible/modules/cloud/google/gcp_dns_resource_record_set_facts.py index 1e3e6917703..9c9ccb31feb 100644 --- a/lib/ansible/modules/cloud/google/gcp_dns_resource_record_set_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_dns_resource_record_set_facts.py @@ -63,14 +63,14 @@ EXAMPLES = ''' ''' RETURN = ''' -items: - description: List of items +resources: + description: List of resources returned: always type: complex contains: name: description: - - For example, U(www.example.com.) + - For example, U(www.example.com). returned: success type: str type: @@ -117,7 +117,7 @@ def main(): items = items.get('rrsets') else: items = [] - return_value = {'items': items} + return_value = {'resources': items} module.exit_json(**return_value) diff --git a/lib/ansible/modules/cloud/google/gcp_iam_role.py b/lib/ansible/modules/cloud/google/gcp_iam_role.py index a9e8a859eae..6a039654f7c 100644 --- a/lib/ansible/modules/cloud/google/gcp_iam_role.py +++ b/lib/ansible/modules/cloud/google/gcp_iam_role.py @@ -67,14 +67,9 @@ options: stage: description: - The current launch stage of the role. + - 'Some valid choices include: "ALPHA", "BETA", "GA", "DEPRECATED", "DISABLED", + "EAP"' required: false - choices: - - ALPHA - - BETA - - GA - - DEPRECATED - - DISABLED - - EAP extends_documentation_fragment: gcp ''' @@ -149,7 +144,7 @@ def main(): title=dict(type='str'), description=dict(type='str'), included_permissions=dict(type='list', elements='str'), - stage=dict(type='str', choices=['ALPHA', 'BETA', 'GA', 'DEPRECATED', 'DISABLED', 'EAP']), + stage=dict(type='str'), ) ) diff --git a/lib/ansible/modules/cloud/google/gcp_iam_role_facts.py b/lib/ansible/modules/cloud/google/gcp_iam_role_facts.py index 9e24ebd65d8..4f675013995 100644 --- a/lib/ansible/modules/cloud/google/gcp_iam_role_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_iam_role_facts.py @@ -53,8 +53,8 @@ EXAMPLES = ''' ''' RETURN = ''' -items: - description: List of items +resources: + description: List of resources returned: always type: complex contains: @@ -113,7 +113,7 @@ def main(): items = items.get('roles') else: items = [] - return_value = {'items': items} + return_value = {'resources': items} module.exit_json(**return_value) diff --git a/lib/ansible/modules/cloud/google/gcp_iam_service_account_facts.py b/lib/ansible/modules/cloud/google/gcp_iam_service_account_facts.py index 151423a24d6..0f4c760bc61 100644 --- a/lib/ansible/modules/cloud/google/gcp_iam_service_account_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_iam_service_account_facts.py @@ -53,8 +53,8 @@ EXAMPLES = ''' ''' RETURN = ''' -items: - description: List of items +resources: + description: List of resources returned: always type: complex contains: @@ -112,7 +112,7 @@ def main(): items = items.get('items') else: items = [] - return_value = {'items': items} + return_value = {'resources': items} module.exit_json(**return_value) diff --git a/lib/ansible/modules/cloud/google/gcp_iam_service_account_key.py b/lib/ansible/modules/cloud/google/gcp_iam_service_account_key.py index a994c23ac2d..b923274ff42 100644 --- a/lib/ansible/modules/cloud/google/gcp_iam_service_account_key.py +++ b/lib/ansible/modules/cloud/google/gcp_iam_service_account_key.py @@ -50,19 +50,13 @@ options: private_key_type: description: - Output format for the service account key. + - 'Some valid choices include: "TYPE_UNSPECIFIED", "TYPE_PKCS12_FILE", "TYPE_GOOGLE_CREDENTIALS_FILE"' required: false - choices: - - TYPE_UNSPECIFIED - - TYPE_PKCS12_FILE - - TYPE_GOOGLE_CREDENTIALS_FILE key_algorithm: description: - Specifies the algorithm for the key. + - 'Some valid choices include: "KEY_ALG_UNSPECIFIED", "KEY_ALG_RSA_1024", "KEY_ALG_RSA_2048"' required: false - choices: - - KEY_ALG_UNSPECIFIED - - KEY_ALG_RSA_1024 - - KEY_ALG_RSA_2048 service_account: description: - The name of the serviceAccount. @@ -175,8 +169,8 @@ def main(): module = GcpModule( argument_spec=dict( state=dict(default='present', choices=['present', 'absent'], type='str'), - private_key_type=dict(type='str', choices=['TYPE_UNSPECIFIED', 'TYPE_PKCS12_FILE', 'TYPE_GOOGLE_CREDENTIALS_FILE']), - key_algorithm=dict(type='str', choices=['KEY_ALG_UNSPECIFIED', 'KEY_ALG_RSA_1024', 'KEY_ALG_RSA_2048']), + private_key_type=dict(type='str'), + key_algorithm=dict(type='str'), service_account=dict(type='dict'), path=dict(type='path'), ) diff --git a/lib/ansible/modules/cloud/google/gcp_pubsub_subscription.py b/lib/ansible/modules/cloud/google/gcp_pubsub_subscription.py index 503edbd7099..31d7df549d5 100644 --- a/lib/ansible/modules/cloud/google/gcp_pubsub_subscription.py +++ b/lib/ansible/modules/cloud/google/gcp_pubsub_subscription.py @@ -76,7 +76,7 @@ options: push_endpoint: description: - A URL locating the endpoint to which messages should be pushed. - - For example, a Webhook endpoint might use "U(https://example.com/push".) + - For example, a Webhook endpoint might use "U(https://example.com/push"). required: true attributes: description: @@ -134,6 +134,26 @@ options: required: false type: bool version_added: 2.8 + expiration_policy: + description: + - A policy that specifies the conditions for this subscription's expiration. + - A subscription is considered active as long as any connected subscriber is successfully + consuming messages from the subscription or is issuing operations on the subscription. + If expirationPolicy is not set, a default policy with ttl of 31 days will be + used. The minimum allowed value for expirationPolicy.ttl is 1 day. + required: false + version_added: 2.9 + suboptions: + ttl: + description: + - Specifies the "time-to-live" duration for an associated resource. The resource + expires if it is not active for a period of ttl. The definition of "activity" + depends on the type of the associated resource. The minimum and maximum + allowed values for ttl depend on the type of the associated resource, as + well. If ttl is not set, the associated resource never expires. + - A duration in seconds with up to nine fractional digits, terminated by 's'. + - Example - "3.5s". + required: false extends_documentation_fragment: gcp notes: - 'API Reference: U(https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions)' @@ -188,7 +208,7 @@ pushConfig: pushEndpoint: description: - A URL locating the endpoint to which messages should be pushed. - - For example, a Webhook endpoint might use "U(https://example.com/push".) + - For example, a Webhook endpoint might use "U(https://example.com/push"). returned: success type: str attributes: @@ -246,6 +266,27 @@ retainAckedMessages: they fall out of the messageRetentionDuration window. returned: success type: bool +expirationPolicy: + description: + - A policy that specifies the conditions for this subscription's expiration. + - A subscription is considered active as long as any connected subscriber is successfully + consuming messages from the subscription or is issuing operations on the subscription. + If expirationPolicy is not set, a default policy with ttl of 31 days will be used. + The minimum allowed value for expirationPolicy.ttl is 1 day. + returned: success + type: complex + contains: + ttl: + description: + - Specifies the "time-to-live" duration for an associated resource. The resource + expires if it is not active for a period of ttl. The definition of "activity" + depends on the type of the associated resource. The minimum and maximum allowed + values for ttl depend on the type of the associated resource, as well. If + ttl is not set, the associated resource never expires. + - A duration in seconds with up to nine fractional digits, terminated by 's'. + - Example - "3.5s". + returned: success + type: str ''' ################################################################################ @@ -273,6 +314,7 @@ def main(): ack_deadline_seconds=dict(type='int'), message_retention_duration=dict(default='604800s', type='str'), retain_acked_messages=dict(type='bool'), + expiration_policy=dict(type='dict', options=dict(ttl=dict(type='str'))), ) ) @@ -331,6 +373,8 @@ def updateMask(request, response): update_mask.append('messageRetentionDuration') if request.get('retainAckedMessages') != response.get('retainAckedMessages'): update_mask.append('retainAckedMessages') + if request.get('expirationPolicy') != response.get('expirationPolicy'): + update_mask.append('expirationPolicy') return ','.join(update_mask) @@ -348,6 +392,7 @@ def resource_to_request(module): u'ackDeadlineSeconds': module.params.get('ack_deadline_seconds'), u'messageRetentionDuration': module.params.get('message_retention_duration'), u'retainAckedMessages': module.params.get('retain_acked_messages'), + u'expirationPolicy': SubscriptionExpirationpolicy(module.params.get('expiration_policy', {}), module).to_request(), } request = encode_request(request, module) return_vals = {} @@ -424,6 +469,7 @@ def response_to_hash(module, response): u'ackDeadlineSeconds': response.get(u'ackDeadlineSeconds'), u'messageRetentionDuration': response.get(u'messageRetentionDuration'), u'retainAckedMessages': response.get(u'retainAckedMessages'), + u'expirationPolicy': SubscriptionExpirationpolicy(response.get(u'expirationPolicy', {}), module).from_response(), } @@ -459,5 +505,20 @@ class SubscriptionPushconfig(object): return remove_nones_from_dict({u'pushEndpoint': self.request.get(u'pushEndpoint'), u'attributes': self.request.get(u'attributes')}) +class SubscriptionExpirationpolicy(object): + def __init__(self, request, module): + self.module = module + if request: + self.request = request + else: + self.request = {} + + def to_request(self): + return remove_nones_from_dict({u'ttl': self.request.get('ttl')}) + + def from_response(self): + return remove_nones_from_dict({u'ttl': self.request.get(u'ttl')}) + + if __name__ == '__main__': main() diff --git a/lib/ansible/modules/cloud/google/gcp_pubsub_subscription_facts.py b/lib/ansible/modules/cloud/google/gcp_pubsub_subscription_facts.py index 30e39be3b2c..062a91e9cc5 100644 --- a/lib/ansible/modules/cloud/google/gcp_pubsub_subscription_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_pubsub_subscription_facts.py @@ -53,8 +53,8 @@ EXAMPLES = ''' ''' RETURN = ''' -items: - description: List of items +resources: + description: List of resources returned: always type: complex contains: @@ -84,7 +84,7 @@ items: pushEndpoint: description: - A URL locating the endpoint to which messages should be pushed. - - For example, a Webhook endpoint might use "U(https://example.com/push".) + - For example, a Webhook endpoint might use "U(https://example.com/push"). returned: success type: str attributes: @@ -144,6 +144,29 @@ items: until they fall out of the messageRetentionDuration window. returned: success type: bool + expirationPolicy: + description: + - A policy that specifies the conditions for this subscription's expiration. + - A subscription is considered active as long as any connected subscriber is + successfully consuming messages from the subscription or is issuing operations + on the subscription. If expirationPolicy is not set, a default policy with + ttl of 31 days will be used. The minimum allowed value for expirationPolicy.ttl + is 1 day. + returned: success + type: complex + contains: + ttl: + description: + - Specifies the "time-to-live" duration for an associated resource. The + resource expires if it is not active for a period of ttl. The definition + of "activity" depends on the type of the associated resource. The minimum + and maximum allowed values for ttl depend on the type of the associated + resource, as well. If ttl is not set, the associated resource never expires. + - A duration in seconds with up to nine fractional digits, terminated by + 's'. + - Example - "3.5s". + returned: success + type: str ''' ################################################################################ @@ -168,7 +191,7 @@ def main(): items = items.get('subscriptions') else: items = [] - return_value = {'items': items} + return_value = {'resources': items} module.exit_json(**return_value) diff --git a/lib/ansible/modules/cloud/google/gcp_pubsub_topic_facts.py b/lib/ansible/modules/cloud/google/gcp_pubsub_topic_facts.py index 466d8a662e4..8e3edf53c92 100644 --- a/lib/ansible/modules/cloud/google/gcp_pubsub_topic_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_pubsub_topic_facts.py @@ -53,8 +53,8 @@ EXAMPLES = ''' ''' RETURN = ''' -items: - description: List of items +resources: + description: List of resources returned: always type: complex contains: @@ -92,7 +92,7 @@ def main(): items = items.get('topics') else: items = [] - return_value = {'items': items} + return_value = {'resources': items} module.exit_json(**return_value) diff --git a/lib/ansible/modules/cloud/google/gcp_redis_instance.py b/lib/ansible/modules/cloud/google/gcp_redis_instance.py index 6dfcfdfef19..7fa5e41ea82 100644 --- a/lib/ansible/modules/cloud/google/gcp_redis_instance.py +++ b/lib/ansible/modules/cloud/google/gcp_redis_instance.py @@ -68,7 +68,7 @@ options: required: false redis_configs: description: - - Redis configuration parameters, according to U(http://redis.io/topics/config.) + - Redis configuration parameters, according to U(http://redis.io/topics/config). - 'Please check Memorystore documentation for the list of supported parameters: U(https://cloud.google.com/memorystore/docs/redis/reference/rest/v1/projects.locations.instances#Instance.FIELDS.redis_configs) .' @@ -105,11 +105,9 @@ options: description: - 'The service tier of the instance. Must be one of these values: - BASIC: standalone instance - STANDARD_HA: highly available primary/replica instances .' + - 'Some valid choices include: "BASIC", "STANDARD_HA"' required: false default: BASIC - choices: - - BASIC - - STANDARD_HA region: description: - The name of the Redis region of the instance. @@ -194,7 +192,7 @@ labels: type: dict redisConfigs: description: - - Redis configuration parameters, according to U(http://redis.io/topics/config.) + - Redis configuration parameters, according to U(http://redis.io/topics/config). - 'Please check Memorystore documentation for the list of supported parameters: U(https://cloud.google.com/memorystore/docs/redis/reference/rest/v1/projects.locations.instances#Instance.FIELDS.redis_configs) .' @@ -280,7 +278,7 @@ def main(): memory_size_gb=dict(required=True, type='int'), redis_version=dict(type='str'), reserved_ip_range=dict(type='str'), - tier=dict(default='BASIC', type='str', choices=['BASIC', 'STANDARD_HA']), + tier=dict(default='BASIC', type='str'), region=dict(required=True, type='str'), ) ) @@ -305,7 +303,7 @@ def main(): changed = True else: if state == 'present': - fetch = create(module, collection(module)) + fetch = create(module, create_link(module)) changed = True else: fetch = {} @@ -378,6 +376,10 @@ def self_link(module): def collection(module): + return "https://redis.googleapis.com/v1/projects/{project}/locations/{region}/instances".format(**module.params) + + +def create_link(module): return "https://redis.googleapis.com/v1/projects/{project}/locations/{region}/instances?instanceId={name}".format(**module.params) diff --git a/lib/ansible/modules/cloud/google/gcp_redis_instance_facts.py b/lib/ansible/modules/cloud/google/gcp_redis_instance_facts.py index bfdf4fe904c..5d430423a39 100644 --- a/lib/ansible/modules/cloud/google/gcp_redis_instance_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_redis_instance_facts.py @@ -58,8 +58,8 @@ EXAMPLES = ''' ''' RETURN = ''' -items: - description: List of items +resources: + description: List of resources returned: always type: complex contains: @@ -109,7 +109,7 @@ items: type: dict redisConfigs: description: - - Redis configuration parameters, according to U(http://redis.io/topics/config.) + - Redis configuration parameters, according to U(http://redis.io/topics/config). - 'Please check Memorystore documentation for the list of supported parameters: U(https://cloud.google.com/memorystore/docs/redis/reference/rest/v1/projects.locations.instances#Instance.FIELDS.redis_configs) .' @@ -188,7 +188,7 @@ def main(): items = items.get('instances') else: items = [] - return_value = {'items': items} + return_value = {'resources': items} module.exit_json(**return_value) diff --git a/lib/ansible/modules/cloud/google/gcp_resourcemanager_project_facts.py b/lib/ansible/modules/cloud/google/gcp_resourcemanager_project_facts.py index 8f4be97ea5a..512ccbf3e44 100644 --- a/lib/ansible/modules/cloud/google/gcp_resourcemanager_project_facts.py +++ b/lib/ansible/modules/cloud/google/gcp_resourcemanager_project_facts.py @@ -53,8 +53,8 @@ EXAMPLES = ''' ''' RETURN = ''' -items: - description: List of items +resources: + description: List of resources returned: always type: complex contains: @@ -139,7 +139,7 @@ def main(): items = items.get('projects') else: items = [] - return_value = {'items': items} + return_value = {'resources': items} module.exit_json(**return_value) diff --git a/test/integration/targets/gcp_dns_managed_zone/tasks/main.yml b/test/integration/targets/gcp_dns_managed_zone/tasks/main.yml index 425836bf0dd..e274a380633 100644 --- a/test/integration/targets/gcp_dns_managed_zone/tasks/main.yml +++ b/test/integration/targets/gcp_dns_managed_zone/tasks/main.yml @@ -50,7 +50,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length == 1 + - results['resources'] | length == 1 # ---------------------------------------------------------------------------- - name: create a managed zone that already exists gcp_dns_managed_zone: @@ -95,7 +95,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length == 0 + - results['resources'] | length == 0 # ---------------------------------------------------------------------------- - name: delete a managed zone that does not exist gcp_dns_managed_zone: diff --git a/test/integration/targets/gcp_iam_role/tasks/main.yml b/test/integration/targets/gcp_iam_role/tasks/main.yml index 6299f760ce2..a8f6da8efae 100644 --- a/test/integration/targets/gcp_iam_role/tasks/main.yml +++ b/test/integration/targets/gcp_iam_role/tasks/main.yml @@ -56,7 +56,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length >= 1 + - results['resources'] | length >= 1 # ---------------------------------------------------------------------------- - name: create a role that already exists gcp_iam_role: @@ -106,7 +106,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length == 0 + - results['resources'] | length == 0 # ---------------------------------------------------------------------------- - name: delete a role that does not exist gcp_iam_role: diff --git a/test/integration/targets/gcp_iam_service_account/tasks/main.yml b/test/integration/targets/gcp_iam_service_account/tasks/main.yml index f302e82e976..52f4af9791d 100644 --- a/test/integration/targets/gcp_iam_service_account/tasks/main.yml +++ b/test/integration/targets/gcp_iam_service_account/tasks/main.yml @@ -46,7 +46,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length >= 1 + - results['resources'] | length >= 1 # ---------------------------------------------------------------------------- - name: create a service account that already exists gcp_iam_service_account: @@ -86,7 +86,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length == 0 + - results['resources'] | length == 0 # ---------------------------------------------------------------------------- - name: delete a service account that does not exist gcp_iam_service_account: diff --git a/test/integration/targets/gcp_redis_instance/tasks/main.yml b/test/integration/targets/gcp_redis_instance/tasks/main.yml index 55febdbcde0..5fd54188f3c 100644 --- a/test/integration/targets/gcp_redis_instance/tasks/main.yml +++ b/test/integration/targets/gcp_redis_instance/tasks/main.yml @@ -73,7 +73,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length >= 1 + - results['resources'] | length >= 1 # ---------------------------------------------------------------------------- - name: create a instance that already exists gcp_redis_instance: @@ -132,7 +132,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length == 0 + - results['resources'] | length == 0 # ---------------------------------------------------------------------------- - name: delete a instance that does not exist gcp_redis_instance: diff --git a/test/integration/targets/gcp_resourcemanager_project/tasks/main.yml b/test/integration/targets/gcp_resourcemanager_project/tasks/main.yml index 50cb58639d7..d98ab5e6ba6 100644 --- a/test/integration/targets/gcp_resourcemanager_project/tasks/main.yml +++ b/test/integration/targets/gcp_resourcemanager_project/tasks/main.yml @@ -50,7 +50,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length >= 1 + - results['resources'] | length >= 1 # ---------------------------------------------------------------------------- - name: create a project that already exists gcp_resourcemanager_project: @@ -94,7 +94,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length == 0 + - results['resources'] | length == 0 # ---------------------------------------------------------------------------- - name: delete a project that does not exist gcp_resourcemanager_project: diff --git a/test/integration/targets/gcp_sourcerepo_repository/tasks/main.yml b/test/integration/targets/gcp_sourcerepo_repository/tasks/main.yml index 5d704fcb6b6..7557acb8c94 100644 --- a/test/integration/targets/gcp_sourcerepo_repository/tasks/main.yml +++ b/test/integration/targets/gcp_sourcerepo_repository/tasks/main.yml @@ -44,7 +44,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length >= 1 + - results['resources'] | length >= 1 # ---------------------------------------------------------------------------- - name: create a repository that already exists gcp_sourcerepo_repository: @@ -82,7 +82,7 @@ - name: verify that command succeeded assert: that: - - results['items'] | length == 0 + - results['resources'] | length == 0 # ---------------------------------------------------------------------------- - name: delete a repository that does not exist gcp_sourcerepo_repository: