diff --git a/README.md b/README.md index 28da0673..79244a30 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,7 @@ Choose what modules YOU would find useful: [Roadmap Poll](https://github.com/ans | **Interfaces** | ansibleguy.opnsense.interface_vip | [Docs](https://opnsense.ansibleguy.net/en/latest/modules/interface.html) | stable | | **NAT** | ansibleguy.opnsense.source_nat, ansibleguy.opnsense.snat | [Docs](https://opnsense.ansibleguy.net/en/latest/modules/source_nat.html) | unstable | | **Dynamic Routing** | ansibleguy.opnsense.frr_diagnostic | [Docs](https://opnsense.ansibleguy.net/en/latest/modules/frr_diagnostic.html) | stable | +| **Dynamic Routing** | ansibleguy.opnsense.frr_general | [Docs](https://opnsense.ansibleguy.net/en/latest/modules/frr_general.html) | stable | | **Dynamic Routing** | ansibleguy.opnsense.frr_bfd_general | [Docs](https://opnsense.ansibleguy.net/en/latest/modules/frr_bfd.html#ansibleguy-opnsense-frr-bfd-general) | stable | | **Dynamic Routing** | ansibleguy.opnsense.frr_bfd_neighbor | [Docs](https://opnsense.ansibleguy.net/en/latest/modules/frr_bfd.html#ansibleguy-opnsense-frr-bfd-neighbor) | stable | | **Dynamic Routing** | ansibleguy.opnsense.frr_bgp_general | [Docs](https://opnsense.ansibleguy.net/en/latest/modules/frr_bgp.html#ansibleguy-opnsense-frr-bgp-general) | stable | diff --git a/docs/source/modules/frr_bfd.md b/docs/source/modules/frr_bfd.md index ba4f3f49..85757018 100644 --- a/docs/source/modules/frr_bfd.md +++ b/docs/source/modules/frr_bfd.md @@ -14,10 +14,6 @@ Thanks to [@telmich](https://github.com/telmich) for sponsoring the development of these modules! -## More FRR modules - -* [Docs](https://github.com/ansibleguy/collection_opnsense/blob/latest/docs/use_frr.md) - ## Prerequisites You need to install the FRR plugin: diff --git a/docs/source/modules/frr_bgp.md b/docs/source/modules/frr_bgp.md index b2f21da3..34c20d8c 100644 --- a/docs/source/modules/frr_bgp.md +++ b/docs/source/modules/frr_bgp.md @@ -19,10 +19,6 @@ Thanks to [@telmich](https://github.com/telmich) for sponsoring the development of these modules! -## More FRR modules - -* [Docs](https://github.com/ansibleguy/collection_opnsense/blob/latest/docs/use_frr.md) - ## Prerequisites You need to install the FRR plugin: diff --git a/docs/source/modules/frr_diagnostic.md b/docs/source/modules/frr_diagnostic.md index 31afbabd..726cddf9 100644 --- a/docs/source/modules/frr_diagnostic.md +++ b/docs/source/modules/frr_diagnostic.md @@ -14,10 +14,6 @@ Thanks to [@telmich](https://github.com/telmich) for sponsoring the development of these modules! -## More FRR modules - -* [Docs](https://github.com/ansibleguy/collection_opnsense/blob/latest/docs/use_frr.md) - ## Prerequisites You need to install the FRR plugin: diff --git a/docs/source/modules/frr_general.md b/docs/source/modules/frr_general.md new file mode 100644 index 00000000..5a658ba2 --- /dev/null +++ b/docs/source/modules/frr_general.md @@ -0,0 +1,66 @@ +# FRR General + +**STATE**: stable + +**TESTS**: [frr_general](https://github.com/ansibleguy/collection_opnsense/blob/latest/tests/frr_general.yml) + +**API Docs**: [Plugins - Quagga](https://docs.opnsense.org/development/api/plugins/quagga.html) + +**Service Docs**: [Dynamic Routing](https://docs.opnsense.org/manual/dynamic_routing.html) + +**FRR Docs**: [FRRouting](https://docs.frrouting.org/) (_make sure you are looking at the current OPNSense package version!_) + +## Prerequisites + +You need to install the FRR plugin: +``` +os-frr +``` + +You can also install it using the [package module](https://github.com/ansibleguy/collection_opnsense/blob/latest/docs/use_package.md). + +## Definition + +For basic parameters see: [Basics](https://github.com/ansibleguy/collection_opnsense/blob/latest/docs/use_basic.md#definition) + +### ansibleguy.opnsense.frr_general + +| Parameter | Type | Required | Default value | Aliases | Comment | +|:----------|:-------|:---------|:----------------------------|:--------------|:---------------------------------------------------------------------------------------------------------------------------------------------| +| enabled | bool | false | true | - | En- or disable the FRR service | +| profile | string | false | 'traditional' | - | One of: 'traditional', 'datacenter'. The 'datacenter' profile is more aggressive. Please refer to the FRR documentation for more information | +| log | bool | false | true | logging | En- or disable (syslog) logging | +| log_level | string | false | 'notifications' | - | One of: 'critical', 'emergencies', 'errors', 'alerts', 'warnings', 'notifications', 'informational', 'debugging'. | +| carp | bool | false | false | carp_failover | Will activate the routing service only on the primary device | +| snmp_agentx | bool | false | false | - | En- or disable support for Net-SNMP AgentX | + + +## Examples + +### ansibleguy.opnsense.frr_general + +```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.frr_general: + # enabled: true + # profile: 'traditional' + # log: true + # log_level: 'notifications' + # snmp_agentx: false + # carp: false + + - name: Enabling FRR + ansibleguy.opnsense.frr_general: + enabled: true + profile: 'traditional' + log: true + log_level: 'notifications' +``` diff --git a/docs/source/modules/frr_ospf.md b/docs/source/modules/frr_ospf.md index 242f2146..21f19d7c 100644 --- a/docs/source/modules/frr_ospf.md +++ b/docs/source/modules/frr_ospf.md @@ -21,10 +21,6 @@ Thanks to [@telmich](https://github.com/telmich) for sponsoring the development of these modules! -## More FRR modules - -* [Docs](https://github.com/ansibleguy/collection_opnsense/blob/latest/docs/use_frr.md) - ## Prerequisites You need to install the FRR plugin: diff --git a/docs/source/modules/frr_rip.md b/docs/source/modules/frr_rip.md index c07ddeec..447ea409 100644 --- a/docs/source/modules/frr_rip.md +++ b/docs/source/modules/frr_rip.md @@ -14,10 +14,6 @@ Thanks to [@telmich](https://github.com/telmich) for sponsoring the development of these modules! -## More FRR modules - -* [Docs](https://github.com/ansibleguy/collection_opnsense/blob/latest/docs/use_frr.md) - ## Prerequisites You need to install the FRR plugin: diff --git a/galaxy.yml b/galaxy.yml index f65f9321..8102bfb9 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -2,7 +2,7 @@ namespace: 'ansibleguy' name: 'opnsense' -version: 1.2.3 +version: 1.2.4 readme: 'README.md' authors: - 'AnsibleGuy ' diff --git a/meta/runtime.yml b/meta/runtime.yml index 53c33ed0..ee21b9ba 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -44,6 +44,7 @@ action_groups: - ansibleguy.opnsense.interface_vip frr: - ansibleguy.opnsense.frr_diagnostic + - ansibleguy.opnsense.frr_general - ansibleguy.opnsense.frr_bfd_general - ansibleguy.opnsense.frr_bfd_neighbor - ansibleguy.opnsense.frr_bgp_general diff --git a/plugins/module_utils/main/frr_general.py b/plugins/module_utils/main/frr_general.py new file mode 100644 index 00000000..ab4f6c7c --- /dev/null +++ b/plugins/module_utils/main/frr_general.py @@ -0,0 +1,34 @@ +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 = 'general' + API_MOD = 'quagga' + API_CONT = 'general' + API_CONT_REL = 'service' + API_CMD_REL = 'reconfigure' + FIELDS_CHANGE = [ + 'enabled', 'profile', 'carp', 'log', 'snmp_agentx', 'log_level', + ] + FIELDS_ALL = FIELDS_CHANGE + FIELDS_TRANSLATE = { + 'carp': 'enablecarp', + 'log': 'enablesyslog', + 'snmp_agentx': 'enablesnmp', + 'log_level': 'sysloglevel', + } + FIELDS_TYPING = { + 'bool': ['enabled', 'carp', 'log', 'snmp_agentx'], + 'select': ['log_level', 'profile'], + } + + def __init__(self, module: AnsibleModule, result: dict, session: Session = None): + GeneralModule.__init__(self=self, m=module, r=result, s=session) diff --git a/plugins/modules/frr_general.py b/plugins/modules/frr_general.py new file mode 100644 index 00000000..654eb518 --- /dev/null +++ b/plugins/modules/frr_general.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + +# Copyright: (C) 2023, 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/quagga.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.utils import profiler + from ansible_collections.ansibleguy.opnsense.plugins.module_utils.helper.main import \ + diff_remove_empty + 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.frr_general import General + +except MODULE_EXCEPTIONS: + module_dependency_error() + +PROFILE = False # create log to profile time consumption + +DOCUMENTATION = 'https://opnsense.ansibleguy.net/en/latest/modules/frr_general.html' +EXAMPLES = 'https://opnsense.ansibleguy.net/en/latest/modules/frr_general.html' + + +def run_module(): + module_args = dict( + carp=dict( + type='bool', required=False, default=False, aliases=['carp_failover'], + description='Will activate the routing service only on the primary device' + ), + profile=dict( + type='str', required=False, default='traditional', + options=['traditional', 'datacenter'], + description="The 'datacenter' profile is more aggressive. " + "Please refer to the FRR documentation for more information" + ), + snmp_agentx=dict( + type='bool', required=False, default=False, + description='En- or disable support for Net-SNMP AgentX' + ), + log=dict( + type='bool', required=False, default=True, aliases=['logging'], + ), + log_level=dict( + type='str', required=False, default='notifications', + options=[ + 'critical', 'emergencies', 'errors', 'alerts', 'warnings', 'notifications', + 'informational', 'debugging', + ], + ), + **RELOAD_MOD_ARG, + **EN_ONLY_MOD_ARG, + **OPN_MOD_ARGS, + ) + + result = dict( + changed=False, + diff={ + 'before': {}, + 'after': {}, + } + ) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=True, + ) + + g = General(module=module, result=result) + + def process(): + g.check() + g.process() + if result['changed'] and module.params['reload']: + g.reload() + + if PROFILE or module.params['debug']: + profiler(check=process, log_file='frr_general.log') + # log in /tmp/ansibleguy.opnsense/ + + else: + process() + + g.s.close() + result['diff'] = diff_remove_empty(result['diff']) + 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 9b43914a..755760d7 100644 --- a/plugins/modules/list.py +++ b/plugins/modules/list.py @@ -32,7 +32,7 @@ 'cron', 'unbound_dot', 'ipsec_cert', 'source_nat', 'frr_bgp_prefix_list', 'frr_bgp_community_list', 'frr_bgp_as_path', 'frr_bgp_route_map', 'frr_ospf_prefix_list', 'frr_ospf_route_map', 'webproxy_forward', 'webproxy_acl', 'webproxy_icap', 'webproxy_auth', 'ipsec_connection', 'ipsec_pool', - 'ipsec_child', 'ipsec_vti', 'ipsec_auth_local', 'ipsec_auth_remote', + 'ipsec_child', 'ipsec_vti', 'ipsec_auth_local', 'ipsec_auth_remote', 'frr_general', ] @@ -155,6 +155,10 @@ def run_module(): from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.source_nat import \ SNat as Target_Obj + elif target == 'frr_general': + from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.frr_general \ + import General as Target_Obj + elif target == 'frr_bfd_neighbor': from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.frr_bfd_neighbor import \ Neighbor as Target_Obj diff --git a/scripts/test.sh b/scripts/test.sh index 47286c6e..8d843d19 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -89,6 +89,7 @@ run_test 'interface_vxlan' 1 run_test 'interface_vip' 1 run_test 'source_nat' 1 run_test 'frr_diagnostic' 1 +run_test 'frr_general' 1 run_test 'frr_bfd_general' 1 run_test 'frr_bfd_neighbor' 1 run_test 'frr_bgp_general' 1 diff --git a/tests/cleanup.yml b/tests/cleanup.yml index 0854d5bd..6c957064 100644 --- a/tests/cleanup.yml +++ b/tests/cleanup.yml @@ -236,6 +236,15 @@ - 'ANSIBLE_TEST_1_1' - 'ANSIBLE_TEST_1_2' + - name: Cleanup FRR general settings + ansibleguy.opnsense.frr_general: + enabled: false + profile: 'traditional' + carp: false + snmp_agentx: false + log: true + log_level: 'notifications' + - name: Cleanup FRR BFD general settings ansibleguy.opnsense.frr_bfd_general: enabled: false diff --git a/tests/frr_general.yml b/tests/frr_general.yml new file mode 100644 index 00000000..41e5b3c9 --- /dev/null +++ b/tests/frr_general.yml @@ -0,0 +1,93 @@ +--- + +- name: Testing FRR general settings + 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: 'frr_general' + + tasks: + - name: Listing + ansibleguy.opnsense.list: + register: opn_pre1 + failed_when: > + opn_pre1.failed or + 'data' not in opn_pre1 + + - name: Configuring + ansibleguy.opnsense.frr_general: + enabled: true + profile: 'traditional' + log: true + log_level: 'notifications' + register: opn1 + failed_when: > + opn1.failed or + not opn1.changed + + - name: Changing + ansibleguy.opnsense.frr_general: + enabled: true + profile: 'datacenter' + log: true + log_level: 'emergencies' + snmp_agentx: true + register: opn5 + failed_when: > + opn5.failed or + not opn5.changed + + - name: Disabling 1 + ansibleguy.opnsense.frr_general: + profile: 'datacenter' + log: true + log_level: 'emergencies' + snmp_agentx: true + enabled: false + register: opn2 + failed_when: > + opn2.failed or + not opn2.changed + when: not ansible_check_mode + + - name: Disabling 1 - nothing changed + ansibleguy.opnsense.frr_general: + profile: 'datacenter' + log: true + log_level: 'emergencies' + snmp_agentx: true + enabled: false + register: opn3 + failed_when: > + opn3.failed or + opn3.changed + when: not ansible_check_mode + + - name: Enabling 1 + ansibleguy.opnsense.frr_general: + profile: 'datacenter' + log: true + log_level: 'emergencies' + snmp_agentx: true + 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 + profile: 'traditional' + carp: false + snmp_agentx: false + log: true + log_level: 'notifications' + when: not ansible_check_mode