1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

Restore removed google modules (#675)

* Revert "Remove entries of modules that no longer exist." partially.

This reverts commit c1e1b37da4.

* Revert "The _info module is in google.cloud."

This reverts commit 26f5c84924.

* Revert "Remove modules that were moved to the google.cloud collection according to ansible/ansible's ansible_builtin_runtime.yml."

This reverts commit a1442ccc35.

* Fix FQCNs in examples and module references.

* Add changelog fragment.

* Update ignore.txt.

* Remove bad lines.
This commit is contained in:
Felix Fontein 2020-07-21 08:45:32 +02:00 committed by GitHub
parent 52cce0b7af
commit 7ac467a359
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1804 additions and 169 deletions

View file

@ -0,0 +1,3 @@
minor_changes:
- Add the deprecated ``gcp_backend_service``, ``gcp_forwarding_rule`` and ``gcp_healthcheck`` modules, which will be removed in 2.0.0. These were originally in community.general, but removed on the assumption that they have been moved to google.cloud. Since this turned out to be incorrect, we re-added them for 1.0.0.
- Add the ``gcpubsub``, ``gcpubsub_info`` and ``gcpubsub_facts`` (to be removed in 3.0.0) modules. These were originally in community.general, but removed on the assumption that they have been moved to google.cloud. Since this turned out to be incorrect, we re-added them for 1.0.0.

View file

@ -258,6 +258,18 @@ plugin_routing:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
gcp_backend_service:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
gcp_forwarding_rule:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
gcp_healthcheck:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
gcp_target_proxy:
deprecation:
removal_version: 2.0.0

View file

@ -0,0 +1,400 @@
#!/usr/bin/python
# Copyright 2017 Google Inc.
# 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 = '''
module: gcp_backend_service
short_description: Create or Destroy a Backend Service.
description:
- Create or Destroy a Backend Service. See
U(https://cloud.google.com/compute/docs/load-balancing/http/backend-service) for an overview.
Full install/configuration instructions for the Google Cloud modules can
be found in the comments of ansible/test/gce_tests.py.
requirements:
- "python >= 2.6"
- "apache-libcloud >= 1.3.0"
notes:
- Update is not currently supported.
- Only global backend services are currently supported. Regional backends not currently supported.
- Internal load balancing not currently supported.
deprecated:
removed_in: 2.0.0 # was Ansible 2.12
why: Updated modules released with increased functionality
alternative: Use M(google.cloud.gcp_compute_backend_service) instead.
author:
- "Tom Melendez (@supertom) <tom@supertom.com>"
options:
backend_service_name:
description:
- Name of the Backend Service.
required: true
backends:
description:
- List of backends that make up the backend service. A backend is made up of
an instance group and optionally several other parameters. See
U(https://cloud.google.com/compute/docs/reference/latest/backendServices)
for details.
required: true
healthchecks:
description:
- List of healthchecks. Only one healthcheck is supported.
required: true
enable_cdn:
description:
- If true, enable Cloud CDN for this Backend Service.
type: bool
port_name:
description:
- Name of the port on the managed instance group (MIG) that backend
services can forward data to. Required for external load balancing.
protocol:
description:
- The protocol this Backend Service uses to communicate with backends.
Possible values are HTTP, HTTPS, TCP, and SSL. The default is HTTP.
required: false
timeout:
description:
- How many seconds to wait for the backend before considering it a failed
request. Default is 30 seconds. Valid range is 1-86400.
required: false
service_account_email:
description:
- Service account email
credentials_file:
description:
- Path to the JSON file associated with the service account email.
project_id:
description:
- GCE project ID.
state:
description:
- Desired state of the resource
default: "present"
choices: ["absent", "present"]
'''
EXAMPLES = '''
- name: Create Minimum Backend Service
community.general.gcp_backend_service:
service_account_email: "{{ service_account_email }}"
credentials_file: "{{ credentials_file }}"
project_id: "{{ project_id }}"
backend_service_name: "{{ bes }}"
backends:
- instance_group: managed_instance_group_1
healthchecks:
- healthcheck_name_for_backend_service
port_name: myhttpport
state: present
- name: Create BES with extended backend parameters
community.general.gcp_backend_service:
service_account_email: "{{ service_account_email }}"
credentials_file: "{{ credentials_file }}"
project_id: "{{ project_id }}"
backend_service_name: "{{ bes }}"
backends:
- instance_group: managed_instance_group_1
max_utilization: 0.6
max_rate: 10
- instance_group: managed_instance_group_2
max_utilization: 0.5
max_rate: 4
healthchecks:
- healthcheck_name_for_backend_service
port_name: myhttpport
state: present
timeout: 60
'''
RETURN = '''
backend_service_created:
description: Indicator Backend Service was created.
returned: When a Backend Service is created.
type: bool
sample: "True"
backend_service_deleted:
description: Indicator Backend Service was deleted.
returned: When a Backend Service is deleted.
type: bool
sample: "True"
backend_service_name:
description: Name of the Backend Service.
returned: Always.
type: str
sample: "my-backend-service"
backends:
description: List of backends (comprised of instance_group) that
make up a Backend Service.
returned: When a Backend Service exists.
type: list
sample: "[ { 'instance_group': 'mig_one', 'zone': 'us-central1-b'} ]"
enable_cdn:
description: If Cloud CDN is enabled. null if not set.
returned: When a backend service exists.
type: bool
sample: "True"
healthchecks:
description: List of healthchecks applied to the Backend Service.
returned: When a Backend Service exists.
type: list
sample: "[ 'my-healthcheck' ]"
protocol:
description: Protocol used to communicate with the Backends.
returned: When a Backend Service exists.
type: str
sample: "HTTP"
port_name:
description: Name of Backend Port.
returned: When a Backend Service exists.
type: str
sample: "myhttpport"
timeout:
description: In seconds, how long before a request sent to a backend is
considered failed.
returned: If specified.
type: int
sample: "myhttpport"
'''
try:
from ast import literal_eval
HAS_PYTHON26 = True
except ImportError:
HAS_PYTHON26 = False
try:
import libcloud
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
from libcloud.common.google import GoogleBaseError, QuotaExceededError, \
ResourceExistsError, ResourceInUseError, ResourceNotFoundError
from libcloud.compute.drivers.gce import GCEAddress
_ = Provider.GCE
HAS_LIBCLOUD = True
except ImportError:
HAS_LIBCLOUD = False
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.gce import gce_connect
from ansible_collections.community.general.plugins.module_utils.gcp import check_params
def _validate_params(params):
"""
Validate backend_service params.
This function calls _validate_backend_params to verify
the backend-specific parameters.
:param params: Ansible dictionary containing configuration.
:type params: ``dict``
:return: True or raises ValueError
:rtype: ``bool`` or `class:ValueError`
"""
fields = [
{'name': 'timeout', 'type': int, 'min': 1, 'max': 86400},
]
try:
check_params(params, fields)
_validate_backend_params(params['backends'])
except Exception:
raise
return (True, '')
def _validate_backend_params(backends):
"""
Validate configuration for backends.
:param backends: Ansible dictionary containing backends configuration (only).
:type backends: ``dict``
:return: True or raises ValueError
:rtype: ``bool`` or `class:ValueError`
"""
fields = [
{'name': 'balancing_mode', 'type': str, 'values': ['UTILIZATION', 'RATE', 'CONNECTION']},
{'name': 'max_utilization', 'type': float},
{'name': 'max_connections', 'type': int},
{'name': 'max_rate', 'type': int},
{'name': 'max_rate_per_instance', 'type': float},
]
if not backends:
raise ValueError('backends should be a list.')
for backend in backends:
try:
check_params(backend, fields)
except Exception:
raise
if 'max_rate' in backend and 'max_rate_per_instance' in backend:
raise ValueError('Both maxRate or maxRatePerInstance cannot be set.')
return (True, '')
def get_backend_service(gce, name):
"""
Get a Backend Service from GCE.
:param gce: An initialized GCE driver object.
:type gce: :class: `GCENodeDriver`
:param name: Name of the Backend Service.
:type name: ``str``
:return: A GCEBackendService object or None.
:rtype: :class: `GCEBackendService` or None
"""
try:
# Does the Backend Service already exist?
return gce.ex_get_backendservice(name=name)
except ResourceNotFoundError:
return None
def get_healthcheck(gce, name):
return gce.ex_get_healthcheck(name)
def get_instancegroup(gce, name, zone=None):
return gce.ex_get_instancegroup(name=name, zone=zone)
def create_backend_service(gce, params):
"""
Create a new Backend Service.
:param gce: An initialized GCE driver object.
:type gce: :class: `GCENodeDriver`
:param params: Dictionary of parameters needed by the module.
:type params: ``dict``
:return: Tuple with changed stats
:rtype: tuple in the format of (bool, bool)
"""
from copy import deepcopy
changed = False
return_data = False
# only one healthcheck is currently supported
hc_name = params['healthchecks'][0]
hc = get_healthcheck(gce, hc_name)
backends = []
for backend in params['backends']:
ig = get_instancegroup(gce, backend['instance_group'],
backend.get('zone', None))
kwargs = deepcopy(backend)
kwargs['instance_group'] = ig
backends.append(gce.ex_create_backend(
**kwargs))
bes = gce.ex_create_backendservice(
name=params['backend_service_name'], healthchecks=[hc], backends=backends,
enable_cdn=params['enable_cdn'], port_name=params['port_name'],
timeout_sec=params['timeout'], protocol=params['protocol'])
if bes:
changed = True
return_data = True
return (changed, return_data)
def delete_backend_service(bes):
"""
Delete a Backend Service. The Instance Groups are NOT destroyed.
"""
changed = False
return_data = False
if bes.destroy():
changed = True
return_data = True
return (changed, return_data)
def main():
module = AnsibleModule(argument_spec=dict(
backends=dict(type='list', required=True),
backend_service_name=dict(required=True),
healthchecks=dict(type='list', required=True),
service_account_email=dict(),
service_account_permissions=dict(type='list'),
enable_cdn=dict(type='bool'),
port_name=dict(type='str'),
protocol=dict(type='str', default='TCP',
choices=['HTTP', 'HTTPS', 'SSL', 'TCP']),
timeout=dict(type='int'),
state=dict(choices=['absent', 'present'], default='present'),
pem_file=dict(),
credentials_file=dict(),
project_id=dict(), ), )
if not HAS_PYTHON26:
module.fail_json(
msg="GCE module requires python's 'ast' module, python v2.6+")
if not HAS_LIBCLOUD:
module.fail_json(
msg='libcloud with GCE Backend Service support (1.3+) required for this module.')
gce = gce_connect(module)
if not hasattr(gce, 'ex_create_instancegroupmanager'):
module.fail_json(
msg='libcloud with GCE Backend Service support (1.3+) required for this module.',
changed=False)
params = {}
params['state'] = module.params.get('state')
params['backend_service_name'] = module.params.get('backend_service_name')
params['backends'] = module.params.get('backends')
params['healthchecks'] = module.params.get('healthchecks')
params['enable_cdn'] = module.params.get('enable_cdn', None)
params['port_name'] = module.params.get('port_name', None)
params['protocol'] = module.params.get('protocol', None)
params['timeout'] = module.params.get('timeout', None)
try:
_validate_params(params)
except Exception as e:
module.fail_json(msg=e.message, changed=False)
changed = False
json_output = {'state': params['state']}
bes = get_backend_service(gce, params['backend_service_name'])
if not bes:
if params['state'] == 'absent':
# Doesn't exist and state==absent.
changed = False
module.fail_json(
msg="Cannot delete unknown backend service: %s" %
(params['backend_service_name']))
else:
# Create
(changed, json_output['backend_service_created']) = create_backend_service(gce,
params)
elif params['state'] == 'absent':
# Delete
(changed, json_output['backend_service_deleted']) = delete_backend_service(bes)
else:
# TODO(supertom): Add update support when it is available in libcloud.
changed = False
json_output['changed'] = changed
json_output.update(params)
module.exit_json(**json_output)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,349 @@
#!/usr/bin/python
# Copyright 2017 Google Inc.
# 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 = '''
---
module: gcp_forwarding_rule
short_description: Create, Update or Destroy a Forwarding_Rule.
description:
- Create, Update or Destroy a Forwarding_Rule. See
U(https://cloud.google.com/compute/docs/load-balancing/http/target-proxies) for an overview.
More details on the Global Forwarding_Rule API can be found at
U(https://cloud.google.com/compute/docs/reference/latest/globalForwardingRules)
More details on the Forwarding Rules API can be found at
U(https://cloud.google.com/compute/docs/reference/latest/forwardingRules)
requirements:
- "python >= 2.6"
- "google-api-python-client >= 1.6.2"
- "google-auth >= 0.9.0"
- "google-auth-httplib2 >= 0.0.2"
deprecated:
removed_in: 2.0.0 # was Ansible 2.12
why: Updated modules released with increased functionality
alternative: Use M(google.cloud.gcp_compute_forwarding_rule) or M(google.cloud.gcp_compute_global_forwarding_rule) instead.
notes:
- Currently only supports global forwarding rules.
As such, Load Balancing Scheme is always EXTERNAL.
author:
- "Tom Melendez (@supertom) <tom@supertom.com>"
options:
address:
description:
- IPv4 or named IP address. Must be of the same scope (regional, global).
Reserved addresses can (and probably should) be used for global
forwarding rules. You may reserve IPs from the console or
via the gce_eip module.
required: false
forwarding_rule_name:
description:
- Name of the Forwarding_Rule.
required: true
port_range:
description:
- For global forwarding rules, must be set to 80 or 8080 for TargetHttpProxy, and
443 for TargetHttpsProxy or TargetSslProxy.
required: false
protocol:
description:
- For global forwarding rules, TCP, UDP, ESP, AH, SCTP or ICMP. Default is TCP.
required: false
region:
description:
- The region for this forwarding rule. Currently, only 'global' is supported.
required: false
state:
description:
- The state of the Forwarding Rule. 'present' or 'absent'
required: true
choices: ["present", "absent"]
target:
description:
- Target resource for forwarding rule. For global proxy, this is a Global
TargetProxy resource. Required for external load balancing (including Global load balancing)
required: false
'''
EXAMPLES = '''
- name: Create Minimum GLOBAL Forwarding_Rule
community.general.gcp_forwarding_rule:
service_account_email: "{{ service_account_email }}"
credentials_file: "{{ credentials_file }}"
project_id: "{{ project_id }}"
forwarding_rule_name: my-forwarding_rule
protocol: TCP
port_range: 80
region: global
target: my-target-proxy
state: present
- name: Create Forwarding_Rule w/reserved static address
community.general.gcp_forwarding_rule:
service_account_email: "{{ service_account_email }}"
credentials_file: "{{ credentials_file }}"
project_id: "{{ project_id }}"
forwarding_rule_name: my-forwarding_rule
protocol: TCP
port_range: 80
address: my-reserved-static-address-name
region: global
target: my-target-proxy
state: present
'''
RETURN = '''
forwarding_rule_name:
description: Name of the Forwarding_Rule
returned: Always
type: str
sample: my-target-proxy
forwarding_rule:
description: GCP Forwarding_Rule dictionary
returned: Always. Refer to GCP documentation for detailed field descriptions.
type: dict
sample: { "name": "my-forwarding_rule", "target": "..." }
region:
description: Region for Forwarding Rule.
returned: Always
type: bool
sample: true
state:
description: state of the Forwarding_Rule
returned: Always.
type: str
sample: present
'''
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.gcp import get_google_api_client, GCPUtils
USER_AGENT_PRODUCT = 'ansible-forwarding_rule'
USER_AGENT_VERSION = '0.0.1'
def _build_global_forwarding_rule_dict(params, project_id=None):
"""
Reformat services in Ansible Params.
:param params: Params from AnsibleModule object
:type params: ``dict``
:param project_id: The GCP project ID.
:type project_id: ``str``
:return: dictionary suitable for submission to GCP API.
:rtype ``dict``
"""
url = ''
if project_id:
url = GCPUtils.build_googleapi_url(project_id)
gcp_dict = GCPUtils.params_to_gcp_dict(params, 'forwarding_rule_name')
if 'target' in gcp_dict:
gcp_dict['target'] = '%s/global/targetHttpProxies/%s' % (url,
gcp_dict['target'])
if 'address' in gcp_dict:
gcp_dict['IPAddress'] = '%s/global/addresses/%s' % (url,
gcp_dict['address'])
del gcp_dict['address']
if 'protocol' in gcp_dict:
gcp_dict['IPProtocol'] = gcp_dict['protocol']
del gcp_dict['protocol']
return gcp_dict
def get_global_forwarding_rule(client, name, project_id=None):
"""
Get a Global Forwarding Rule from GCP.
:param client: An initialized GCE Compute Discovery resource.
:type client: :class: `googleapiclient.discovery.Resource`
:param name: Name of the Global Forwarding Rule.
:type name: ``str``
:param project_id: The GCP project ID.
:type project_id: ``str``
:return: A dict resp from the respective GCP 'get' request.
:rtype: ``dict``
"""
try:
req = client.globalForwardingRules().get(
project=project_id, forwardingRule=name)
return GCPUtils.execute_api_client_req(req, raise_404=False)
except Exception:
raise
def create_global_forwarding_rule(client, params, project_id):
"""
Create a new Global Forwarding Rule.
:param client: An initialized GCE Compute Discovery resource.
:type client: :class: `googleapiclient.discovery.Resource`
:param params: Dictionary of arguments from AnsibleModule.
:type params: ``dict``
:return: Tuple with changed status and response dict
:rtype: ``tuple`` in the format of (bool, dict)
"""
gcp_dict = _build_global_forwarding_rule_dict(params, project_id)
try:
req = client.globalForwardingRules().insert(project=project_id, body=gcp_dict)
return_data = GCPUtils.execute_api_client_req(req, client, raw=False)
if not return_data:
return_data = get_global_forwarding_rule(client,
name=params['forwarding_rule_name'],
project_id=project_id)
return (True, return_data)
except Exception:
raise
def delete_global_forwarding_rule(client, name, project_id):
"""
Delete a Global Forwarding Rule.
:param client: An initialized GCE Compute Discovery resource.
:type client: :class: `googleapiclient.discovery.Resource`
:param name: Name of the Target Proxy.
:type name: ``str``
:param project_id: The GCP project ID.
:type project_id: ``str``
:return: Tuple with changed status and response dict
:rtype: ``tuple`` in the format of (bool, dict)
"""
try:
req = client.globalForwardingRules().delete(
project=project_id, forwardingRule=name)
return_data = GCPUtils.execute_api_client_req(req, client)
return (True, return_data)
except Exception:
raise
def update_global_forwarding_rule(client, forwarding_rule, params, name, project_id):
"""
Update a Global Forwarding_Rule. Currently, only a target can be updated.
If the forwarding_rule has not changed, the update will not occur.
:param client: An initialized GCE Compute Discovery resource.
:type client: :class: `googleapiclient.discovery.Resource`
:param forwarding_rule: Name of the Target Proxy.
:type forwarding_rule: ``dict``
:param params: Dictionary of arguments from AnsibleModule.
:type params: ``dict``
:param name: Name of the Global Forwarding Rule.
:type name: ``str``
:param project_id: The GCP project ID.
:type project_id: ``str``
:return: Tuple with changed status and response dict
:rtype: ``tuple`` in the format of (bool, dict)
"""
gcp_dict = _build_global_forwarding_rule_dict(params, project_id)
GCPUtils.are_params_equal(forwarding_rule, gcp_dict)
if forwarding_rule['target'] == gcp_dict['target']:
return (False, 'no update necessary')
try:
req = client.globalForwardingRules().setTarget(project=project_id,
forwardingRule=name,
body={'target': gcp_dict['target']})
return_data = GCPUtils.execute_api_client_req(
req, client=client, raw=False)
return (True, return_data)
except Exception:
raise
def main():
module = AnsibleModule(argument_spec=dict(
forwarding_rule_name=dict(required=True),
region=dict(required=True),
target=dict(required=False),
address=dict(type='str', required=False),
protocol=dict(required=False, default='TCP', choices=['TCP']),
port_range=dict(required=False),
load_balancing_scheme=dict(
required=False, default='EXTERNAL', choices=['EXTERNAL']),
state=dict(required=True, choices=['absent', 'present']),
service_account_email=dict(),
service_account_permissions=dict(type='list'),
pem_file=dict(),
credentials_file=dict(),
project_id=dict(), ), )
client, conn_params = get_google_api_client(module, 'compute', user_agent_product=USER_AGENT_PRODUCT,
user_agent_version=USER_AGENT_VERSION)
params = {}
params['state'] = module.params.get('state')
params['forwarding_rule_name'] = module.params.get('forwarding_rule_name')
params['region'] = module.params.get('region')
params['target'] = module.params.get('target', None)
params['protocol'] = module.params.get('protocol', None)
params['port_range'] = module.params.get('port_range')
if module.params.get('address', None):
params['address'] = module.params.get('address', None)
if params['region'] != 'global':
# This module currently doesn't support regional rules.
module.fail_json(
msg=("%s - Only global forwarding rules currently supported. "
"Be sure to specify 'global' for the region option.") %
(params['forwarding_rule_name']))
changed = False
json_output = {'state': params['state']}
forwarding_rule = None
if params['region'] == 'global':
forwarding_rule = get_global_forwarding_rule(client,
name=params['forwarding_rule_name'],
project_id=conn_params['project_id'])
if not forwarding_rule:
if params['state'] == 'absent':
# Doesn't exist in GCE, and state==absent.
changed = False
module.fail_json(
msg="Cannot delete unknown forwarding_rule: %s" %
(params['forwarding_rule_name']))
else:
# Create
changed, json_output['forwarding_rule'] = create_global_forwarding_rule(client,
params=params,
project_id=conn_params['project_id'])
elif params['state'] == 'absent':
# Delete
changed, json_output['forwarding_rule'] = delete_global_forwarding_rule(client,
name=params['forwarding_rule_name'],
project_id=conn_params['project_id'])
else:
changed, json_output['forwarding_rule'] = update_global_forwarding_rule(client,
forwarding_rule=forwarding_rule,
params=params,
name=params['forwarding_rule_name'],
project_id=conn_params['project_id'])
json_output['changed'] = changed
json_output.update(params)
module.exit_json(**json_output)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,444 @@
#!/usr/bin/python
# Copyright 2017 Google Inc.
# 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 = '''
---
module: gcp_healthcheck
short_description: Create, Update or Destroy a Healthcheck.
description:
- Create, Update or Destroy a Healthcheck. Currently only HTTP and
HTTPS Healthchecks are supported. Healthchecks are used to monitor
individual instances, managed instance groups and/or backend
services. Healtchecks are reusable.
- Visit
U(https://cloud.google.com/compute/docs/load-balancing/health-checks)
for an overview of Healthchecks on GCP.
- See
U(https://cloud.google.com/compute/docs/reference/latest/httpHealthChecks) for
API details on HTTP Healthchecks.
- See
U(https://cloud.google.com/compute/docs/reference/latest/httpsHealthChecks)
for more details on the HTTPS Healtcheck API.
requirements:
- "python >= 2.6"
- "google-api-python-client >= 1.6.2"
- "google-auth >= 0.9.0"
- "google-auth-httplib2 >= 0.0.2"
notes:
- Only supports HTTP and HTTPS Healthchecks currently.
deprecated:
removed_in: 2.0.0 # was Ansible 2.12
why: Updated modules released with increased functionality
alternative: >
Use M(google.cloud.gcp_compute_health_check), M(google.cloud.gcp_compute_http_health_check) or
M(google.cloud.gcp_compute_https_health_check) instead.
author:
- "Tom Melendez (@supertom) <tom@supertom.com>"
options:
check_interval:
description:
- How often (in seconds) to send a health check.
default: 5
healthcheck_name:
description:
- Name of the Healthcheck.
required: true
healthcheck_type:
description:
- Type of Healthcheck.
required: true
choices: ["HTTP", "HTTPS"]
host_header:
description:
- The value of the host header in the health check request. If left
empty, the public IP on behalf of which this health
check is performed will be used.
required: true
default: ""
port:
description:
- The TCP port number for the health check request. The default value is
443 for HTTPS and 80 for HTTP.
request_path:
description:
- The request path of the HTTPS health check request.
required: false
default: "/"
state:
description: State of the Healthcheck.
required: true
choices: ["present", "absent"]
timeout:
description:
- How long (in seconds) to wait for a response before claiming
failure. It is invalid for timeout
to have a greater value than check_interval.
default: 5
unhealthy_threshold:
description:
- A so-far healthy instance will be marked unhealthy after this
many consecutive failures.
default: 2
healthy_threshold:
description:
- A so-far unhealthy instance will be marked healthy after this
many consecutive successes.
default: 2
service_account_email:
description:
- service account email
service_account_permissions:
description:
- service account permissions (see
U(https://cloud.google.com/sdk/gcloud/reference/compute/instances/create),
--scopes section for detailed information)
choices: [
"bigquery", "cloud-platform", "compute-ro", "compute-rw",
"useraccounts-ro", "useraccounts-rw", "datastore", "logging-write",
"monitoring", "sql-admin", "storage-full", "storage-ro",
"storage-rw", "taskqueue", "userinfo-email"
]
credentials_file:
description:
- Path to the JSON file associated with the service account email
project_id:
description:
- Your GCP project ID
'''
EXAMPLES = '''
- name: Create Minimum HealthCheck
community.general.gcp_healthcheck:
service_account_email: "{{ service_account_email }}"
credentials_file: "{{ credentials_file }}"
project_id: "{{ project_id }}"
healthcheck_name: my-healthcheck
healthcheck_type: HTTP
state: present
- name: Create HTTP HealthCheck
community.general.gcp_healthcheck:
service_account_email: "{{ service_account_email }}"
credentials_file: "{{ credentials_file }}"
project_id: "{{ project_id }}"
healthcheck_name: my-healthcheck
healthcheck_type: HTTP
host: my-host
request_path: /hc
check_interval: 10
timeout: 30
unhealthy_threshhold: 2
healthy_threshhold: 1
state: present
- name: Create HTTPS HealthCheck
community.general.gcp_healthcheck:
service_account_email: "{{ service_account_email }}"
credentials_file: "{{ credentials_file }}"
project_id: "{{ project_id }}"
healthcheck_name: "{{ https_healthcheck }}"
healthcheck_type: HTTPS
host_header: my-host
request_path: /hc
check_interval: 5
timeout: 5
unhealthy_threshold: 2
healthy_threshold: 1
state: present
'''
RETURN = '''
state:
description: state of the Healthcheck
returned: Always.
type: str
sample: present
healthcheck_name:
description: Name of the Healthcheck
returned: Always
type: str
sample: my-url-map
healthcheck_type:
description: Type of the Healthcheck
returned: Always
type: str
sample: HTTP
healthcheck:
description: GCP Healthcheck dictionary
returned: Always. Refer to GCP documentation for detailed field descriptions.
type: dict
sample: { "name": "my-hc", "port": 443, "requestPath": "/foo" }
'''
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.gcp import get_google_api_client, GCPUtils
USER_AGENT_PRODUCT = 'ansible-healthcheck'
USER_AGENT_VERSION = '0.0.1'
def _validate_healthcheck_params(params):
"""
Validate healthcheck params.
Simple validation has already assumed by AnsibleModule.
:param params: Ansible dictionary containing configuration.
:type params: ``dict``
:return: True or raises ValueError
:rtype: ``bool`` or `class:ValueError`
"""
if params['timeout'] > params['check_interval']:
raise ValueError("timeout (%s) is greater than check_interval (%s)" % (
params['timeout'], params['check_interval']))
return (True, '')
def _build_healthcheck_dict(params):
"""
Reformat services in Ansible Params for GCP.
:param params: Params from AnsibleModule object
:type params: ``dict``
:param project_id: The GCP project ID.
:type project_id: ``str``
:return: dictionary suitable for submission to GCP
HealthCheck (HTTP/HTTPS) API.
:rtype ``dict``
"""
gcp_dict = GCPUtils.params_to_gcp_dict(params, 'healthcheck_name')
if 'timeout' in gcp_dict:
gcp_dict['timeoutSec'] = gcp_dict['timeout']
del gcp_dict['timeout']
if 'checkInterval' in gcp_dict:
gcp_dict['checkIntervalSec'] = gcp_dict['checkInterval']
del gcp_dict['checkInterval']
if 'hostHeader' in gcp_dict:
gcp_dict['host'] = gcp_dict['hostHeader']
del gcp_dict['hostHeader']
if 'healthcheckType' in gcp_dict:
del gcp_dict['healthcheckType']
return gcp_dict
def _get_req_resource(client, resource_type):
if resource_type == 'HTTPS':
return (client.httpsHealthChecks(), 'httpsHealthCheck')
else:
return (client.httpHealthChecks(), 'httpHealthCheck')
def get_healthcheck(client, name, project_id=None, resource_type='HTTP'):
"""
Get a Healthcheck from GCP.
:param client: An initialized GCE Compute Discovery resource.
:type client: :class: `googleapiclient.discovery.Resource`
:param name: Name of the Url Map.
:type name: ``str``
:param project_id: The GCP project ID.
:type project_id: ``str``
:return: A dict resp from the respective GCP 'get' request.
:rtype: ``dict``
"""
try:
resource, entity_name = _get_req_resource(client, resource_type)
args = {'project': project_id, entity_name: name}
req = resource.get(**args)
return GCPUtils.execute_api_client_req(req, raise_404=False)
except Exception:
raise
def create_healthcheck(client, params, project_id, resource_type='HTTP'):
"""
Create a new Healthcheck.
:param client: An initialized GCE Compute Discovery resource.
:type client: :class: `googleapiclient.discovery.Resource`
:param params: Dictionary of arguments from AnsibleModule.
:type params: ``dict``
:return: Tuple with changed status and response dict
:rtype: ``tuple`` in the format of (bool, dict)
"""
gcp_dict = _build_healthcheck_dict(params)
try:
resource, _ = _get_req_resource(client, resource_type)
args = {'project': project_id, 'body': gcp_dict}
req = resource.insert(**args)
return_data = GCPUtils.execute_api_client_req(req, client, raw=False)
if not return_data:
return_data = get_healthcheck(client,
name=params['healthcheck_name'],
project_id=project_id)
return (True, return_data)
except Exception:
raise
def delete_healthcheck(client, name, project_id, resource_type='HTTP'):
"""
Delete a Healthcheck.
:param client: An initialized GCE Compute Discovery resource.
:type client: :class: `googleapiclient.discovery.Resource`
:param name: Name of the Url Map.
:type name: ``str``
:param project_id: The GCP project ID.
:type project_id: ``str``
:return: Tuple with changed status and response dict
:rtype: ``tuple`` in the format of (bool, dict)
"""
try:
resource, entity_name = _get_req_resource(client, resource_type)
args = {'project': project_id, entity_name: name}
req = resource.delete(**args)
return_data = GCPUtils.execute_api_client_req(req, client)
return (True, return_data)
except Exception:
raise
def update_healthcheck(client, healthcheck, params, name, project_id,
resource_type='HTTP'):
"""
Update a Healthcheck.
If the healthcheck has not changed, the update will not occur.
:param client: An initialized GCE Compute Discovery resource.
:type client: :class: `googleapiclient.discovery.Resource`
:param healthcheck: Name of the Url Map.
:type healthcheck: ``dict``
:param params: Dictionary of arguments from AnsibleModule.
:type params: ``dict``
:param name: Name of the Url Map.
:type name: ``str``
:param project_id: The GCP project ID.
:type project_id: ``str``
:return: Tuple with changed status and response dict
:rtype: ``tuple`` in the format of (bool, dict)
"""
gcp_dict = _build_healthcheck_dict(params)
ans = GCPUtils.are_params_equal(healthcheck, gcp_dict)
if ans:
return (False, 'no update necessary')
try:
resource, entity_name = _get_req_resource(client, resource_type)
args = {'project': project_id, entity_name: name, 'body': gcp_dict}
req = resource.update(**args)
return_data = GCPUtils.execute_api_client_req(
req, client=client, raw=False)
return (True, return_data)
except Exception:
raise
def main():
module = AnsibleModule(argument_spec=dict(
healthcheck_name=dict(required=True),
healthcheck_type=dict(required=True,
choices=['HTTP', 'HTTPS']),
request_path=dict(required=False, default='/'),
check_interval=dict(required=False, type='int', default=5),
healthy_threshold=dict(required=False, type='int', default=2),
unhealthy_threshold=dict(required=False, type='int', default=2),
host_header=dict(required=False, type='str', default=''),
timeout=dict(required=False, type='int', default=5),
port=dict(required=False, type='int'),
state=dict(choices=['absent', 'present'], default='present'),
service_account_email=dict(),
service_account_permissions=dict(type='list'),
credentials_file=dict(),
project_id=dict(), ), )
client, conn_params = get_google_api_client(module, 'compute', user_agent_product=USER_AGENT_PRODUCT,
user_agent_version=USER_AGENT_VERSION)
params = {}
params['healthcheck_name'] = module.params.get('healthcheck_name')
params['healthcheck_type'] = module.params.get('healthcheck_type')
params['request_path'] = module.params.get('request_path')
params['check_interval'] = module.params.get('check_interval')
params['healthy_threshold'] = module.params.get('healthy_threshold')
params['unhealthy_threshold'] = module.params.get('unhealthy_threshold')
params['host_header'] = module.params.get('host_header')
params['timeout'] = module.params.get('timeout')
params['port'] = module.params.get('port', None)
params['state'] = module.params.get('state')
if not params['port']:
params['port'] = 80
if params['healthcheck_type'] == 'HTTPS':
params['port'] = 443
try:
_validate_healthcheck_params(params)
except Exception as e:
module.fail_json(msg=e.message, changed=False)
changed = False
json_output = {'state': params['state']}
healthcheck = get_healthcheck(client,
name=params['healthcheck_name'],
project_id=conn_params['project_id'],
resource_type=params['healthcheck_type'])
if not healthcheck:
if params['state'] == 'absent':
# Doesn't exist in GCE, and state==absent.
changed = False
module.fail_json(
msg="Cannot delete unknown healthcheck: %s" %
(params['healthcheck_name']))
else:
# Create
changed, json_output['healthcheck'] = create_healthcheck(client,
params=params,
project_id=conn_params['project_id'],
resource_type=params['healthcheck_type'])
elif params['state'] == 'absent':
# Delete
changed, json_output['healthcheck'] = delete_healthcheck(client,
name=params['healthcheck_name'],
project_id=conn_params['project_id'],
resource_type=params['healthcheck_type'])
else:
changed, json_output['healthcheck'] = update_healthcheck(client,
healthcheck=healthcheck,
params=params,
name=params['healthcheck_name'],
project_id=conn_params['project_id'],
resource_type=params['healthcheck_type'])
json_output['changed'] = changed
json_output.update(params)
module.exit_json(**json_output)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,328 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2016, Google Inc.
# 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 = '''
---
module: gcpubsub
short_description: Create and Delete Topics/Subscriptions, Publish and pull messages on PubSub
description:
- Create and Delete Topics/Subscriptions, Publish and pull messages on PubSub.
See U(https://cloud.google.com/pubsub/docs) for an overview.
requirements:
- google-auth >= 0.5.0
- google-cloud-pubsub >= 0.22.0
notes:
- Subscription pull happens before publish. You cannot publish and pull in the same task.
author:
- Tom Melendez (@supertom) <tom@supertom.com>
options:
topic:
description:
- GCP pubsub topic name.
- Only the name, not the full path, is required.
required: yes
subscription:
description:
- Dictionary containing a subscription name associated with a topic (required), along with optional ack_deadline, push_endpoint and pull.
For pulling from a subscription, message_ack (bool), max_messages (int) and return_immediate are available as subfields.
See subfields name, push_endpoint and ack_deadline for more information.
name:
description: Subfield of subscription. Required if subscription is specified. See examples.
ack_deadline:
description: Subfield of subscription. Not required. Default deadline for subscriptions to ACK the message before it is resent. See examples.
pull:
description:
- Subfield of subscription. Not required. If specified, messages will be retrieved from topic via the provided subscription name.
max_messages (int; default None; max number of messages to pull), message_ack (bool; default False; acknowledge the message) and return_immediately
(bool; default True, don't wait for messages to appear). If the messages are acknowledged, changed is set to True, otherwise, changed is False.
push_endpoint:
description:
- Subfield of subscription. Not required. If specified, message will be sent to an endpoint.
See U(https://cloud.google.com/pubsub/docs/advanced#push_endpoints) for more information.
publish:
description:
- List of dictionaries describing messages and attributes to be published. Dictionary is in message(str):attributes(dict) format.
Only message is required.
state:
description:
- State of the topic or queue.
- Applies to the most granular resource.
- If subscription isspecified we remove it.
- If only topic is specified, that is what is removed.
- NOTE - A topic can be removed without first removing the subscription.
choices: [ absent, present ]
default: present
'''
EXAMPLES = '''
# (Message will be pushed; there is no check to see if the message was pushed before
- name: Create a topic and publish a message to it
community.general.gcpubsub:
topic: ansible-topic-example
state: present
# Subscriptions associated with topic are not deleted.
- name: Delete Topic
community.general.gcpubsub:
topic: ansible-topic-example
state: absent
# Setting absent will keep the messages from being sent
- name: Publish multiple messages, with attributes (key:value available with the message)
community.general.gcpubsub:
topic: '{{ topic_name }}'
state: present
publish:
- message: this is message 1
attributes:
mykey1: myvalue
mykey2: myvalu2
mykey3: myvalue3
- message: this is message 2
attributes:
server: prod
sla: "99.9999"
owner: fred
- name: Create Subscription (pull)
community.general.gcpubsub:
topic: ansible-topic-example
subscription:
- name: mysub
state: present
# pull is default, ack_deadline is not required
- name: Create Subscription with ack_deadline and push endpoint
community.general.gcpubsub:
topic: ansible-topic-example
subscription:
- name: mysub
ack_deadline: "60"
push_endpoint: http://pushendpoint.example.com
state: present
# Setting push_endpoint to "None" converts subscription to pull.
- name: Subscription change from push to pull
community.general.gcpubsub:
topic: ansible-topic-example
subscription:
name: mysub
push_endpoint: "None"
### Topic will not be deleted
- name: Delete subscription
community.general.gcpubsub:
topic: ansible-topic-example
subscription:
- name: mysub
state: absent
# only pull keyword is required.
- name: Pull messages from subscription
community.general.gcpubsub:
topic: ansible-topic-example
subscription:
name: ansible-topic-example-sub
pull:
message_ack: yes
max_messages: "100"
'''
RETURN = '''
publish:
description: List of dictionaries describing messages and attributes to be published. Dictionary is in message(str):attributes(dict) format.
Only message is required.
returned: Only when specified
type: list
sample: "publish: ['message': 'my message', attributes: {'key1': 'value1'}]"
pulled_messages:
description: list of dictionaries containing message info. Fields are ack_id, attributes, data, message_id.
returned: Only when subscription.pull is specified
type: list
sample: [{ "ack_id": "XkASTCcYREl...","attributes": {"key1": "val1",...}, "data": "this is message 1", "message_id": "49107464153705"},..]
state:
description: The state of the topic or subscription. Value will be either 'absent' or 'present'.
returned: Always
type: str
sample: "present"
subscription:
description: Name of subscription.
returned: When subscription fields are specified
type: str
sample: "mysubscription"
topic:
description: Name of topic.
returned: Always
type: str
sample: "mytopic"
'''
try:
from ast import literal_eval
HAS_PYTHON26 = True
except ImportError:
HAS_PYTHON26 = False
try:
from google.cloud import pubsub
HAS_GOOGLE_CLOUD_PUBSUB = True
except ImportError as e:
HAS_GOOGLE_CLOUD_PUBSUB = False
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.gcp import check_min_pkg_version, get_google_cloud_credentials
CLOUD_CLIENT = 'google-cloud-pubsub'
CLOUD_CLIENT_MINIMUM_VERSION = '0.22.0'
CLOUD_CLIENT_USER_AGENT = 'ansible-pubsub-0.1'
def publish_messages(message_list, topic):
with topic.batch() as batch:
for message in message_list:
msg = message['message']
attrs = {}
if 'attributes' in message:
attrs = message['attributes']
batch.publish(bytes(msg), **attrs)
return True
def pull_messages(pull_params, sub):
"""
:rtype: tuple (output, changed)
"""
changed = False
max_messages = pull_params.get('max_messages', None)
message_ack = pull_params.get('message_ack', 'no')
return_immediately = pull_params.get('return_immediately', False)
output = []
pulled = sub.pull(return_immediately=return_immediately, max_messages=max_messages)
for ack_id, msg in pulled:
msg_dict = {'message_id': msg.message_id,
'attributes': msg.attributes,
'data': msg.data,
'ack_id': ack_id}
output.append(msg_dict)
if message_ack:
ack_ids = [m['ack_id'] for m in output]
if ack_ids:
sub.acknowledge(ack_ids)
changed = True
return (output, changed)
def main():
module = AnsibleModule(
argument_spec=dict(
topic=dict(type='str', required=True),
state=dict(type='str', default='present', choices=['absent', 'present']),
publish=dict(type='list'),
subscription=dict(type='dict'),
service_account_email=dict(type='str'),
credentials_file=dict(type='str'),
project_id=dict(type='str'),
),
)
if not HAS_PYTHON26:
module.fail_json(
msg="GCE module requires python's 'ast' module, python v2.6+")
if not HAS_GOOGLE_CLOUD_PUBSUB:
module.fail_json(msg="Please install google-cloud-pubsub library.")
if not check_min_pkg_version(CLOUD_CLIENT, CLOUD_CLIENT_MINIMUM_VERSION):
module.fail_json(msg="Please install %s client version %s" % (CLOUD_CLIENT, CLOUD_CLIENT_MINIMUM_VERSION))
mod_params = {}
mod_params['publish'] = module.params.get('publish')
mod_params['state'] = module.params.get('state')
mod_params['topic'] = module.params.get('topic')
mod_params['subscription'] = module.params.get('subscription')
creds, params = get_google_cloud_credentials(module)
pubsub_client = pubsub.Client(project=params['project_id'], credentials=creds, use_gax=False)
pubsub_client.user_agent = CLOUD_CLIENT_USER_AGENT
changed = False
json_output = {}
t = None
if mod_params['topic']:
t = pubsub_client.topic(mod_params['topic'])
s = None
if mod_params['subscription']:
# Note: default ack deadline cannot be changed without deleting/recreating subscription
s = t.subscription(mod_params['subscription']['name'],
ack_deadline=mod_params['subscription'].get('ack_deadline', None),
push_endpoint=mod_params['subscription'].get('push_endpoint', None))
if mod_params['state'] == 'absent':
# Remove the most granular resource. If subscription is specified
# we remove it. If only topic is specified, that is what is removed.
# Note that a topic can be removed without first removing the subscription.
# TODO(supertom): Enhancement: Provide an option to only delete a topic
# if there are no subscriptions associated with it (which the API does not support).
if s is not None:
if s.exists():
s.delete()
changed = True
else:
if t.exists():
t.delete()
changed = True
elif mod_params['state'] == 'present':
if not t.exists():
t.create()
changed = True
if s:
if not s.exists():
s.create()
s.reload()
changed = True
else:
# Subscription operations
# TODO(supertom): if more 'update' operations arise, turn this into a function.
s.reload()
push_endpoint = mod_params['subscription'].get('push_endpoint', None)
if push_endpoint is not None:
if push_endpoint != s.push_endpoint:
if push_endpoint == 'None':
push_endpoint = None
s.modify_push_configuration(push_endpoint=push_endpoint)
s.reload()
changed = push_endpoint == s.push_endpoint
if 'pull' in mod_params['subscription']:
if s.push_endpoint is not None:
module.fail_json(msg="Cannot pull messages, push_endpoint is configured.")
(json_output['pulled_messages'], changed) = pull_messages(
mod_params['subscription']['pull'], s)
# publish messages to the topic
if mod_params['publish'] and len(mod_params['publish']) > 0:
changed = publish_messages(mod_params['publish'], t)
json_output['changed'] = changed
json_output.update(mod_params)
module.exit_json(**json_output)
if __name__ == '__main__':
main()

View file

@ -1,150 +0,0 @@
#!/usr/bin/python
# Copyright 2016 Google Inc.
# 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 = '''
---
module: gcpubsub_facts
deprecated:
removed_in: 3.0.0 # was Ansible 2.13
why: The module does not return Ansible facts
alternative: Use C(gcpubsub_info) from the C(google.cloud) collection instead
short_description: List Topics/Subscriptions and Messages from Google PubSub.
description:
- List Topics/Subscriptions from Google PubSub. Use the gcpubsub module for
topic/subscription management.
See U(https://cloud.google.com/pubsub/docs) for an overview.
- This module was called C(gcpubsub_facts) before Ansible 2.9. The usage did not change.
requirements:
- "python >= 2.6"
- "google-auth >= 0.5.0"
- "google-cloud-pubsub >= 0.22.0"
notes:
- list state enables user to list topics or subscriptions in the project. See examples for details.
author:
- "Tom Melendez (@supertom) <tom@supertom.com>"
options:
topic:
description:
- GCP pubsub topic name. Only the name, not the full path, is required.
required: False
view:
description:
- Choices are 'topics' or 'subscriptions'
required: True
state:
description:
- list is the only valid option.
required: False
'''
EXAMPLES = '''
- name: List all Topics in a project
gcpubsub_info:
view: topics
state: list
- name: List all Subscriptions in a project
gcpubsub_info:
view: subscriptions
state: list
- name: List all Subscriptions for a Topic in a project
gcpubsub_info:
view: subscriptions
topic: my-topic
state: list
'''
RETURN = '''
subscriptions:
description: List of subscriptions.
returned: When view is set to subscriptions.
type: list
sample: ["mysubscription", "mysubscription2"]
topic:
description: Name of topic. Used to filter subscriptions.
returned: Always
type: str
sample: "mytopic"
topics:
description: List of topics.
returned: When view is set to topics.
type: list
sample: ["mytopic", "mytopic2"]
'''
try:
from ast import literal_eval
HAS_PYTHON26 = True
except ImportError:
HAS_PYTHON26 = False
try:
from google.cloud import pubsub
HAS_GOOGLE_CLOUD_PUBSUB = True
except ImportError as e:
HAS_GOOGLE_CLOUD_PUBSUB = False
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.gcp import check_min_pkg_version, get_google_cloud_credentials
def list_func(data, member='name'):
"""Used for state=list."""
return [getattr(x, member) for x in data]
def main():
module = AnsibleModule(argument_spec=dict(
view=dict(choices=['topics', 'subscriptions'], default='topics'),
topic=dict(required=False),
state=dict(choices=['list'], default='list'),
service_account_email=dict(),
credentials_file=dict(),
project_id=dict(), ),)
if module._name in ('gcpubsub_facts', 'community.general.gcpubsub_facts'):
module.deprecate("The 'gcpubsub_facts' module has been renamed to 'gcpubsub_info'",
version='3.0.0', collection_name='community.general') # was Ansible 2.13
if not HAS_PYTHON26:
module.fail_json(
msg="GCE module requires python's 'ast' module, python v2.6+")
if not HAS_GOOGLE_CLOUD_PUBSUB:
module.fail_json(msg="Please install google-cloud-pubsub library.")
CLIENT_MINIMUM_VERSION = '0.22.0'
if not check_min_pkg_version('google-cloud-pubsub', CLIENT_MINIMUM_VERSION):
module.fail_json(msg="Please install google-cloud-pubsub library version %s" % CLIENT_MINIMUM_VERSION)
mod_params = {}
mod_params['state'] = module.params.get('state')
mod_params['topic'] = module.params.get('topic')
mod_params['view'] = module.params.get('view')
creds, params = get_google_cloud_credentials(module)
pubsub_client = pubsub.Client(project=params['project_id'], credentials=creds, use_gax=False)
pubsub_client.user_agent = 'ansible-pubsub-0.1'
json_output = {}
if mod_params['view'] == 'topics':
json_output['topics'] = list_func(pubsub_client.list_topics())
elif mod_params['view'] == 'subscriptions':
if mod_params['topic']:
t = pubsub_client.topic(mod_params['topic'])
json_output['subscriptions'] = list_func(t.list_subscriptions())
else:
json_output['subscriptions'] = list_func(pubsub_client.list_subscriptions())
json_output['changed'] = False
json_output.update(mod_params)
module.exit_json(**json_output)
if __name__ == '__main__':
main()

View file

@ -0,0 +1 @@
gcpubsub_info.py

View file

@ -0,0 +1,146 @@
#!/usr/bin/python
# Copyright 2016 Google Inc.
# 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 = '''
---
module: gcpubsub_info
short_description: List Topics/Subscriptions and Messages from Google PubSub.
description:
- List Topics/Subscriptions from Google PubSub. Use the gcpubsub module for
topic/subscription management.
See U(https://cloud.google.com/pubsub/docs) for an overview.
- This module was called C(gcpubsub_facts) before Ansible 2.9. The usage did not change.
requirements:
- "python >= 2.6"
- "google-auth >= 0.5.0"
- "google-cloud-pubsub >= 0.22.0"
notes:
- list state enables user to list topics or subscriptions in the project. See examples for details.
author:
- "Tom Melendez (@supertom) <tom@supertom.com>"
options:
topic:
description:
- GCP pubsub topic name. Only the name, not the full path, is required.
required: False
view:
description:
- Choices are 'topics' or 'subscriptions'
required: True
state:
description:
- list is the only valid option.
required: False
'''
EXAMPLES = '''
- name: List all Topics in a project
community.general.gcpubsub_info:
view: topics
state: list
- name: List all Subscriptions in a project
community.general.gcpubsub_info:
view: subscriptions
state: list
- name: List all Subscriptions for a Topic in a project
community.general.gcpubsub_info:
view: subscriptions
topic: my-topic
state: list
'''
RETURN = '''
subscriptions:
description: List of subscriptions.
returned: When view is set to subscriptions.
type: list
sample: ["mysubscription", "mysubscription2"]
topic:
description: Name of topic. Used to filter subscriptions.
returned: Always
type: str
sample: "mytopic"
topics:
description: List of topics.
returned: When view is set to topics.
type: list
sample: ["mytopic", "mytopic2"]
'''
try:
from ast import literal_eval
HAS_PYTHON26 = True
except ImportError:
HAS_PYTHON26 = False
try:
from google.cloud import pubsub
HAS_GOOGLE_CLOUD_PUBSUB = True
except ImportError as e:
HAS_GOOGLE_CLOUD_PUBSUB = False
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.gcp import check_min_pkg_version, get_google_cloud_credentials
def list_func(data, member='name'):
"""Used for state=list."""
return [getattr(x, member) for x in data]
def main():
module = AnsibleModule(argument_spec=dict(
view=dict(choices=['topics', 'subscriptions'], default='topics'),
topic=dict(required=False),
state=dict(choices=['list'], default='list'),
service_account_email=dict(),
credentials_file=dict(),
project_id=dict(), ),)
if module._name in ('gcpubsub_facts', 'community.general.gcpubsub_facts'):
module.deprecate("The 'gcpubsub_facts' module has been renamed to 'gcpubsub_info'",
version='3.0.0', collection_name='community.general') # was Ansible 2.13
if not HAS_PYTHON26:
module.fail_json(
msg="GCE module requires python's 'ast' module, python v2.6+")
if not HAS_GOOGLE_CLOUD_PUBSUB:
module.fail_json(msg="Please install google-cloud-pubsub library.")
CLIENT_MINIMUM_VERSION = '0.22.0'
if not check_min_pkg_version('google-cloud-pubsub', CLIENT_MINIMUM_VERSION):
module.fail_json(msg="Please install google-cloud-pubsub library version %s" % CLIENT_MINIMUM_VERSION)
mod_params = {}
mod_params['state'] = module.params.get('state')
mod_params['topic'] = module.params.get('topic')
mod_params['view'] = module.params.get('view')
creds, params = get_google_cloud_credentials(module)
pubsub_client = pubsub.Client(project=params['project_id'], credentials=creds, use_gax=False)
pubsub_client.user_agent = 'ansible-pubsub-0.1'
json_output = {}
if mod_params['view'] == 'topics':
json_output['topics'] = list_func(pubsub_client.list_topics())
elif mod_params['view'] == 'subscriptions':
if mod_params['topic']:
t = pubsub_client.topic(mod_params['topic'])
json_output['subscriptions'] = list_func(t.list_subscriptions())
else:
json_output['subscriptions'] = list_func(pubsub_client.list_subscriptions())
json_output['changed'] = False
json_output.update(mod_params)
module.exit_json(**json_output)
if __name__ == '__main__':
main()

View file

@ -0,0 +1 @@
./cloud/google/gcp_backend_service.py

View file

@ -0,0 +1 @@
./cloud/google/gcp_forwarding_rule.py

View file

@ -0,0 +1 @@
./cloud/google/gcp_healthcheck.py

1
plugins/modules/gcpubsub.py Symbolic link
View file

@ -0,0 +1 @@
./cloud/google/gcpubsub.py

View file

@ -1 +0,0 @@
cloud/google/gcpubsub_facts.py

View file

@ -0,0 +1 @@
./cloud/google/gcpubsub_info.py

View file

@ -123,6 +123,27 @@ plugins/modules/cloud/google/gce_snapshot.py validate-modules:parameter-type-not
plugins/modules/cloud/google/gce_tag.py pylint:blacklisted-name
plugins/modules/cloud/google/gce_tag.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gce_tag.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcp_backend_service.py pylint:blacklisted-name
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:doc-required-mismatch
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcp_healthcheck.py pylint:blacklisted-name
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:doc-required-mismatch
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcp_target_proxy.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcp_target_proxy.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcp_target_proxy.py validate-modules:doc-required-mismatch
@ -135,12 +156,16 @@ plugins/modules/cloud/google/gcp_url_map.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcp_url_map.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gcp_url_map.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcp_url_map.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:doc-required-mismatch
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:parameter-state-invalid-choice
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcpubsub.py validate-modules:nonexistent-parameter-documented
plugins/modules/cloud/google/gcpubsub.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gcpubsub.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcpubsub.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:doc-required-mismatch
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:parameter-state-invalid-choice
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcspanner.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcspanner.py validate-modules:undocumented-parameter
plugins/modules/cloud/heroku/heroku_collaborator.py validate-modules:parameter-list-no-elements
@ -1309,6 +1334,8 @@ plugins/modules/web_infrastructure/taiga_issue.py validate-modules:doc-missing-t
plugins/modules/web_infrastructure/taiga_issue.py validate-modules:parameter-list-no-elements
plugins/modules/web_infrastructure/taiga_issue.py validate-modules:parameter-type-not-in-doc
scripts/inventory/gce.py pylint:blacklisted-name
tests/unit/plugins/modules/cloud/google/test_gcp_forwarding_rule.py future-import-boilerplate
tests/unit/plugins/modules/cloud/google/test_gcp_forwarding_rule.py metaclass-boilerplate
tests/unit/plugins/modules/system/interfaces_file/test_interfaces_file.py pylint:blacklisted-name
tests/utils/shippable/check_matrix.py replace-urlopen
tests/utils/shippable/timing.py shebang

View file

@ -123,6 +123,27 @@ plugins/modules/cloud/google/gce_snapshot.py validate-modules:parameter-type-not
plugins/modules/cloud/google/gce_tag.py pylint:blacklisted-name
plugins/modules/cloud/google/gce_tag.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gce_tag.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcp_backend_service.py pylint:blacklisted-name
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:doc-required-mismatch
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcp_healthcheck.py pylint:blacklisted-name
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:doc-required-mismatch
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcp_target_proxy.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcp_target_proxy.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcp_target_proxy.py validate-modules:doc-required-mismatch
@ -135,12 +156,16 @@ plugins/modules/cloud/google/gcp_url_map.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcp_url_map.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gcp_url_map.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcp_url_map.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:doc-required-mismatch
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:parameter-state-invalid-choice
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcpubsub.py validate-modules:nonexistent-parameter-documented
plugins/modules/cloud/google/gcpubsub.py validate-modules:parameter-list-no-elements
plugins/modules/cloud/google/gcpubsub.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcpubsub.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:doc-required-mismatch
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:parameter-state-invalid-choice
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcspanner.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcspanner.py validate-modules:undocumented-parameter
plugins/modules/cloud/heroku/heroku_collaborator.py validate-modules:parameter-list-no-elements
@ -1309,6 +1334,8 @@ plugins/modules/web_infrastructure/taiga_issue.py validate-modules:doc-missing-t
plugins/modules/web_infrastructure/taiga_issue.py validate-modules:parameter-list-no-elements
plugins/modules/web_infrastructure/taiga_issue.py validate-modules:parameter-type-not-in-doc
scripts/inventory/gce.py pylint:blacklisted-name
tests/unit/plugins/modules/cloud/google/test_gcp_forwarding_rule.py future-import-boilerplate
tests/unit/plugins/modules/cloud/google/test_gcp_forwarding_rule.py metaclass-boilerplate
tests/unit/plugins/modules/system/interfaces_file/test_interfaces_file.py pylint:blacklisted-name
tests/utils/shippable/check_matrix.py replace-urlopen
tests/utils/shippable/timing.py shebang

View file

@ -97,18 +97,30 @@ plugins/modules/cloud/google/gce_snapshot.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gce_snapshot.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gce_tag.py pylint:blacklisted-name
plugins/modules/cloud/google/gce_tag.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcp_backend_service.py pylint:blacklisted-name
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:deprecation-mismatch
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:invalid-documentation
plugins/modules/cloud/google/gcp_backend_service.py validate-modules:missing-main-call
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:deprecation-mismatch
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:invalid-documentation
plugins/modules/cloud/google/gcp_forwarding_rule.py validate-modules:missing-main-call
plugins/modules/cloud/google/gcp_healthcheck.py pylint:blacklisted-name
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:deprecation-mismatch
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:invalid-documentation
plugins/modules/cloud/google/gcp_healthcheck.py validate-modules:missing-main-call
plugins/modules/cloud/google/gcp_target_proxy.py validate-modules:deprecation-mismatch
plugins/modules/cloud/google/gcp_target_proxy.py validate-modules:invalid-documentation
plugins/modules/cloud/google/gcp_target_proxy.py validate-modules:missing-main-call
plugins/modules/cloud/google/gcp_url_map.py validate-modules:deprecation-mismatch
plugins/modules/cloud/google/gcp_url_map.py validate-modules:invalid-documentation
plugins/modules/cloud/google/gcp_url_map.py validate-modules:missing-main-call
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:deprecation-mismatch
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:invalid-documentation
plugins/modules/cloud/google/gcpubsub_facts.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcpubsub.py validate-modules:nonexistent-parameter-documented
plugins/modules/cloud/google/gcpubsub.py validate-modules:parameter-type-not-in-doc
plugins/modules/cloud/google/gcpubsub.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:doc-choices-do-not-match-spec
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:doc-default-does-not-match-spec
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:doc-missing-type
plugins/modules/cloud/google/gcpubsub_info.py validate-modules:undocumented-parameter
plugins/modules/cloud/google/gcspanner.py validate-modules:deprecation-mismatch
plugins/modules/cloud/google/gcspanner.py validate-modules:invalid-documentation
plugins/modules/cloud/google/gcspanner.py validate-modules:missing-main-call
@ -1018,6 +1030,8 @@ plugins/modules/web_infrastructure/supervisorctl.py validate-modules:parameter-t
plugins/modules/web_infrastructure/taiga_issue.py validate-modules:doc-missing-type
plugins/modules/web_infrastructure/taiga_issue.py validate-modules:parameter-type-not-in-doc
scripts/inventory/gce.py pylint:blacklisted-name
tests/unit/plugins/modules/cloud/google/test_gcp_forwarding_rule.py future-import-boilerplate
tests/unit/plugins/modules/cloud/google/test_gcp_forwarding_rule.py metaclass-boilerplate
tests/unit/plugins/modules/system/interfaces_file/test_interfaces_file.py pylint:blacklisted-name
tests/utils/shippable/check_matrix.py replace-urlopen
tests/utils/shippable/timing.py shebang

View file

@ -0,0 +1,30 @@
import unittest
from ansible_collections.community.general.plugins.modules.cloud.google.gcp_forwarding_rule import _build_global_forwarding_rule_dict
class TestGCPFowardingRule(unittest.TestCase):
"""Unit tests for gcp_fowarding_rule module."""
params_dict = {
'forwarding_rule_name': 'foo_fowarding_rule_name',
'address': 'foo_external_address',
'target': 'foo_targetproxy',
'region': 'global',
'port_range': 80,
'protocol': 'TCP',
'state': 'present',
}
def test__build_global_forwarding_rule_dict(self):
expected = {
'name': 'foo_fowarding_rule_name',
'IPAddress': 'https://www.googleapis.com/compute/v1/projects/my-project/global/addresses/foo_external_address',
'target': 'https://www.googleapis.com/compute/v1/projects/my-project/global/targetHttpProxies/foo_targetproxy',
'region': 'global',
'portRange': 80,
'IPProtocol': 'TCP',
}
actual = _build_global_forwarding_rule_dict(
self.params_dict, 'my-project')
self.assertEqual(expected, actual)