diff --git a/meta/runtime.yml b/meta/runtime.yml index 42762b2..64adf4c 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -127,6 +127,7 @@ action_groups: dhcp: - ansibleguy.opnsense.dhcp_reservation - ansibleguy.opnsense.dhcp_controlagent + - ansibleguy.opnsense.dhcp_subnet acme: - ansibleguy.opnsense.acme_general - ansibleguy.opnsense.acme_account diff --git a/plugins/module_utils/main/dhcp_subnet_v4.py b/plugins/module_utils/main/dhcp_subnet_v4.py new file mode 100644 index 0000000..0df85ca --- /dev/null +++ b/plugins/module_utils/main/dhcp_subnet_v4.py @@ -0,0 +1,46 @@ +from ansible.module_utils.basic import AnsibleModule + +from ansible_collections.ansibleguy.opnsense.plugins.module_utils.base.api import \ + Session +from ansible_collections.ansibleguy.opnsense.plugins.module_utils.helper.main import \ + is_ip, is_network, is_unset +from ansible_collections.ansibleguy.opnsense.plugins.module_utils.base.cls import BaseModule + +class SubnetV4(BaseModule): + FIELD_ID = 'subnet' + CMDS = { + 'add': 'addSubnet', + 'del': 'delSubnet', + 'set': 'setSubnet', + 'search': 'searchSubnet', + 'detail': 'getSubnet', + } + API_KEY_PATH = 'subnet4' + API_MOD = 'kea' + API_CONT = 'dhcpv4' + API_CONT_REL = 'service' + FIELDS_CHANGE = [ + 'subnet', 'description', 'pools' + ] + FIELDS_ALL = [FIELD_ID] + FIELDS_ALL.extend(FIELDS_CHANGE) + FIELDS_TYPING = {} + FIELDS_TRANSLATE = {} + EXIST_ATTR = 'subnet' + + def __init__(self, module: AnsibleModule, result: dict, session: Session = None): + BaseModule.__init__(self=self, m=module, r=result, s=session) + self.subnet = {} + self.existing_subnets = None + + def check(self) -> None: + if self.p['state'] == 'present': + if is_unset(self.p['subnet']): + self.m.fail_json( + "You need to provide the 'subnet' you want to create. E.g. (192.168.1.0/24)!" + ) + + if is_unset(self.p['pools']): + self.m.fail_json("You need to provide the IP 'pools' to be used in the subnet!") + + self._base_check() diff --git a/plugins/modules/dhcp_subnet.py b/plugins/modules/dhcp_subnet.py new file mode 100644 index 0000000..6df320c --- /dev/null +++ b/plugins/modules/dhcp_subnet.py @@ -0,0 +1,60 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (C) 2024, AnsibleGuy +# GNU General Public License v3.0+ (see https://www.gnu.org/licenses/gpl-3.0.txt) + +# see: https://docs.opnsense.org/development/api/core/kea.html + +from ansible.module_utils.basic import AnsibleModule + +from ansible_collections.ansibleguy.opnsense.plugins.module_utils.base.handler import \ + module_dependency_error, MODULE_EXCEPTIONS + +try: + from ansible_collections.ansibleguy.opnsense.plugins.module_utils.helper.wrapper import module_wrapper + from ansible_collections.ansibleguy.opnsense.plugins.module_utils.defaults.main import \ + OPN_MOD_ARGS, STATE_MOD_ARG, RELOAD_MOD_ARG + from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.dhcp_subnet_v4 import SubnetV4 + +except MODULE_EXCEPTIONS: + module_dependency_error() + + +# DOCUMENTATION = 'https://opnsense.ansibleguy.net/modules/dhcp.html' +# EXAMPLES = 'https://opnsense.ansibleguy.net/modules/dhcp.html' + + +def run_module(): + module_args = dict( + subnet=dict(type='str', required=True, description='Subnet to create'), + description=dict(type='str', required=False), + pools=dict(type='str', required=True, description='IP address pools to offer in the subnet'), + **RELOAD_MOD_ARG, + **STATE_MOD_ARG, + **OPN_MOD_ARGS, + ) + + result = dict( + changed=False, + diff={ + 'before': {}, + 'after': {}, + } + ) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=True, + ) + + module_wrapper(SubnetV4(module=module, result=result)) + module.exit_json(**result) + + +def main(): + run_module() + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/list.py b/plugins/modules/list.py index 1aa02c5..92e7d17 100644 --- a/plugins/modules/list.py +++ b/plugins/modules/list.py @@ -36,7 +36,7 @@ 'ipsec_child', 'ipsec_vti', 'ipsec_auth_local', 'ipsec_auth_remote', 'frr_general', 'unbound_general', 'unbound_acl', 'ids_general', 'ids_policy', 'ids_rule', 'ids_ruleset', 'ids_user_rule', 'ids_policy_rule', 'openvpn_instance', 'openvpn_static_key', 'openvpn_client_override', 'dhcrelay_destination', 'dhcrelay_relay', - 'interface_lagg', 'interface_loopback', 'unbound_dnsbl', 'dhcp_reservation', 'acme_general', 'acme_account', + 'interface_lagg', 'interface_loopback', 'unbound_dnsbl', 'dhcp_reservation', 'dhcp_subnet', 'acme_general', 'acme_account', 'acme_validation', 'acme_action', 'acme_certificate', ] @@ -419,6 +419,11 @@ def run_module(): from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.acme_certificate import \ Certificate as Target_Obj + elif target == 'dhcp_subnet': + from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.dhcp_subnet_v4 import \ + SubnetV4 as Target_Obj + + except AttributeError: module_dependency_error()