diff --git a/README.md b/README.md index 04a11358..a8428cdb 100644 --- a/README.md +++ b/README.md @@ -1,182 +1,182 @@ # VyOS Collection [![Codecov](https://codecov.io/gh/ansible-collections/vyos.vyos/branch/main/graph/badge.svg)](https://codecov.io/gh/ansible-collections/vyos.vyos) [![CI](https://github.com/ansible-collections/vyos.vyos/actions/workflows/tests.yml/badge.svg?branch=main&event=schedule)](https://github.com/ansible-collections/vyos.vyos/actions/workflows/tests.yml) The Ansible VyOS collection includes a variety of Ansible content to help automate the management of VyOS network appliances. This collection has been tested against VyOS 1.1.8 (helium). ## Communication * Join the Ansible forum: * [Get Help](https://forum.ansible.com/c/help/6): get help or help others. * [Posts tagged with 'vyos'](https://forum.ansible.com/tag/vyos): subscribe to participate in collection-related conversations. * [Social Spaces](https://forum.ansible.com/c/chat/4): gather and interact with fellow enthusiasts. * [News & Announcements](https://forum.ansible.com/c/news/5): track project-wide announcements including social events. * The Ansible [Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn): used to announce releases and important changes. For more information about communication, see the [Ansible communication guide](https://docs.ansible.com/ansible/devel/community/communication.html). ## Ansible version compatibility This collection has been tested against following Ansible versions: **>=2.15.0**. For collections that support Ansible 2.9, please ensure you update your `network_os` to use the fully qualified collection name (for example, `cisco.ios.ios`). Plugins and modules within a collection may be tested with only specific Ansible versions. A collection may contain metadata that identifies these versions. PEP440 is the schema used to describe the versions of Ansible. ### Supported connections The VyOS collection supports ``network_cli`` connections. ## Included content ### Cliconf plugins Name | Description --- | --- [vyos.vyos.vyos](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_cliconf.rst)|Use vyos cliconf to run command on VyOS platform ### Modules Name | Description --- | --- [vyos.vyos.vyos_banner](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_banner_module.rst)|Manage multiline banners on VyOS devices [vyos.vyos.vyos_bgp_address_family](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_bgp_address_family_module.rst)|BGP Address Family Resource Module. [vyos.vyos.vyos_bgp_global](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_bgp_global_module.rst)|BGP Global Resource Module. [vyos.vyos.vyos_command](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_command_module.rst)|Run one or more commands on VyOS devices [vyos.vyos.vyos_config](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_config_module.rst)|Manage VyOS configuration on remote device [vyos.vyos.vyos_facts](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_facts_module.rst)|Get facts about vyos devices. [vyos.vyos.vyos_firewall_global](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_firewall_global_module.rst)|FIREWALL global resource module -[vyos.vyos.vyos_firewall_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_firewall_interfaces_module.rst)|FIREWALL interfaces resource module +[vyos.vyos.vyos_firewall_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_firewall_interfaces_module.rst)|Manage firewall rules attributes of interfaces on VyOS devices [vyos.vyos.vyos_firewall_rules](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_firewall_rules_module.rst)|FIREWALL rules resource module [vyos.vyos.vyos_hostname](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_hostname_module.rst)|Manages hostname resource module [vyos.vyos.vyos_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_interfaces_module.rst)|Interfaces resource module [vyos.vyos.vyos_l3_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_l3_interfaces_module.rst)|L3 interfaces resource module [vyos.vyos.vyos_lag_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_lag_interfaces_module.rst)|LAG interfaces resource module [vyos.vyos.vyos_lldp_global](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_lldp_global_module.rst)|LLDP global resource module [vyos.vyos.vyos_lldp_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_lldp_interfaces_module.rst)|LLDP interfaces resource module [vyos.vyos.vyos_logging](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_logging_module.rst)|Manage logging on network devices [vyos.vyos.vyos_logging_global](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_logging_global_module.rst)|Logging resource module [vyos.vyos.vyos_ntp_global](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_ntp_global_module.rst)|Manages ntp modules of Vyos network devices [vyos.vyos.vyos_ospf_interfaces](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_ospf_interfaces_module.rst)|OSPF Interfaces Resource Module. [vyos.vyos.vyos_ospfv2](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_ospfv2_module.rst)|OSPFv2 resource module [vyos.vyos.vyos_ospfv3](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_ospfv3_module.rst)|OSPFV3 resource module [vyos.vyos.vyos_ping](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_ping_module.rst)|Tests reachability using ping from VyOS network devices [vyos.vyos.vyos_prefix_lists](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_prefix_lists_module.rst)|Prefix-Lists resource module for VyOS [vyos.vyos.vyos_route_maps](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_route_maps_module.rst)|Route Map Resource Module. [vyos.vyos.vyos_snmp_server](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_snmp_server_module.rst)|Manages snmp_server resource module [vyos.vyos.vyos_static_routes](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_static_routes_module.rst)|Static routes resource module [vyos.vyos.vyos_system](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_system_module.rst)|Run `set system` commands on VyOS devices [vyos.vyos.vyos_user](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_user_module.rst)|Manage the collection of local users on VyOS device [vyos.vyos.vyos_vlan](https://github.com/ansible-collections/vyos.vyos/blob/main/docs/vyos.vyos.vyos_vlan_module.rst)|Manage VLANs on VyOS network devices Click the ``Content`` button to see the list of content included in this collection. ## Installing this collection You can install the VyOS collection with the Ansible Galaxy CLI: ansible-galaxy collection install vyos.vyos You can also include it in a `requirements.yml` file and install it with `ansible-galaxy collection install -r requirements.yml`, using the format: ```yaml --- collections: - name: vyos.vyos ``` ## Using this collection This collection includes [network resource modules](https://docs.ansible.com/ansible/latest/network/user_guide/network_resource_modules.html). ### Using modules from the VyOS collection in your playbooks You can call modules by their Fully Qualified Collection Namespace (FQCN), such as `vyos.vyos.vyos_static_routes`. The following example task replaces configuration changes in the existing configuration on a VyOS network device, using the FQCN: ```yaml --- - name: Replace device configurations of listed static routes with provided configurations register: result vyos.vyos.vyos_static_routes: &id001 config: - address_families: - afi: ipv4 routes: - dest: 192.0.2.32/28 blackhole_config: distance: 2 next_hops: - forward_router_address: 192.0.2.7 - forward_router_address: 192.0.2.8 - forward_router_address: 192.0.2.9 state: replaced ``` **NOTE**: For Ansible 2.9, you may not see deprecation warnings when you run your playbooks with this collection. Use this documentation to track when a module is deprecated. ### See Also: * [VyOS Platform Options](https://docs.ansible.com/ansible/latest/network/user_guide/platform_vyos.html) * [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details. ## Contributing to this collection We welcome community contributions to this collection. If you find problems, please open an issue or create a PR against the [VyOS collection repository](https://github.com/ansible-collections/vyos). See [Contributing to Ansible-maintained collections](https://docs.ansible.com/ansible/devel/community/contributing_maintained_collections.html#contributing-maintained-collections) for complete details. You can also join us on: - IRC - the ``#ansible-network`` [irc.libera.chat](https://libera.chat/) channel - Slack - https://ansiblenetwork.slack.com See the [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html) for details on contributing to Ansible. ### Code of Conduct This collection follows the Ansible project's [Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html). Please read and familiarize yourself with this document. ## Changelogs ## Release notes Release notes are available [here](https://github.com/ansible-collections/vyos.vyos/blob/main/CHANGELOG.rst). ## Roadmap ## More information - [Ansible network resources](https://docs.ansible.com/ansible/latest/network/getting_started/network_resources.html) - [Ansible Collection overview](https://github.com/ansible-collections/overview) - [Ansible User guide](https://docs.ansible.com/ansible/latest/user_guide/index.html) - [Ansible Developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html) - [Ansible Community code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) ## Licensing GNU General Public License v3.0 or later. See [LICENSE](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text. diff --git a/changelogs/fragments/firewall_interface_types.yml b/changelogs/fragments/firewall_interface_types.yml new file mode 100644 index 00000000..29451e87 --- /dev/null +++ b/changelogs/fragments/firewall_interface_types.yml @@ -0,0 +1,4 @@ +--- +minor_changes: + - added support for VIF interfaces + - expanded firewall interface types to match existing types diff --git a/docs/vyos.vyos.vyos_firewall_interfaces_module.rst b/docs/vyos.vyos.vyos_firewall_interfaces_module.rst index 85108121..386d52b4 100644 --- a/docs/vyos.vyos.vyos_firewall_interfaces_module.rst +++ b/docs/vyos.vyos.vyos_firewall_interfaces_module.rst @@ -1,1413 +1,1370 @@ .. _vyos.vyos.vyos_firewall_interfaces_module: ********************************** vyos.vyos.vyos_firewall_interfaces ********************************** -**FIREWALL interfaces resource module** +**Manage firewall rules attributes of interfaces on VyOS devices** -Version added: 1.0.0 +Version added: 2.10.0 .. contents:: :local: :depth: 1 Synopsis -------- -- Manage firewall rules of interfaces on VyOS network devices. +- Manage firewall rules of interfaces on VyOS network devices. (1.3-) Parameters ---------- .. raw:: html
Parameter Choices/Defaults Comments
config
list / elements=dictionary
A list of firewall rules options for interfaces.
access_rules
list / elements=dictionary
Specifies firewall rules attached to the interfaces.
afi
string / required
    Choices:
  • ipv4
  • ipv6
Specifies the AFI for the Firewall rules to be configured on this interface.
rules
list / elements=dictionary
Specifies the firewall rules for the provided AFI.
direction
string / required
    Choices:
  • in
  • local
  • out
Specifies the direction of packets that the firewall rule will be applied on.
name
string
Specifies the name of the IPv4/IPv6 Firewall rule for the interface.
name
string / required
Name/Identifier for the interface.
running_config
string
The module, by default, will connect to the remote device and retrieve the current running-config to use as a base for comparing against the contents of source. There are times when it is not desirable to have the task get the current running-config for every task in a playbook. The running_config argument allows the implementer to pass in the configuration to use as the base config for comparison. This value of this option should be the output received from device by executing command show configuration commands | grep 'firewall'.
state
string
    Choices:
  • merged ←
  • replaced
  • overridden
  • deleted
  • parsed
  • rendered
  • gathered
