#!/usr/bin/python
#
# Copyright (C) 2019 Huawei
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later

from __future__ import annotations

###############################################################################
# Documentation
###############################################################################

DOCUMENTATION = r"""
module: hwc_vpc_port
description:
  - VPC port management.
short_description: Creates a resource of VPC/Port in Huawei Cloud
version_added: '0.2.0'
author: Huawei Inc. (@huaweicloud)
requirements:
  - keystoneauth1 >= 3.6.0
attributes:
  check_mode:
    support: full
  diff_mode:
    support: none
options:
  state:
    description:
      - Whether the given object should exist in Huawei Cloud.
    type: str
    choices: ['present', 'absent']
    default: 'present'
  timeouts:
    description:
      - The timeouts for each operations.
    type: dict
    default: {}
    suboptions:
      create:
        description:
          - The timeouts for create operation.
        type: str
        default: '15m'
  subnet_id:
    description:
      - Specifies the ID of the subnet to which the port belongs.
    type: str
    required: true
  admin_state_up:
    description:
      - Specifies the administrative state of the port.
    type: bool
  allowed_address_pairs:
    description:
      - Specifies a set of zero or more allowed address pairs.
    type: list
    elements: dict
    suboptions:
      ip_address:
        description:
          - Specifies the IP address. It cannot set it to 0.0.0.0. Configure an independent security group for the port if
            a large CIDR block (subnet mask less than 24) is configured for parameter allowed_address_pairs.
        type: str
      mac_address:
        description:
          - Specifies the MAC address.
        type: str
  extra_dhcp_opts:
    description:
      - Specifies the extended option of DHCP.
    type: list
    elements: dict
    suboptions:
      name:
        description:
          - Specifies the option name.
        type: str
      value:
        description:
          - Specifies the option value.
        type: str
  ip_address:
    description:
      - Specifies the port IP address.
    type: str
  name:
    description:
      - Specifies the port name. The value can contain no more than 255 characters.
    type: str
  security_groups:
    description:
      - Specifies the ID of the security group.
    type: list
    elements: str
extends_documentation_fragment:
  - community.general._hwc
  - community.general._attributes
"""

EXAMPLES = r"""
# create a port
- name: Create vpc
  hwc_network_vpc:
    cidr: "192.168.100.0/24"
    name: "ansible_network_vpc_test"
  register: vpc
- name: Create subnet
  hwc_vpc_subnet:
    gateway_ip: "192.168.100.32"
    name: "ansible_network_subnet_test"
    dhcp_enable: true
    vpc_id: "{{ vpc.id }}"
    cidr: "192.168.100.0/26"
  register: subnet
- name: Create a port
  community.general.hwc_vpc_port:
    subnet_id: "{{ subnet.id }}"
    ip_address: "192.168.100.33"
"""

RETURN = r"""
subnet_id:
  description:
    - Specifies the ID of the subnet to which the port belongs.
  type: str
  returned: success
admin_state_up:
  description:
    - Specifies the administrative state of the port.
  type: bool
  returned: success
allowed_address_pairs:
  description:
    - Specifies a set of zero or more allowed address pairs.
  type: list
  returned: success
  contains:
    ip_address:
      description:
        - Specifies the IP address. It cannot set it to 0.0.0.0. Configure an independent security group for the port if a
          large CIDR block (subnet mask less than 24) is configured for parameter allowed_address_pairs.
      type: str
      returned: success
    mac_address:
      description:
        - Specifies the MAC address.
      type: str
      returned: success
extra_dhcp_opts:
  description:
    - Specifies the extended option of DHCP.
  type: list
  returned: success
  contains:
    name:
      description:
        - Specifies the option name.
      type: str
      returned: success
    value:
      description:
        - Specifies the option value.
      type: str
      returned: success
ip_address:
  description:
    - Specifies the port IP address.
  type: str
  returned: success
name:
  description:
    - Specifies the port name. The value can contain no more than 255 characters.
  type: str
  returned: success
security_groups:
  description:
    - Specifies the ID of the security group.
  type: list
  returned: success
mac_address:
  description:
    - Specifies the port MAC address.
  type: str
  returned: success
"""

from ansible_collections.community.general.plugins.module_utils._hwc_utils import (
    Config,
    HwcClientException,
    HwcClientException404,
    HwcModule,
    are_different_dicts,
    build_path,
    get_region,
    is_empty_value,
    navigate_value,
    wait_to_finish,
)


