Ryan Brown 2018-10-18 10:55:42 -04:00 committed by Alex Stephen
commit 5c97cc1da0
78 changed files with 2531 additions and 1137 deletions

View file

@ -81,6 +81,11 @@ options:
network:
description:
- The network to which all instances in the instance group belong.
- 'This field represents a link to a Network resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
and then set this network field to "{{ name-of-resource }}" Alternatively, you can
set this network to a dictionary with the selfLink key where the value is the selfLink
of your Network.'
required: false
region:
description:
@ -89,11 +94,25 @@ options:
subnetwork:
description:
- The subnetwork to which all instances in the instance group belong.
- 'This field represents a link to a Subnetwork resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_subnetwork
task and then set this subnetwork field to "{{ name-of-resource }}" Alternatively,
you can set this subnetwork to a dictionary with the selfLink key where the value
is the selfLink of your Subnetwork.'
required: false
zone:
description:
- A reference to the zone where the instance group resides.
required: true
instances:
description:
- The list of instances associated with this InstanceGroup.
- All instances must be created before being added to an InstanceGroup.
- All instances not in this list will be removed from the InstanceGroup and will not
be deleted.
- Only the full identifier of the instance will be returned.
required: false
version_added: 2.8
extends_documentation_fragment: gcp
'''
@ -116,13 +135,13 @@ EXAMPLES = '''
network: "{{ network }}"
zone: us-central1-a
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -144,7 +163,7 @@ RETURN = '''
- The name must be 1-63 characters long, and comply with RFC1035.
returned: success
type: str
named_ports:
namedPorts:
description:
- Assigns a name to a port number.
- 'For example: {name: "http", port: 80}.'
@ -186,6 +205,15 @@ RETURN = '''
- A reference to the zone where the instance group resides.
returned: success
type: str
instances:
description:
- The list of instances associated with this InstanceGroup.
- All instances must be created before being added to an InstanceGroup.
- All instances not in this list will be removed from the InstanceGroup and will not
be deleted.
- Only the full identifier of the instance will be returned.
returned: success
type: list
'''
################################################################################
@ -217,7 +245,8 @@ def main():
network=dict(type='dict'),
region=dict(type='str'),
subnetwork=dict(type='dict'),
zone=dict(required=True, type='str')
zone=dict(required=True, type='str'),
instances=dict(type='list', elements='dict')
)
)
@ -233,7 +262,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -246,6 +276,10 @@ def main():
else:
fetch = {}
if fetch:
instance = InstanceLogic(module)
instance.run()
fetch.update({'instances': instance.list_instances()})
fetch.update({'changed': changed})
module.exit_json(**fetch)
@ -257,7 +291,8 @@ def create(module, link, kind):
def update(module, link, kind):
module.fail_json(msg="InstanceGroup cannot be edited")
instance = InstanceLogic(module)
instance.run()
def delete(module, link, kind):
@ -283,9 +318,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -296,9 +331,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instanceGroups".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -313,8 +348,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -398,6 +431,66 @@ def raise_if_errors(response, err_path, module):
module.fail_json(msg=errors)
class InstanceLogic(object):
def __init__(self, module):
self.module = module
self.current_instances = self.list_instances()
self.module_instances = []
# Transform module list of instances (dicts of instance responses) into a list of selfLinks.
instances = self.module.params.get('instances')
if instances:
for instance in instances:
self.module_instances.append(replace_resource_dict(instance, 'selfLink'))
def run(self):
# Find all instances to add and add them
instances_to_add = list(set(self.module_instances) - set(self.current_instances))
if instances_to_add:
self.add_instances(instances_to_add)
# Find all instances to remove and remove them
instances_to_remove = list(set(self.current_instances) - set(self.module_instances))
if instances_to_remove:
self.remove_instances(instances_to_remove)
def list_instances(self):
auth = GcpSession(self.module, 'compute')
response = return_if_object(self.module, auth.post(self._list_instances_url(), {'instanceState': 'ALL'}),
'compute#instanceGroupsListInstances')
# Transform instance list into a list of selfLinks for diffing with module parameters
instances = []
for instance in response.get('items', []):
instances.append(instance['instance'])
return instances
def add_instances(self, instances):
auth = GcpSession(self.module, 'compute')
wait_for_operation(self.module, auth.post(self._add_instances_url(), self._build_request(instances)))
def remove_instances(self, instances):
auth = GcpSession(self.module, 'compute')
wait_for_operation(self.module, auth.post(self._remove_instances_url(), self._build_request(instances)))
def _list_instances_url(self):
return "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instanceGroups/{name}/listInstances".format(**self.module.params)
def _remove_instances_url(self):
return "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instanceGroups/{name}/removeInstances".format(**self.module.params)
def _add_instances_url(self):
return "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instanceGroups/{name}/addInstances".format(**self.module.params)
def _build_request(self, instances):
request = {
'instances': []
}
for instance in instances:
request['instances'].append({'instance': instance})
return request
class InstanceGroupNamedPortsArray(object):
def __init__(self, request, module):
self.module = module