plugins/modules/ali_slb_vsg.py (319 lines of code) (raw):

#!/usr/bin/python # Copyright (c) 2017-present Alibaba Group Holding Limited. <xiaozhu36> # 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 ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} DOCUMENTATION = ''' --- module: ali_slb_vsg short_description: Create, Delete VServerGroup and Modify its name or backend servers. description: - Create and delete a VServer group - Add or remove backend servers or network interfaces to/from the VServer group options: state: description: - Create and delete a VServer group. default: 'present' choices: ['present', 'absent'] type: str load_balancer_id: description: - The Server Load Balancer instance ID. This is used in combination with C(name) to determine if a VServer group already exists. required: True aliases: ['lb_id'] type: str vserver_group_name: description: - Virtual server group name. - One of I(vserver_group_name) and I(vserver_group_id) must be specified when operate existing slb group. aliases: ['group_name', 'name'] type: str backend_servers: description: - List of that need to be added or. - List of hash/dictionaries backend servers or network interfaces to add in this group (see example). If none are supplied, no backend servers will be enabled. Each server has several keys and refer to https://www.alibabacloud.com/help/doc-detail/35215.htm. Each key should be format as under_score. Currently the valid keys including "server_ids", "server_id", "port", "weight" and "type". - If you have multiple servers to add and they have the same port, weight, type, you can use the server_ids parameter, which is a list of ids. type: list elements: dict purge_backend_servers: description: - Purge existing backend servers or ENIs on VServer group that are not found in backend_servers. - If True, existing servers or ENIs will be purged from the resource to match exactly what is defined by I(backend_servers). If the I(backend_servers) is not set then servers will not be modified. - If True, it means you have to specify all the desired backend servers or ENIs on each task affecting a VServer group. default: False type: bool vserver_group_id: description: - Virtual server group id. - One of I(vserver_group_name) and I(vserver_group_id) must be specified when operate existing slb group. aliases: ['group_id'] type: str multi_ok: description: - By default the module will not create another Load Balancer if there is another Load Balancer with the same I(name). Specify this as true if you want duplicate Load Balancers created. default: False type: bool requirements: - "python >= 3.6" - "footmark >= 1.19.0" extends_documentation_fragment: - alibaba.alicloud.alicloud author: - "He Guimin (@xiaozhu36)" ''' EXAMPLES = ''' # Note: These examples do not set authentication details, see the Alibaba Cloud Guide for details. - name: Create VServer Group in SLB alibaba.alicloud.ali_slb_vsg: load_balancer_id: 'lb-cnqnc234' name: 'ansible-vsg' - name: Add backend servers to vserver group alibaba.alicloud.ali_slb_vsg: load_balancer_id: 'lb-cnqnc234' name: 'ansible-vsg' backend_servers: - instance_id: 'i-f2n3cn34c' port: 8080 weight: 100 type: ecs - instance_id: 'eni-n34cjf4vd' port: 8081 weight: 100 type: eni - name: Purge backend servers from vserver group alibaba.alicloud.ali_slb_vsg: load_balancer_id: 'lb-cnqnc234' name: 'ansible-vsg' backend_servers: - instance_id: 'eni-f2n3cn34c' port: 8080 weight: 100 type: eni - instance_id: 'eni-n34cjf4vd' port: 8081 weight: 100 type: eni purge_backend_servers: True - name: Delete VServer Group in SLB alibaba.alicloud.ali_slb_vsg: load_balancer_id: 'lb-cnqnc234' name: 'ansible-vsg' state: absent ''' RETURN = ''' vserver_group: description: - info about the virtual server group that was created or deleted. returned: on present type: complex contains: address: description: The IP address of the loal balancer returned: always type: str sample: "47.94.26.126" backend_servers: description: The load balancer's backend servers returned: always type: complex contains: port: description: The backend server port returned: always type: int sample: 22 server_id: description: The backend server id returned: always type: str sample: "i-vqunci342" type: description: The backend server type, ecs or eni returned: always type: str sample: "ecs" weight: description: The backend server weight returned: always type: int sample: 100 id: description: The ID of the virtual server group was created. Same as vserver_group_id. returned: always type: str sample: "rsp-2zehblhcv" vserver_group_id: description: The ID of the virtual server group was created. returned: always type: str sample: "rsp-2zehblhcv" vserver_group_name: description: The name of the virtual server group was created. returned: always type: str sample: "ansible-ali_slb_vsg" name: description: The name of the virtual server group was created. returned: always type: str sample: "ansible-ali_slb_vsg" tags: description: The load balancer tags returned: always type: dict sample: {} ''' from ansible.module_utils.basic import AnsibleModule from ansible_collections.alibaba.alicloud.plugins.module_utils.alicloud_ecs import ecs_argument_spec, slb_connect HAS_FOOTMARK = False try: from footmark.exception import SLBResponseError HAS_FOOTMARK = True except ImportError: HAS_FOOTMARK = False VALID_SERVER_PARAMS = ["server_id", "port", "weight", "type", "server_ids"] def check_backend_servers(module, servers): for s in servers: for key in list(s.keys()): if key not in VALID_SERVER_PARAMS: module.fail_json(msg='Invalid backend server key {0}. Valid keys: {1}.'.format(key, VALID_SERVER_PARAMS)) def parse_server_ids(servers): parse_server = [] if servers: for s in servers: if "server_ids" in s: ids = s.pop("server_ids") for id in ids: server = {"server_id": id} server.update(s) parse_server.append(server) else: parse_server.append(s) return parse_server def format_backend_servers(servers): backend_servers = [] if servers: parse_server = parse_server_ids(servers) for s in parse_server: server = {} for key, value in list(s.items()): split = [] for k in str(key).split("_"): split.append(str.upper(k[0]) + k[1:]) server["".join(split)] = value backend_servers.append(server) return backend_servers def filter_backend_servers(existing, inputting): old = [] new = [] removed = [] existingList = [] inputtingList = [] oldList = [] inputting = parse_server_ids(inputting) for s in existing: existingList.append(s['server_id']) for s in inputting: inputtingList.append(s['server_id']) for s in inputting: if s['server_id'] in existingList: old.append(s) oldList.append([s['server_id']]) continue new.append(s) for s in existing: key = s['server_id'] if key in inputtingList: if key not in oldList: old.append(s) continue removed.append(s) return old, new, removed def main(): argument_spec = ecs_argument_spec() argument_spec.update(dict( state=dict(type='str', default='present', choices=['present', 'absent']), load_balancer_id=dict(type='str', required=True, aliases=['lb_id']), vserver_group_name=dict(type='str', required=True, aliases=['group_name', 'name']), backend_servers=dict(type='list', elements='dict'), vserver_group_id=dict(type='str', aliases=['group_id']), purge_backend_servers=dict(type='bool', default=False), multi_ok=dict(type='bool', default=False) )) module = AnsibleModule(argument_spec=argument_spec, required_if=([ ('state', 'present', ['backend_servers']) ]) ) if HAS_FOOTMARK is False: module.fail_json(msg='footmark required for the module ali_slb_vsg.') slb = slb_connect(module) state = module.params['state'] lb_id = module.params['load_balancer_id'] vsg_name = module.params['vserver_group_name'] vserver_group_id = module.params['vserver_group_id'] changed = False matching = None if not module.params['multi_ok']: try: matching_vsgs = [] for group in slb.describe_vserver_groups(**{'load_balancer_id': lb_id}): if vsg_name and group.name != vsg_name: continue if vserver_group_id and group.id != vserver_group_id: continue matching_vsgs.append(group) if len(matching_vsgs) == 1: matching = matching_vsgs[0] elif len(matching_vsgs) > 1: module.fail_json(msg='Currently there are {0} virtual server groups that have the same name {1}. ' 'If you would like to create anyway ' 'please pass True to the multi_ok param.'.format(len(matching_vsgs), vsg_name)) except Exception as e: module.fail_json(msg=str("Unable to describe vserver group attribute, error:{0}".format(e))) if state == 'absent': if matching: try: changed = matching.delete() except Exception as e: module.fail_json(msg=str("Unable to delete vserver group, error: {0}".format(e))) module.exit_json(changed=changed, vserver_group={}) backend_servers = module.params['backend_servers'] check_backend_servers(module, backend_servers) if not matching: try: params = module.params params['backend_servers'] = format_backend_servers(backend_servers[:20]) matching = slb.create_vserver_group(**params) changed = True except Exception as e: module.fail_json(msg=str("Unable to create vserver group error:{0}".format(e))) if backend_servers: old, new, removed = filter_backend_servers(matching.backend_servers['backend_server'], backend_servers) if old: try: if matching.modify(backend_servers=old): changed = True except Exception as e: module.fail_json(msg='Modify backend servers failed: {0}'.format(e)) if new: try: if matching.add(backend_servers=new): changed = True except Exception as e: module.fail_json(msg='Add backend servers failed: {0}'.format(e)) if module.params['purge_backend_servers'] and removed: try: if matching.remove(backend_servers=removed): changed = True except Exception as e: module.fail_json(msg='Remove backend servers failed: {0}'.format(e)) module.exit_json(changed=changed, vserver_group=matching.get().read()) if __name__ == '__main__': main()