def build_module():
    return HwcModule(
        argument_spec=dict(
            state=dict(default="present", choices=["present", "absent"], type="str"),
            timeouts=dict(
                type="dict",
                options=dict(
                    create=dict(default="15m", type="str"),
                ),
                default=dict(),
            ),
            subnet_id=dict(type="str", required=True),
            admin_state_up=dict(type="bool"),
            allowed_address_pairs=dict(
                type="list",
                elements="dict",
                options=dict(ip_address=dict(type="str"), mac_address=dict(type="str")),
            ),
            extra_dhcp_opts=dict(
                type="list", elements="dict", options=dict(name=dict(type="str"), value=dict(type="str"))
            ),
            ip_address=dict(type="str"),
            name=dict(type="str"),
            security_groups=dict(type="list", elements="str"),
        ),
        supports_check_mode=True,
    )


def main():
    """Main function"""

    module = build_module()
    config = Config(module, "vpc")

    try:
        resource = None
        if module.params["id"]:
            resource = True
        else:
            v = search_resource(config)
            if len(v) > 1:
                raise Exception(f"Found more than one resource({', '.join([navigate_value(i, ['id']) for i in v])})")

            if len(v) == 1:
                resource = v[0]
                module.params["id"] = navigate_value(resource, ["id"])

        result = {}
        changed = False
        if module.params["state"] == "present":
            if resource is None:
                if not module.check_mode:
                    create(config)
                changed = True

            current = read_resource(config, exclude_output=True)
            expect = user_input_parameters(module)
            if are_different_dicts(expect, current):
                if not module.check_mode:
                    update(config)
                changed = True

            result = read_resource(config)
            result["id"] = module.params.get("id")
        else:
            if resource:
                if not module.check_mode:
                    delete(config)
                changed = True

    except Exception as ex:
        module.fail_json(msg=str(ex))

    else:
        result["changed"] = changed
        module.exit_json(**result)


def user_input_parameters(module):
    return {
        "admin_state_up": module.params.get("admin_state_up"),
        "allowed_address_pairs": module.params.get("allowed_address_pairs"),
        "extra_dhcp_opts": module.params.get("extra_dhcp_opts"),
        "ip_address": module.params.get("ip_address"),
        "name": module.params.get("name"),
        "security_groups": module.params.get("security_groups"),
        "subnet_id": module.params.get("subnet_id"),
    }


def create(config):
    module = config.module
    client = config.client(get_region(module), "vpc", "project")
    timeout = 60 * int(module.params["timeouts"]["create"].rstrip("m"))
    opts = user_input_parameters(module)

    params = build_create_parameters(opts)
    r = send_create_request(module, params, client)
    obj = async_wait_create(config, r, client, timeout)
    module.params["id"] = navigate_value(obj, ["port", "id"])


def update(config):
    module = config.module
    client = config.client(get_region(module), "vpc", "project")
    opts = user_input_parameters(module)

    params = build_update_parameters(opts)
    if params:
        send_update_request(module, params, client)


def delete(config):
    module = config.module
    client = config.client(get_region(module), "vpc", "project")

    send_delete_request(module, None, client)

    url = build_path(module, "ports/{id}")

    def _refresh_status():
        try:
            client.get(url)
        except HwcClientException404:
            return True, "Done"

        except Exception:
            return None, ""

        return True, "Pending"

    timeout = 60 * int(module.params["timeouts"]["create"].rstrip("m"))
    try:
        wait_to_finish(["Done"], ["Pending"], _refresh_status, timeout)
    except Exception as ex:
        module.fail_json(msg=f"module(hwc_vpc_port): error waiting for api(delete) to be done, error= {ex}")


def read_resource(config, exclude_output=False):
    module = config.module
    client = config.client(get_region(module), "vpc", "project")

    res = {}

    r = send_read_request(module, client)
    res["read"] = fill_read_resp_body(r)

    array_index = {
        "read.fixed_ips": 0,
    }

    return update_properties(module, res, array_index, exclude_output)


def _build_query_link(opts):
    query_params = []

    v = navigate_value(opts, ["subnet_id"])
    if v:
        query_params.append(f"network_id={v}")

    v = navigate_value(opts, ["name"])
    if v:
        query_params.append(f"name={v}")

    v = navigate_value(opts, ["admin_state_up"])
    if v:
        query_params.append(f"admin_state_up={v}")

    query_link = "?marker={marker}&limit=10"
    if query_params:
        query_link += f"&{'&'.join(query_params)}"

    return query_link


