diff --git a/meta/runtime.yml b/meta/runtime.yml index 9429691f..8e956f00 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -31,6 +31,7 @@ action_groups: - ipam_ip_space_info - ipam_subnet - ipam_subnet_info + - ipam_next_available_subnet_info - ipam_address_block - ipam_address_block_info - ipam_range diff --git a/plugins/modules/ipam_next_available_subnet_info.py b/plugins/modules/ipam_next_available_subnet_info.py new file mode 100644 index 00000000..449c9c9c --- /dev/null +++ b/plugins/modules/ipam_next_available_subnet_info.py @@ -0,0 +1,149 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: Infoblox Inc. +# 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 + +DOCUMENTATION = r""" +--- +module: ipam_next_available_subnet_info +short_description: Retrieves the Next available subnet +description: + - Retrieves the Next Available Subnet in the specified Address Block +version_added: 2.0.0 +author: Infoblox Inc. (@infobloxopen) +options: + id: + description: + - An application specific resource identity of a resource + type: str + required: true + cidr: + description: + - The cidr value of address blocks to be created. + type: int + required: true + count: + description: + - Number of address blocks to generate. Default 1 if not set. + type: int + required: false + +extends_documentation_fragment: + - infoblox.bloxone.common +""" # noqa: E501 + +EXAMPLES = r""" + - name: "Create an IP Space (required as parent)" + infoblox.bloxone.ipam_ip_space: + name: "example-ipspace" + state: "present" + register: ip_space + + - name: "Create an Address Block (required as parent)" + infoblox.bloxone.ipam_address_block: + address: "10.0.0.0/16" + space: "{{ ip_space.id }}" + state: "present" + register: address_block + + - name: "Get information about the Subnet" + infoblox.bloxone.ipam_next_available_subnet_info: + id: "{{ address_block.id }}" + cidr: 24 + + - name: "Get information about the Subnet with count" + infoblox.bloxone.ipam_next_available_subnet_info: + id: "{{ address_block.id }}" + cidr: 24 + count: 5 + +""" + +RETURN = r""" +id: + description: + - ID of the Subnet object + type: str + returned: Always +objects: + description: + - List of next available subnet addresses + type: list + elements: str + returned: Always +""" # noqa: E501 + +from ansible_collections.infoblox.bloxone.plugins.module_utils.modules import BloxoneAnsibleModule + +try: + from ipam import AddressBlockApi + from universal_ddi_client import ApiException +except ImportError: + pass # Handled by BloxoneAnsibleModule + + +class NextAvailableSubnetInfoModule(BloxoneAnsibleModule): + def __init__(self, *args, **kwargs): + super(NextAvailableSubnetInfoModule, self).__init__(*args, **kwargs) + self._existing = None + self._limit = 1000 + + def find(self): + all_results = [] + offset = 0 + + while True: + try: + resp = AddressBlockApi(self.client).list_next_available_subnet( + id=self.params["id"], cidr=self.params["cidr"], count=self.params["count"] + ) + all_results.extend(resp.results) + + if len(resp.results) < self._limit: + break + offset += self._limit + + except ApiException as e: + self.fail_json(msg=f"Failed to execute command: {e.status} {e.reason} {e.body}") + + return all_results + + def run_command(self): + result = dict(objects=[]) + + if self.check_mode: + self.exit_json(**result) + + find_results = self.find() + + all_results = [] + for r in find_results: + # The expected output is a list of addresses as strings. + # Therefore, we extract only the 'address' field from each object in the results. + all_results.append(r.address) + + result["objects"] = all_results + self.exit_json(**result) + + +def main(): + # define available arguments/parameters a user can pass to the module + module_args = dict( + id=dict(type="str", required=True), + cidr=dict(type="int", required=True), + count=dict(type="int", required=False), + ) + + module = NextAvailableSubnetInfoModule( + argument_spec=module_args, + supports_check_mode=True, + ) + module.run_command() + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/ipam_subnet.py b/plugins/modules/ipam_subnet.py index 4ba84c0d..bd51daf2 100644 --- a/plugins/modules/ipam_subnet.py +++ b/plugins/modules/ipam_subnet.py @@ -13,6 +13,7 @@ short_description: Manage Subnet description: - Manage Subnet + - The Subnet object represents a set of addresses from which addresses are assigned to network equipment interfaces. version_added: 2.0.0 author: Infoblox Inc. (@infobloxopen) options: @@ -76,7 +77,8 @@ - "The minimum percentage of addresses that must be available outside of the DHCP ranges and fixed addresses when making a suggested change.." type: int reenable_date: - description: "" + description: + - "The date at which notifications will be re-enabled automatically." type: str cidr: description: @@ -744,28 +746,40 @@ description: - "The low threshold value for the percentage of used IP addresses relative to the total IP addresses available in the scope of the object. Thresholds are inclusive in the comparison test." type: int + next_available_id: + description: + - "The resource identifier for the address block where the next available subnet should be generated." + type: str extends_documentation_fragment: - infoblox.bloxone.common """ # noqa: E501 EXAMPLES = r""" - - name: "Create an ip space" + - name: "Create an IP Space (required as parent)" infoblox.bloxone.ipam_ip_space: - name: "my-ip-space" + name: "example-ipspace" state: "present" register: ip_space + - name: "Create an Address Block (required as parent)" + infoblox.bloxone.ipam_address_block: + address: "10.0.0.0/16" + space: "{{ ip_space.id }}" + state: "present" + register: address_block + - name: "Create a subnet" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" space: "{{ ip_space.id }}" state: "present" - - name: "Create a subnet with dhcp_config overridden" + - name: "Create a subnet with Additional Fields" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" space: "{{ ip_space_id }}" + tags: [location: "site1" ] state: "present" dhcp_config: abandoned_reclaim_time: 3600 @@ -797,6 +811,13 @@ lease_time_v6: action: inherit + - name: "Create a Next available Subnet" + infoblox.bloxone.ipam_subnet: + cidr: 24 + next_available_id: "{{ address_block.id }}" + space: "{{ ip_space.id }}" + state: "present" + - name: "Delete a subnet" infoblox.bloxone.ipam_subnet: address: "10.0.0.0" @@ -874,7 +895,8 @@ type: int returned: Always reenable_date: - description: "" + description: + - "The date at which notifications will be re-enabled automatically." type: str returned: Always asm_scope_flag: @@ -2368,23 +2390,28 @@ returned: Always contains: abandoned: - description: "" + description: + - "The number of IP addresses in the scope of the object which are in the abandoned state (issued by a DHCP server and then declined by the client)." type: str returned: Always dynamic: - description: "" + description: + - "The number of IP addresses handed out by DHCP in the scope of the object. This includes all leased addresses, fixed addresses that are defined but not currently leased and abandoned leases." type: str returned: Always static: - description: "" + description: + - "The number of defined IP addresses such as reservations or DNS records. It can be computed as _static_ = _used_ - _dynamic_." type: str returned: Always total: - description: "" + description: + - "The total number of IP addresses available in the scope of the object." type: str returned: Always used: - description: "" + description: + - "The number of IP addresses used in the scope of the object." type: str returned: Always """ # noqa: E501 @@ -2402,11 +2429,13 @@ class SubnetModule(BloxoneAnsibleModule): def __init__(self, *args, **kwargs): super(SubnetModule, self).__init__(*args, **kwargs) - if "/" in self.params["address"]: - self.params["address"], netmask = self.params["address"].split("/") - self.params["cidr"] = int(netmask) + self.next_available_id = self.params.get("next_available_id") + if self.params["address"] is not None: + if "/" in self.params["address"]: + self.params["address"], netmask = self.params["address"].split("/") + self.params["cidr"] = int(netmask) - exclude = ["state", "csp_url", "api_key", "portal_url", "portal_key", "id"] + exclude = ["state", "csp_url", "api_key", "portal_url", "portal_key", "id", "next_available_id"] self._payload_params = {k: v for k, v in self.params.items() if v is not None and k not in exclude} self._payload = Subnet.from_dict(self._payload_params) @@ -2451,6 +2480,9 @@ def find(self): return None raise e else: + if self.params["address"] is None: + return None + filter = f"address=='{self.params['address']}' and space=='{self.params['space']}' and cidr=={self.params['cidr']}" resp = SubnetApi(self.client).list(filter=filter, inherit="full") if len(resp.results) == 1: @@ -2464,6 +2496,9 @@ def create(self): if self.check_mode: return None + if self.next_available_id is not None: + naId = f"{self.next_available_id}/nextavailablesubnet" + self._payload.address = naId resp = SubnetApi(self.client).create(body=self.payload, inherit="full") return resp.result.model_dump(by_alias=True, exclude_none=True) @@ -2528,6 +2563,7 @@ def main(): id=dict(type="str", required=False), state=dict(type="str", required=False, choices=["present", "absent"], default="present"), address=dict(type="str"), + next_available_id=dict(type="str", required=False), asm_config=dict( type="dict", options=dict( @@ -2822,7 +2858,10 @@ def main(): module = SubnetModule( argument_spec=module_args, supports_check_mode=True, - required_if=[("state", "present", ["address", "space"])], + mutually_exclusive=[["address", "next_available_id"]], + required_if=[("state", "present", ["space"])], + required_one_of=[["address", "next_available_id"]], + required_by={"next_available_id": "cidr"}, ) module.run_command() diff --git a/plugins/modules/ipam_subnet_info.py b/plugins/modules/ipam_subnet_info.py index 80420f78..9461e118 100644 --- a/plugins/modules/ipam_subnet_info.py +++ b/plugins/modules/ipam_subnet_info.py @@ -10,9 +10,10 @@ DOCUMENTATION = r""" --- module: ipam_subnet_info -short_description: Manage Subnet +short_description: Retrieve a Subnet description: - - Manage Subnet + - Retrieves information about existing Subnets. + - The Subnet object represents a set of addresses from which addresses are assigned to network equipment interfaces. version_added: 2.0.0 author: Infoblox Inc. (@infobloxopen) options: @@ -146,7 +147,8 @@ type: int returned: Always reenable_date: - description: "" + description: + - "The date at which notifications will be re-enabled automatically." type: str returned: Always asm_scope_flag: @@ -1652,23 +1654,28 @@ returned: Always contains: abandoned: - description: "" + description: + - "The number of IP addresses in the scope of the object which are in the abandoned state (issued by a DHCP server and then declined by the client)." type: str returned: Always dynamic: - description: "" + description: + - "The number of IP addresses handed out by DHCP in the scope of the object. This includes all leased addresses, fixed addresses that are defined but not currently leased and abandoned leases." type: str returned: Always static: - description: "" + description: + - "The number of defined IP addresses such as reservations or DNS records. It can be computed as _static_ = _used_ - _dynamic_." type: str returned: Always total: - description: "" + description: + - "The total number of IP addresses available in the scope of the object." type: str returned: Always used: - description: "" + description: + - "The number of IP addresses used in the scope of the object." type: str returned: Always """ # noqa: E501 diff --git a/tests/integration/targets/ipam_next_available_subnet_info/meta/main.yml b/tests/integration/targets/ipam_next_available_subnet_info/meta/main.yml new file mode 100644 index 00000000..22868b1d --- /dev/null +++ b/tests/integration/targets/ipam_next_available_subnet_info/meta/main.yml @@ -0,0 +1,2 @@ +--- +dependencies: [setup_ip_space, setup_address_block] diff --git a/tests/integration/targets/ipam_next_available_subnet_info/tasks/main.yml b/tests/integration/targets/ipam_next_available_subnet_info/tasks/main.yml new file mode 100644 index 00000000..83a1560d --- /dev/null +++ b/tests/integration/targets/ipam_next_available_subnet_info/tasks/main.yml @@ -0,0 +1,37 @@ +--- +- module_defaults: + group/infoblox.bloxone.all: + portal_url: "{{ portal_url }}" + portal_key: "{{ portal_key }}" + block: + # Create a random IP space name to avoid conflicts + - ansible.builtin.set_fact: + tag_value: "site-{{ 999999 | random | string }}" + + - name: "Get information about the next available Subnet" + infoblox.bloxone.ipam_next_available_subnet_info: + id: "{{ _address_block.id }}" + cidr: 24 + register: subnet_info + - assert: + that: + - subnet_info is not failed + - subnet_info.objects | length == 1 + + - name: "Get information about the next available Subnet with count" + infoblox.bloxone.ipam_next_available_subnet_info: + id: "{{ _address_block.id }}" + cidr: 24 + count: 5 + register: subnet_info + - assert: + that: + - subnet_info is not failed + - subnet_info.objects | length == 5 + + always: + # Cleanup if the test fails + - name: "Delete IP Space" + ansible.builtin.include_role: + name: setup_ip_space + tasks_from: cleanup.yml diff --git a/tests/integration/targets/ipam_subnet/meta/main.yml b/tests/integration/targets/ipam_subnet/meta/main.yml new file mode 100644 index 00000000..22868b1d --- /dev/null +++ b/tests/integration/targets/ipam_subnet/meta/main.yml @@ -0,0 +1,2 @@ +--- +dependencies: [setup_ip_space, setup_address_block] diff --git a/tests/integration/targets/ipam_subnet/tasks/main.yml b/tests/integration/targets/ipam_subnet/tasks/main.yml index 1d61213b..29594f01 100644 --- a/tests/integration/targets/ipam_subnet/tasks/main.yml +++ b/tests/integration/targets/ipam_subnet/tasks/main.yml @@ -6,20 +6,12 @@ block: # Create a random IP space name to avoid conflicts - ansible.builtin.set_fact: - name: "test-ip-space-{{ 999999 | random | string }}" tag_value: "site-{{ 999999 | random | string }}" - # Basic tests for Subnet - - name: "Create an IP space" - infoblox.bloxone.ipam_ip_space: - name: "{{ name }}" - state: "present" - register: ip_space - - name: "Create a Subnet (check mode)" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" check_mode: true register: subnet @@ -27,7 +19,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -39,14 +31,14 @@ - name: "Create a Subnet" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" register: subnet - name: Get information about the Subnet infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -59,7 +51,7 @@ - name: "Create a Subnet (idempotent)" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" register: subnet - assert: @@ -70,7 +62,7 @@ - name: "Delete a Subnet (check mode)" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "absent" check_mode: true register: subnet @@ -78,7 +70,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -90,14 +82,14 @@ - name: "Delete a Subnet" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "absent" register: subnet - name: Get information about the Subnet infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -109,7 +101,7 @@ - name: "Delete a Subnet (idempotent)" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "absent" register: subnet - assert: @@ -120,7 +112,7 @@ - name: "Create a Subnet with ASM config overridden" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" asm_config: asm_threshold: 70 @@ -154,7 +146,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -169,7 +161,7 @@ - name: "Create a Subnet with comment" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" comment: "Comment." register: subnet @@ -177,7 +169,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -189,7 +181,7 @@ - name: "Create a Subnet with ddns_client_update set to server" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" ddns_client_update: "server" register: subnet @@ -197,7 +189,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -209,7 +201,7 @@ - name: "Create a Subnet with ddns_conflict_resolution_mode set to no_check_with_dhcid" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" ddns_conflict_resolution_mode: "no_check_with_dhcid" register: subnet @@ -217,7 +209,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -229,7 +221,7 @@ - name: "Create a Subnet with ddns_domain set to non empty" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" ddns_domain: "abc" register: subnet @@ -237,7 +229,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -249,7 +241,7 @@ - name: "Create a Subnet with ddns_generate_name set to true" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" ddns_generate_name: "true" register: subnet @@ -257,7 +249,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -269,7 +261,7 @@ - name: "Create a Subnet with ddns_send_updates set to false" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" ddns_send_updates: "false" register: subnet @@ -277,7 +269,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -289,7 +281,7 @@ - name: "Create a Subnet with ddns_update_on_renew set to true" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" ddns_update_on_renew: "true" register: subnet @@ -297,7 +289,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -306,31 +298,30 @@ - subnet_info.objects | length == 1 - subnet_info.objects[0].ddns_update_on_renew == true -# Skip this due to backend bug NORTHSTAR-12587 -# - name: "Create a Subnet with ddns_ttl_percent set to 25" -# infoblox.bloxone.ipam_subnet: -# address: "10.0.0.0/24" -# space: "{{ ip_space.id }}" -# state: "present" -# ddns_ttl_percent: 25.0 -# register: subnet -# - name: Get information about the Subnet -# infoblox.bloxone.ipam_subnet_info: -# filters: -# address: "10.0.0.0" -# space: "{{ ip_space.id }}" -# cidr: 24 -# register: subnet_info -# - assert: -# that: -# - subnet is not failed -# - subnet_info.objects | length == 1 -# - subnet_info.objects[0].ddns_ttl_percent == 25.0 + - name: "Create a Subnet with ddns_ttl_percent set to 25" + infoblox.bloxone.ipam_subnet: + address: "10.0.0.0/24" + space: "{{ _ip_space.id }}" + state: "present" + ddns_ttl_percent: 25.0 + register: subnet + - name: Get information about the Subnet + infoblox.bloxone.ipam_subnet_info: + filters: + address: "10.0.0.0" + space: "{{ _ip_space.id }}" + cidr: 24 + register: subnet_info + - assert: + that: + - subnet is not failed + - subnet_info.objects | length == 1 + - subnet_info.objects[0].ddns_ttl_percent == 25.0 - name: "Create a Subnet with ddns_use_conflict_resolution set to false" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" ddns_use_conflict_resolution: "false" register: subnet @@ -338,7 +329,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -350,7 +341,7 @@ - name: "Create a Subnet with DHCP config overridden" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" dhcp_config: lease_time: 3600 inheritance_sources: @@ -385,7 +376,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -398,7 +389,7 @@ - name: "Create a Subnet with DHCP disabled" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" disable_dhcp: "true" register: subnet @@ -406,7 +397,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -418,7 +409,7 @@ - name: "Create a Subnet with hostname_rewrite_enabled set to true" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" hostname_rewrite_enabled: "true" register: subnet @@ -426,7 +417,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -438,7 +429,7 @@ - name: "Create a Subnet with rebind_time set to 60 and renew_time set to 50" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" rebind_time: 60 renew_time: 50 @@ -447,7 +438,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -460,7 +451,7 @@ - name: "Create a Subnet with tags" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" tags: location: "{{ tag_value }}" state: "present" @@ -469,7 +460,7 @@ infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -482,14 +473,14 @@ infoblox.bloxone.ipam_subnet: address: "10.0.0.0" cidr: 24 - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" state: "present" register: subnet - name: Get information about the Subnet infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -499,10 +490,26 @@ - subnet_info.objects[0].id == subnet.id - subnet_info.objects[0].cidr == 24 + - name: "Create a Next available Subnet inside an Address Block" + infoblox.bloxone.ipam_subnet: + cidr: 24 + next_available_id: "{{ _address_block.id }}" + space: "{{ _ip_space.id }}" + state: "present" + register: next_available_subnet + - name: Get information about the Subnet + infoblox.bloxone.ipam_subnet_info: + id: "{{ next_available_subnet.id }}" + register: next_available_subnet_info + - assert: + that: + - next_available_subnet is changed + - next_available_subnet is not failed + - next_available_subnet_info.objects | length == 1 + always: # Cleanup if the test fails - name: "Delete IP Space" - infoblox.bloxone.ipam_ip_space: - name: "{{ name }}" - state: "absent" - ignore_errors: true + ansible.builtin.include_role: + name: setup_ip_space + tasks_from: cleanup.yml diff --git a/tests/integration/targets/ipam_subnet_info/meta/main.yml b/tests/integration/targets/ipam_subnet_info/meta/main.yml new file mode 100644 index 00000000..32c7cbc6 --- /dev/null +++ b/tests/integration/targets/ipam_subnet_info/meta/main.yml @@ -0,0 +1,2 @@ +--- +dependencies: [setup_ip_space] diff --git a/tests/integration/targets/ipam_subnet_info/tasks/main.yml b/tests/integration/targets/ipam_subnet_info/tasks/main.yml index 4cb1e1f1..c11e55a9 100644 --- a/tests/integration/targets/ipam_subnet_info/tasks/main.yml +++ b/tests/integration/targets/ipam_subnet_info/tasks/main.yml @@ -6,19 +6,12 @@ block: # Create a random IP space name to avoid conflicts - ansible.builtin.set_fact: - name: "test-ip-space-{{ 999999 | random | string }}" tag_value: "site-{{ 999999 | random | string }}" - - name: "Create an IP space" - infoblox.bloxone.ipam_ip_space: - name: "{{ name }}" - state: "present" - register: ip_space - - name: "Create a Subnet" infoblox.bloxone.ipam_subnet: address: "10.0.0.0/24" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" tags: location: "{{ tag_value }}" state: "present" @@ -32,12 +25,13 @@ that: - subnet_info.objects | length == 1 - subnet_info.objects[0].name == subnet.object.name + - subnet_info.objects[0].id == subnet.id - name: Get Subnet information by filters infoblox.bloxone.ipam_subnet_info: filters: address: "10.0.0.0" - space: "{{ ip_space.id }}" + space: "{{ _ip_space.id }}" cidr: 24 register: subnet_info - assert: @@ -47,7 +41,7 @@ - name: Get Subnet information by filter query infoblox.bloxone.ipam_subnet_info: - filter_query: "address=='10.0.0.0' and space=='{{ ip_space.id }}' and cidr==24" + filter_query: "address=='10.0.0.0' and space=='{{ _ip_space.id }}' and cidr==24" register: subnet_info - assert: that: @@ -66,14 +60,7 @@ always: # Cleanup if the test fails - - name: "Delete Subnet" - infoblox.bloxone.ipam_subnet: - address: "10.0.0.0/24" - space: "{{ ip_space.id }}" - state: "absent" - ignore_errors: true - name: "Delete IP Space" - infoblox.bloxone.ipam_ip_space: - name: "{{ name }}" - state: "absent" - ignore_errors: true + ansible.builtin.include_role: + name: setup_ip_space + tasks_from: cleanup.yml