Skip to content

Commit

Permalink
Merge pull request #136 from woelfle/manage-dhcp-general
Browse files Browse the repository at this point in the history
add module to manage general Kea DHCP settings
  • Loading branch information
ansibleguy authored Feb 7, 2025
2 parents 42c8171 + 9af9bac commit 73ef9c0
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ not implemented => development => [testing](https://github.com/ansibleguy/collec
| **Nginx** | ansibleguy.opnsense.nginx_upstream_server | [Docs](https://opnsense.ansibleguy.net/modules/nginx.html#ansibleguy-opnsense-nginx-upstream-server) | unstable |
| **DHCP Relay** | ansibleguy.opnsense.dhcrelay | [Docs](https://opnsense.ansibleguy.net/modules/dhcrelay_relay.html) | unstable |
| **DHCP Relay** | ansibleguy.opnsense.dhcrelay_destination | [Docs](https://opnsense.ansibleguy.net/modules/dhcrelay_destination.html) | unstable |
| **DHCP** | ansibleguy.opnsense.dhcp_general | [Docs](https://opnsense.ansibleguy.net/modules/dhcp.html) | unstable |
| **DHCP Subnet** | ansibleguy.opnsense.dhcp_subnet | [Docs](https://opnsense.ansibleguy.net/modules/dhcp.html) | unstable |
| **DHCP Reservation** | ansibleguy.opnsense.dhcp_reservation | [Docs](https://opnsense.ansibleguy.net/modules/dhcp.html) | unstable |
| **DHCP Controlagent** | ansibleguy.opnsense.dhcp_controlagent | [Docs](https://opnsense.ansibleguy.net/modules/dhcp.html) | unstable |
Expand Down
39 changes: 37 additions & 2 deletions docs/source/modules/dhcp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ DHCP

**TESTS**: `Reservation <https://github.com/ansibleguy/collection_opnsense/blob/latest/tests/dhcp_reservation.yml>`_ |
`ControlAgent <https://github.com/ansibleguy/collection_opnsense/blob/latest/tests/dhcp_controlagent.yml>`_ |
`Subnet <https://github.com/ansibleguy/collection_opnsense/blob/latest/tests/dhcp_subnet.yml>`_
`Subnet <https://github.com/ansibleguy/collection_opnsense/blob/latest/tests/dhcp_subnet.yml>`_ |
`Subnet <https://github.com/ansibleguy/collection_opnsense/blob/latest/tests/dhcp_general.yml>`_

**API Docs**: `Core - KEA <https://docs.opnsense.org/development/api/core/kea.html>`_

Expand All @@ -21,14 +22,25 @@ Contribution

Thanks to `@KalleDK <https://github.com/KalleDK>`_, `@superstes <https://github.com/superstes>`_ and `@woelfle <https://github.com/woelfle>`_ for developing these modules!


----

Definition
**********

.. include:: ../_include/param_basic.rst

ansibleguy.opnsense.dhcp_general
================================

.. csv-table:: Definition
:header: "Parameter", "Type", "Required", "Default", "Aliases", "Comment"
:widths: 15 10 10 10 10 45

"interfaces","list","false","\-","ints","Comma separated list of network interfaces to listen on for DHCP requests"
"socket_type","string","false","raw","dhcp_socket_type","One of: 'raw', 'udp'. Socket type used for DHCP communication."
"fw_rules","boolean","false","true","fwrules, rules","Automatically add a basic set of firewall rules to allow DHCP traffic"
"lifetime","int","false","4000","valid_lifetime","Defines how long the addresses (leases) given out by the server are valid (in seconds)"

ansibleguy.opnsense.dhcp_reservation
====================================

Expand Down Expand Up @@ -83,6 +95,29 @@ ansibleguy.opnsense.dhcp_subnet
Examples
********

ansibleguy.opnsense.dhcp_general
================================

.. code-block:: yaml
- hosts: localhost
gather_facts: no
module_defaults:
group/ansibleguy.opnsense.all:
firewall: 'opnsense.template.ansibleguy.net'
api_credentials_file: '/home/guy/.secret/opn.key'
tasks:
- name: Listen to network interfaces
ansibleguy.opnsense.dhcp_general:
enabled: true
interfaces: 'lan,opt1,opt2,vlan0.10'
# socket_type: 'raw'
# fw_rules: true
# lifetime: 4000
----

ansibleguy.opnsense.dhcp_reservation
====================================

Expand Down
1 change: 1 addition & 0 deletions meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ action_groups:
dhcp:
- ansibleguy.opnsense.dhcp_reservation
- ansibleguy.opnsense.dhcp_controlagent
- ansibleguy.opnsense.dhcp_general
- ansibleguy.opnsense.dhcp_subnet
acme:
- ansibleguy.opnsense.acme_general
Expand Down
38 changes: 38 additions & 0 deletions plugins/module_utils/main/dhcp_general.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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.base.cls import GeneralModule


class General(GeneralModule):
CMDS = {
'set': 'set',
'search': 'get'
}
API_KEY_PATH = 'dhcpv4.general'
API_KEY_PATH_REQ = API_KEY_PATH
API_MOD = 'kea'
API_CONT = 'dhcpv4'
API_CONT_REL = 'service'
FIELDS_CHANGE = [
'enabled', 'interfaces', 'socket_type', 'fw_rules', 'lifetime'
]
FIELDS_ALL = FIELDS_CHANGE
FIELDS_TRANSLATE = {
'lifetime': 'valid_lifetime',
'fw_rules': 'fwrules',
'socket_type': 'dhcp_socket_type',
}
FIELDS_TYPING = {
'bool': ['enabled', 'fw_rules'],
'int': ['lifetime'],
'list': ['interfaces'],
'select': ['socket_type'],
}
INT_VALIDATIONS = {
'lifetime': {'min': 0},
}

def __init__(self, module: AnsibleModule, result: dict, session: Session = None):
GeneralModule.__init__(self=self, m=module, r=result, s=session)
74 changes: 74 additions & 0 deletions plugins/modules/dhcp_general.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright: (C) 2024, AnsibleGuy <[email protected]>
# GNU General Public License v3.0+ (see https://www.gnu.org/licenses/gpl-3.0.txt)

# see: https://docs.opnsense.org/development/api/plugins/nginx.html

from ansible.module_utils.basic import AnsibleModule

from ansible_collections.ansibleguy.opnsense.plugins.module_utils.base.handler import \
module_dependency_error, MODULE_EXCEPTIONS
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.helper.wrapper import module_wrapper

try:
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.defaults.main import \
EN_ONLY_MOD_ARG, OPN_MOD_ARGS, RELOAD_MOD_ARG
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.dhcp_general import General


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(
interfaces=dict(
type='list', elements='str', required=False, default=[], aliases=['ints'],
description='Comma separated list of network interfaces to listen on for DHCP requests'
),
socket_type=dict(
type='str', required=False, default='raw', choices=['raw', 'udp'], aliases=['dhcp_socket_type'],
description='Socket type used for DHCP communication',
),
fw_rules=dict(
type='bool', required=False, default=True, aliases=['fwrules', 'rules'],
description='Automatically add a basic set of firewall rules to allow dhcp traffic, '
'more fine grained controls can be offered manually when disabling this option',
),
lifetime=dict(
type='int', required=False, default=4000, aliases=['valid_lifetime'],
description='Defines how long the addresses (leases) given out by the server are valid (in seconds)',
),
**EN_ONLY_MOD_ARG,
**RELOAD_MOD_ARG,
**OPN_MOD_ARGS,
)

module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True,
)

result = dict(
changed=False,
diff={
'before': {},
'after': {},
}
)

module_wrapper(General(module=module, result=result))
module.exit_json(**result)


def main():
run_module()


if __name__ == '__main__':
main()
6 changes: 5 additions & 1 deletion plugins/modules/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
'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', 'dhcp_subnet', 'acme_general',
'acme_account', 'acme_validation', 'acme_action', 'acme_certificate',
'dhcp_general', 'acme_account', 'acme_validation', 'acme_action', 'acme_certificate',
]


Expand Down Expand Up @@ -419,6 +419,10 @@ def run_module():
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.acme_certificate import \
Certificate as Target_Obj

elif target == 'dhcp_general':
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.dhcp_general import \
General as Target_Obj

elif target == 'dhcp_subnet':
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.dhcp_subnet_v4 import \
SubnetV4 as Target_Obj
Expand Down
1 change: 1 addition & 0 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,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_general' 1
run_test 'dhcp_controlagent' 1
run_test 'dhcp_subnet' 1
run_test 'dhcp_reservation' 1
Expand Down
4 changes: 4 additions & 0 deletions tests/1_cleanup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,10 @@
- 'ANSIBLE_TEST_1_10'
- 'ANSIBLE_TEST_DUMMY_1_1'

- name: Cleanup DHCP Settings
ansibleguy.opnsense.dhcp_general:
enabled: false

- name: Cleanup DHCP Subnets
ansibleguy.opnsense.dhcp_subnet:
subnet: "{{ item }}"
Expand Down
64 changes: 64 additions & 0 deletions tests/dhcp_general.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---

- name: Testing DHCP Setting
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

ansibleguy.opnsense.list:
target: 'dhcp_general'

tasks:
- name: Listing
ansibleguy.opnsense.list:
register: opn_pre1
failed_when: >
opn_pre1.failed or
'data' not in opn_pre1
- name: Configuring - failing because of invalid lifetime
ansibleguy.opnsense.dhcp_general:
lifetime: -1
register: opn_fail1
failed_when: not opn_fail1.failed

- name: Configuring
ansibleguy.opnsense.dhcp_general:
enabled: true
interfaces: ['opt1']
register: opn1
failed_when: >
opn1.failed or
not opn1.changed
- name: Changing
ansibleguy.opnsense.dhcp_general:
enabled: true
interfaces: ['opt1', 'lan']
fw_rules: false
lifetime: 5000
register: opn2
failed_when: >
opn2.failed or
not opn2.changed
when: not ansible_check_mode

- name: Nothing changed
ansibleguy.opnsense.dhcp_general:
enabled: true
interfaces: ['opt1', 'lan']
fw_rules: false
lifetime: 5000
register: opn3
failed_when: >
opn3.failed or
opn3.changed
when: not ansible_check_mode

- name: Cleanup
ansibleguy.opnsense.dhcp_general:
enabled: false

0 comments on commit 73ef9c0

Please sign in to comment.