def search_resource(config):
    module = config.module
    client = config.client(get_region(module), "vpc", "project")
    opts = user_input_parameters(module)
    identity_obj = _build_identity_object(opts)
    query_link = _build_query_link(opts)
    link = f"ports{query_link}"

    result = []
    p = {"marker": ""}
    while True:
        url = link.format(**p)
        r = send_list_request(module, client, url)
        if not r:
            break

        for item in r:
            item = fill_list_resp_body(item)
            if not are_different_dicts(identity_obj, item):
                result.append(item)

        if len(result) > 1:
            break

        p["marker"] = r[-1].get("id")

    return result


def build_create_parameters(opts):
    params = dict()

    v = navigate_value(opts, ["admin_state_up"], None)
    if not is_empty_value(v):
        params["admin_state_up"] = v

    v = expand_create_allowed_address_pairs(opts, None)
    if not is_empty_value(v):
        params["allowed_address_pairs"] = v

    v = expand_create_extra_dhcp_opts(opts, None)
    if not is_empty_value(v):
        params["extra_dhcp_opts"] = v

    v = expand_create_fixed_ips(opts, None)
    if not is_empty_value(v):
        params["fixed_ips"] = v

    v = navigate_value(opts, ["name"], None)
    if not is_empty_value(v):
        params["name"] = v

    v = navigate_value(opts, ["subnet_id"], None)
    if not is_empty_value(v):
        params["network_id"] = v

    v = navigate_value(opts, ["security_groups"], None)
    if not is_empty_value(v):
        params["security_groups"] = v

    if not params:
        return params

    params = {"port": params}

    return params


def expand_create_allowed_address_pairs(d, array_index):
    new_array_index = dict()
    if array_index:
        new_array_index.update(array_index)

    req = []

    v = navigate_value(d, ["allowed_address_pairs"], new_array_index)
    if not v:
        return req
    n = len(v)
    for i in range(n):
        new_array_index["allowed_address_pairs"] = i
        transformed = dict()

        v = navigate_value(d, ["allowed_address_pairs", "ip_address"], new_array_index)
        if not is_empty_value(v):
            transformed["ip_address"] = v

        v = navigate_value(d, ["allowed_address_pairs", "mac_address"], new_array_index)
        if not is_empty_value(v):
            transformed["mac_address"] = v

        if transformed:
            req.append(transformed)

    return req


def expand_create_extra_dhcp_opts(d, array_index):
    new_array_index = dict()
    if array_index:
        new_array_index.update(array_index)

    req = []

    v = navigate_value(d, ["extra_dhcp_opts"], new_array_index)
    if not v:
        return req
    n = len(v)
    for i in range(n):
        new_array_index["extra_dhcp_opts"] = i
        transformed = dict()

        v = navigate_value(d, ["extra_dhcp_opts", "name"], new_array_index)
        if not is_empty_value(v):
            transformed["opt_name"] = v

        v = navigate_value(d, ["extra_dhcp_opts", "value"], new_array_index)
        if not is_empty_value(v):
            transformed["opt_value"] = v

        if transformed:
            req.append(transformed)

    return req


def expand_create_fixed_ips(d, array_index):
    new_array_index = dict()
    if array_index:
        new_array_index.update(array_index)

    req = []

    transformed = dict()

    v = navigate_value(d, ["ip_address"], new_array_index)
    if not is_empty_value(v):
        transformed["ip_address"] = v

    if transformed:
        req.append(transformed)

    return req


def send_create_request(module, params, client):
    url = "ports"
    try:
        r = client.post(url, params)
    except HwcClientException as ex:
        msg = f"module(hwc_vpc_port): error running api(create), error: {ex}"
        module.fail_json(msg=msg)

    return r


def async_wait_create(config, result, client, timeout):
    module = config.module

    path_parameters = {
        "port_id": ["port", "id"],
    }
    data = {key: navigate_value(result, path) for key, path in path_parameters.items()}

    url = build_path(module, "ports/{port_id}", data)

    def _query_status():
        r = None
        try:
            r = client.get(url, timeout=timeout)
        except HwcClientException:
            return None, ""

        try:
            s = navigate_value(r, ["port", "status"])
            return r, s
        except Exception:
            return None, ""

    try:
        return wait_to_finish(["ACTIVE", "DOWN"], ["BUILD"], _query_status, timeout)
    except Exception as ex:
        module.fail_json(msg=f"module(hwc_vpc_port): error waiting for api(create) to be done, error= {ex}")