The state the configuration should be left in.

+Notes +----- + +.. note:: + - Deprecated in VyOS 1.4+, firewalls are no longer connected directly to interfaces. See the Firewall Configuration documentation for how to establish a connection betwen the firewall rulesets and the flow, interface, or zone. + Examples -------- .. code-block:: yaml # Using merged # # Before state: # ------------- # # vyos@192# run show configuration commands | grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # - name: Merge the provided configuration with the existing running configuration vyos.vyos.vyos_firewall_interfaces: config: - access_rules: - afi: ipv4 rules: - name: INBOUND direction: in - name: OUTBOUND direction: out - name: LOCAL direction: local - afi: ipv6 rules: - name: V6-LOCAL direction: local name: eth1 - access_rules: - afi: ipv4 rules: - name: INBOUND direction: in - name: OUTBOUND direction: out - name: LOCAL direction: local - afi: ipv6 rules: - name: V6-LOCAL direction: local name: eth3 state: merged # # # ------------------------- # Module Execution Result # ------------------------- # # before": [ # { # "name": "eth0" # }, # { # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "name": "eth3" # } # ] # # "commands": [ # "set interfaces ethernet eth1 firewall in name 'INBOUND'", # "set interfaces ethernet eth1 firewall out name 'OUTBOUND'", # "set interfaces ethernet eth1 firewall local name 'LOCAL'", # "set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL'", # "set interfaces ethernet eth3 firewall in name 'INBOUND'", # "set interfaces ethernet eth3 firewall out name 'OUTBOUND'", # "set interfaces ethernet eth3 firewall local name 'LOCAL'", # "set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL'" # ] # # "after": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth3" # } # ] # # After state: # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall in name 'INBOUND' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall local name 'LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth3 firewall local name 'LOCAL' # set interfaces ethernet eth3 firewall out name 'OUTBOUND' # Using merged - # + # Before state: # ------------- - # - # vyos@vyos:~$ show configuration commands| grep firewall - # set firewall ipv6-name 'V6-LOCAL' - # set firewall name 'INBOUND' - # set firewall name 'LOCAL' - # set firewall name 'OUTBOUND' - # set interfaces ethernet eth1 firewall in name 'INBOUND' - # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' - # set interfaces ethernet eth1 firewall local name 'LOCAL' - # set interfaces ethernet eth1 firewall out name 'OUTBOUND' - # set interfaces ethernet eth3 firewall in name 'INBOUND' - # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' - # set interfaces ethernet eth3 firewall local name 'LOCAL' - # set interfaces ethernet eth3 firewall out name 'OUTBOUND' - # - - name: Merge the provided configuration with the existing running configuration - vyos.vyos.vyos_firewall_interfaces: + # vyos@vyos:~$ show configuration commands | grep interfaces + # set interfaces bonding 'bond0' + # set interfaces bonding 'bond1' + # set interfaces bonding bond2 'ip' + # set interfaces bonding bond2 'ipv6' + # set interfaces ethernet eth0 address 'dhcp' + # set interfaces ethernet eth0 duplex 'auto' + # set interfaces ethernet eth0 'ip' + # set interfaces ethernet eth0 'ipv6' + # set interfaces ethernet eth0 smp_affinity 'auto' + # set interfaces ethernet eth0 speed 'auto' + # set interfaces ethernet 'eth1' + # set interfaces ethernet 'eth2' + + - name: Merge provided configuration with device configuration + vyos.vyos.vyos_interfaces: config: - - access_rules: - - afi: ipv4 - rules: - - name: OUTBOUND - direction: in - - name: INBOUND - direction: out - name: eth1 + - name: eth2 + description: Configured by Ansible + enabled: true + vifs: + - vlan_id: 200 + description: VIF 200 - ETH2 + - name: eth3 + description: Configured by Ansible + mtu: 1500 + - name: bond1 + description: Bond - 1 + mtu: 1200 + - name: vti2 + description: VTI - 2 + enabled: false state: merged - # - # - # ------------------------- - # Module Execution Result - # ------------------------- - # - # "before": [ - # { - # "name": "eth0" - # }, - # { - # "access_rules": [ - # { - # "afi": "ipv4", - # "rules": [ - # { - # "direction": "in", - # "name": "INBOUND" - # }, - # { - # "direction": "local", - # "name": "LOCAL" - # }, - # { - # "direction": "out", - # "name": "OUTBOUND" - # } - # ] - # }, - # { - # "afi": "ipv6", - # "rules": [ - # { - # "direction": "local", - # "name": "V6-LOCAL" - # } - # ] - # } - # ], - # "name": "eth1" - # }, - # { - # "name": "eth2" - # }, - # { - # "access_rules": [ - # { - # "afi": "ipv4", - # "rules": [ - # { - # "direction": "in", - # "name": "INBOUND" - # }, - # { - # "direction": "local", - # "name": "LOCAL" - # }, - # { - # "direction": "out", - # "name": "OUTBOUND" - # } - # ] - # }, - # { - # "afi": "ipv6", - # "rules": [ - # { - # "direction": "local", - # "name": "V6-LOCAL" - # } - # ] - # } - # ], - # "name": "eth3" - # } - # ] - # - # "commands": [ - # "set interfaces ethernet eth1 firewall in name 'OUTBOUND'", - # "set interfaces ethernet eth1 firewall out name 'INBOUND'" - # ] - # - # "after": [ - # { - # "name": "eth0" - # }, - # { - # "access_rules": [ - # { - # "afi": "ipv4", - # "rules": [ - # { - # "direction": "in", - # "name": "OUTBOUND" - # }, - # { - # "direction": "local", - # "name": "LOCAL" - # }, - # { - # "direction": "out", - # "name": "INBOUND" - # } - # ] - # }, - # { - # "afi": "ipv6", - # "rules": [ - # { - # "direction": "local", - # "name": "V6-LOCAL" - # } - # ] - # } - # ], - # "name": "eth1" - # }, - # { - # "name": "eth2" - # }, - # { - # "access_rules": [ - # { - # "afi": "ipv4", - # "rules": [ - # { - # "direction": "in", - # "name": "INBOUND" - # }, - # { - # "direction": "local", - # "name": "LOCAL" - # }, - # { - # "direction": "out", - # "name": "OUTBOUND" - # } - # ] - # }, - # { - # "afi": "ipv6", - # "rules": [ - # { - # "direction": "local", - # "name": "V6-LOCAL" - # } - # ] - # } - # ], - # "name": "eth3" - # } - # ] - # + # Task Output + # ----------- + # before: + # - enabled: true + # name: lo + # - enabled: true + # name: eth3 + # - enabled: true + # name: eth2 + # - enabled: true + # name: eth1 + # - duplex: auto + # enabled: true + # name: eth0 + # speed: auto + # commands: + # - set interfaces ethernet eth2 description 'Configured by Ansible' + # - set interfaces ethernet eth2 vif 200 + # - set interfaces ethernet eth2 vif 200 description 'VIF 200 - ETH2' + # - set interfaces ethernet eth3 description 'Configured by Ansible' + # - set interfaces ethernet eth3 mtu '1500' + # - set interfaces bonding bond1 + # - set interfaces bonding bond1 description 'Bond - 1' + # - set interfaces bonding bond1 mtu '1200' + # - set interfaces vti vti2 + # - set interfaces vti vti2 description 'VTI - 2' + # - set interfaces vti vti2 disable + # after: + # - description: Bond - 1 + # enabled: true + # mtu: 1200 + # name: bond1 + # - enabled: true + # name: lo + # - description: VTI - 2 + # enabled: false + # name: vti2 + # - description: Configured by Ansible + # enabled: true + # mtu: 1500 + # name: eth3 + # - description: Configured by Ansible + # enabled: true + # name: eth2 + # vifs: + # - description: VIF 200 - ETH2 + # enabled: true + # vlan_id: '200' + # - enabled: true + # name: eth1 + # - duplex: auto + # enabled: true + # name: eth0 + # speed: auto + # After state: - # ------------- - # - # vyos@vyos:~$ show configuration commands| grep firewall - # set firewall ipv6-name 'V6-LOCAL' - # set firewall name 'INBOUND' - # set firewall name 'LOCAL' - # set firewall name 'OUTBOUND' - # set interfaces ethernet eth1 firewall in name 'OUTBOUND' - # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' - # set interfaces ethernet eth1 firewall local name 'LOCAL' - # set interfaces ethernet eth1 firewall out name 'INBOUND' - # set interfaces ethernet eth3 firewall in name 'INBOUND' - # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' - # set interfaces ethernet eth3 firewall local name 'LOCAL' - # set interfaces ethernet eth3 firewall out name 'OUTBOUND' + # ------------ + # vyos@vyos:~$ show configuration commands | grep interfaces + # set interfaces bonding bond1 description 'Bond - 1' + # set interfaces bonding bond1 mtu '1200' + # set interfaces ethernet eth0 address 'dhcp' + # set interfaces ethernet eth0 address 'dhcpv6' + # set interfaces ethernet eth0 duplex 'auto' + # set interfaces ethernet eth0 hw-id '08:00:27:30:f0:22' + # set interfaces ethernet eth0 smp-affinity 'auto' + # set interfaces ethernet eth0 speed 'auto' + # set interfaces ethernet eth1 hw-id '08:00:27:ea:0f:b9' + # set interfaces ethernet eth1 smp-affinity 'auto' + # set interfaces ethernet eth2 description 'Configured by Ansible' + # set interfaces ethernet eth2 hw-id '08:00:27:c2:98:23' + # set interfaces ethernet eth2 smp-affinity 'auto' + # set interfaces ethernet eth2 vif 200 description 'VIF 200 - ETH2' + # set interfaces ethernet eth3 description 'Configured by Ansible' + # set interfaces ethernet eth3 hw-id '08:00:27:43:70:8c' + # set interfaces ethernet eth3 mtu '1500' + # set interfaces loopback lo + # set interfaces vti vti2 description 'VTI - 2' + # set interfaces vti vti2 disable # Using replaced # # Before state: # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall in name 'INBOUND' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall local name 'LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth3 firewall local name 'LOCAL' # set interfaces ethernet eth3 firewall out name 'OUTBOUND' # - name: >- Replace device configurations of listed firewall interfaces with provided configurations vyos.vyos.vyos_firewall_interfaces: config: - name: eth1 access_rules: - afi: ipv4 rules: - name: OUTBOUND direction: out - afi: ipv6 rules: - name: V6-LOCAL direction: local - name: eth3 access_rules: - afi: ipv4 rules: - name: INBOUND direction: in state: replaced - # # # ------------------------- # Module Execution Result # ------------------------- # # "before": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth3" # } # ] # # "commands": [ # "delete interfaces ethernet eth1 firewall in name", # "delete interfaces ethernet eth1 firewall local name", # "delete interfaces ethernet eth3 firewall local name", # "delete interfaces ethernet eth3 firewall out name", # "delete interfaces ethernet eth3 firewall local ipv6-name" # ] # # "after": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # } # ] # } # ], # "name": "eth3" # } # ] # # After state: # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall 'in' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall 'local' # set interfaces ethernet eth3 firewall 'out' # Using overridden # # Before state # -------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall 'in' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall 'local' # set interfaces ethernet eth3 firewall 'out' # - name: Overrides all device configuration with provided configuration vyos.vyos.vyos_firewall_interfaces: config: - name: eth3 access_rules: - afi: ipv4 rules: - name: INBOUND direction: out state: overridden # # # ------------------------- # Module Execution Result # ------------------------- # # "before":[ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # } # ] # } # ], # "name": "eth3" # } # ] # # "commands": [ # "delete interfaces ethernet eth1 firewall", # "delete interfaces ethernet eth3 firewall in name", # "set interfaces ethernet eth3 firewall out name 'INBOUND'" - # + # ] # # "after": [ # { # "name": "eth0" # }, # { # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "out", # "name": "INBOUND" # } # ] # } # ], # "name": "eth3" # } # ] # # # After state # ------------ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth3 firewall 'in' # set interfaces ethernet eth3 firewall 'local' # set interfaces ethernet eth3 firewall out name 'INBOUND' # Using deleted per interface name # # Before state # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall in name 'INBOUND' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall local name 'LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth3 firewall local name 'LOCAL' # set interfaces ethernet eth3 firewall out name 'OUTBOUND' # - name: Delete firewall interfaces based on interface name. vyos.vyos.vyos_firewall_interfaces: config: - name: eth1 - name: eth3 state: deleted # # # ------------------------ # Module Execution Results # ------------------------ # # "before": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth3" # } # ] # "commands": [ # "delete interfaces ethernet eth1 firewall", # "delete interfaces ethernet eth3 firewall" # ] # - # "after": [ - # { - # "name": "eth0" - # }, - # { - # "name": "eth1" - # }, - # { - # "name": "eth2" - # }, - # { - # "name": "eth3" - # } - # ] + # "after" : [] # After state # ------------ # vyos@vyos# run show configuration commands | grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # Using deleted per afi # # Before state # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall in name 'INBOUND' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall local name 'LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth3 firewall local name 'LOCAL' # set interfaces ethernet eth3 firewall out name 'OUTBOUND' # - name: Delete firewall interfaces config per afi. vyos.vyos.vyos_firewall_interfaces: config: - name: eth1 access_rules: - afi: ipv4 - afi: ipv6 state: deleted # # # ------------------------ # Module Execution Results # ------------------------ # # "commands": [ # "delete interfaces ethernet eth1 firewall in name", # "delete interfaces ethernet eth1 firewall out name", # "delete interfaces ethernet eth1 firewall local name", # "delete interfaces ethernet eth1 firewall local ipv6-name" # ] # # After state # ------------ # vyos@vyos# run show configuration commands | grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' + # Using deleted without config # # Before state # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall in name 'INBOUND' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall local name 'LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth3 firewall local name 'LOCAL' # set interfaces ethernet eth3 firewall out name 'OUTBOUND' # - name: Delete firewall interfaces config when empty config provided. vyos.vyos.vyos_firewall_interfaces: state: deleted + # After state + # ------------ + # vyos@vyos# run show configuration commands | grep firewall + # set firewall ipv6-name 'V6-LOCAL' + # set firewall name 'INBOUND' + # set firewall name 'LOCAL' + # set firewall name 'OUTBOUND' # # # ------------------------ # Module Execution Results # ------------------------ # # "commands": [ # "delete interfaces ethernet eth1 firewall", # "delete interfaces ethernet eth1 firewall" # ] # - # After state - # ------------ - # vyos@vyos# run show configuration commands | grep firewall - # set firewall ipv6-name 'V6-LOCAL' - # set firewall name 'INBOUND' - # set firewall name 'LOCAL' - # set firewall name 'OUTBOUND' # Using parsed # + # - name: Parse the provided configuration vyos.vyos.vyos_firewall_interfaces: running_config: "set interfaces ethernet eth1 firewall in name 'INBOUND' set interfaces ethernet eth1 firewall out name 'OUTBOUND' set interfaces ethernet eth1 firewall local name 'LOCAL' set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' set interfaces ethernet eth2 firewall in name 'INBOUND' set interfaces ethernet eth2 firewall out name 'OUTBOUND' set interfaces ethernet eth2 firewall local name 'LOCAL' set interfaces ethernet eth2 firewall local ipv6-name 'V6-LOCAL'" state: parsed # # # ------------------------- # Module Execution Result # ------------------------- # # # "parsed": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth2" # }, # { # "name": "eth3" # } # ] # Using gathered # # Before state: # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall 'in' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall 'local' # set interfaces ethernet eth3 firewall 'out' # - name: Gather listed firewall interfaces. vyos.vyos.vyos_firewall_interfaces: state: gathered # # # ------------------------- # Module Execution Result # ------------------------- # # "gathered": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # } # ] # } # ], # "name": "eth3" # } # ] # # # After state: # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall 'in' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall 'local' # set interfaces ethernet eth3 firewall 'out' # Using rendered # # - name: Render the commands for provided configuration vyos.vyos.vyos_firewall_interfaces: config: - name: eth2 access_rules: - afi: ipv4 rules: - - direction: in - name: INGRESS - - direction: out - name: OUTGRESS - - direction: local - name: DROP + - name: INGRESS + direction: in + - name: OUTGRESS + direction: out + - name: DROP + direction: local state: rendered - # # # ------------------------- # Module Execution Result # ------------------------- # # # "rendered": [ # "set interfaces ethernet eth2 firewall in name 'INGRESS'", # "set interfaces ethernet eth2 firewall out name 'OUTGRESS'", # "set interfaces ethernet eth2 firewall local name 'DROP'", # "set interfaces ethernet eth2 firewall local ipv6-name 'LOCAL'" # ] Return Values ------------- Common return values are documented `here `_, the following are the fields unique to this module: .. raw:: html - + + + + + + + + + + + + + + + +
Key Returned Description
after
- list + dictionary
when changed -
The resulting configuration model invocation.
+
The resulting configuration after module execution.

