Support for named_ports in Managed Instance Groups. A libcloud guard has been implemented, as this feature will only be available in libcloud >= 1.3, or by using trunk. (#5167)
This commit is contained in:
parent
0ec56bb563
commit
b85bcb71c3
1 changed files with 124 additions and 0 deletions
|
@ -84,6 +84,13 @@ options:
|
||||||
on Autoscaling.
|
on Autoscaling.
|
||||||
required: false
|
required: false
|
||||||
default: null
|
default: null
|
||||||
|
named_ports:
|
||||||
|
version_added: "2.3"
|
||||||
|
description:
|
||||||
|
- Define named ports that backend services can forward data to. Format is a a list of
|
||||||
|
name:port dictionaries.
|
||||||
|
required: false
|
||||||
|
default: null
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = '''
|
||||||
|
@ -104,6 +111,11 @@ EXAMPLES = '''
|
||||||
state: present
|
state: present
|
||||||
size: 1
|
size: 1
|
||||||
template: my-instance-template-1
|
template: my-instance-template-1
|
||||||
|
named_ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
- name: foobar
|
||||||
|
port: 82
|
||||||
- pause: seconds=30
|
- pause: seconds=30
|
||||||
- name: Recreate MIG Instances with Instance Template change.
|
- name: Recreate MIG Instances with Instance Template change.
|
||||||
gce_mig:
|
gce_mig:
|
||||||
|
@ -167,6 +179,12 @@ name:
|
||||||
type: string
|
type: string
|
||||||
sample: "my-managed-instance-group"
|
sample: "my-managed-instance-group"
|
||||||
|
|
||||||
|
named_ports:
|
||||||
|
description: list of named ports acted upon
|
||||||
|
returned: when named_ports are initially set or updated
|
||||||
|
type: list
|
||||||
|
sample: [{ "name": "http", "port": 80 }, { "name": "foo", "port": 82 }]
|
||||||
|
|
||||||
size:
|
size:
|
||||||
description: Number of VMs in Managed Instance Group.
|
description: Number of VMs in Managed Instance Group.
|
||||||
returned: changed
|
returned: changed
|
||||||
|
@ -222,6 +240,18 @@ deleted_autoscaler:
|
||||||
returned: When the delete of an Autoscaler was attempted.
|
returned: When the delete of an Autoscaler was attempted.
|
||||||
type: bool
|
type: bool
|
||||||
sample: true
|
sample: true
|
||||||
|
|
||||||
|
set_named_ports:
|
||||||
|
description: True if the named_ports have been set
|
||||||
|
returned: named_ports have been set
|
||||||
|
type: bool
|
||||||
|
sample: true
|
||||||
|
|
||||||
|
updated_named_ports:
|
||||||
|
description: True if the named_ports have been updated
|
||||||
|
returned: named_ports have been updated
|
||||||
|
type: bool
|
||||||
|
sample: true
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
|
@ -324,6 +354,38 @@ def _validate_autoscaling_params(params):
|
||||||
return (True, '')
|
return (True, '')
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_named_port_params(params):
|
||||||
|
"""
|
||||||
|
Validate the named ports parameters
|
||||||
|
|
||||||
|
:param params: Ansible dictionary containing named_ports configuration
|
||||||
|
It is expected that autoscaling config will be found at the
|
||||||
|
key 'named_ports'. That key should contain a list of
|
||||||
|
{name : port} dictionaries.
|
||||||
|
:type params: ``dict``
|
||||||
|
|
||||||
|
:return: Tuple containing a boolean and a string. True if params
|
||||||
|
are valid, False otherwise, plus str for message.
|
||||||
|
:rtype: ``(``bool``, ``str``)``
|
||||||
|
"""
|
||||||
|
if not params['named_ports']:
|
||||||
|
# It's optional, so if not set at all, it's valid.
|
||||||
|
return (True, '')
|
||||||
|
if not isinstance(params['named_ports'], list):
|
||||||
|
return (False, 'named_ports: expected list of name:port dictionaries.')
|
||||||
|
req_fields = [
|
||||||
|
{'name': 'name', 'required': True, 'type': str},
|
||||||
|
{'name': 'port', 'required': True, 'type': int}
|
||||||
|
] # yapf: disable
|
||||||
|
|
||||||
|
for np in params['named_ports']:
|
||||||
|
(valid_named_ports, np_msg) = _check_params(np, req_fields)
|
||||||
|
if not valid_named_ports:
|
||||||
|
return (False, np_msg)
|
||||||
|
|
||||||
|
return (True, '')
|
||||||
|
|
||||||
|
|
||||||
def _get_instance_list(mig, field='name', filter_list=['NONE']):
|
def _get_instance_list(mig, field='name', filter_list=['NONE']):
|
||||||
"""
|
"""
|
||||||
Helper to grab field from instances response.
|
Helper to grab field from instances response.
|
||||||
|
@ -595,6 +657,38 @@ def get_mig(gce, name, zone):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def update_named_ports(mig, named_ports):
|
||||||
|
"""
|
||||||
|
Set the named ports on a Managed Instance Group.
|
||||||
|
|
||||||
|
Sort the existing named ports and new. If different, update.
|
||||||
|
This also implicitly allows for the removal of named_por
|
||||||
|
|
||||||
|
:param mig: Managed Instance Group Object from libcloud.
|
||||||
|
:type mig: :class: `GCEInstanceGroupManager`
|
||||||
|
|
||||||
|
:param named_ports: list of dictionaries in the format of {'name': port}
|
||||||
|
:type named_ports: ``list`` of ``dict``
|
||||||
|
|
||||||
|
:return: True if successful
|
||||||
|
:rtype: ``bool``
|
||||||
|
"""
|
||||||
|
changed = False
|
||||||
|
existing_ports = []
|
||||||
|
new_ports = []
|
||||||
|
if hasattr(mig.instance_group, 'named_ports'):
|
||||||
|
existing_ports = sorted(mig.instance_group.named_ports,
|
||||||
|
key=lambda x: x['name'])
|
||||||
|
if named_ports is not None:
|
||||||
|
new_ports = sorted(named_ports, key=lambda x: x['name'])
|
||||||
|
|
||||||
|
if existing_ports != new_ports:
|
||||||
|
if mig.instance_group.set_named_ports(named_ports):
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
return changed
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
module = AnsibleModule(argument_spec=dict(
|
module = AnsibleModule(argument_spec=dict(
|
||||||
name=dict(required=True),
|
name=dict(required=True),
|
||||||
|
@ -607,6 +701,7 @@ def main():
|
||||||
state=dict(choices=['absent', 'present'], default='present'),
|
state=dict(choices=['absent', 'present'], default='present'),
|
||||||
zone=dict(required=True),
|
zone=dict(required=True),
|
||||||
autoscaling=dict(type='dict', default=None),
|
autoscaling=dict(type='dict', default=None),
|
||||||
|
named_ports=dict(type='list', default=None),
|
||||||
service_account_email=dict(),
|
service_account_email=dict(),
|
||||||
service_account_permissions=dict(type='list'),
|
service_account_permissions=dict(type='list'),
|
||||||
pem_file=dict(),
|
pem_file=dict(),
|
||||||
|
@ -634,11 +729,22 @@ def main():
|
||||||
params['template'] = module.params.get('template')
|
params['template'] = module.params.get('template')
|
||||||
params['recreate_instances'] = module.params.get('recreate_instances')
|
params['recreate_instances'] = module.params.get('recreate_instances')
|
||||||
params['autoscaling'] = module.params.get('autoscaling', None)
|
params['autoscaling'] = module.params.get('autoscaling', None)
|
||||||
|
params['named_ports'] = module.params.get('named_ports', None)
|
||||||
|
|
||||||
(valid_autoscaling, as_msg) = _validate_autoscaling_params(params)
|
(valid_autoscaling, as_msg) = _validate_autoscaling_params(params)
|
||||||
if not valid_autoscaling:
|
if not valid_autoscaling:
|
||||||
module.fail_json(msg=as_msg, changed=False)
|
module.fail_json(msg=as_msg, changed=False)
|
||||||
|
|
||||||
|
if params['named_ports'] is not None and not hasattr(
|
||||||
|
gce, 'ex_instancegroup_set_named_ports'):
|
||||||
|
module.fail_json(
|
||||||
|
msg="Apache Libcloud 1.3.0+ is required to use 'named_ports' option",
|
||||||
|
changed=False)
|
||||||
|
|
||||||
|
(valid_named_ports, np_msg) = _validate_named_port_params(params)
|
||||||
|
if not valid_named_ports:
|
||||||
|
module.fail_json(msg=np_msg, changed=False)
|
||||||
|
|
||||||
changed = False
|
changed = False
|
||||||
json_output = {'state': params['state'], 'zone': params['zone']}
|
json_output = {'state': params['state'], 'zone': params['zone']}
|
||||||
mig = get_mig(gce, params['name'], params['zone'])
|
mig = get_mig(gce, params['name'], params['zone'])
|
||||||
|
@ -681,6 +787,18 @@ def main():
|
||||||
changed=False)
|
changed=False)
|
||||||
|
|
||||||
json_output['created_autoscaler'] = True
|
json_output['created_autoscaler'] = True
|
||||||
|
# Add named ports if available
|
||||||
|
if params['named_ports']:
|
||||||
|
mig = get_mig(gce, params['name'], params['zone'])
|
||||||
|
if not mig:
|
||||||
|
module.fail_json(
|
||||||
|
msg='Unable to fetch created MIG %s to create \
|
||||||
|
autoscaler in zone: %s' % (
|
||||||
|
params['name'], params['zone']), changed=False)
|
||||||
|
json_output['set_named_ports'] = update_named_ports(
|
||||||
|
mig, params['named_ports'])
|
||||||
|
if json_output['set_named_ports']:
|
||||||
|
json_output['named_ports'] = params['named_ports']
|
||||||
|
|
||||||
elif params['state'] == 'absent':
|
elif params['state'] == 'absent':
|
||||||
# Delete MIG
|
# Delete MIG
|
||||||
|
@ -704,6 +822,7 @@ def main():
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Update MIG
|
# Update MIG
|
||||||
|
|
||||||
# If we're going to update a MIG, we need a size and template values.
|
# If we're going to update a MIG, we need a size and template values.
|
||||||
# If not specified, we use the values from the existing MIG.
|
# If not specified, we use the values from the existing MIG.
|
||||||
if not params['size']:
|
if not params['size']:
|
||||||
|
@ -755,6 +874,11 @@ def main():
|
||||||
changed = update_autoscaler(gce, autoscaler,
|
changed = update_autoscaler(gce, autoscaler,
|
||||||
params['autoscaling'])
|
params['autoscaling'])
|
||||||
json_output['updated_autoscaler'] = changed
|
json_output['updated_autoscaler'] = changed
|
||||||
|
named_ports = params['named_ports'] or []
|
||||||
|
json_output['updated_named_ports'] = update_named_ports(mig,
|
||||||
|
named_ports)
|
||||||
|
if json_output['updated_named_ports']:
|
||||||
|
json_output['named_ports'] = named_ports
|
||||||
|
|
||||||
json_output['changed'] = changed
|
json_output['changed'] = changed
|
||||||
json_output.update(params)
|
json_output.update(params)
|
||||||
|
|
Loading…
Reference in a new issue