def build_update_parameters(opts):
    params = dict()

    v = expand_update_allowed_address_pairs(opts, None)
    if v is not None:
        params["allowed_address_pairs"] = v

    v = expand_update_extra_dhcp_opts(opts, None)
    if v is not None:
        params["extra_dhcp_opts"] = v

    v = navigate_value(opts, ["name"], None)
    if not is_empty_value(v):
        params["name"] = v

    v = navigate_value(opts, ["security_groups"], None)
    if not is_empty_value(v):
        params["security_groups"] = v

    if not params:
        return params

    params = {"port": params}

    return params


def expand_update_allowed_address_pairs(d, array_index):
    new_array_index = dict()
    if array_index:
        new_array_index.update(array_index)

    req = []

    v = navigate_value(d, ["allowed_address_pairs"], new_array_index)
    if not v:
        return req
    n = len(v)
    for i in range(n):
        new_array_index["allowed_address_pairs"] = i
        transformed = dict()

        v = navigate_value(d, ["allowed_address_pairs", "ip_address"], new_array_index)
        if not is_empty_value(v):
            transformed["ip_address"] = v

        v = navigate_value(d, ["allowed_address_pairs", "mac_address"], new_array_index)
        if not is_empty_value(v):
            transformed["mac_address"] = v

        if transformed:
            req.append(transformed)

    return req


def expand_update_extra_dhcp_opts(d, array_index):
    new_array_index = dict()
    if array_index:
        new_array_index.update(array_index)

    req = []

    v = navigate_value(d, ["extra_dhcp_opts"], new_array_index)
    if not v:
        return req
    n = len(v)
    for i in range(n):
        new_array_index["extra_dhcp_opts"] = i
        transformed = dict()

        v = navigate_value(d, ["extra_dhcp_opts", "name"], new_array_index)
        if not is_empty_value(v):
            transformed["opt_name"] = v

        v = navigate_value(d, ["extra_dhcp_opts", "value"], new_array_index)
        if not is_empty_value(v):
            transformed["opt_value"] = v

        if transformed:
            req.append(transformed)

    return req


def send_update_request(module, params, client):
    url = build_path(module, "ports/{id}")

    try:
        r = client.put(url, params)
    except HwcClientException as ex:
        msg = f"module(hwc_vpc_port): error running api(update), error: {ex}"
        module.fail_json(msg=msg)

    return r


def send_delete_request(module, params, client):
    url = build_path(module, "ports/{id}")

    try:
        r = client.delete(url, params)
    except HwcClientException as ex:
        msg = f"module(hwc_vpc_port): error running api(delete), error: {ex}"
        module.fail_json(msg=msg)

    return r


def send_read_request(module, client):
    url = build_path(module, "ports/{id}")

    r = None
    try:
        r = client.get(url)
    except HwcClientException as ex:
        msg = f"module(hwc_vpc_port): error running api(read), error: {ex}"
        module.fail_json(msg=msg)

    return navigate_value(r, ["port"], None)


def fill_read_resp_body(body):
    result = dict()

    result["admin_state_up"] = body.get("admin_state_up")

    v = fill_read_resp_allowed_address_pairs(body.get("allowed_address_pairs"))
    result["allowed_address_pairs"] = v

    result["binding_host_id"] = body.get("binding_host_id")

    result["binding_vnic_type"] = body.get("binding_vnic_type")

    result["device_id"] = body.get("device_id")

    result["device_owner"] = body.get("device_owner")

    result["dns_name"] = body.get("dns_name")

    v = fill_read_resp_extra_dhcp_opts(body.get("extra_dhcp_opts"))
    result["extra_dhcp_opts"] = v

    v = fill_read_resp_fixed_ips(body.get("fixed_ips"))
    result["fixed_ips"] = v

    result["id"] = body.get("id")

    result["mac_address"] = body.get("mac_address")

    result["name"] = body.get("name")

    result["network_id"] = body.get("network_id")

    result["security_groups"] = body.get("security_groups")

    result["status"] = body.get("status")

    result["tenant_id"] = body.get("tenant_id")

    return result


