#!/usr/bin/python
# Copyright (c) 2017-present Alibaba Group Holding Limited. He Guimin <heguimin36@163.com.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
#  This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see http://www.gnu.org/licenses/.


__metaclass__ = type

ANSIBLE_METADATA = {'metadata_version': '1.1',
                    'status': ['preview'],
                    'supported_by': 'community'}

DOCUMENTATION = """
---
module: ali_slb_server_facts
version_added: "1.5.0"
short_description: Gather facts on backend server of Alibaba Cloud SLB.
description:
     - This module fetches data from the Open API in Alicloud.
       The module must be called from within the SLB backend server itself.
options:    
    load_balancer_id:
      description:
        - ID of server load balancer.
      required: true
      aliases: [ "lb_id" ]
    listener_ports:
      description:
        - A list of backend server listening ports.
      aliases: [ "ports" ]
author:
    - "He Guimin (@xiaozhu36)"
requirements:
    - "python >= 2.6"
    - "footmark"
extends_documentation_fragment:
    - alicloud
"""

EXAMPLES = '''
# Fetch backend server health status details according to setting different filters
- name: fetch backend server health status in the specified region
  hosts: localhost
  connection: local
  vars:
    alicloud_access_key: <your-alicloud-access-key-id>
    alicloud_secret_key: <your-alicloud-access-secret-key>
    alicloud_region: cn-beijing
    load_balancer_id: lb-dj1e5kwh41n87vkn1pxn5
    ports:
      - 100
      - 90
  tasks:
    - name: Find all backend server health status in specified region
      ali_slb_server_facts:
        alicloud_access_key: '{{ alicloud_access_key }}'
        alicloud_secret_key: '{{ alicloud_secret_key }}'
        alicloud_region: '{{ alicloud_region }}'
        load_balancer_id: '{{ load_balancer_id }}'
      register: all_backend_server
    - debug: var=all_backend_server

    - name: Find all backend server health status based on specified port no.
      ali_slb_server_facts:
        alicloud_access_key: '{{ alicloud_access_key }}'
        alicloud_secret_key: '{{ alicloud_secret_key }}'
        alicloud_region: '{{ alicloud_region }}'
        load_balancer_id: '{{ load_balancer_id }}'
        listener_ports: '{{ ports }}'
      register: backend_servera_by_ports
    - debug: var=backend_servera_by_ports
'''

RETURN = '''
load_balancer_id:
    description: ID of the load balancer.
    returned: when success
    type: string
    sample: "lb-dj1jywbux1zslfna6pvnv"
"backend_servers":
    description: Details about the backened-servers that were added.
    returned: when success
    type: list
    sample: [
        {
            "id": "i-2ze35dldjc05dcvezgwk",
            "listener_port": 80,
            "port": 80,
            "server_health_status": "unavailable"
        },
        {
            "id": "i-2ze35dldjc05dcvezgwk",
            "listener_port": 8080,
            "port": 8080,
            "server_health_status": "unavailable"
        },
        {
            "id": "i-2ze35dldjc05dcvezgwk",
            "listener_port": 8085,
            "port": 8085,
            "server_health_status": "unavailable"
        }
    ]
'''

import time
import sys
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.alicloud_ecs import get_acs_connection_info, ecs_argument_spec, slb_connect

try:
    from footmark.exception import SLBResponseError

    HAS_FOOTMARK = True
except ImportError:
    HAS_FOOTMARK = False


def get_info(backend_server):
    """
    get info from backend server object
    :param backend_server: backend server object
    :return: info of backend server
    """
    return {
        'id': backend_server.server_id,
        'port': backend_server.port,
        'listener_port': backend_server.listener_port,
        'server_health_status': backend_server.server_health_status,
    }


def main():
    argument_spec = ecs_argument_spec()
    argument_spec.update(dict(
        load_balancer_id=dict(required=True, aliases=['lb_id']),
        listener_ports=dict(type='list', aliases=['ports']),
    ))

    module = AnsibleModule(argument_spec=argument_spec)

    if HAS_FOOTMARK is False:
        module.fail_json(msg="Package 'footmark' required for this module.")

    load_balancer_id = module.params['load_balancer_id']
    ports = module.params['listener_ports']
    result = []

    if ports and (not isinstance(ports, list) or len(ports)) < 1:
        module.fail_json(msg='backend_server_ports should be a list of backend server ports, aborting')

    try:
        slb = slb_connect(module)

        # check whether server load balancer exist or not
        laod_balancer = slb.describe_load_balancers(load_balancer_id=load_balancer_id)
        if laod_balancer and len(laod_balancer) == 1:
            if ports:
                # list slb servers by port no.
                for port in ports:
                    for backend_server in slb.describe_backend_servers_health_status(
                            load_balancer_id=load_balancer_id, port=port):
                        result.append(get_info(backend_server))

            else:
                # list all slb servers
                for backend_server in slb.describe_backend_servers_health_status(load_balancer_id=load_balancer_id):
                    result.append(get_info(backend_server))

            module.exit_json(changed=False, load_balancer_id=load_balancer_id, backend_servers=result)

        else:
            module.fail_json(msg="Unable to list slb backend server health status, invalid load balancer id")
    except Exception as e:
        module.fail_json(msg="Unable to list slb backend server health status, and got an error: {0}.".format(e))


if __name__ == '__main__':
    main()
