Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add module to manage general Kea DHCP settings #136

Open
wants to merge 3 commits into
base: latest
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 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 |
| **ACME (Certificates)** | ansibleguy.opnsense.acme_account | [Docs](https://opnsense.ansibleguy.net/modules/acmeclient.html) | unstable |
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
acme:
- ansibleguy.opnsense.acme_general
- ansibleguy.opnsense.acme_account
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()
8 changes: 6 additions & 2 deletions plugins/modules/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
'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',
'acme_validation', 'acme_action', 'acme_certificate',
'interface_lagg', 'interface_loopback', 'unbound_dnsbl', 'dhcp_reservation', 'dhcp_general', 'acme_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

except AttributeError:
module_dependency_error()

Expand Down
1 change: 1 addition & 0 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,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_reservation' 1
run_test 'system' 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 @@ -717,3 +717,7 @@
- 'ANSIBLE_TEST_1_9'
- 'ANSIBLE_TEST_1_10'
- 'ANSIBLE_TEST_DUMMY_1_1'

- name: Cleanup DHCP Settings
ansibleguy.opnsense.dhcp_general:
enabled: false
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']
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']
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
Loading