def fill_read_resp_allowed_address_pairs(value):
    if not value:
        return None

    result = []
    for item in value:
        val = dict()

        val["ip_address"] = item.get("ip_address")

        val["mac_address"] = item.get("mac_address")

        result.append(val)

    return result


def fill_read_resp_extra_dhcp_opts(value):
    if not value:
        return None

    result = []
    for item in value:
        val = dict()

        val["opt_name"] = item.get("opt_name")

        val["opt_value"] = item.get("opt_value")

        result.append(val)

    return result


def fill_read_resp_fixed_ips(value):
    if not value:
        return None

    result = []
    for item in value:
        val = dict()

        val["ip_address"] = item.get("ip_address")

        result.append(val)

    return result


def update_properties(module, response, array_index, exclude_output=False):
    r = user_input_parameters(module)

    v = navigate_value(response, ["read", "admin_state_up"], array_index)
    r["admin_state_up"] = v

    v = r.get("allowed_address_pairs")
    v = flatten_allowed_address_pairs(response, array_index, v, exclude_output)
    r["allowed_address_pairs"] = v

    v = r.get("extra_dhcp_opts")
    v = flatten_extra_dhcp_opts(response, array_index, v, exclude_output)
    r["extra_dhcp_opts"] = v

    v = navigate_value(response, ["read", "fixed_ips", "ip_address"], array_index)
    r["ip_address"] = v

    if not exclude_output:
        v = navigate_value(response, ["read", "mac_address"], array_index)
        r["mac_address"] = v

    v = navigate_value(response, ["read", "name"], array_index)
    r["name"] = v

    v = navigate_value(response, ["read", "security_groups"], array_index)
    r["security_groups"] = v

    v = navigate_value(response, ["read", "network_id"], array_index)
    r["subnet_id"] = v

    return r


def flatten_allowed_address_pairs(d, array_index, current_value, exclude_output):
    n = 0
    result = current_value
    has_init_value = True
    if result:
        n = len(result)
    else:
        has_init_value = False
        result = []
        v = navigate_value(d, ["read", "allowed_address_pairs"], array_index)
        if not v:
            return current_value
        n = len(v)

    new_array_index = dict()
    if array_index:
        new_array_index.update(array_index)

    for i in range(n):
        new_array_index["read.allowed_address_pairs"] = i

        val = dict()
        if len(result) >= (i + 1) and result[i]:
            val = result[i]

        v = navigate_value(d, ["read", "allowed_address_pairs", "ip_address"], new_array_index)
        val["ip_address"] = v

        v = navigate_value(d, ["read", "allowed_address_pairs", "mac_address"], new_array_index)
        val["mac_address"] = v

        if len(result) >= (i + 1):
            result[i] = val
        else:
            for v in val.values():
                if v is not None:
                    result.append(val)
                    break

    return result if (has_init_value or result) else current_value


def flatten_extra_dhcp_opts(d, array_index, current_value, exclude_output):
    n = 0
    result = current_value
    has_init_value = True
    if result:
        n = len(result)
    else:
        has_init_value = False
        result = []
        v = navigate_value(d, ["read", "extra_dhcp_opts"], array_index)
        if not v:
            return current_value
        n = len(v)

    new_array_index = dict()
    if array_index:
        new_array_index.update(array_index)

    for i in range(n):
        new_array_index["read.extra_dhcp_opts"] = i

        val = dict()
        if len(result) >= (i + 1) and result[i]:
            val = result[i]

        v = navigate_value(d, ["read", "extra_dhcp_opts", "opt_name"], new_array_index)
        val["name"] = v

        v = navigate_value(d, ["read", "extra_dhcp_opts", "opt_value"], new_array_index)
        val["value"] = v

        if len(result) >= (i + 1):
            result[i] = val
        else:
            for v in val.values():
                if v is not None:
                    result.append(val)
                    break

    return result if (has_init_value or result) else current_value


def send_list_request(module, client, url):
    r = None
    try:
        r = client.get(url)
    except HwcClientException as ex:
        msg = f"module(hwc_vpc_port): error running api(list), error: {ex}"
        module.fail_json(msg=msg)

    return navigate_value(r, ["ports"], None)


