From 2ba9b640780e52f42f1fd09817ce34ab3a949142 Mon Sep 17 00:00:00 2001 From: "Kalle M. Aagaard" Date: Mon, 4 Nov 2024 15:39:43 +0100 Subject: [PATCH 1/4] Added DHCP Controlagent first draft --- README.md | 1 + docs/source/modules/dhcp.rst | 44 +++++++++++++ meta/runtime.yml | 1 + .../module_utils/main/dhcp_controlagent.py | 44 +++++++++++++ plugins/modules/dhcp_controlagent.py | 66 +++++++++++++++++++ scripts/test.sh | 1 + tests/cleanup.yml | 6 ++ tests/dhcp_controlagent.yml | 64 ++++++++++++++++++ 8 files changed, 227 insertions(+) create mode 100644 plugins/module_utils/main/dhcp_controlagent.py create mode 100644 plugins/modules/dhcp_controlagent.py create mode 100644 tests/dhcp_controlagent.yml diff --git a/README.md b/README.md index 5ca98d4..ca892b0 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,7 @@ not implemented => development => [testing](https://github.com/ansibleguy/collec | **DHCP Relay** | ansibleguy.opnsense.dhcrelay | [Docs](https://opnsense.ansibleguy.net/en/latest/modules/dhcrelay_relay.html) | unstable | | **DHCP Relay** | ansibleguy.opnsense.dhcrelay_destination | [Docs](https://opnsense.ansibleguy.net/en/latest/modules/dhcrelay_destination.html) | unstable | | **DHCP Reservation** | ansibleguy.opnsense.dhcp_reservation | [Docs](https://opnsense.ansibleguy.net/en/latest/modules/dhcp.html) | unstable | +| **DHCP Controlagent** | ansibleguy.opnsense.dhcp_controlagent | [Docs](https://opnsense.ansibleguy.net/en/latest/modules/dhcp.html) | unstable | ### Roadmap diff --git a/docs/source/modules/dhcp.rst b/docs/source/modules/dhcp.rst index 9b69760..5b336d7 100644 --- a/docs/source/modules/dhcp.rst +++ b/docs/source/modules/dhcp.rst @@ -18,6 +18,7 @@ Contribution ************ Thanks to `@KalleDK `_ for helping with the Reservation module! +Thanks to `@KalleDK `_ for helping with the Controlagent module! ---- @@ -91,3 +92,46 @@ ansibleguy.opnsense.dhcp_reservation - name: Show existing reservations ansible.builtin.debug: var: existing_entries.data + + +ansibleguy.opnsense.dhcp_controlagent +==================================== + +.. csv-table:: Definition + :header: "Parameter", "Type", "Required", "Default", "Aliases", "Comment" + :widths: 15 10 10 10 10 45 + + "enabled","boolean","false","true","\-","Enable or disable the control agent" + "http_host","string","false","127.0.0.1","","Address on which the RESTful interface should be available" + "http_port","int","false","8000","","MAC/Ether address of the client in question" + "reload","boolean","false","true","\-", .. include:: ../_include/param_reload.rst + +---- + +Examples +******** + +ansibleguy.opnsense.dhcp_controlagent +==================================== +.. code-block:: yaml + + - hosts: localhost + gather_facts: no + module_defaults: + group/ansibleguy.opnsense.all: + firewall: 'opnsense.template.ansibleguy.net' + api_credential_file: '/home/guy/.secret/opn.key' + + tasks: + - name: Example + ansibleguy.opnsense.dhcp_controlagent: + enabled: true + http_host: 127.0.0.1 + http_port: 8000 + # reload: true + # debug: false + + - name: Stopping + ansibleguy.opnsense.dhcp_controlagent: + enabled: false + reload: true \ No newline at end of file diff --git a/meta/runtime.yml b/meta/runtime.yml index 1c2ea29..807d928 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -127,6 +127,7 @@ action_groups: - ansibleguy.opnsense.dhcrelay_relay dhcp: - ansibleguy.opnsense.dhcp_reservation + - ansibleguy.opnsense.dhcp_controlagent all: - metadata: extend_group: diff --git a/plugins/module_utils/main/dhcp_controlagent.py b/plugins/module_utils/main/dhcp_controlagent.py new file mode 100644 index 0000000..e384f7c --- /dev/null +++ b/plugins/module_utils/main/dhcp_controlagent.py @@ -0,0 +1,44 @@ +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, validate_port +from ansible_collections.ansibleguy.opnsense.plugins.module_utils.base.cls import GeneralModule + + +class ControlAgent(GeneralModule): + FIELD_ID = 'ip' + CMDS = { + 'set': 'set', + 'search': 'get', + } + API_KEY_PATH = 'ctrlagent.general' + API_KEY_PATH_REQ = API_KEY_PATH + API_MOD = 'kea' + API_CONT = 'ctrl_agent' + API_CONT_REL = 'service' + API_CMD_REL = 'reconfigure' + FIELDS_CHANGE = [ + 'enabled', 'http_host', 'http_port' + ] + FIELDS_ALL = [*FIELDS_CHANGE] + FIELDS_TYPING = { + 'bool': ['enabled'], + 'int': ['http_port'], + } + INT_VALIDATIONS = { + 'http_port': {'min': 1, 'max': 65535}, + } + + def __init__(self, module: AnsibleModule, result: dict, session: Session = None): + GeneralModule.__init__(self=self, m=module, r=result, s=session) + + def check(self) -> None: + if not validate_port(module=self.m, port=self.p['http_port']): + self.m.fail_json('The provided port is invalid!') + if not is_ip(self.p['http_host']): + self.m.fail_json('The provided IP is invalid!') + super().check() + + diff --git a/plugins/modules/dhcp_controlagent.py b/plugins/modules/dhcp_controlagent.py new file mode 100644 index 0000000..ff21962 --- /dev/null +++ b/plugins/modules/dhcp_controlagent.py @@ -0,0 +1,66 @@ +#!/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/plugins/wireguard.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, EN_ONLY_MOD_ARG, RELOAD_MOD_ARG + from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.dhcp_controlagent import ControlAgent + +except MODULE_EXCEPTIONS: + module_dependency_error() + + +# DOCUMENTATION = 'https://opnsense.ansibleguy.net/en/latest/modules/dhcp.html' +# EXAMPLES = 'https://opnsense.ansibleguy.net/en/latest/modules/dhcp.html' + + +def run_module(): + module_args = dict( + http_port=dict( + type='int', required=False, default=8000, + description='Portnumber to use for the RESTful interface' + ), + http_host=dict( + type='str', required=False, default="127.0.0.1", aliases=['host'], + description='Address on which the RESTful interface should be available' + ), + **EN_ONLY_MOD_ARG, + **OPN_MOD_ARGS, + **RELOAD_MOD_ARG, + ) + + result = dict( + changed=False, + diff={ + 'before': {}, + 'after': {}, + } + ) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=True, + ) + + module_wrapper(ControlAgent(module=module, result=result)) + module.exit_json(**result) + + +def main(): + run_module() + + +if __name__ == '__main__': + main() diff --git a/scripts/test.sh b/scripts/test.sh index 640c342..ca91ff1 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -152,6 +152,7 @@ run_test 'nginx_general' 1 run_test 'nginx_upstream_server' 1 run_test 'dhcrelay_destination' 1 run_test 'dhcrelay_relay' 1 +run_test 'dhcp_controlagent' 1 run_test 'dhcp_reservation' 1 run_test 'system' 1 run_test 'package' 1 diff --git a/tests/cleanup.yml b/tests/cleanup.yml index f11ccc2..859cba7 100644 --- a/tests/cleanup.yml +++ b/tests/cleanup.yml @@ -669,3 +669,9 @@ loop: - '192.168.69.76' - '192.168.69.86' + + - name: Cleanup DHCP-Controlagent + ansibleguy.opnsense.dhcp_controlagent: + enabled: false + http_host: 127.0.0.1 + http_port: 8000 diff --git a/tests/dhcp_controlagent.yml b/tests/dhcp_controlagent.yml new file mode 100644 index 0000000..0bcae95 --- /dev/null +++ b/tests/dhcp_controlagent.yml @@ -0,0 +1,64 @@ +--- + +- name: Testing DHCP DHCP-Controlagent + hosts: localhost + gather_facts: no + module_defaults: + group/ansibleguy.opnsense.all: + firewall: "{{ lookup('ansible.builtin.env', 'TEST_FIREWALL') }}" + api_credential_file: "{{ lookup('ansible.builtin.env', 'TEST_API_KEY') }}" + ssl_verify: false + + + + tasks: + - name: Configuring + ansibleguy.opnsense.dhcp_controlagent: + enabled: true + register: opn1 + failed_when: > + opn1.failed or + not opn1.changed + + - name: Changing + ansibleguy.opnsense.dhcp_controlagent: + enabled: true + http_port: 8082 + register: opn5 + failed_when: > + opn5.failed or + not opn5.changed + + - name: Disabling 1 + ansibleguy.opnsense.dhcp_controlagent: + enabled: false + register: opn2 + failed_when: > + opn2.failed or + not opn2.changed + when: not ansible_check_mode + + - name: Disabling 1 - nothing changed + ansibleguy.opnsense.dhcp_controlagent: + enabled: false + register: opn3 + failed_when: > + opn3.failed or + opn3.changed + when: not ansible_check_mode + + - name: Enabling 1 + ansibleguy.opnsense.frr_general: + enabled: true + register: opn4 + failed_when: > + opn4.failed or + not opn4.changed + when: not ansible_check_mode + + - name: Cleanup + ansibleguy.opnsense.frr_general: + enabled: false + http_host: 127.0.0.1 + http_port: 8000 + when: not ansible_check_mode From ec82711aba6095bf5466d7fcfe250f24336d4bf6 Mon Sep 17 00:00:00 2001 From: Rath Pascal Date: Sat, 7 Dec 2024 13:54:07 +0100 Subject: [PATCH 2/4] dhcp-controlagent fixes --- docs/source/modules/dhcp.rst | 39 +++++++++---------- .../module_utils/main/dhcp_controlagent.py | 2 + plugins/modules/dhcp_controlagent.py | 2 +- tests/cleanup.yml | 2 +- tests/dhcp_controlagent.yml | 17 +++++--- 5 files changed, 33 insertions(+), 29 deletions(-) diff --git a/docs/source/modules/dhcp.rst b/docs/source/modules/dhcp.rst index 5b336d7..166f60b 100644 --- a/docs/source/modules/dhcp.rst +++ b/docs/source/modules/dhcp.rst @@ -8,7 +8,8 @@ DHCP **STATE**: unstable -**TESTS**: `Playbook `_ +**TESTS**: `Reservation `_ | +`ControlAgent `_ **API Docs**: `Core - KEA `_ @@ -17,8 +18,7 @@ DHCP Contribution ************ -Thanks to `@KalleDK `_ for helping with the Reservation module! -Thanks to `@KalleDK `_ for helping with the Controlagent module! +Thanks to `@KalleDK `_ for developing these module! ---- @@ -41,6 +41,18 @@ ansibleguy.opnsense.dhcp_reservation "description","string","false","","\-","Optional description" "reload","boolean","false","true","\-", .. include:: ../_include/param_reload.rst +ansibleguy.opnsense.dhcp_controlagent +===================================== + +.. csv-table:: Definition + :header: "Parameter", "Type", "Required", "Default", "Aliases", "Comment" + :widths: 15 10 10 10 10 45 + + "enabled","boolean","false","true","\-","Enable or disable the control agent" + "http_host","string","false","127.0.0.1","","Address on which the RESTful interface should be available" + "http_port","int","false","8000","","MAC/Ether address of the client in question" + "reload","boolean","false","true","\-", .. include:: ../_include/param_reload.rst + ---- Examples @@ -93,26 +105,11 @@ ansibleguy.opnsense.dhcp_reservation ansible.builtin.debug: var: existing_entries.data - -ansibleguy.opnsense.dhcp_controlagent -==================================== - -.. csv-table:: Definition - :header: "Parameter", "Type", "Required", "Default", "Aliases", "Comment" - :widths: 15 10 10 10 10 45 - - "enabled","boolean","false","true","\-","Enable or disable the control agent" - "http_host","string","false","127.0.0.1","","Address on which the RESTful interface should be available" - "http_port","int","false","8000","","MAC/Ether address of the client in question" - "reload","boolean","false","true","\-", .. include:: ../_include/param_reload.rst - ---- -Examples -******** - ansibleguy.opnsense.dhcp_controlagent -==================================== +===================================== + .. code-block:: yaml - hosts: localhost @@ -134,4 +131,4 @@ ansibleguy.opnsense.dhcp_controlagent - name: Stopping ansibleguy.opnsense.dhcp_controlagent: enabled: false - reload: true \ No newline at end of file + reload: true diff --git a/plugins/module_utils/main/dhcp_controlagent.py b/plugins/module_utils/main/dhcp_controlagent.py index e384f7c..b7cfbd6 100644 --- a/plugins/module_utils/main/dhcp_controlagent.py +++ b/plugins/module_utils/main/dhcp_controlagent.py @@ -37,8 +37,10 @@ def __init__(self, module: AnsibleModule, result: dict, session: Session = None) def check(self) -> None: if not validate_port(module=self.m, port=self.p['http_port']): self.m.fail_json('The provided port is invalid!') + if not is_ip(self.p['http_host']): self.m.fail_json('The provided IP is invalid!') + super().check() diff --git a/plugins/modules/dhcp_controlagent.py b/plugins/modules/dhcp_controlagent.py index ff21962..bdad487 100644 --- a/plugins/modules/dhcp_controlagent.py +++ b/plugins/modules/dhcp_controlagent.py @@ -33,7 +33,7 @@ def run_module(): description='Portnumber to use for the RESTful interface' ), http_host=dict( - type='str', required=False, default="127.0.0.1", aliases=['host'], + type='str', required=False, default='127.0.0.1', aliases=['host'], description='Address on which the RESTful interface should be available' ), **EN_ONLY_MOD_ARG, diff --git a/tests/cleanup.yml b/tests/cleanup.yml index 859cba7..0c07736 100644 --- a/tests/cleanup.yml +++ b/tests/cleanup.yml @@ -673,5 +673,5 @@ - name: Cleanup DHCP-Controlagent ansibleguy.opnsense.dhcp_controlagent: enabled: false - http_host: 127.0.0.1 + http_host: '127.0.0.1' http_port: 8000 diff --git a/tests/dhcp_controlagent.yml b/tests/dhcp_controlagent.yml index 0bcae95..f6a77ef 100644 --- a/tests/dhcp_controlagent.yml +++ b/tests/dhcp_controlagent.yml @@ -1,6 +1,6 @@ --- -- name: Testing DHCP DHCP-Controlagent +- name: Testing DHCP-Controlagent hosts: localhost gather_facts: no module_defaults: @@ -9,8 +9,6 @@ api_credential_file: "{{ lookup('ansible.builtin.env', 'TEST_API_KEY') }}" ssl_verify: false - - tasks: - name: Configuring ansibleguy.opnsense.dhcp_controlagent: @@ -24,6 +22,7 @@ ansibleguy.opnsense.dhcp_controlagent: enabled: true http_port: 8082 + http_host: '192.168.0.55' register: opn5 failed_when: > opn5.failed or @@ -32,6 +31,8 @@ - name: Disabling 1 ansibleguy.opnsense.dhcp_controlagent: enabled: false + http_port: 8082 + http_host: '192.168.0.55' register: opn2 failed_when: > opn2.failed or @@ -41,6 +42,8 @@ - name: Disabling 1 - nothing changed ansibleguy.opnsense.dhcp_controlagent: enabled: false + http_port: 8082 + http_host: '192.168.0.55' register: opn3 failed_when: > opn3.failed or @@ -48,8 +51,10 @@ when: not ansible_check_mode - name: Enabling 1 - ansibleguy.opnsense.frr_general: + ansibleguy.opnsense.dhcp_controlagent: enabled: true + http_port: 8082 + http_host: '192.168.0.55' register: opn4 failed_when: > opn4.failed or @@ -57,8 +62,8 @@ when: not ansible_check_mode - name: Cleanup - ansibleguy.opnsense.frr_general: + ansibleguy.opnsense.dhcp_controlagent: enabled: false - http_host: 127.0.0.1 + http_host: '127.0.0.1' http_port: 8000 when: not ansible_check_mode From 79dca3bd97f60dae45217136d3c3aeb134ba9ca1 Mon Sep 17 00:00:00 2001 From: Rath Pascal Date: Sat, 7 Dec 2024 13:56:10 +0100 Subject: [PATCH 3/4] lint fix --- plugins/module_utils/main/dhcp_controlagent.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/module_utils/main/dhcp_controlagent.py b/plugins/module_utils/main/dhcp_controlagent.py index b7cfbd6..556d07e 100644 --- a/plugins/module_utils/main/dhcp_controlagent.py +++ b/plugins/module_utils/main/dhcp_controlagent.py @@ -42,5 +42,3 @@ def check(self) -> None: self.m.fail_json('The provided IP is invalid!') super().check() - - From a74b6ee328eef950e2a5a7fc2a54aa675995e0ca Mon Sep 17 00:00:00 2001 From: Rath Pascal Date: Sat, 7 Dec 2024 13:57:29 +0100 Subject: [PATCH 4/4] lint fix --- tests/cleanup.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cleanup.yml b/tests/cleanup.yml index 0c07736..b936ad9 100644 --- a/tests/cleanup.yml +++ b/tests/cleanup.yml @@ -669,7 +669,7 @@ loop: - '192.168.69.76' - '192.168.69.86' - + - name: Cleanup DHCP-Controlagent ansibleguy.opnsense.dhcp_controlagent: enabled: false