Sample:
-
The configuration returned will always be in the same format - of the parameters above.
+
This output will always be in the same format as the module argspec.
before
- list + dictionary
alwayswhen state is merged, replaced, overridden, deleted or purged -
The configuration prior to the model invocation.
+
The configuration prior to the module execution.

Sample:
-
The configuration returned will always be in the same format - of the parameters above.
+
This output will always be in the same format as the module argspec.
commands
list
always
The set of commands pushed to the remote device.

Sample:
["set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL'", "set interfaces ethernet eth3 firewall in name 'INBOUND'"]
+
+ gathered + +
+ list +
+
when state is gathered +
Facts about the network resource gathered from the remote device as structured data.
+
+
Sample:
+
This output will always be in the same format as the module argspec.
+
+
+ parsed + +
+ list +
+
when state is parsed +
The device native config provided in running_config option parsed into structured data as per module argspec.
+
+
Sample:
+
This output will always be in the same format as the module argspec.
+
+
+ rendered + +
+ list +
+
when state is rendered +
The provided configuration in the task rendered in device-native format (offline).
+
+
Sample:
+
["set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL'", "set interfaces ethernet eth3 firewall in name 'INBOUND'"]
+


Status ------ Authors ~~~~~~~ - Rohit Thakur (@rohitthakur2590) diff --git a/plugins/module_utils/network/vyos/argspec/firewall_interfaces/firewall_interfaces.py b/plugins/module_utils/network/vyos/argspec/firewall_interfaces/firewall_interfaces.py index a613ccd3..93c898e8 100644 --- a/plugins/module_utils/network/vyos/argspec/firewall_interfaces/firewall_interfaces.py +++ b/plugins/module_utils/network/vyos/argspec/firewall_interfaces/firewall_interfaces.py @@ -1,85 +1,93 @@ # # -*- coding: utf-8 -*- # Copyright 2019 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) ############################################# # WARNING # ############################################# # # This file is auto generated by the resource # module builder playbook. # # Do not edit this file manually. # # Changes to this file will be over written # by the resource module builder. # # Changes should be made in the model used to # generate this file or in the resource module # builder template. # ############################################# """ The arg spec for the vyos_firewall_interfaces module """ + from __future__ import absolute_import, division, print_function __metaclass__ = type class Firewall_interfacesArgs(object): # pylint: disable=R0903 """The arg spec for the vyos_firewall_interfaces module""" def __init__(self, **kwargs): pass argument_spec = { "config": { "elements": "dict", "options": { "access_rules": { "elements": "dict", "options": { "afi": { - "choices": ["ipv4", "ipv6"], + "choices": [ + "ipv4", + "ipv6", + ], "required": True, "type": "str", }, "rules": { "elements": "dict", "options": { "direction": { - "choices": ["in", "local", "out"], + "choices": [ + "in", + "local", + "out", + ], "required": True, "type": "str", }, "name": {"type": "str"}, }, "type": "list", }, }, "type": "list", }, "name": {"required": True, "type": "str"}, }, "type": "list", }, "running_config": {"type": "str"}, "state": { "choices": [ "merged", "replaced", "overridden", "deleted", "parsed", "rendered", "gathered", ], "default": "merged", "type": "str", }, } # pylint: disable=C0301 diff --git a/plugins/module_utils/network/vyos/config/firewall_interfaces/firewall_interfaces.py b/plugins/module_utils/network/vyos/config/firewall_interfaces/firewall_interfaces.py index 5c4db736..85a8042f 100644 --- a/plugins/module_utils/network/vyos/config/firewall_interfaces/firewall_interfaces.py +++ b/plugins/module_utils/network/vyos/config/firewall_interfaces/firewall_interfaces.py @@ -1,414 +1,431 @@ # # -*- coding: utf-8 -*- # Copyright 2019 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) """ The vyos_firewall_interfaces class It is in this file where the current configuration (as dict) is compared to the provided configuration (as dict) and the command set necessary to bring the current configuration to it's desired end-state is created """ from __future__ import absolute_import, division, print_function __metaclass__ = type from copy import deepcopy from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( remove_empties, search_obj_in_list, to_list, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import Facts +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import ( + get_interface_type, +) class Firewall_interfaces(ConfigBase): """ The vyos_firewall_interfaces class """ gather_subset = [ "!all", "!min", ] gather_network_resources = [ "firewall_interfaces", ] def __init__(self, module): super(Firewall_interfaces, self).__init__(module) def get_firewall_interfaces_facts(self, data=None): """Get the 'facts' (the current configuration) :rtype: A dictionary :returns: The current configuration as a dictionary """ facts, _warnings = Facts(self._module).get_facts( self.gather_subset, self.gather_network_resources, data=data, ) firewall_interfaces_facts = facts["ansible_network_resources"].get("firewall_interfaces") if not firewall_interfaces_facts: return [] return firewall_interfaces_facts def execute_module(self): """Execute the module :rtype: A dictionary :returns: The result from module execution """ result = {"changed": False} warnings = list() commands = list() if self.state in self.ACTION_STATES: existing_firewall_interfaces_facts = self.get_firewall_interfaces_facts() else: existing_firewall_interfaces_facts = [] if self.state in self.ACTION_STATES or self.state == "rendered": commands.extend(self.set_config(existing_firewall_interfaces_facts)) if commands and self.state in self.ACTION_STATES: if not self._module.check_mode: self._connection.edit_config(commands) result["changed"] = True if self.state in self.ACTION_STATES: result["commands"] = commands if self.state in self.ACTION_STATES or self.state == "gathered": changed_firewall_interfaces_facts = self.get_firewall_interfaces_facts() elif self.state == "rendered": result["rendered"] = commands elif self.state == "parsed": running_config = self._module.params["running_config"] if not running_config: self._module.fail_json( msg="value of running_config parameter must not be empty for state parsed", ) result["parsed"] = self.get_firewall_interfaces_facts(data=running_config) else: changed_firewall_interfaces_facts = [] if self.state in self.ACTION_STATES: result["before"] = existing_firewall_interfaces_facts if result["changed"]: result["after"] = changed_firewall_interfaces_facts elif self.state == "gathered": result["gathered"] = changed_firewall_interfaces_facts result["warnings"] = warnings return result def set_config(self, existing_firewall_interfaces_facts): """Collect the configuration from the args passed to the module, collect the current configuration (as a dict from facts) :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ want = self._module.params["config"] have = existing_firewall_interfaces_facts resp = self.set_state(want, have) return to_list(resp) def set_state(self, w, h): """Select the appropriate function based on the state provided :param want: the desired configuration as a dictionary :param have: the current configuration as a dictionary :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ commands = [] if self.state in ("merged", "replaced", "overridden", "rendered") and not w: self._module.fail_json( msg="value of config parameter must not be empty for state {0}".format(self.state), ) if self.state == "overridden": commands.extend(self._state_overridden(w, h)) elif self.state == "deleted": commands.extend(self._state_deleted(w, h)) elif w: if self.state == "merged" or self.state == "rendered": commands.extend(self._state_merged(w, h)) elif self.state == "replaced": commands.extend(self._state_replaced(w, h)) return commands def _state_replaced(self, want, have): """The command generator when state is replaced :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ commands = [] if have: for h in have: w = search_obj_in_list(h["name"], want) commands.extend(self._render_access_rules(h, w, opr=False)) commands.extend(self._state_merged(want, have)) return commands def _state_overridden(self, want, have): """The command generator when state is overridden :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ commands = [] if have: for h_ar in have: w_ar = search_obj_in_list(h_ar["name"], want) if not w_ar and "access_rules" in h_ar: commands.append(self._compute_command(name=h_ar["name"], opr=False)) else: h_rules = h_ar.get("access_rules") or [] key = "direction" if w_ar: w_rules = w_ar.get("access_rules") or [] if not w_rules and h_rules: commands.append(self._compute_command(name=h_ar["name"], opr=False)) if h_rules: for h_rule in h_rules: w_rule = search_obj_in_list(h_rule["afi"], w_rules, key="afi") have_rules = h_rule.get("rules") or [] if w_rule: want_rules = w_rule.get("rules") or [] for h in have_rules: if key in h: w = search_obj_in_list(h[key], want_rules, key=key) if ( not w or key not in w or ("name" in h and w and "name" not in w) ): commands.append( self._compute_command( afi=h_rule["afi"], name=h_ar["name"], attrib=h[key], opr=False, ), ) commands.extend(self._state_merged(want, have)) return commands def _state_merged(self, want, have): """The command generator when state is merged :rtype: A list :returns: the commands necessary to merge the provided into the current configuration """ commands = [] for w in want: h = search_obj_in_list(w["name"], have) commands.extend(self._render_access_rules(w, h)) return commands def _state_deleted(self, want, have): """The command generator when state is deleted :rtype: A list :returns: the commands necessary to remove the current configuration of the provided objects """ commands = [] if want: for w in want: h = search_obj_in_list(w["name"], have) if h and "access_rules" in h: commands.extend(self._delete_access_rules(w, h, opr=False)) elif have: for h in have: if "access_rules" in h: commands.append(self._compute_command(name=h["name"], opr=False)) return commands def _delete_access_rules(self, want, have, opr=False): """ This function forms the delete commands based on the 'opr' type for 'access_rules' attributes. :param want: desired config. :param have: target config. :param opr: True/False. :return: generated commands list. """ commands = [] h_rules = {} w_rs = deepcopy(remove_empties(want)) w_rules = w_rs.get("access_rules") or [] if have: h_rs = deepcopy(remove_empties(have)) h_rules = h_rs.get("access_rules") or [] # if all firewall config needed to be deleted for specific interface # when operation is delete. if not w_rules and h_rules: commands.append(self._compute_command(name=want["name"], opr=opr)) if w_rules: for w in w_rules: h = search_obj_in_list(w["afi"], h_rules, key="afi") commands.extend(self._delete_rules(want["name"], w, h)) return commands def _delete_rules(self, name, want, have, opr=False): """ This function forms the delete commands based on the 'opr' type for rules attributes. :param name: interface id/name. :param want: desired config. :param have: target config. :param opr: True/False. :return: generated commands list. """ commands = [] h_rules = [] key = "direction" w_rules = want.get("rules") or [] if have: h_rules = have.get("rules") or [] # when rule set needed to be removed on # (inbound|outbound|local interface) if h_rules and not w_rules: for h in h_rules: if key in h: commands.append( self._compute_command(afi=want["afi"], name=name, attrib=h[key], opr=opr), ) for w in w_rules: h = search_obj_in_list(w[key], h_rules, key=key) if ( key in w and h and key in h and "name" in w and "name" in h and w["name"] == h["name"] ): commands.append( self._compute_command( afi=want["afi"], name=name, attrib=w[key], value=w["name"], opr=opr, ), ) return commands def _render_access_rules(self, want, have, opr=True): """ This function forms the set/delete commands based on the 'opr' type for 'access_rules' attributes. :param want: desired config. :param have: target config. :param opr: True/False. :return: generated commands list. """ commands = [] h_rules = {} w_rs = deepcopy(remove_empties(want)) w_rules = w_rs.get("access_rules") or [] if have: h_rs = deepcopy(remove_empties(have)) h_rules = h_rs.get("access_rules") or [] if w_rules: for w in w_rules: h = search_obj_in_list(w["afi"], h_rules, key="afi") commands.extend(self._render_rules(want["name"], w, h, opr)) return commands def _render_rules(self, name, want, have, opr=True): """ This function forms the set/delete commands based on the 'opr' type for rules attributes. :param name: interface id/name. :param want: desired config. :param have: target config. :param opr: True/False. :return: generated commands list. """ commands = [] h_rules = [] key = "direction" w_rules = want.get("rules") or [] if have: h_rules = have.get("rules") or [] for w in w_rules: h = search_obj_in_list(w[key], h_rules, key=key) if key in w: if opr: if "name" in w and not (h and h[key] == w[key] and h["name"] == w["name"]): commands.append( self._compute_command( afi=want["afi"], name=name, attrib=w[key], value=w["name"], ), ) elif not (h and key in h): commands.append( self._compute_command(afi=want["afi"], name=name, attrib=w[key]), ) elif not opr: if not h or key not in h or ("name" in w and h and "name" not in h): commands.append( self._compute_command( afi=want["afi"], name=name, attrib=w[key], opr=opr, ), ) return commands def _compute_command(self, afi=None, name=None, attrib=None, value=None, opr=True): """ This function construct the add/delete command based on passed attributes. :param afi: address type. :param name: interface name. :param attrib: attribute name. :param value: attribute value. :param opr: operation flag. :return: generated command. """ + + # Append vif if interface contains a dot + vlan = None + interface_real = name + if "." in name: + interface_real, vlan = name.split(".") + + if vlan is not None: + interface_real = interface_real + " vif " + vlan + + # if interface name is bondX, then it's a bonding interface. Everything else is an ethernet + iftype = get_interface_type(interface_real) + if not opr: - cmd = "delete interfaces ethernet" + " " + name + " firewall" + cmd = "delete interfaces " + iftype + " " + interface_real + " firewall" else: - cmd = "set interfaces ethernet" + " " + name + " firewall" + cmd = "set interfaces " + iftype + " " + interface_real + " firewall" + if attrib: cmd += " " + attrib if afi: cmd += " " + self._get_fw_type(afi) if value: cmd += " '" + str(value) + "'" return cmd def _get_fw_type(self, afi): """ This function returns the firewall rule-set type based on IP address. :param afi: address type :return: rule-set type. """ return "ipv6-name" if afi == "ipv6" else "name" diff --git a/plugins/module_utils/network/vyos/facts/firewall_interfaces/firewall_interfaces.py b/plugins/module_utils/network/vyos/facts/firewall_interfaces/firewall_interfaces.py index b9804692..bac31920 100644 --- a/plugins/module_utils/network/vyos/facts/firewall_interfaces/firewall_interfaces.py +++ b/plugins/module_utils/network/vyos/facts/firewall_interfaces/firewall_interfaces.py @@ -1,188 +1,203 @@ # # -*- coding: utf-8 -*- # Copyright 2019 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) """ The vyos firewall_interfaces fact class It is in this file the configuration is collected from the device for a given resource, parsed, and the facts tree is populated based on the configuration. """ from __future__ import absolute_import, division, print_function __metaclass__ = type from copy import deepcopy from re import M, findall, search from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.firewall_interfaces.firewall_interfaces import ( Firewall_interfacesArgs, ) class Firewall_interfacesFacts(object): """The vyos firewall_interfaces fact class""" def __init__(self, module, subspec="config", options="options"): self._module = module self.argument_spec = Firewall_interfacesArgs.argument_spec spec = deepcopy(self.argument_spec) if subspec: if options: facts_argument_spec = spec[subspec][options] else: facts_argument_spec = spec[subspec] else: facts_argument_spec = spec self.generated_spec = utils.generate_dict(facts_argument_spec) def get_device_data(self, connection): return connection.get_config() def populate_facts(self, connection, ansible_facts, data=None): """Populate the facts for firewall_interfaces :param connection: the device connection :param ansible_facts: Facts dictionary :param data: previously collected conf :rtype: dictionary :returns: facts """ if not data: # typically data is populated from the current device configuration # data = connection.get('show running-config | section ^interface') # using mock data instead data = self.get_device_data(connection) objs = [] - interfaces = findall(r"^set interfaces ethernet (?:\'*)(\S+)(?:\'*)", data, M) + # Search all set from configuration with set interface, including ethernet and bonding + interfaces_raw = findall(r"^set interfaces \S+ (\S+) firewall (?:\'*)", data, M) + interfaces_vif = findall(r"^set interfaces \S+ (\S+) vif (\d+)* firewall (?:\'*)", data, M) + interfaces = interfaces_raw + interfaces_vif if interfaces: objs = self.get_names(data, interfaces) ansible_facts["ansible_network_resources"].pop("firewall_interfaces", None) facts = {} if objs: facts["firewall_interfaces"] = [] params = utils.validate_config(self.argument_spec, {"config": objs}) for cfg in params["config"]: facts["firewall_interfaces"].append(utils.remove_empties(cfg)) ansible_facts["ansible_network_resources"].update(facts) return ansible_facts def get_names(self, data, interfaces): """ This function performs following: - Form regex to fetch 'interface name' from interfaces firewall data. - Form the name list. :param data: configuration. :param rules: list of interfaces. :return: generated firewall interfaces configuration. """ names = [] for r in set(interfaces): - int_regex = r" %s .+$" % r.strip("'") - cfg = findall(int_regex, data, M) - fi = self.render_config(cfg) - fi["name"] = r.strip("'") + myvif = None + if isinstance(r, tuple): + myinterface, myvif = r + else: + myinterface = r + # Parse interfaces that contains string or tuple when the interface is in a vlan + if myvif is not None: + int_regex = r" %s vif \d+ firewall .+$" % myinterface + cfg = findall(int_regex, data, M) + fi = self.render_config(cfg) + fi["name"] = myinterface + "." + myvif + else: + int_regex = r" %s firewall .+$" % myinterface + cfg = findall(int_regex, data, M) + fi = self.render_config(cfg) + fi["name"] = myinterface names.append(fi) if names: names = sorted(names, key=lambda i: i["name"]) return names def render_config(self, conf): """ Render config as dictionary structure and delete keys from spec for null values :param spec: The facts tree, generated from the argspec :param conf: The configuration :rtype: dictionary :returns: The generated config """ conf = "\n".join(filter(lambda x: "firewall" in x, conf)) config = {"access_rules": self.parse_access_rules(conf)} return config def parse_access_rules(self, conf): """ This function forms the regex to fetch the 'access-rules' for specific interface. :param conf: configuration data. :return: generated access-rules list configuration. """ ar_lst = [] v4_ar = findall(r"^.*(in|out|local) name .*$", conf, M) v6_ar = findall(r"^.*(in|out|local) ipv6-name .*$", conf, M) if v4_ar: v4_conf = "\n".join(findall(r"(^.*?%s.*?$)" % " name", conf, M)) config = self.parse_int_rules(v4_conf, "ipv4") if config: ar_lst.append(config) if v6_ar: v6_conf = "\n".join(findall(r"(^.*?%s.*?$)" % " ipv6-name", conf, M)) config = self.parse_int_rules(v6_conf, "ipv6") if config: ar_lst.append(config) if ar_lst: ar_lst = sorted(ar_lst, key=lambda i: i["afi"]) else: empty_rules = findall(r"^.*(in|out|local).*", conf, M) if empty_rules: ar_lst.append({"afi": "ipv4", "rules": []}) ar_lst.append({"afi": "ipv6", "rules": []}) return ar_lst def parse_int_rules(self, conf, afi): """ This function forms the regex to fetch the 'access-rules' for specific interface based on ip-type. :param conf: configuration data. :param rules: rules configured per interface. :param afi: ip address type. :return: generated rule configuration dictionary. """ r_lst = [] config = {} rules = ["in", "out", "local"] for r in set(rules): fr = {} r_regex = r" %s .+$" % r cfg = "\n".join(findall(r_regex, conf, M)) if cfg: fr = self.parse_rules(cfg, afi) else: out = search(r"^.*firewall " + "'" + r + "'" + "(.*)", conf, M) if out: fr = {"direction": r} if fr: r_lst.append(fr) if r_lst: r_lst = sorted(r_lst, key=lambda i: i["direction"]) config = {"afi": afi, "rules": r_lst} return config def parse_rules(self, conf, afi): """ This function triggers the parsing of 'rule' attributes. a_lst is a list having rule attributes which doesn't have further sub attributes. :param conf: configuration. :param afi: ip address type. :return: generated rule configuration dictionary. """ cfg = {} out = findall(r"[^\s]+", conf, M) if out: cfg["direction"] = out[0].strip("'") if afi == "ipv6": out = findall(r"[^\s]+ ipv6-name (?:\'*)(\S+)(?:\'*)", conf, M) if out: cfg["name"] = str(out[0]).strip("'") else: out = findall(r"[^\s]+ name (?:\'*)(\S+)(?:\'*)", conf, M) if out: cfg["name"] = out[-1].strip("'") return cfg diff --git a/plugins/modules/vyos_firewall_interfaces.py b/plugins/modules/vyos_firewall_interfaces.py index 11f3e527..2feabe49 100644 --- a/plugins/modules/vyos_firewall_interfaces.py +++ b/plugins/modules/vyos_firewall_interfaces.py @@ -1,1288 +1,1222 @@ #!/usr/bin/python # -*- coding: utf-8 -*- # Copyright 2019 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) ############################################# # WARNING # ############################################# # # This file is auto generated by the resource # module builder playbook. # # Do not edit this file manually. # # Changes to this file will be over written # by the resource module builder. # # Changes should be made in the model used to # generate this file or in the resource module # builder template. # ############################################# """ The module file for vyos_firewall_interfaces """ from __future__ import absolute_import, division, print_function __metaclass__ = type +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "network", +} DOCUMENTATION = """ +--- module: vyos_firewall_interfaces -short_description: FIREWALL interfaces resource module -description: Manage firewall rules of interfaces on VyOS network devices. -version_added: 1.0.0 +version_added: '2.10.0' +short_description: Manage firewall rules attributes of interfaces on VyOS devices +description: Manage firewall rules of interfaces on VyOS network devices. (1.3-) author: - Rohit Thakur (@rohitthakur2590) +notes: +- Deprecated in VyOS 1.4+, firewalls are no longer connected directly to interfaces. + See the Firewall Configuration documentation for how to establish a + connection betwen the firewall rulesets and the flow, interface, or zone. options: config: description: A list of firewall rules options for interfaces. type: list elements: dict suboptions: name: description: - Name/Identifier for the interface. type: str required: true access_rules: description: - Specifies firewall rules attached to the interfaces. type: list elements: dict suboptions: afi: description: - Specifies the AFI for the Firewall rules to be configured on this interface. type: str choices: - ipv4 - ipv6 required: true rules: description: - Specifies the firewall rules for the provided AFI. type: list elements: dict suboptions: name: description: - Specifies the name of the IPv4/IPv6 Firewall rule for the interface. type: str direction: description: - Specifies the direction of packets that the firewall rule will be applied on. type: str choices: - in - local - out required: true running_config: description: - The module, by default, will connect to the remote device and retrieve the current running-config to use as a base for comparing against the contents of source. There are times when it is not desirable to have the task get the current running-config for every task in a playbook. The I(running_config) argument allows the implementer to pass in the configuration to use as the base config for comparison. This value of this option should be the output received from device by executing command C(show configuration commands | grep 'firewall'). type: str state: description: - The state the configuration should be left in. type: str choices: - merged - replaced - overridden - deleted - parsed - rendered - gathered default: merged - """ EXAMPLES = """ # Using merged # # Before state: # ------------- # # vyos@192# run show configuration commands | grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # - name: Merge the provided configuration with the existing running configuration vyos.vyos.vyos_firewall_interfaces: config: - access_rules: - afi: ipv4 rules: - name: INBOUND direction: in - name: OUTBOUND direction: out - name: LOCAL direction: local - afi: ipv6 rules: - name: V6-LOCAL direction: local name: eth1 - access_rules: - afi: ipv4 rules: - name: INBOUND direction: in - name: OUTBOUND direction: out - name: LOCAL direction: local - afi: ipv6 rules: - name: V6-LOCAL direction: local name: eth3 state: merged # # # ------------------------- # Module Execution Result # ------------------------- # # before": [ # { # "name": "eth0" # }, # { # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "name": "eth3" # } # ] # # "commands": [ # "set interfaces ethernet eth1 firewall in name 'INBOUND'", # "set interfaces ethernet eth1 firewall out name 'OUTBOUND'", # "set interfaces ethernet eth1 firewall local name 'LOCAL'", # "set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL'", # "set interfaces ethernet eth3 firewall in name 'INBOUND'", # "set interfaces ethernet eth3 firewall out name 'OUTBOUND'", # "set interfaces ethernet eth3 firewall local name 'LOCAL'", # "set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL'" # ] # # "after": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth3" # } # ] # # After state: # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall in name 'INBOUND' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall local name 'LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth3 firewall local name 'LOCAL' # set interfaces ethernet eth3 firewall out name 'OUTBOUND' # Using merged -# + # Before state: # ------------- -# -# vyos@vyos:~$ show configuration commands| grep firewall -# set firewall ipv6-name 'V6-LOCAL' -# set firewall name 'INBOUND' -# set firewall name 'LOCAL' -# set firewall name 'OUTBOUND' -# set interfaces ethernet eth1 firewall in name 'INBOUND' -# set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' -# set interfaces ethernet eth1 firewall local name 'LOCAL' -# set interfaces ethernet eth1 firewall out name 'OUTBOUND' -# set interfaces ethernet eth3 firewall in name 'INBOUND' -# set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' -# set interfaces ethernet eth3 firewall local name 'LOCAL' -# set interfaces ethernet eth3 firewall out name 'OUTBOUND' -# -- name: Merge the provided configuration with the existing running configuration - vyos.vyos.vyos_firewall_interfaces: +# vyos@vyos:~$ show configuration commands | grep interfaces +# set interfaces bonding 'bond0' +# set interfaces bonding 'bond1' +# set interfaces bonding bond2 'ip' +# set interfaces bonding bond2 'ipv6' +# set interfaces ethernet eth0 address 'dhcp' +# set interfaces ethernet eth0 duplex 'auto' +# set interfaces ethernet eth0 'ip' +# set interfaces ethernet eth0 'ipv6' +# set interfaces ethernet eth0 smp_affinity 'auto' +# set interfaces ethernet eth0 speed 'auto' +# set interfaces ethernet 'eth1' +# set interfaces ethernet 'eth2' + +- name: Merge provided configuration with device configuration + vyos.vyos.vyos_interfaces: config: - - access_rules: - - afi: ipv4 - rules: - - name: OUTBOUND - direction: in - - name: INBOUND - direction: out - name: eth1 + - name: eth2 + description: Configured by Ansible + enabled: true + vifs: + - vlan_id: 200 + description: VIF 200 - ETH2 + - name: eth3 + description: Configured by Ansible + mtu: 1500 + - name: bond1 + description: Bond - 1 + mtu: 1200 + - name: vti2 + description: VTI - 2 + enabled: false state: merged -# -# -# ------------------------- -# Module Execution Result -# ------------------------- -# -# "before": [ -# { -# "name": "eth0" -# }, -# { -# "access_rules": [ -# { -# "afi": "ipv4", -# "rules": [ -# { -# "direction": "in", -# "name": "INBOUND" -# }, -# { -# "direction": "local", -# "name": "LOCAL" -# }, -# { -# "direction": "out", -# "name": "OUTBOUND" -# } -# ] -# }, -# { -# "afi": "ipv6", -# "rules": [ -# { -# "direction": "local", -# "name": "V6-LOCAL" -# } -# ] -# } -# ], -# "name": "eth1" -# }, -# { -# "name": "eth2" -# }, -# { -# "access_rules": [ -# { -# "afi": "ipv4", -# "rules": [ -# { -# "direction": "in", -# "name": "INBOUND" -# }, -# { -# "direction": "local", -# "name": "LOCAL" -# }, -# { -# "direction": "out", -# "name": "OUTBOUND" -# } -# ] -# }, -# { -# "afi": "ipv6", -# "rules": [ -# { -# "direction": "local", -# "name": "V6-LOCAL" -# } -# ] -# } -# ], -# "name": "eth3" -# } -# ] -# -# "commands": [ -# "set interfaces ethernet eth1 firewall in name 'OUTBOUND'", -# "set interfaces ethernet eth1 firewall out name 'INBOUND'" -# ] -# -# "after": [ -# { -# "name": "eth0" -# }, -# { -# "access_rules": [ -# { -# "afi": "ipv4", -# "rules": [ -# { -# "direction": "in", -# "name": "OUTBOUND" -# }, -# { -# "direction": "local", -# "name": "LOCAL" -# }, -# { -# "direction": "out", -# "name": "INBOUND" -# } -# ] -# }, -# { -# "afi": "ipv6", -# "rules": [ -# { -# "direction": "local", -# "name": "V6-LOCAL" -# } -# ] -# } -# ], -# "name": "eth1" -# }, -# { -# "name": "eth2" -# }, -# { -# "access_rules": [ -# { -# "afi": "ipv4", -# "rules": [ -# { -# "direction": "in", -# "name": "INBOUND" -# }, -# { -# "direction": "local", -# "name": "LOCAL" -# }, -# { -# "direction": "out", -# "name": "OUTBOUND" -# } -# ] -# }, -# { -# "afi": "ipv6", -# "rules": [ -# { -# "direction": "local", -# "name": "V6-LOCAL" -# } -# ] -# } -# ], -# "name": "eth3" -# } -# ] -# +# Task Output +# ----------- +# before: +# - enabled: true +# name: lo +# - enabled: true +# name: eth3 +# - enabled: true +# name: eth2 +# - enabled: true +# name: eth1 +# - duplex: auto +# enabled: true +# name: eth0 +# speed: auto +# commands: +# - set interfaces ethernet eth2 description 'Configured by Ansible' +# - set interfaces ethernet eth2 vif 200 +# - set interfaces ethernet eth2 vif 200 description 'VIF 200 - ETH2' +# - set interfaces ethernet eth3 description 'Configured by Ansible' +# - set interfaces ethernet eth3 mtu '1500' +# - set interfaces bonding bond1 +# - set interfaces bonding bond1 description 'Bond - 1' +# - set interfaces bonding bond1 mtu '1200' +# - set interfaces vti vti2 +# - set interfaces vti vti2 description 'VTI - 2' +# - set interfaces vti vti2 disable +# after: +# - description: Bond - 1 +# enabled: true +# mtu: 1200 +# name: bond1 +# - enabled: true +# name: lo +# - description: VTI - 2 +# enabled: false +# name: vti2 +# - description: Configured by Ansible +# enabled: true +# mtu: 1500 +# name: eth3 +# - description: Configured by Ansible +# enabled: true +# name: eth2 +# vifs: +# - description: VIF 200 - ETH2 +# enabled: true +# vlan_id: '200' +# - enabled: true +# name: eth1 +# - duplex: auto +# enabled: true +# name: eth0 +# speed: auto + # After state: -# ------------- -# -# vyos@vyos:~$ show configuration commands| grep firewall -# set firewall ipv6-name 'V6-LOCAL' -# set firewall name 'INBOUND' -# set firewall name 'LOCAL' -# set firewall name 'OUTBOUND' -# set interfaces ethernet eth1 firewall in name 'OUTBOUND' -# set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' -# set interfaces ethernet eth1 firewall local name 'LOCAL' -# set interfaces ethernet eth1 firewall out name 'INBOUND' -# set interfaces ethernet eth3 firewall in name 'INBOUND' -# set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' -# set interfaces ethernet eth3 firewall local name 'LOCAL' -# set interfaces ethernet eth3 firewall out name 'OUTBOUND' +# ------------ +# vyos@vyos:~$ show configuration commands | grep interfaces +# set interfaces bonding bond1 description 'Bond - 1' +# set interfaces bonding bond1 mtu '1200' +# set interfaces ethernet eth0 address 'dhcp' +# set interfaces ethernet eth0 address 'dhcpv6' +# set interfaces ethernet eth0 duplex 'auto' +# set interfaces ethernet eth0 hw-id '08:00:27:30:f0:22' +# set interfaces ethernet eth0 smp-affinity 'auto' +# set interfaces ethernet eth0 speed 'auto' +# set interfaces ethernet eth1 hw-id '08:00:27:ea:0f:b9' +# set interfaces ethernet eth1 smp-affinity 'auto' +# set interfaces ethernet eth2 description 'Configured by Ansible' +# set interfaces ethernet eth2 hw-id '08:00:27:c2:98:23' +# set interfaces ethernet eth2 smp-affinity 'auto' +# set interfaces ethernet eth2 vif 200 description 'VIF 200 - ETH2' +# set interfaces ethernet eth3 description 'Configured by Ansible' +# set interfaces ethernet eth3 hw-id '08:00:27:43:70:8c' +# set interfaces ethernet eth3 mtu '1500' +# set interfaces loopback lo +# set interfaces vti vti2 description 'VTI - 2' +# set interfaces vti vti2 disable # Using replaced # # Before state: # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall in name 'INBOUND' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall local name 'LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth3 firewall local name 'LOCAL' # set interfaces ethernet eth3 firewall out name 'OUTBOUND' # - name: >- Replace device configurations of listed firewall interfaces with provided configurations vyos.vyos.vyos_firewall_interfaces: config: - name: eth1 access_rules: - afi: ipv4 rules: - name: OUTBOUND direction: out - afi: ipv6 rules: - name: V6-LOCAL direction: local - name: eth3 access_rules: - afi: ipv4 rules: - name: INBOUND direction: in state: replaced - # # # ------------------------- # Module Execution Result # ------------------------- # # "before": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth3" # } # ] # # "commands": [ # "delete interfaces ethernet eth1 firewall in name", # "delete interfaces ethernet eth1 firewall local name", # "delete interfaces ethernet eth3 firewall local name", # "delete interfaces ethernet eth3 firewall out name", # "delete interfaces ethernet eth3 firewall local ipv6-name" # ] # # "after": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # } # ] # } # ], # "name": "eth3" # } # ] # # After state: # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall 'in' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall 'local' # set interfaces ethernet eth3 firewall 'out' # Using overridden # # Before state # -------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall 'in' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall 'local' # set interfaces ethernet eth3 firewall 'out' # - name: Overrides all device configuration with provided configuration vyos.vyos.vyos_firewall_interfaces: config: - name: eth3 access_rules: - afi: ipv4 rules: - name: INBOUND direction: out state: overridden # # # ------------------------- # Module Execution Result # ------------------------- # # "before":[ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # } # ] # } # ], # "name": "eth3" # } # ] # # "commands": [ # "delete interfaces ethernet eth1 firewall", # "delete interfaces ethernet eth3 firewall in name", # "set interfaces ethernet eth3 firewall out name 'INBOUND'" -# +# ] # # "after": [ # { # "name": "eth0" # }, # { # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "out", # "name": "INBOUND" # } # ] # } # ], # "name": "eth3" # } # ] # # # After state # ------------ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth3 firewall 'in' # set interfaces ethernet eth3 firewall 'local' # set interfaces ethernet eth3 firewall out name 'INBOUND' # Using deleted per interface name # # Before state # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall in name 'INBOUND' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall local name 'LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth3 firewall local name 'LOCAL' # set interfaces ethernet eth3 firewall out name 'OUTBOUND' # - name: Delete firewall interfaces based on interface name. vyos.vyos.vyos_firewall_interfaces: config: - name: eth1 - name: eth3 state: deleted # # # ------------------------ # Module Execution Results # ------------------------ # # "before": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth3" # } # ] # "commands": [ # "delete interfaces ethernet eth1 firewall", # "delete interfaces ethernet eth3 firewall" # ] # -# "after": [ -# { -# "name": "eth0" -# }, -# { -# "name": "eth1" -# }, -# { -# "name": "eth2" -# }, -# { -# "name": "eth3" -# } -# ] +# "after" : [] # After state # ------------ # vyos@vyos# run show configuration commands | grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # Using deleted per afi # # Before state # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall in name 'INBOUND' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall local name 'LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth3 firewall local name 'LOCAL' # set interfaces ethernet eth3 firewall out name 'OUTBOUND' # - name: Delete firewall interfaces config per afi. vyos.vyos.vyos_firewall_interfaces: config: - name: eth1 access_rules: - afi: ipv4 - afi: ipv6 state: deleted # # # ------------------------ # Module Execution Results # ------------------------ # # "commands": [ # "delete interfaces ethernet eth1 firewall in name", # "delete interfaces ethernet eth1 firewall out name", # "delete interfaces ethernet eth1 firewall local name", # "delete interfaces ethernet eth1 firewall local ipv6-name" # ] # # After state # ------------ # vyos@vyos# run show configuration commands | grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' + # Using deleted without config # # Before state # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall in name 'INBOUND' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall local name 'LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth3 firewall local name 'LOCAL' # set interfaces ethernet eth3 firewall out name 'OUTBOUND' # - name: Delete firewall interfaces config when empty config provided. vyos.vyos.vyos_firewall_interfaces: state: deleted +# After state +# ------------ +# vyos@vyos# run show configuration commands | grep firewall +# set firewall ipv6-name 'V6-LOCAL' +# set firewall name 'INBOUND' +# set firewall name 'LOCAL' +# set firewall name 'OUTBOUND' # # # ------------------------ # Module Execution Results # ------------------------ # # "commands": [ # "delete interfaces ethernet eth1 firewall", # "delete interfaces ethernet eth1 firewall" # ] # -# After state -# ------------ -# vyos@vyos# run show configuration commands | grep firewall -# set firewall ipv6-name 'V6-LOCAL' -# set firewall name 'INBOUND' -# set firewall name 'LOCAL' -# set firewall name 'OUTBOUND' # Using parsed # +# - name: Parse the provided configuration vyos.vyos.vyos_firewall_interfaces: running_config: "set interfaces ethernet eth1 firewall in name 'INBOUND' set interfaces ethernet eth1 firewall out name 'OUTBOUND' set interfaces ethernet eth1 firewall local name 'LOCAL' set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' set interfaces ethernet eth2 firewall in name 'INBOUND' set interfaces ethernet eth2 firewall out name 'OUTBOUND' set interfaces ethernet eth2 firewall local name 'LOCAL' set interfaces ethernet eth2 firewall local ipv6-name 'V6-LOCAL'" state: parsed # # # ------------------------- # Module Execution Result # ------------------------- # # # "parsed": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # }, # { # "direction": "local", # "name": "LOCAL" # }, # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth2" # }, # { # "name": "eth3" # } # ] # Using gathered # # Before state: # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall 'in' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall 'local' # set interfaces ethernet eth3 firewall 'out' # - name: Gather listed firewall interfaces. vyos.vyos.vyos_firewall_interfaces: state: gathered # # # ------------------------- # Module Execution Result # ------------------------- # # "gathered": [ # { # "name": "eth0" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "out", # "name": "OUTBOUND" # } # ] # }, # { # "afi": "ipv6", # "rules": [ # { # "direction": "local", # "name": "V6-LOCAL" # } # ] # } # ], # "name": "eth1" # }, # { # "name": "eth2" # }, # { # "access_rules": [ # { # "afi": "ipv4", # "rules": [ # { # "direction": "in", # "name": "INBOUND" # } # ] # } # ], # "name": "eth3" # } # ] # # # After state: # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall ipv6-name 'V6-LOCAL' # set firewall name 'INBOUND' # set firewall name 'LOCAL' # set firewall name 'OUTBOUND' # set interfaces ethernet eth1 firewall 'in' # set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL' # set interfaces ethernet eth1 firewall out name 'OUTBOUND' # set interfaces ethernet eth3 firewall in name 'INBOUND' # set interfaces ethernet eth3 firewall 'local' # set interfaces ethernet eth3 firewall 'out' # Using rendered # # - name: Render the commands for provided configuration vyos.vyos.vyos_firewall_interfaces: config: - name: eth2 access_rules: - afi: ipv4 rules: - - direction: in - name: INGRESS - - direction: out - name: OUTGRESS - - direction: local - name: DROP + - name: INGRESS + direction: in + - name: OUTGRESS + direction: out + - name: DROP + direction: local state: rendered - # # # ------------------------- # Module Execution Result # ------------------------- # # # "rendered": [ # "set interfaces ethernet eth2 firewall in name 'INGRESS'", # "set interfaces ethernet eth2 firewall out name 'OUTGRESS'", # "set interfaces ethernet eth2 firewall local name 'DROP'", # "set interfaces ethernet eth2 firewall local ipv6-name 'LOCAL'" # ] """ RETURN = """ before: - description: The configuration prior to the model invocation. - returned: always - type: list + description: The configuration prior to the module execution. + returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) + type: dict sample: > - The configuration returned will always be in the same format - of the parameters above. + This output will always be in the same format as the + module argspec. after: - description: The resulting configuration model invocation. + description: The resulting configuration after module execution. returned: when changed - type: list + type: dict sample: > - The configuration returned will always be in the same format - of the parameters above. + This output will always be in the same format as the + module argspec. commands: description: The set of commands pushed to the remote device. returned: always type: list sample: - "set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL'" - "set interfaces ethernet eth3 firewall in name 'INBOUND'" +rendered: + description: The provided configuration in the task rendered in device-native format (offline). + returned: when I(state) is C(rendered) + type: list + sample: + - "set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL'" + - "set interfaces ethernet eth3 firewall in name 'INBOUND'" +gathered: + description: Facts about the network resource gathered from the remote device as structured data. + returned: when I(state) is C(gathered) + type: list + sample: > + This output will always be in the same format as the + module argspec. +parsed: + description: The device native config provided in I(running_config) option parsed into structured data as per module argspec. + returned: when I(state) is C(parsed) + type: list + sample: > + This output will always be in the same format as the + module argspec. + """ from ansible.module_utils.basic import AnsibleModule from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.firewall_interfaces.firewall_interfaces import ( Firewall_interfacesArgs, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.firewall_interfaces.firewall_interfaces import ( Firewall_interfaces, ) def main(): """ Main entry point for module execution :returns: the result form module invocation """ required_if = [ ("state", "merged", ("config",)), ("state", "replaced", ("config",)), + ("state", "rendered", ("config",)), ("state", "overridden", ("config",)), ("state", "parsed", ("running_config",)), ] mutually_exclusive = [("config", "running_config")] module = AnsibleModule( argument_spec=Firewall_interfacesArgs.argument_spec, required_if=required_if, supports_check_mode=True, mutually_exclusive=mutually_exclusive, ) result = Firewall_interfaces(module).execute_module() module.exit_json(**result) if __name__ == "__main__": main() diff --git a/tests/unit/modules/network/vyos/test_vyos_firewall_interfaces.py b/tests/unit/modules/network/vyos/test_vyos_firewall_interfaces.py index 3034d589..f921c508 100644 --- a/tests/unit/modules/network/vyos/test_vyos_firewall_interfaces.py +++ b/tests/unit/modules/network/vyos/test_vyos_firewall_interfaces.py @@ -1,390 +1,455 @@ # (c) 2016 Red Hat Inc. # # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . # Make coding more python3-ish from __future__ import absolute_import, division, print_function __metaclass__ = type from unittest.mock import patch from ansible_collections.vyos.vyos.plugins.modules import vyos_firewall_interfaces from ansible_collections.vyos.vyos.tests.unit.modules.utils import set_module_args from .vyos_module import TestVyosModule, load_fixture class TestVyosFirewallInterfacesModule(TestVyosModule): module = vyos_firewall_interfaces def setUp(self): super(TestVyosFirewallInterfacesModule, self).setUp() self.mock_get_config = patch( "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", ) self.get_config = self.mock_get_config.start() self.mock_load_config = patch( "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", ) self.load_config = self.mock_load_config.start() self.mock_get_resource_connection_config = patch( "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", ) self.get_resource_connection_config = self.mock_get_resource_connection_config.start() self.mock_get_resource_connection_facts = patch( "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", ) self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() self.mock_execute_show_command = patch( "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos." "facts.firewall_interfaces.firewall_interfaces.Firewall_interfacesFacts.get_device_data", ) self.execute_show_command = self.mock_execute_show_command.start() def tearDown(self): super(TestVyosFirewallInterfacesModule, self).tearDown() self.mock_get_resource_connection_config.stop() self.mock_get_resource_connection_facts.stop() self.mock_get_config.stop() self.mock_load_config.stop() self.mock_execute_show_command.stop() def load_fixtures(self, commands=None, filename=None): def load_from_file(*args, **kwargs): return load_fixture("vyos_firewall_interfaces_config.cfg") self.execute_show_command.side_effect = load_from_file def test_vyos_firewall_rule_set_01_merged(self): set_module_args( dict( config=[ dict( name="eth1", access_rules=[ dict( afi="ipv4", rules=[ dict(name="INBOUND", direction="in"), dict(name="OUTBOUND", direction="out"), dict(name="LOCAL", direction="local"), ], ), dict( afi="ipv6", rules=[dict(name="V6-LOCAL", direction="local")], ), ], ), dict( name="eth3", access_rules=[ dict( afi="ipv4", rules=[ dict(name="INBOUND", direction="in"), dict(name="OUTBOUND", direction="out"), dict(name="LOCAL", direction="local"), ], ), dict( afi="ipv6", rules=[dict(name="V6-LOCAL", direction="local")], ), ], ), ], state="merged", ), ) commands = [ "set interfaces ethernet eth1 firewall in name 'INBOUND'", "set interfaces ethernet eth1 firewall out name 'OUTBOUND'", "set interfaces ethernet eth1 firewall local name 'LOCAL'", "set interfaces ethernet eth1 firewall local ipv6-name 'V6-LOCAL'", "set interfaces ethernet eth3 firewall in name 'INBOUND'", "set interfaces ethernet eth3 firewall out name 'OUTBOUND'", "set interfaces ethernet eth3 firewall local name 'LOCAL'", "set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL'", ] self.execute_module(changed=True, commands=commands) def test_vyos_firewall_rule_set_02_merged_idem(self): set_module_args( dict( config=[ dict( name="eth0", access_rules=[ dict( afi="ipv4", rules=[ dict(name="INBOUND", direction="in"), dict(name="OUTBOUND", direction="out"), dict(name="LOCAL", direction="local"), ], ), dict( afi="ipv6", rules=[dict(name="V6-LOCAL", direction="local")], ), ], ), dict( name="eth2", access_rules=[ dict( afi="ipv4", rules=[ dict(name="INBOUND", direction="in"), dict(name="OUTBOUND", direction="out"), dict(name="LOCAL", direction="local"), ], ), dict( afi="ipv6", rules=[dict(name="V6-LOCAL", direction="local")], ), ], ), ], state="merged", ), ) self.execute_module(changed=False, commands=[]) def test_vyos_firewall_rule_set_01_deleted_per_afi(self): set_module_args( dict( config=[ dict( name="eth0", access_rules=[dict(afi="ipv4"), dict(afi="ipv6")], ), ], state="deleted", ), ) commands = [ "delete interfaces ethernet eth0 firewall in name", "delete interfaces ethernet eth0 firewall local name", "delete interfaces ethernet eth0 firewall out name", "delete interfaces ethernet eth0 firewall local ipv6-name", ] self.execute_module(changed=True, commands=commands) def test_vyos_firewall_rule_set_03_deleted_per_interface(self): set_module_args(dict(config=[dict(name="eth0"), dict(name="eth2")], state="deleted")) commands = [ "delete interfaces ethernet eth0 firewall", "delete interfaces ethernet eth2 firewall", ] self.execute_module(changed=True, commands=commands) def test_vyos_firewall_rule_set_03_deleted_all(self): set_module_args(dict(config=[], state="deleted")) commands = [ "delete interfaces ethernet eth0 firewall", "delete interfaces ethernet eth2 firewall", ] self.execute_module(changed=True, commands=commands) def test_vyos_firewall_rule_set_03_deleted(self): set_module_args(dict(config=[dict(name="eth0"), dict(name="eth2")], state="deleted")) commands = [ "delete interfaces ethernet eth0 firewall", "delete interfaces ethernet eth2 firewall", ] self.execute_module(changed=True, commands=commands) def test_vyos_firewall_rule_set_04_deleted_interface_idem(self): set_module_args(dict(config=[dict(name="eth1"), dict(name="eth3")], state="deleted")) self.execute_module(changed=False, commands=[]) def test_vyos_firewall_rule_set_02_replaced_idem(self): set_module_args( dict( config=[ dict( name="eth0", access_rules=[ dict( afi="ipv4", rules=[ dict(name="INBOUND", direction="in"), dict(name="OUTBOUND", direction="out"), dict(name="LOCAL", direction="local"), ], ), dict( afi="ipv6", rules=[dict(name="V6-LOCAL", direction="local")], ), ], ), dict( name="eth2", access_rules=[ dict( afi="ipv4", rules=[ dict(name="INBOUND", direction="in"), dict(name="OUTBOUND", direction="out"), dict(name="LOCAL", direction="local"), ], ), dict( afi="ipv6", rules=[dict(name="V6-LOCAL", direction="local")], ), ], ), ], state="replaced", ), ) self.execute_module(changed=False, commands=[]) def test_vyos_firewall_rule_set_01_replaced(self): set_module_args( dict( config=[ dict( name="eth0", access_rules=[ dict( afi="ipv4", rules=[dict(name="INBOUND", direction="in")], ), dict( afi="ipv6", rules=[dict(name="V6-LOCAL", direction="local")], ), ], ), dict( name="eth2", access_rules=[ dict( afi="ipv4", rules=[dict(name="LOCAL", direction="local")], ), dict( afi="ipv6", rules=[dict(name="V6-LOCAL", direction="local")], ), ], ), dict( name="eth3", access_rules=[ dict( afi="ipv4", rules=[dict(name="LOCAL", direction="local")], ), dict( afi="ipv6", rules=[dict(name="V6-LOCAL", direction="local")], ), ], ), ], state="replaced", ), ) commands = [ "delete interfaces ethernet eth0 firewall out name", "delete interfaces ethernet eth0 firewall local name", "delete interfaces ethernet eth2 firewall in name", "delete interfaces ethernet eth2 firewall out name", "set interfaces ethernet eth3 firewall local name 'LOCAL'", "set interfaces ethernet eth3 firewall local ipv6-name 'V6-LOCAL'", ] self.execute_module(changed=True, commands=commands) def test_vyos_firewall_rule_set_01_overridden(self): set_module_args( dict( config=[ dict( name="eth1", access_rules=[ dict( afi="ipv4", rules=[dict(name="INBOUND", direction="in")], ), ], ), ], state="overridden", ), ) commands = [ "delete interfaces ethernet eth0 firewall", "delete interfaces ethernet eth2 firewall", "set interfaces ethernet eth1 firewall in name 'INBOUND'", ] self.execute_module(changed=True, commands=commands) def test_vyos_firewall_rule_set_02_overridden_idem(self): set_module_args( dict( config=[ dict( name="eth0", access_rules=[ dict( afi="ipv4", rules=[ dict(name="INBOUND", direction="in"), dict(name="OUTBOUND", direction="out"), dict(name="LOCAL", direction="local"), ], ), dict( afi="ipv6", rules=[dict(name="V6-LOCAL", direction="local")], ), ], ), dict( name="eth2", access_rules=[ dict( afi="ipv4", rules=[ dict(name="INBOUND", direction="in"), dict(name="OUTBOUND", direction="out"), dict(name="LOCAL", direction="local"), ], ), dict( afi="ipv6", rules=[dict(name="V6-LOCAL", direction="local")], ), ], ), ], state="overridden", ), ) self.execute_module(changed=False, commands=[]) + + def test_vyos_firewall_rule_set_02_replaced(self): + set_module_args( + dict( + config=[ + dict( + name="eth0.100", + access_rules=[ + dict( + afi="ipv4", + rules=[dict(name="INBOUND", direction="in")], + ), + dict( + afi="ipv6", + rules=[dict(name="V6-LOCAL", direction="local")], + ), + ], + ), + dict( + name="bond2", + access_rules=[ + dict( + afi="ipv4", + rules=[dict(name="LOCAL", direction="local")], + ), + dict( + afi="ipv6", + rules=[dict(name="V6-LOCAL", direction="local")], + ), + ], + ), + dict( + name="wg4", + access_rules=[ + dict( + afi="ipv4", + rules=[dict(name="LOCAL", direction="local")], + ), + dict( + afi="ipv6", + rules=[dict(name="V6-LOCAL", direction="local")], + ), + ], + ), + ], + state="replaced", + ), + ) + commands = [ + 'delete interfaces ethernet eth0 firewall in name', + 'delete interfaces ethernet eth0 firewall local name', + 'delete interfaces ethernet eth0 firewall out name', + 'delete interfaces ethernet eth0 firewall local ipv6-name', + 'delete interfaces ethernet eth2 firewall in name', + 'delete interfaces ethernet eth2 firewall local name', + 'delete interfaces ethernet eth2 firewall out name', + 'delete interfaces ethernet eth2 firewall local ipv6-name', + "set interfaces ethernet eth0 vif 100 firewall in name 'INBOUND'", + "set interfaces ethernet eth0 vif 100 firewall local ipv6-name 'V6-LOCAL'", + "set interfaces bonding bond2 firewall local name 'LOCAL'", + "set interfaces bonding bond2 firewall local ipv6-name 'V6-LOCAL'", + "set interfaces wireguard wg4 firewall local name 'LOCAL'", + "set interfaces wireguard wg4 firewall local ipv6-name 'V6-LOCAL'" + ] + self.execute_module(changed=True, commands=commands)