def _build_identity_object(all_opts):
    result = dict()

    v = navigate_value(all_opts, ["admin_state_up"], None)
    result["admin_state_up"] = v

    v = expand_list_allowed_address_pairs(all_opts, None)
    result["allowed_address_pairs"] = v

    result["binding_host_id"] = None

    result["binding_vnic_type"] = None

    result["device_id"] = None

    result["device_owner"] = None

    result["dns_name"] = None

    v = expand_list_extra_dhcp_opts(all_opts, None)
    result["extra_dhcp_opts"] = v

    v = expand_list_fixed_ips(all_opts, None)
    result["fixed_ips"] = v

    result["id"] = None

    result["mac_address"] = None

    v = navigate_value(all_opts, ["name"], None)
    result["name"] = v

    v = navigate_value(all_opts, ["subnet_id"], None)
    result["network_id"] = v

    v = navigate_value(all_opts, ["security_groups"], None)
    result["security_groups"] = v

    result["status"] = None

    result["tenant_id"] = None

    return result


def expand_list_allowed_address_pairs(d, array_index):
    new_array_index = dict()
    if array_index:
        new_array_index.update(array_index)

    req = []

    v = navigate_value(d, ["allowed_address_pairs"], new_array_index)

    n = len(v) if v else 1
    for i in range(n):
        new_array_index["allowed_address_pairs"] = i
        transformed = dict()

        v = navigate_value(d, ["allowed_address_pairs", "ip_address"], new_array_index)
        transformed["ip_address"] = v

        v = navigate_value(d, ["allowed_address_pairs", "mac_address"], new_array_index)
        transformed["mac_address"] = v

        for v in transformed.values():
            if v is not None:
                req.append(transformed)
                break

    return req if req else None


def expand_list_extra_dhcp_opts(d, array_index):
    new_array_index = dict()
    if array_index:
        new_array_index.update(array_index)

    req = []

    v = navigate_value(d, ["extra_dhcp_opts"], new_array_index)

    n = len(v) if v else 1
    for i in range(n):
        new_array_index["extra_dhcp_opts"] = i
        transformed = dict()

        v = navigate_value(d, ["extra_dhcp_opts", "name"], new_array_index)
        transformed["opt_name"] = v

        v = navigate_value(d, ["extra_dhcp_opts", "value"], new_array_index)
        transformed["opt_value"] = v

        for v in transformed.values():
            if v is not None:
                req.append(transformed)
                break

    return req if req else None


def expand_list_fixed_ips(d, array_index):
    new_array_index = dict()
    if array_index:
        new_array_index.update(array_index)

    req = []

    transformed = dict()

    v = navigate_value(d, ["ip_address"], new_array_index)
    transformed["ip_address"] = v

    for v in transformed.values():
        if v is not None:
            req.append(transformed)
            break

    return req if req else None


def fill_list_resp_body(body):
    result = dict()

    result["admin_state_up"] = body.get("admin_state_up")

    v = fill_list_resp_allowed_address_pairs(body.get("allowed_address_pairs"))
    result["allowed_address_pairs"] = v

    result["binding_host_id"] = body.get("binding_host_id")

    result["binding_vnic_type"] = body.get("binding_vnic_type")

    result["device_id"] = body.get("device_id")

    result["device_owner"] = body.get("device_owner")

    result["dns_name"] = body.get("dns_name")

    v = fill_list_resp_extra_dhcp_opts(body.get("extra_dhcp_opts"))
    result["extra_dhcp_opts"] = v

    v = fill_list_resp_fixed_ips(body.get("fixed_ips"))
    result["fixed_ips"] = v

    result["id"] = body.get("id")

    result["mac_address"] = body.get("mac_address")

    result["name"] = body.get("name")

    result["network_id"] = body.get("network_id")

    result["security_groups"] = body.get("security_groups")

    result["status"] = body.get("status")

    result["tenant_id"] = body.get("tenant_id")

    return result


def fill_list_resp_allowed_address_pairs(value):
    if not value:
        return None

    result = []
    for item in value:
        val = dict()

        val["ip_address"] = item.get("ip_address")

        val["mac_address"] = item.get("mac_address")

        result.append(val)

    return result


def fill_list_resp_extra_dhcp_opts(value):
    if not value:
        return None

    result = []
    for item in value:
        val = dict()

        val["opt_name"] = item.get("opt_name")

        val["opt_value"] = item.get("opt_value")

        result.append(val)

    return result


def fill_list_resp_fixed_ips(value):
    if not value:
        return None

    result = []
    for item in value:
        val = dict()

        val["ip_address"] = item.get("ip_address")

        result.append(val)

    return result


if __name__ == "__main__":
    main()
