diff options
Diffstat (limited to 'plugins/modules')
34 files changed, 6532 insertions, 1010 deletions
diff --git a/plugins/modules/vyos_banner.py b/plugins/modules/vyos_banner.py index 6b1da84b..98a5b0ba 100644 --- a/plugins/modules/vyos_banner.py +++ b/plugins/modules/vyos_banner.py @@ -2,7 +2,6 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, division, print_function - __metaclass__ = type # (c) 2017, Ansible by Red Hat, inc @@ -33,7 +32,7 @@ description: VyOS. It allows playbooks to add or remote banner text from the active running configuration. version_added: 1.0.0 notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: banner: diff --git a/plugins/modules/vyos_bgp_address_family.py b/plugins/modules/vyos_bgp_address_family.py index 14c3605d..4172643e 100644 --- a/plugins/modules/vyos_bgp_address_family.py +++ b/plugins/modules/vyos_bgp_address_family.py @@ -10,7 +10,6 @@ The module file for vyos_bgp_address_family from __future__ import absolute_import, division, print_function - __metaclass__ = type DOCUMENTATION = """ @@ -19,7 +18,8 @@ version_added: 1.0.0 short_description: BGP Address Family resource module description: - This module manages BGP address family configuration of interfaces on devices running VYOS. -- Tested against VYOS 1.3, 1.4 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 +- The provided examples of commands are valid for VyOS 1.4+ author: Gomathi Selvi Srinivasan (@GomathiselviS) options: config: @@ -285,17 +285,18 @@ EXAMPLES = """ # After State: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight '50' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight '50' # vyos@vyos:~$ # # Module Execution: @@ -363,17 +364,17 @@ EXAMPLES = """ # "before": {}, # "changed": true, # "commands": [ -# "set protocols bgp 100 address-family ipv4-unicast redistribute static metric 50", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number 4", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map map01", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export 10", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix 45", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export map01", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import map01", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight 50" +# "set protocols bgp address-family ipv4-unicast redistribute static metric 50", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number 4", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map map01", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export 10", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix 45", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map export map01", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map import map01", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight 50" # ], # @@ -382,17 +383,18 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight '50' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight '50' # vyos@vyos:~$ - name: Replace provided configuration with device configuration @@ -422,15 +424,16 @@ EXAMPLES = """ # After State: # # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export '10' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix '45' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast as-override +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export '10' # vyos@vyos:~$ # # @@ -549,39 +552,40 @@ EXAMPLES = """ # }, # "changed": true, # "commands": [ -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list", -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate", -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged", -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number 4", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map map01", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export 10", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix 45", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self" +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list", +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate", +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged", +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number 4", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast as-override", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map map01", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export 10", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix 45", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self" # ], # Using overridden # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast network 35.1.1.0/24 backdoor -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 address-family ipv6-unicast aggregate-address 6601:1:1:1::/64 summary-only -# set protocols bgp 100 address-family ipv6-unicast network 5001:1:1:1::/64 route-map 'map01' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export '10' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast network 35.1.1.0/24 backdoor +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp address-family ipv6-unicast aggregate-address 6601:1:1:1::/64 summary-only +# set protocols bgp address-family ipv6-unicast network 5001:1:1:1::/64 route-map 'map01' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix '45' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast as-override +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export '10' # vyos@vyos:~$ - name: Override @@ -611,13 +615,14 @@ EXAMPLES = """ # After State # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only -# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast route-map import 'map01' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only +# set protocols bgp address-family ipv6-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix '45' +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast route-map import 'map01' # vyos@vyos:~$ @@ -742,21 +747,21 @@ EXAMPLES = """ # }, # "changed": true, # "commands": [ -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in", -# "delete protocols bgp 100 address-family ipv6 aggregate-address", -# "delete protocols bgp 100 address-family ipv6 network", -# "delete protocols bgp 100 address-family ipv4 network", -# "delete protocols bgp 100 address-family ipv4 redistribute", -# "set protocols bgp 100 address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only", -# "set protocols bgp 100 address-family ipv6-unicast redistribute static metric 50", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix 45", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast route-map import map01" +# "delete protocols bgp neighbor 20.33.1.1/24 address-family", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast distribute-list", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast default-originate", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast as-override", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast allowas-in", +# "delete protocols bgp address-family ipv6 aggregate-address", +# "delete protocols bgp address-family ipv6 network", +# "delete protocols bgp address-family ipv4 network", +# "delete protocols bgp address-family ipv4 redistribute", +# "set protocols bgp address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only", +# "set protocols bgp address-family ipv6-unicast redistribute static metric 50", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix 45", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast route-map import map01" # ], # @@ -765,22 +770,23 @@ EXAMPLES = """ # Before State: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight '50' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast route-map import 'map01' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp address-family ipv6-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight '50' +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix '45' +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast route-map import 'map01' # vyos@vyos:~$ - name: Delete @@ -800,11 +806,12 @@ EXAMPLES = """ # After State: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 100.11.34.12 +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv6-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 100.11.34.12 # vyos@vyos:~$ # # @@ -927,9 +934,9 @@ EXAMPLES = """ # }, # "changed": true, # "commands": [ -# "delete protocols bgp 100 address-family ipv4-unicast", -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family" +# "delete protocols bgp address-family ipv4-unicast", +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast", +# "delete protocols bgp neighbor 100.11.34.12 address-family" # ], # @@ -1019,15 +1026,16 @@ EXAMPLES = """ # Native config: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast network 35.1.1.0/24 backdoor -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 address-family ipv6-unicast aggregate-address 6601:1:1:1::/64 summary-only -# set protocols bgp 100 address-family ipv6-unicast network 5001:1:1:1::/64 route-map 'map01' -# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 100.11.34.12 +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast network 35.1.1.0/24 backdoor +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp address-family ipv6-unicast aggregate-address 6601:1:1:1::/64 summary-only +# set protocols bgp address-family ipv6-unicast network 5001:1:1:1::/64 route-map 'map01' +# set protocols bgp address-family ipv6-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 100.11.34.12 - name: gather configs vyos.vyos.vyos_bgp_address_family: @@ -1131,17 +1139,17 @@ EXAMPLES = """ # Module Execution: # "rendered": [ -# "set protocols bgp 100 address-family ipv4-unicast redistribute static metric 50", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number 4", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map map01", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export 10", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix 45", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export map01", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import map01", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight 50" +# "set protocols bgp address-family ipv4-unicast redistribute static metric 50", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number 4", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map map01", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export 10", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix 45", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map export map01", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map import map01", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight 50" # ] """ diff --git a/plugins/modules/vyos_bgp_global.py b/plugins/modules/vyos_bgp_global.py index 4d7db472..02f5e590 100644 --- a/plugins/modules/vyos_bgp_global.py +++ b/plugins/modules/vyos_bgp_global.py @@ -10,7 +10,6 @@ The module file for vyos_bgp_global from __future__ import absolute_import, division, print_function - __metaclass__ = type DOCUMENTATION = """ @@ -19,7 +18,8 @@ version_added: 1.0.0 short_description: BGP global resource module description: - This module manages BGP global configuration of interfaces on devices running VYOS. -- Tested against VYOS 1.3, 1.4 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 +- The provided examples of commands are valid for VyOS 1.4+ author: - Gomathi Selvi Srinivasan (@GomathiselviS) options: @@ -73,37 +73,6 @@ options: description: - Minimum interval for sending routing updates. type: int - # bfd: # <-- added in 1.3 - # description: Enable Bidirectional Forwarding Detection (BFD) support - # type: dict - # suboptions: - # check-control-plane-failure: - # description: - # - Allow to write CBIT independence in BFD outgoing packets - # and read both C-BIT value of BFD and lookup BGP peer status - # type: bool - # allowas_in: --> Moved to address-family before 1.3 - # description: - # - Number of occurrences of AS number. - # type: int - # as_override: --> Moved to address-family before 1.3 - # description: - # - AS for routes sent to this neighbor to be the local AS. - # type: bool - # attribute_unchanged: --> Moved to address-family before 1.3 - # description: - # - BGP attributes are sent unchanged. - # type: dict - # suboptions: - # as_path: - # description: as_path - # type: bool - # med: - # description: med - # type: bool - # next_hop: - # description: next_hop - # type: bool capability: description: - Advertise capabilities to this neighbor. @@ -117,13 +86,6 @@ options: description: - Advertise extended nexthop capability to this neighbor. type: bool - # orf: --> Removed before 1.3 - # description: - # - Advertise ORF capability to this neighbor. - # type: str - # choices: - # - send - # - receive default_originate: description: - Send default route to this neighbor @@ -145,70 +107,14 @@ options: - Disable sending community attributes to this neighbor. type: str choices: ['extended', 'standard'] - # distribute_list: --> Moved to address-family before 1.3 - # description: Access-list to filter route updates to/from this neighbor. - # type: list - # elements: dict - # suboptions: - # action: - # description: Access-list to filter outgoing/incoming route updates to this neighbor - # type: str - # choices: ['export', 'import'] - # acl: - # description: Access-list number. - # type: int ebgp_multihop: description: - Allow this EBGP neighbor to not be on a directly connected network. Specify - the number hops. + the number of hops. type: int - # interface: # <-- added in 1.3 - # description: interface parameters - # type: dict - # suboptions: - # peer_group: - # description: Peer group for this neighbor - # type: str - # remote_as: - # description: - # - Remote AS number - # - Or 'external' for any number except this AS number - # - or 'internal' for this AS number - # type: str - # v6only: - # description: Enable BGP with v6 link-local only - # type: dict - # suboptions: - # peer_group: - # description: Peer group for this neighbor - # type: str - # remote_as: - # description: - # - Remote AS number - # - Or 'external' for any number except this AS number - # - or 'internal' for this AS number - # filter_list: --> Moved to address-family before 1.3 - # description: As-path-list to filter route updates to/from this neighbor. - # type: list - # elements: dict - # suboptions: - # action: - # description: filter outgoing/incoming route updates - # type: str - # choices: ['export', 'import'] - # path_list: - # description: As-path-list to filter - # type: str local_as: description: local as number not to be prepended to updates from EBGP peers type: int - # maximum_prefix: --> Moved to address-family before 1.3 - # description: Maximum number of prefixes to accept from this neighbor - # nexthop-self Nexthop for routes sent to this neighbor to be the local router. - # type: int - # nexthop_self: --> Moved to address-family before 1.3 - # description: Nexthop for routes sent to this neighbor to be the local router. - # type: bool override_capability: description: Ignore capability negotiation with specified neighbor. type: bool @@ -227,61 +133,18 @@ options: port: description: Neighbor's BGP port type: int - # prefix_list: --> Moved to address-family before 1.3 - # description: Prefix-list to filter route updates to/from this neighbor. - # type: list - # elements: dict - # suboptions: - # action: - # description: filter outgoing/incoming route updates - # type: str - # choices: ['export', 'import'] - # prefix_list: - # description: Prefix-list to filter - # type: str remote_as: description: Neighbor BGP AS number type: int - # remove_private_as: --> Moved to address-family before 1.3 - # description: Remove private AS numbers from AS path in outbound route updates - # type: bool - # route_map: --> Moved to address-family before 1.3 - # description: Route-map to filter route updates to/from this neighbor. - # type: list - # elements: dict - # suboptions: - # action: - # description: filter outgoing/incoming route updates - # type: str - # choices: ['export', 'import'] - # route_map: - # description: route-map to filter - # type: str - # route_reflector_client: --> Moved to address-family before 1.3 - # description: Neighbor as a route reflector client - # type: bool - # route_server_client: --> Removed prior to 1.3 - # description: Neighbor is route server client - # type: bool shutdown: description: Administratively shut down neighbor type: bool - # soft_reconfiguration: --> Moved to address-family before 1.3 - # description: Soft reconfiguration for neighbor - # type: bool solo: # <-- added in 1.3 description: Do not send back prefixes learned from the neighbor type: bool strict_capability_match: description: Enable strict capability negotiation type: bool - # unsuppress_map: --> Moved to address-family before 1.3 - # description: Route-map to selectively unsuppress suppressed routes - # type: str - - # weight: --> Moved to address-family before 1.3 - # description: Default weight for routes from this neighbor - # type: int timers: description: Neighbor timers type: dict @@ -539,33 +402,34 @@ EXAMPLES = """ # After State # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 aggregate-address 192.0.2.0/24 'summary-only' -# set protocols bgp 65536 aggregate-address 203.0.113.0/24 'as-set' -# set protocols bgp 65536 maximum-paths ebgp '20' -# set protocols bgp 65536 maximum-paths ibgp '55' -# set protocols bgp 65536 neighbor 192.0.2.25 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.25 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.25 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'as-path' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'med' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'next-hop' -# set protocols bgp 65536 neighbor 203.0.113.5 ebgp-multihop '2' -# set protocols bgp 65536 neighbor 203.0.113.5 remote-as '101' -# set protocols bgp 65536 neighbor 203.0.113.5 update-source '192.0.2.25' -# set protocols bgp 65536 neighbor 5001::64 distribute-list export '20' -# set protocols bgp 65536 neighbor 5001::64 distribute-list import '40' -# set protocols bgp 65536 neighbor 5001::64 maximum-prefix '34' -# set protocols bgp 65536 network 192.1.13.0/24 'backdoor' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters confederation identifier '66' -# set protocols bgp 65536 parameters confederation peers '20' -# set protocols bgp 65536 parameters confederation peers '55' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters router-id '192.1.2.9' -# set protocols bgp 65536 redistribute connected route-map 'map01' -# set protocols bgp 65536 redistribute kernel metric '45' -# set protocols bgp 65536 timers keepalive '35' +# set protocols bgp system-as 65536 +# set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' +# set protocols bgp aggregate-address 203.0.113.0/24 'as-set' +# set protocols bgp maximum-paths ebgp '20' +# set protocols bgp maximum-paths ibgp '55' +# set protocols bgp neighbor 192.0.2.25 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.25 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.25 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' +# set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' +# set protocols bgp neighbor 203.0.113.5 remote-as '101' +# set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' +# set protocols bgp neighbor 5001::64 distribute-list export '20' +# set protocols bgp neighbor 5001::64 distribute-list import '40' +# set protocols bgp neighbor 5001::64 maximum-prefix '34' +# set protocols bgp network 192.1.13.0/24 'backdoor' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters confederation identifier '66' +# set protocols bgp parameters confederation peers '20' +# set protocols bgp parameters confederation peers '55' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters router-id '192.1.2.9' +# set protocols bgp redistribute connected route-map 'map01' +# set protocols bgp redistribute kernel metric '45' +# set protocols bgp timers keepalive '35' # vyos@vyos:~$ # # # Module Execution: @@ -671,33 +535,33 @@ EXAMPLES = """ # "before": {}, # "changed": true, # "commands": [ -# "set protocols bgp 65536 neighbor 192.0.2.25 disable-connected-check", -# "set protocols bgp 65536 neighbor 192.0.2.25 timers holdtime 30", -# "set protocols bgp 65536 neighbor 192.0.2.25 timers keepalive 10", -# "set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged as-path", -# "set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged med", -# "set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged next-hop", -# "set protocols bgp 65536 neighbor 203.0.113.5 ebgp-multihop 2", -# "set protocols bgp 65536 neighbor 203.0.113.5 remote-as 101", -# "set protocols bgp 65536 neighbor 203.0.113.5 update-source 192.0.2.25", -# "set protocols bgp 65536 neighbor 5001::64 maximum-prefix 34", -# "set protocols bgp 65536 neighbor 5001::64 distribute-list export 20", -# "set protocols bgp 65536 neighbor 5001::64 distribute-list import 40", -# "set protocols bgp 65536 redistribute kernel metric 45", -# "set protocols bgp 65536 redistribute connected route-map map01", -# "set protocols bgp 65536 network 192.1.13.0/24 backdoor", -# "set protocols bgp 65536 aggregate-address 203.0.113.0/24 as-set", -# "set protocols bgp 65536 aggregate-address 192.0.2.0/24 summary-only", -# "set protocols bgp 65536 parameters bestpath as-path confed", -# "set protocols bgp 65536 parameters bestpath compare-routerid", -# "set protocols bgp 65536 parameters default no-ipv4-unicast", -# "set protocols bgp 65536 parameters router-id 192.1.2.9", -# "set protocols bgp 65536 parameters confederation peers 20", -# "set protocols bgp 65536 parameters confederation peers 55", -# "set protocols bgp 65536 parameters confederation identifier 66", -# "set protocols bgp 65536 maximum-paths ebgp 20", -# "set protocols bgp 65536 maximum-paths ibgp 55", -# "set protocols bgp 65536 timers keepalive 35" +# "set protocols bgp neighbor 192.0.2.25 disable-connected-check", +# "set protocols bgp neighbor 192.0.2.25 timers holdtime 30", +# "set protocols bgp neighbor 192.0.2.25 timers keepalive 10", +# "set protocols bgp neighbor 203.0.113.5 attribute-unchanged as-path", +# "set protocols bgp neighbor 203.0.113.5 attribute-unchanged med", +# "set protocols bgp neighbor 203.0.113.5 attribute-unchanged next-hop", +# "set protocols bgp neighbor 203.0.113.5 ebgp-multihop 2", +# "set protocols bgp neighbor 203.0.113.5 remote-as 101", +# "set protocols bgp neighbor 203.0.113.5 update-source 192.0.2.25", +# "set protocols bgp neighbor 5001::64 maximum-prefix 34", +# "set protocols bgp neighbor 5001::64 distribute-list export 20", +# "set protocols bgp neighbor 5001::64 distribute-list import 40", +# "set protocols bgp redistribute kernel metric 45", +# "set protocols bgp redistribute connected route-map map01", +# "set protocols bgp network 192.1.13.0/24 backdoor", +# "set protocols bgp aggregate-address 203.0.113.0/24 as-set", +# "set protocols bgp aggregate-address 192.0.2.0/24 summary-only", +# "set protocols bgp parameters bestpath as-path confed", +# "set protocols bgp parameters bestpath compare-routerid", +# "set protocols bgp parameters default no-ipv4-unicast", +# "set protocols bgp parameters router-id 192.1.2.9", +# "set protocols bgp parameters confederation peers 20", +# "set protocols bgp parameters confederation peers 55", +# "set protocols bgp parameters confederation identifier 66", +# "set protocols bgp maximum-paths ebgp 20", +# "set protocols bgp maximum-paths ibgp 55", +# "set protocols bgp timers keepalive 35" # ], # Using replaced: @@ -706,33 +570,34 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 aggregate-address 192.0.2.0/24 'summary-only' -# set protocols bgp 65536 aggregate-address 203.0.113.0/24 'as-set' -# set protocols bgp 65536 maximum-paths ebgp '20' -# set protocols bgp 65536 maximum-paths ibgp '55' -# set protocols bgp 65536 neighbor 192.0.2.25 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.25 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.25 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'as-path' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'med' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'next-hop' -# set protocols bgp 65536 neighbor 203.0.113.5 ebgp-multihop '2' -# set protocols bgp 65536 neighbor 203.0.113.5 remote-as '101' -# set protocols bgp 65536 neighbor 203.0.113.5 update-source '192.0.2.25' -# set protocols bgp 65536 neighbor 5001::64 distribute-list export '20' -# set protocols bgp 65536 neighbor 5001::64 distribute-list import '40' -# set protocols bgp 65536 neighbor 5001::64 maximum-prefix '34' -# set protocols bgp 65536 network 192.1.13.0/24 'backdoor' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters confederation identifier '66' -# set protocols bgp 65536 parameters confederation peers '20' -# set protocols bgp 65536 parameters confederation peers '55' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters router-id '192.1.2.9' -# set protocols bgp 65536 redistribute connected route-map 'map01' -# set protocols bgp 65536 redistribute kernel metric '45' -# set protocols bgp 65536 timers keepalive '35' +# set protocols bgp system-as 65536 +# set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' +# set protocols bgp aggregate-address 203.0.113.0/24 'as-set' +# set protocols bgp maximum-paths ebgp '20' +# set protocols bgp maximum-paths ibgp '55' +# set protocols bgp neighbor 192.0.2.25 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.25 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.25 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' +# set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' +# set protocols bgp neighbor 203.0.113.5 remote-as '101' +# set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' +# set protocols bgp neighbor 5001::64 distribute-list export '20' +# set protocols bgp neighbor 5001::64 distribute-list import '40' +# set protocols bgp neighbor 5001::64 maximum-prefix '34' +# set protocols bgp network 192.1.13.0/24 'backdoor' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters confederation identifier '66' +# set protocols bgp parameters confederation peers '20' +# set protocols bgp parameters confederation peers '55' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters router-id '192.1.2.9' +# set protocols bgp redistribute connected route-map 'map01' +# set protocols bgp redistribute kernel metric '45' +# set protocols bgp timers keepalive '35' # vyos@vyos:~$ - name: Replace @@ -757,11 +622,12 @@ EXAMPLES = """ # After state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 neighbor 192.0.2.40 advertisement-interval '72' -# set protocols bgp 65536 neighbor 192.0.2.40 capability orf prefix-list 'receive' -# set protocols bgp 65536 network 203.0.113.0/24 route-map 'map01' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 redistribute static route-map 'map01' +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.40 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.40 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ # # @@ -896,26 +762,26 @@ EXAMPLES = """ # }, # "changed": true, # "commands": [ -# "delete protocols bgp 65536 timers", -# "delete protocols bgp 65536 maximum-paths ", -# "delete protocols bgp 65536 maximum-paths ", -# "delete protocols bgp 65536 parameters router-id 192.1.2.9", -# "delete protocols bgp 65536 parameters default", -# "delete protocols bgp 65536 parameters confederation", -# "delete protocols bgp 65536 parameters bestpath compare-routerid", -# "delete protocols bgp 65536 aggregate-address", -# "delete protocols bgp 65536 network 192.1.13.0/24", -# "delete protocols bgp 65536 redistribute kernel", -# "delete protocols bgp 65536 redistribute kernel", -# "delete protocols bgp 65536 redistribute connected", -# "delete protocols bgp 65536 redistribute connected", -# "delete protocols bgp 65536 neighbor 5001::64", -# "delete protocols bgp 65536 neighbor 203.0.113.5", -# "delete protocols bgp 65536 neighbor 192.0.2.25", -# "set protocols bgp 65536 neighbor 192.0.2.40 advertisement-interval 72", -# "set protocols bgp 65536 neighbor 192.0.2.40 capability orf prefix-list receive", -# "set protocols bgp 65536 redistribute static route-map map01", -# "set protocols bgp 65536 network 203.0.113.0/24 route-map map01" +# "delete protocols bgp timers", +# "delete protocols bgp maximum-paths ", +# "delete protocols bgp maximum-paths ", +# "delete protocols bgp parameters router-id 192.1.2.9", +# "delete protocols bgp parameters default", +# "delete protocols bgp parameters confederation", +# "delete protocols bgp parameters bestpath compare-routerid", +# "delete protocols bgp aggregate-address", +# "delete protocols bgp network 192.1.13.0/24", +# "delete protocols bgp redistribute kernel", +# "delete protocols bgp redistribute kernel", +# "delete protocols bgp redistribute connected", +# "delete protocols bgp redistribute connected", +# "delete protocols bgp neighbor 5001::64", +# "delete protocols bgp neighbor 203.0.113.5", +# "delete protocols bgp neighbor 192.0.2.25", +# "set protocols bgp neighbor 192.0.2.40 advertisement-interval 72", +# "set protocols bgp neighbor 192.0.2.40 capability orf prefix-list receive", +# "set protocols bgp redistribute static route-map map01", +# "set protocols bgp network 203.0.113.0/24 route-map map01" # ], # Using deleted: @@ -924,11 +790,12 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 neighbor 192.0.2.40 advertisement-interval '72' -# set protocols bgp 65536 neighbor 192.0.2.40 capability orf prefix-list 'receive' -# set protocols bgp 65536 network 203.0.113.0/24 route-map 'map01' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 redistribute static route-map 'map01' +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.40 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.40 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ - name: Delete configuration @@ -980,10 +847,10 @@ EXAMPLES = """ # }, # "changed": true, # "commands": [ -# "delete protocols bgp 65536 neighbor 192.0.2.40", -# "delete protocols bgp 65536 redistribute", -# "delete protocols bgp 65536 network", -# "delete protocols bgp 65536 parameters" +# "delete protocols bgp neighbor 192.0.2.40", +# "delete protocols bgp redistribute", +# "delete protocols bgp network", +# "delete protocols bgp parameters" # ], # Using purged: @@ -991,33 +858,34 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 aggregate-address 192.0.2.0/24 'summary-only' -# set protocols bgp 65536 aggregate-address 203.0.113.0/24 'as-set' -# set protocols bgp 65536 maximum-paths ebgp '20' -# set protocols bgp 65536 maximum-paths ibgp '55' -# set protocols bgp 65536 neighbor 192.0.2.25 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.25 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.25 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'as-path' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'med' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'next-hop' -# set protocols bgp 65536 neighbor 203.0.113.5 ebgp-multihop '2' -# set protocols bgp 65536 neighbor 203.0.113.5 remote-as '101' -# set protocols bgp 65536 neighbor 203.0.113.5 update-source '192.0.2.25' -# set protocols bgp 65536 neighbor 5001::64 distribute-list export '20' -# set protocols bgp 65536 neighbor 5001::64 distribute-list import '40' -# set protocols bgp 65536 neighbor 5001::64 maximum-prefix '34' -# set protocols bgp 65536 network 192.1.13.0/24 'backdoor' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters confederation identifier '66' -# set protocols bgp 65536 parameters confederation peers '20' -# set protocols bgp 65536 parameters confederation peers '55' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters router-id '192.1.2.9' -# set protocols bgp 65536 redistribute connected route-map 'map01' -# set protocols bgp 65536 redistribute kernel metric '45' -# set protocols bgp 65536 timers keepalive '35' +# set protocols bgp system-as 65536 +# set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' +# set protocols bgp aggregate-address 203.0.113.0/24 'as-set' +# set protocols bgp maximum-paths ebgp '20' +# set protocols bgp maximum-paths ibgp '55' +# set protocols bgp neighbor 192.0.2.25 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.25 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.25 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' +# set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' +# set protocols bgp neighbor 203.0.113.5 remote-as '101' +# set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' +# set protocols bgp neighbor 5001::64 distribute-list export '20' +# set protocols bgp neighbor 5001::64 distribute-list import '40' +# set protocols bgp neighbor 5001::64 maximum-prefix '34' +# set protocols bgp network 192.1.13.0/24 'backdoor' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters confederation identifier '66' +# set protocols bgp parameters confederation peers '20' +# set protocols bgp parameters confederation peers '55' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters router-id '192.1.2.9' +# set protocols bgp redistribute connected route-map 'map01' +# set protocols bgp redistribute kernel metric '45' +# set protocols bgp timers keepalive '35' # vyos@vyos:~$ @@ -1143,26 +1011,27 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 neighbor 192.0.2.43 advertisement-interval '72' -# set protocols bgp 65536 neighbor 192.0.2.43 capability 'dynamic' -# set protocols bgp 65536 neighbor 192.0.2.43 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.43 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.43 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.0 address-family 'ipv6-unicast' -# set protocols bgp 65536 neighbor 203.0.113.0 capability orf prefix-list 'receive' -# set protocols bgp 65536 network 203.0.113.0/24 route-map 'map01' -# set protocols bgp 65536 parameters 'always-compare-med' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters dampening half-life '33' -# set protocols bgp 65536 parameters dampening max-suppress-time '20' -# set protocols bgp 65536 parameters dampening re-use '60' -# set protocols bgp 65536 parameters dampening start-suppress-time '5' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters distance global external '66' -# set protocols bgp 65536 parameters distance global internal '20' -# set protocols bgp 65536 parameters distance global local '10' -# set protocols bgp 65536 redistribute static route-map 'map01' +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.43 capability 'dynamic' +# set protocols bgp neighbor 192.0.2.43 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.43 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.43 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' +# set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters 'always-compare-med' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters dampening half-life '33' +# set protocols bgp parameters dampening max-suppress-time '20' +# set protocols bgp parameters dampening re-use '60' +# set protocols bgp parameters dampening start-suppress-time '5' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters distance global external '66' +# set protocols bgp parameters distance global internal '20' +# set protocols bgp parameters distance global local '10' +# set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ ^C # vyos@vyos:~$ @@ -1199,26 +1068,27 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 neighbor 192.0.2.43 advertisement-interval '72' -# set protocols bgp 65536 neighbor 192.0.2.43 capability 'dynamic' -# set protocols bgp 65536 neighbor 192.0.2.43 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.43 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.43 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.0 address-family 'ipv6-unicast' -# set protocols bgp 65536 neighbor 203.0.113.0 capability orf prefix-list 'receive' -# set protocols bgp 65536 network 203.0.113.0/24 route-map 'map01' -# set protocols bgp 65536 parameters 'always-compare-med' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters dampening half-life '33' -# set protocols bgp 65536 parameters dampening max-suppress-time '20' -# set protocols bgp 65536 parameters dampening re-use '60' -# set protocols bgp 65536 parameters dampening start-suppress-time '5' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters distance global external '66' -# set protocols bgp 65536 parameters distance global internal '20' -# set protocols bgp 65536 parameters distance global local '10' -# set protocols bgp 65536 redistribute static route-map 'map01' +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.43 capability 'dynamic' +# set protocols bgp neighbor 192.0.2.43 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.43 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.43 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' +# set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters 'always-compare-med' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters dampening half-life '33' +# set protocols bgp parameters dampening max-suppress-time '20' +# set protocols bgp parameters dampening re-use '60' +# set protocols bgp parameters dampening start-suppress-time '5' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters distance global external '66' +# set protocols bgp parameters distance global internal '20' +# set protocols bgp parameters distance global local '10' +# set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ ^C - name: gather configs @@ -1292,26 +1162,26 @@ EXAMPLES = """ # parsed.cfg -# set protocols bgp 65536 neighbor 192.0.2.43 advertisement-interval '72' -# set protocols bgp 65536 neighbor 192.0.2.43 capability 'dynamic' -# set protocols bgp 65536 neighbor 192.0.2.43 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.43 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.43 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.0 address-family 'ipv6-unicast' -# set protocols bgp 65536 neighbor 203.0.113.0 capability orf prefix-list 'receive' -# set protocols bgp 65536 network 203.0.113.0/24 route-map 'map01' -# set protocols bgp 65536 parameters 'always-compare-med' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters dampening half-life '33' -# set protocols bgp 65536 parameters dampening max-suppress-time '20' -# set protocols bgp 65536 parameters dampening re-use '60' -# set protocols bgp 65536 parameters dampening start-suppress-time '5' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters distance global external '66' -# set protocols bgp 65536 parameters distance global internal '20' -# set protocols bgp 65536 parameters distance global local '10' -# set protocols bgp 65536 redistribute static route-map 'map01' +# set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.43 capability 'dynamic' +# set protocols bgp neighbor 192.0.2.43 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.43 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.43 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' +# set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters 'always-compare-med' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters dampening half-life '33' +# set protocols bgp parameters dampening max-suppress-time '20' +# set protocols bgp parameters dampening re-use '60' +# set protocols bgp parameters dampening start-suppress-time '5' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters distance global external '66' +# set protocols bgp parameters distance global internal '20' +# set protocols bgp parameters distance global local '10' +# set protocols bgp redistribute static route-map 'map01' - name: parse configs vyos.vyos.vyos_bgp_global: @@ -1430,25 +1300,25 @@ EXAMPLES = """ # Module Execution: # "rendered": [ -# "set protocols bgp 65536 neighbor 192.0.2.43 disable-connected-check", -# "set protocols bgp 65536 neighbor 192.0.2.43 advertisement-interval 72", -# "set protocols bgp 65536 neighbor 192.0.2.43 capability dynamic", -# "set protocols bgp 65536 neighbor 192.0.2.43 timers holdtime 30", -# "set protocols bgp 65536 neighbor 192.0.2.43 timers keepalive 10", -# "set protocols bgp 65536 neighbor 203.0.113.0 capability orf prefix-list receive", -# "set protocols bgp 65536 redistribute static route-map map01", -# "set protocols bgp 65536 network 203.0.113.0/24 route-map map01", -# "set protocols bgp 65536 parameters always-compare-med", -# "set protocols bgp 65536 parameters dampening half-life 33", -# "set protocols bgp 65536 parameters dampening max-suppress-time 20", -# "set protocols bgp 65536 parameters dampening re-use 60", -# "set protocols bgp 65536 parameters dampening start-suppress-time 5", -# "set protocols bgp 65536 parameters distance global internal 20", -# "set protocols bgp 65536 parameters distance global local 10", -# "set protocols bgp 65536 parameters distance global external 66", -# "set protocols bgp 65536 parameters bestpath as-path confed", -# "set protocols bgp 65536 parameters bestpath compare-routerid", -# "set protocols bgp 65536 parameters default no-ipv4-unicast" +# "set protocols bgp neighbor 192.0.2.43 disable-connected-check", +# "set protocols bgp neighbor 192.0.2.43 advertisement-interval 72", +# "set protocols bgp neighbor 192.0.2.43 capability dynamic", +# "set protocols bgp neighbor 192.0.2.43 timers holdtime 30", +# "set protocols bgp neighbor 192.0.2.43 timers keepalive 10", +# "set protocols bgp neighbor 203.0.113.0 capability orf prefix-list receive", +# "set protocols bgp redistribute static route-map map01", +# "set protocols bgp network 203.0.113.0/24 route-map map01", +# "set protocols bgp parameters always-compare-med", +# "set protocols bgp parameters dampening half-life 33", +# "set protocols bgp parameters dampening max-suppress-time 20", +# "set protocols bgp parameters dampening re-use 60", +# "set protocols bgp parameters dampening start-suppress-time 5", +# "set protocols bgp parameters distance global internal 20", +# "set protocols bgp parameters distance global local 10", +# "set protocols bgp parameters distance global external 66", +# "set protocols bgp parameters bestpath as-path confed", +# "set protocols bgp parameters bestpath compare-routerid", +# "set protocols bgp parameters default no-ipv4-unicast" # ] """ @@ -1472,17 +1342,17 @@ commands: returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) type: list sample: - - set protocols bgp 65536 redistribute static route-map map01 - - set protocols bgp 65536 network 203.0.113.0/24 route-map map01 - - set protocols bgp 65536 parameters always-compare-med + - set protocols bgp redistribute static route-map map01 + - set protocols bgp network 203.0.113.0/24 route-map map01 + - set protocols bgp parameters always-compare-med 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 protocols bgp 65536 redistribute static route-map map01 - - set protocols bgp 65536 network 203.0.113.0/24 route-map map01 - - set protocols bgp 65536 parameters always-compare-med + - set protocols bgp redistribute static route-map map01 + - set protocols bgp network 203.0.113.0/24 route-map map01 + - set protocols bgp parameters always-compare-med gathered: description: Facts about the network resource gathered from the remote device as structured data. returned: when I(state) is C(gathered) diff --git a/plugins/modules/vyos_command.py b/plugins/modules/vyos_command.py index bacbe26a..5131dd88 100644 --- a/plugins/modules/vyos_command.py +++ b/plugins/modules/vyos_command.py @@ -17,7 +17,6 @@ # from __future__ import absolute_import, division, print_function - __metaclass__ = type @@ -86,7 +85,7 @@ options: default: 1 type: int notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - Running C(show system boot-messages all) will cause the module to hang since VyOS is using a custom pager setting to display the output of that command. - If a command sent to the device requires answering a prompt, it is possible to pass diff --git a/plugins/modules/vyos_config.py b/plugins/modules/vyos_config.py index 60be02c8..53f8e043 100644 --- a/plugins/modules/vyos_config.py +++ b/plugins/modules/vyos_config.py @@ -34,10 +34,13 @@ version_added: 1.0.0 extends_documentation_fragment: - vyos.vyos.vyos notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). - To ensure idempotency and correct diff the configuration lines in the relevant module options should be similar to how they appear if present in the running configuration on device including the indentation. +- C(replace=config) currently has no way to scope its effect to part of the + configuration; it always operates against the entire device configuration. + There is no C(path) parameter to constrain it to a subtree. options: lines: description: @@ -46,6 +49,7 @@ options: device running-config to ensure idempotency and correct diff. Be sure to note the configuration command syntax as some commands are automatically modified by the device config parser. + - Not supported when C(replace) is set to C(config) -- see C(replace) below. type: list elements: str src: @@ -55,18 +59,38 @@ options: file can include Jinja2 template variables. The configuration lines in the source file should be similar to how it will appear if present in the running-configuration of the device including indentation to ensure idempotency and correct diff. + - When C(replace) is set to C(config), C(src) is required and must contain a + complete configuration in hierarchical/bracket format -- the same format + produced by C(show configuration) or found in C(/config/config.boot). Flat + C(set)/C(delete) command format (as produced by C(show configuration + commands)) is not accepted in that mode; VyOS's native C(load) command + rejects it with a parse error. type: path match: description: - The C(match) argument controls the method used to match against the current active configuration. By default, the desired config is matched against the active config and the deltas are loaded. If the C(match) argument is set to - C(none) the active configuration is ignored and the configuration is always - loaded. + C(none), the active configuration is ignored and the configuration is always + loaded. If the C(match) argument is set to C(enforce), the supplied C(lines) + or C(src) are treated as the complete desired end-state of the configuration, + rather than a set of deltas to apply. + C(enforce) enforces only the top-level configuration + sections present in the supplied candidate as complete end-states; + existing configuration within those sections but not mentioned in the + candidate is removed, so C(enforce) can generate C(delete) commands for + configuration the candidate does not mention. Top-level sections the + candidate does not reference at all are left completely untouched. + C(enforce) is intended for candidates made up of C(set) commands only; + supplying C(delete) lines alongside C(match=enforce) is not supported + and will raise an error. + - Ignored when C(replace) is set to C(config), since no line-level diff is + computed in that mode. type: str default: line choices: - line + - enforce - none backup: description: @@ -84,6 +108,28 @@ options: is ignored. default: configured by vyos_config type: str + confirm: + description: + - The C(confirm) argument will tell vyos to revert to the previous configuration + if not explicitly confirmed after applying the new config. When set to C(automatic) + this module will automatically confirm the configuration, if the current session + remains working with the new config. When set to C(manual), this module does + not issue the confirmation itself. + - Defaults to C(automatic) when C(match) is set to C(enforce), since C(enforce) + can generate C(delete) commands for configuration not mentioned in the + candidate and a bad commit should self-revert rather than leave the device + unreachable. Defaults to C(none) for all other C(match) values. + type: str + choices: + - automatic + - manual + - none + confirm_timeout: + description: + - Minutes to wait for confirmation before reverting the configuration. Does + not apply when C(confirm) is set to C(none) . + type: int + default: 10 config: description: - The C(config) argument specifies the base configuration to use to compare against @@ -92,12 +138,13 @@ options: The configuration lines in the option value should be similar to how it will appear if present in the running-configuration of the device including indentation to ensure idempotency and correct diff. + - Ignored when C(replace) is set to C(config). type: str save: description: - The C(save) argument controls whether or not changes made to the active configuration are saved to disk. This is independent of committing the config. When set - to True, the active configuration is saved. + to C(True), the active configuration is saved. type: bool default: no backup_options: @@ -123,6 +170,79 @@ options: in C(filename) within I(backup) directory. type: path type: dict + replace: + description: + - Controls how the module applies configuration to the device. + - When set to C(line) (default), the module computes a set/delete command + diff and pushes only the changed lines -- this is the existing behavior, + unchanged. + - When set to C(config), the module uploads the full candidate configuration + (C(src)) to the device and issues VyOS's native C(load) command in + configuration mode, which replaces the running configuration wholesale + with the candidate's exact contents. VyOS's own configuration engine + performs the reconciliation, rather than the module computing per-line + deltas. This mirrors the mechanism offered by C(cisco.iosxr.iosxr_config)'s + C(replace=config). + - C(replace=config) requires C(src) and does not accept C(lines) -- there is + no way to convert flat set/delete commands into the hierarchical form + C(load) requires without re-implementing VyOS's own config-tree builder. + - As with C(src) in the default C(line) mode, the module does not validate + the candidate's contents or format under C(replace=config) -- supplying a + well-formed, complete configuration is the caller's responsibility. + - C(replace=config) requires the device to accept file transfer (SCP) over + the same C(network_cli) SSH session used for configuration commands. + - C(replace=config) writes the candidate to a fixed path on the device + (overwritten on each run, matching C(cisco.iosxr.iosxr_config)'s own + C(replace=config) precedent). Running C(replace=config) concurrently + against the same host is not supported. + - Any configuration present on the device but omitted from the candidate + will be removed, including management interfaces, SSH access, and login + users if they are omitted. Always supply a complete configuration, never + a partial one. + - When capturing a candidate from the device's own output (for example + via C(show configuration)) rather than from a trusted, separately + maintained source, be aware that VyOS may return masked placeholder + values (for example a run of literal asterisks) in place of local + users' C(encrypted-password)/C(plaintext-password) values when queried + through automation, even though the identical command returns the real + value when typed interactively at a terminal. Pushing a masked capture + back through C(replace=config) sends the literal placeholder as the new + password value; VyOS's own commit-time validation is expected to reject + an obviously malformed hash, but a masked value that happens to pass + basic format validation could apply silently. Prefer sourcing + C(replace=config) candidates from a trusted, version-controlled + artifact rather than a live automated capture whenever the + configuration contains local password-based users. + - Even under C(check_mode), the candidate is written to a temporary file on + the device so that VyOS's own C(compare) can produce an accurate preview + diff. No C(commit) occurs in check mode. + - When combined with C(backup=yes), the value of C(changed) reflects + whether the backup file's content changed on the Ansible control node, + not whether the device configuration changed -- this is existing + behavior in the shared netcommon action plugin backing config-family + modules across collections, not specific to C(replace=config). + type: str + default: line + choices: + - line + - config + allow_password_change: + description: + - The C(allow_password_change) argument specifies whether any configuration lines which + would change a user's password should be filtered out. By default only plaintext + password changes are allowed and any encrypted-password keys are filtered out. In + order to allow all password updates, both plaintext and encrypted, set this argument + to C(all). + - Not applied when C(replace) is set to C(config); the candidate is loaded + as-is via VyOS's native C(load), which has no equivalent filtering + mechanism. + type: str + default: plaintext + choices: + - all + - plaintext + - encrypted + - none """ EXAMPLES = """ @@ -140,8 +260,14 @@ EXAMPLES = """ - name: render a Jinja2 template onto the VyOS router vyos.vyos.vyos_config: + match: enforce src: vyos_template.j2 +- name: revert after ten minutes, if connection is lost + vyos.vyos.vyos_config: + src: vyos_template.j2 + confirm: automatic + - name: for idempotency, use full-form commands vyos.vyos.vyos_config: lines: @@ -154,16 +280,40 @@ EXAMPLES = """ backup_options: filename: backup.cfg dir_path: /home/user + +- name: capture the complete hierarchical configuration for editing + # replace=config requires the complete desired configuration in + # hierarchical/bracket format -- never a partial one, and never flat + # set-command format. `backup: true` alone won't work here: it captures + # flat set-command output (via `show configuration commands`), which + # replace=config's underlying `load` command rejects. Capture the + # hierarchical form directly instead, edit it, then replace with the + # edited whole, as shown here. + vyos.vyos.vyos_command: + commands: "show configuration" + register: current_config + +- name: (edit current_config.stdout[0] as needed, save it locally, then) + vyos.vyos.vyos_config: + src: /home/user/edited_config.cfg + replace: config """ RETURN = """ commands: - description: The list of configuration commands sent to the device + description: + - In C(replace=line) mode (default), the list of set/delete commands sent to + the device. + - In C(replace=config) mode, contains only the single C(load <path>) command + actually issued to the device -- not an itemized diff. See C(diff) for the + actual change content, sourced from VyOS's own C(compare) output. returned: always type: list sample: ['...', '...'] filtered: - description: The list of configuration commands removed to avoid a load failure + description: + - The list of configuration commands removed to avoid a load failure. + - Not populated when C(replace) is set to C(config). returned: always type: list sample: ['...', '...'] @@ -193,13 +343,16 @@ time: type: str sample: "22:28:34" """ +import os import re +import tempfile -from ansible.module_utils._text import to_text +from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.connection import ConnectionError from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + copy_file, get_config, get_connection, load_config, @@ -209,9 +362,48 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import DEFAULT_COMMENT = "configured by vyos_config" -CONFIG_FILTERS = [ - re.compile(r"set system login user \S+ authentication encrypted-password"), -] +PASSWORD_NEEDLE = re.compile( + r"(?:set|delete) system login user \S+ authentication (encrypted|plaintext)-password", +) + +# diff_match=enforce's scoping can collapse an entire untouched subtree into +# a single parent delete (e.g. "delete system login" when a candidate +# touches system without restating login, or "delete system login user +# admin" without a specific authentication line). PASSWORD_NEEDLE can't see +# into a collapsed delete to know whether it removes a password -- since +# real users almost always have one configured, treat any subtree-level +# login deletion as password-bearing by default, same conservative stance +# as PASSWORD_NEEDLE itself. +LOGIN_SUBTREE_DELETE_NEEDLE = re.compile( + r"^delete system login(?:\s+user\s+\S+(?:\s+authentication)?)?\s*$", +) + + +def sanitize_config(config, result, allow): + result["filtered"] = list() + + if allow == "all": + return + + index_to_filter = list() + + for index, line in enumerate(list(config)): + found = PASSWORD_NEEDLE.search(line) + + if found is not None: + if allow == found[1]: + continue + result["filtered"].append(line) + index_to_filter.append(index) + continue + + if LOGIN_SUBTREE_DELETE_NEEDLE.match(line.strip()): + result["filtered"].append(line) + index_to_filter.append(index) + + # Delete all filtered configs + for filter_index in sorted(index_to_filter, reverse=True): + del config[filter_index] def get_candidate(module): @@ -270,22 +462,10 @@ def diff_config(commands, config): return list(updates) -def sanitize_config(config, result): - result["filtered"] = list() - index_to_filter = list() - for regex in CONFIG_FILTERS: - for index, line in enumerate(list(config)): - if regex.search(line): - result["filtered"].append(line) - index_to_filter.append(index) - # Delete all filtered configs - for filter_index in sorted(index_to_filter, reverse=True): - del config[filter_index] - - def run(module, result): # get the current active config from the node or passed in via # the config param + config = module.params["config"] or get_config(module) # create the candidate config object from the arguments @@ -303,16 +483,27 @@ def run(module, result): module.fail_json(msg=to_text(exc, errors="surrogate_then_replace")) commands = response.get("config_diff") - sanitize_config(commands, result) + + allow_password_change = module.params["allow_password_change"] + sanitize_config(commands, result, allow=allow_password_change) result["commands"] = commands + confirm_param = module.params["confirm"] + if confirm_param is None: + confirm_param = "automatic" if module.params["match"] == "enforce" else "none" + commit = not module.check_mode comment = module.params["comment"] + confirm = None + if confirm_param in ("automatic", "manual"): + confirm = module.params["confirm_timeout"] diff = None if commands: - diff = load_config(module, commands, commit=commit, comment=comment) + diff = load_config(module, commands, commit=commit, comment=comment, confirm=confirm) + if confirm_param == "automatic" and not module.check_mode: + run_commands(module, ["configure", "confirm", "exit"]) if result.get("filtered"): result["warnings"].append( @@ -325,24 +516,105 @@ def run(module, result): result["diff"] = {"prepared": diff} +def run_replace_config(module, result): + # replace=config: push the full candidate to the device and let VyOS's + # own `load` command perform the replacement natively, rather than + # computing a set/delete diff in Python. + # + # Deliberately smaller than cisco.iosxr's equivalent implementation: + # - No bidirectional pre-diff to decide whether anything changed -- + # confirmed on real VyOS 1.5 hardware that `load` of an + # already-applied file, followed by `compare`, natively reports + # "No changes between working and active configurations" with no + # Python-side pre-check needed. + # - No special `replace=<path>` argument threaded through load_config()/ + # edit_config() -- confirmed that `load <path>` behaves as an ordinary + # configuration command through the existing configure/compare/commit + # flow already implemented in Cliconf.edit_config(), unmodified. + # + # Candidate format requirement (hierarchical/bracket, not flat + # set/delete) is enforced by VyOS's own `load` parser, not by this + # module -- confirmed empirically: flat set-command input produces + # "ValueError: Failed to parse config: Syntax error...". + # module.params["src"] is already the rendered file *content* by this + # point, not a path -- netcommon's generic action plugin for src-based + # network config modules reads the local file and substitutes its + # (Jinja2-rendered) content into this param before the module runs. Same + # assumption get_candidate() already relies on elsewhere in this file. + candidate = to_bytes(module.params["src"], errors="surrogate_or_strict") + + tmp = tempfile.NamedTemporaryFile(delete=False) + local_path = tmp.name + try: + tmp.write(candidate) + tmp.close() + + # Fixed remote filename, always overwritten -- same precedent as + # cisco.iosxr.iosxr_config's copy_file_to_node(), which always + # writes to the same "/harddisk:/ansible_config.txt". Avoids + # per-run temp-file accumulation on the device, at the accepted + # cost (shared with iosxr_config) that two concurrent replace=config + # runs against the same host could race on this path. + remote_path = "/tmp/ansible_vyos_replace.cfg" + copy_file(module, local_path, remote_path, "scp") + finally: + os.unlink(local_path) + + confirm_param = module.params["confirm"] + if confirm_param is None: + confirm_param = "none" + + commit = not module.check_mode + comment = module.params["comment"] + confirm = None + if confirm_param in ("automatic", "manual"): + confirm = module.params["confirm_timeout"] + + diff = load_config( + module, + ["load %s" % remote_path], + commit=commit, + comment=comment, + confirm=confirm, + ) + if confirm_param == "automatic" and diff and not module.check_mode: + run_commands(module, ["configure", "confirm", "exit"]) + + result["commands"] = ["load %s" % remote_path] + result["filtered"] = [] + result["changed"] = bool(diff) + + if module._diff: + result["diff"] = {"prepared": diff} + + def main(): backup_spec = dict(filename=dict(), dir_path=dict(type="path")) argument_spec = dict( src=dict(type="path"), lines=dict(type="list", elements="str"), - match=dict(default="line", choices=["line", "none"]), + match=dict(default="line", choices=["line", "enforce", "none"]), comment=dict(default=DEFAULT_COMMENT), + confirm=dict(choices=["automatic", "manual", "none"], default=None), + confirm_timeout=dict(type="int", default=10), config=dict(), backup=dict(type="bool", default=False), backup_options=dict(type="dict", options=backup_spec), save=dict(type="bool", default=False), + replace=dict(type="str", default="line", choices=["line", "config"]), + allow_password_change=dict( + default="plaintext", + choices=["all", "encrypted", "plaintext", "none"], + ), ) mutually_exclusive = [("lines", "src")] + required_if = [("replace", "config", ["src"])] module = AnsibleModule( argument_spec=argument_spec, mutually_exclusive=mutually_exclusive, + required_if=required_if, supports_check_mode=True, ) @@ -353,21 +625,27 @@ def main(): if module.params["backup"]: result["__backup__"] = get_config(module=module) - if any((module.params["src"], module.params["lines"])): + if module.params["replace"] == "config": + run_replace_config(module, result) + elif any((module.params["src"], module.params["lines"])): run(module, result) if module.params["save"]: diff = run_commands(module, commands=["configure", "compare saved"])[1] if diff not in { "[edit]", - "No changes between working and saved configurations.\n\n[edit]" + "No changes between working and saved configurations.\n\n[edit]", }: if not module.check_mode: run_commands(module, commands=["save"]) result["changed"] = True run_commands(module, commands=["exit"]) - if result.get("changed") and any((module.params["src"], module.params["lines"])): + if ( + result.get("changed") + and module.params["replace"] != "config" + and any((module.params["src"], module.params["lines"])) + ): msg = ( "To ensure idempotency and correct diff the input configuration lines should be" " similar to how they appear if present in" diff --git a/plugins/modules/vyos_facts.py b/plugins/modules/vyos_facts.py index a999bd31..3d6d1b05 100644 --- a/plugins/modules/vyos_facts.py +++ b/plugins/modules/vyos_facts.py @@ -5,7 +5,6 @@ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function - __metaclass__ = type """ The module file for vyos_facts @@ -28,7 +27,7 @@ author: extends_documentation_fragment: - vyos.vyos.vyos notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: gather_subset: diff --git a/plugins/modules/vyos_file.py b/plugins/modules/vyos_file.py new file mode 100644 index 00000000..312a7a74 --- /dev/null +++ b/plugins/modules/vyos_file.py @@ -0,0 +1,520 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2026, VyOS maintainers and contributors +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +DOCUMENTATION = """ +module: vyos_file +short_description: Manage files, directories, and their ownership on VyOS devices +description: + - Creates, updates, or removes a file or directory on a VyOS device, optionally + pushing content from a local file (I(src)) or inline text (I(content)), and + setting owner/group/mode via sudo chown/chmod. + - This module does not touch the configuration tree (config.boot). It manages + arbitrary filesystem paths such as certificates or auth files under + /config/auth/, which are not tracked by commit/save/rollback. + - All logic runs inside this module's main(), using the standard + get_connection()/run_commands() pattern shared with vyos_command — there is + no dedicated action plugin; this module uses the shared generic vyos action + plugin like every other module in the collection. +version_added: "6.0.0" +author: + - VyOS maintainers and contributors (@vyos) +options: + dest: + description: Absolute path to the remote file or directory to manage. + type: path + required: true + state: + description: Whether the path should exist (present) or be removed (absent). + type: str + choices: [present, absent] + default: present + src: + description: + - Path to a local file (on the Ansible controller) whose content should be + pushed to I(dest). Transferred via a real SCP session over the + connection's own persistent socket (the same mechanism + M(ansible.netcommon.net_put) uses), never placed inside a command + string. Mutually exclusive with I(content). + - File bytes are uploaded exactly as they exist on disk — Ansible does + not render Jinja expressions inside the file's contents for I(src), + only in the option values of the task itself (e.g. a templated path + string). To push templated text, render it first with the C(template) + lookup and pass the result via I(content) instead. + type: path + content: + description: + - Inline text content to write to I(dest). Marked no_log, since this module + is commonly used to push credential material. Mutually exclusive with + I(src). + - Since I(content) is a normal string-type module option, Ansible renders + any Jinja expressions in it (e.g. C({{ my_var }})) before this module + ever runs, the same as any other option value — no special templating + support is implemented by this module itself. + type: str + owner: + description: Name of the user that should own I(dest). + type: str + group: + description: Name of the group that should own I(dest). + type: str + mode: + description: + - Permission bits for I(dest), as a string (e.g. '0600'). Compared against + stat output after normalizing to 4 digits; '600' and '0600' are treated + as equivalent. + type: str + become: + description: Whether to prefix remote commands with sudo. + type: bool + default: true +notes: + - This module works with connection C(ansible.netcommon.network_cli). + - File state managed by this module is independent of VyOS's config revision + system. A rollback to a previous config revision will not revert changes + made by this module. + - Paths under I(/config/auth) are deliberately setgid C(vyattacfg) by VyOS's + own config-management convention (see vyos.dev T2713). If I(mode) is given + with a leading digit of C(0) (e.g. C('0750')), this module compares only + the rwx bits and will not report a diff for VyOS's own setgid bit. To + manage the setgid/setuid/sticky bit explicitly, pass a non-zero leading + digit (e.g. C('2750')). +""" + +EXAMPLES = """ +- name: ensure the auth directory exists with correct ownership + vyos.vyos.vyos_file: + dest: /config/auth/office-vpn + owner: openvpn + group: openvpn + mode: '0750' + +- name: push a client certificate with correct ownership + vyos.vyos.vyos_file: + dest: /config/auth/office-vpn/client.pem + src: files/office-vpn-client.pem + owner: openvpn + group: openvpn + mode: '0600' + +- name: remove a stale cert + vyos.vyos.vyos_file: + dest: /config/auth/old-vpn/client.pem + state: absent + +- name: push templated LDAP auth config (content is rendered by Ansible before this module runs) + vyos.vyos.vyos_file: + dest: /config/auth/office-vpn/ldap-auth.config + content: "{{ lookup('template', 'ldap_auth.config.j2') }}" + owner: openvpn + group: openvpn + mode: '0640' +""" + +RETURN = """ +diff_fields: + description: Fields that differed between requested and actual state and were converged. + returned: always + type: list + elements: str + sample: ["owner", "mode", "content"] +""" + +import hashlib +import os +import re +import shlex +import tempfile +import uuid + +from ansible.module_utils.basic import AnsibleModule + +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + get_connection, + run_commands, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos_file import ( + build_want, + diff_want_have, + parse_stat, +) + + +ARGUMENT_SPEC = dict( + dest=dict(type="path", required=True), + state=dict(type="str", choices=["present", "absent"], default="present"), + src=dict(type="path"), + content=dict(type="str", no_log=True), + owner=dict(type="str"), + group=dict(type="str"), + mode=dict(type="str"), + become=dict(type="bool", default=True), +) + + +def get_have(module, become, dest, need_content_hash=False): + quoted_dest = shlex.quote(dest) + # check_rc=False is required here: a missing path is a normal, expected + # outcome on first-run creation, not a failure. With the default + # check_rc=True, run_commands() would call module.fail_json() on every + # "file doesn't exist yet" case, which is exactly the case we need to + # handle gracefully to build `have`. + responses = run_commands( + module, + ["{0}stat --format='%a %U %G %s' {1}".format(become, quoted_dest)], + check_rc=False, + ) + out = responses[0] if responses else "" + + if not out: + return None + if "No such file" in out: + return None + + have = parse_stat(out) + if have is None: + # Anything that isn't the specific "doesn't exist" message and + # doesn't parse as valid stat output is a real problem — permission + # denied, I/O error, unexpected format, etc. Fail loudly rather than + # silently treating it as "create it", which could otherwise lead + # this module to attempt mkdir/chown/chmod against a path it + # actually has no real visibility into. + module.fail_json( + msg="vyos_file: unexpected stat output for {0}: {1}".format(dest, out.strip()), + ) + + if need_content_hash: + # Only hash when content comparison actually matters (src/content + # given) — no need to pay this cost for plain directory/ownership + # management. Without this, `have["content_hash"]` would always be + # None, so `content` would show as "different" forever, even right + # after a successful write. + hash_responses = run_commands( + module, + ["{0}sha256sum {1}".format(become, quoted_dest)], + check_rc=False, + ) + hash_out = hash_responses[0] if hash_responses else "" + # sha256sum output format: "<hex digest> <path>" + parts = hash_out.strip().split() + if parts and len(parts[0]) == 64 and all(c in "0123456789abcdef" for c in parts[0].lower()): + have["content_hash"] = parts[0] + # else: leave content_hash unset — a malformed/errored sha256sum + # (e.g. the file vanished in a race between stat and sha256sum) + # should surface as a real diff on the next comparison, not get + # silently recorded as a bogus "hash". + + return have + + +_OCTAL_DIGIT_TO_SYMBOLIC = { + "0": "", + "1": "x", + "2": "w", + "3": "wx", + "4": "r", + "5": "rx", + "6": "rw", + "7": "rwx", +} + + +def _rwx_digits_to_symbolic_mode(mode4): + """Convert the last 3 digits of a normalized 4-digit mode string into a + symbolic chmod argument (e.g. "0750" -> "u=rwx,g=rx,o="). Symbolic mode + assignment for u/g/o only touches those classes — unlike any numeric + chmod form, it leaves existing setuid/setgid/sticky bits untouched + unless explicitly referenced (u+s, g+s, +t), which is exactly the + "special bits are unmanaged for implicit mode requests" guarantee this + module's docs and diff logic already promise but a plain numeric chmod + would silently violate. + """ + u, g, o = mode4[-3], mode4[-2], mode4[-1] + return "u={0},g={1},o={2}".format( + _OCTAL_DIGIT_TO_SYMBOLIC[u], + _OCTAL_DIGIT_TO_SYMBOLIC[g], + _OCTAL_DIGIT_TO_SYMBOLIC[o], + ) + + +def _build_chmod_command(become, mode4, quoted_dest): + if mode4[0] == "0": + # Implicit special bits (caller didn't ask for them): use symbolic + # mode so existing setuid/setgid/sticky bits survive. A numeric + # chmod here — even a bare 3-digit form — always explicitly sets + # the special-bits digit to 0, silently clearing e.g. VyOS's own + # setgid convention on /config/auth (vyos.dev T2713) the moment any + # rwx change is needed, rather than genuinely leaving it unmanaged. + symbolic = _rwx_digits_to_symbolic_mode(mode4) + return "{0}chmod {1} {2}".format(become, shlex.quote(symbolic), quoted_dest) + # Explicit non-zero leading digit: caller wants exact control over + # special bits too, so a plain numeric chmod is correct here. + return "{0}chmod {1} {2}".format(become, shlex.quote(mode4), quoted_dest) + + +def local_content_hash(params): + if params.get("src"): + h = hashlib.sha256() + with open(params["src"], "rb") as f: + for chunk in iter(lambda: f.read(65536), b""): + h.update(chunk) + return h.hexdigest() + if params.get("content") is not None: + return hashlib.sha256(params["content"].encode()).hexdigest() + return None + + +def read_local_bytes(params): + if params.get("src"): + with open(params["src"], "rb") as f: + return f.read() + if params.get("content") is not None: + return params["content"].encode() + return None + + +def push_content_via_scp(module, connection, become, dest, params): + # Real SCP transfer over the connection's own persistent SSH session — + # content/src bytes never appear inside a command string sent through + # run_commands(). The earlier base64-in-a-shell-command approach was + # only ever encoded, not encrypted, and remained fully readable to + # anything logging connection traffic (e.g. persistent connection + # logging), regardless of no_log on the task — a real problem given + # this module's actual purpose (VPN certs, LDAP credentials). + # + # net_put's own action plugin uses this exact mechanism — connection + # here is get_connection(module), the same Connection(module._socket_path) + # JSON-RPC proxy net_put builds via Connection(socket_path) — so this is + # not action-plugin-only, despite that being true historically for some + # other network_cli file-transfer patterns. + # + # connection.copy_file() writes as the connecting user with NO `become` + # applied — it has no concept of sudo. That's fine for a destination + # the connecting user already has access to (e.g. /config/auth, which + # `vyos` can write via its vyattacfg group membership), but it would + # fail outright against a genuinely protected destination. So: always + # transfer to a /tmp staging path the connecting user can unconditionally + # write to, then relocate it into the real `dest` via a sudo-prefixed + # `mv` — `mv` only ever references paths, never content, so this still + # never puts secret material inside a command string. + cleanup_local = False + if params.get("src"): + local_path = params["src"] + else: + data = read_local_bytes(params) + fd, local_path = tempfile.mkstemp(prefix="vyos_file_") + cleanup_local = True + try: + with os.fdopen(fd, "wb") as f: + f.write(data) + except Exception: + os.remove(local_path) + raise + + remote_staging_path = "/tmp/.vyos_file_staging_{0}".format(uuid.uuid4().hex) + try: + timeout = connection.get_option("persistent_command_timeout") + connection.copy_file( + source=local_path, + destination=remote_staging_path, + proto="scp", + timeout=timeout, + ) + finally: + if cleanup_local: + os.remove(local_path) + + run_commands( + module, + [ + "{0}mv {1} {2}".format( + become, + shlex.quote(remote_staging_path), + shlex.quote(dest), + ), + ], + ) + + +def converge(module, become, dest, want, diff, params): + cmds = [] + quoted_dest = shlex.quote(dest) + + if want["state"] == "absent": + cmds.append("{0}rm -rf {1}".format(become, quoted_dest)) + run_commands(module, cmds) + post_have = get_have(module, become, dest) + if post_have is not None: + module.fail_json( + msg="vyos_file: removal of {0} did not take effect".format(dest), + ) + return + + if "content" in diff: + connection = get_connection(module) + push_content_via_scp(module, connection, become, dest, params) + elif "state" in diff and have_is_missing(diff): + cmds.append("{0}mkdir -p {1}".format(become, quoted_dest)) + + if "owner" in diff and "group" in diff: + cmds.append( + "{0}chown {1}:{2} {3}".format( + become, + shlex.quote(want["owner"]), + shlex.quote(want["group"]), + quoted_dest, + ), + ) + elif "owner" in diff: + cmds.append( + "{0}chown {1} {2}".format(become, shlex.quote(want["owner"]), quoted_dest), + ) + elif "group" in diff: + cmds.append( + "{0}chgrp {1} {2}".format(become, shlex.quote(want["group"]), quoted_dest), + ) + + if "mode" in diff: + cmds.append(_build_chmod_command(become, want["mode"], quoted_dest)) + + if cmds: + run_commands(module, cmds) + + # run_commands() only confirms the CLI accepted each command line + # syntactically — it does NOT confirm the underlying binary succeeded. + # A chown against a nonexistent group, for example, prints an error to + # stdout but the CLI wrapper still reports the line as "executed"; we + # would otherwise report changed=true for a write that silently did + # nothing. Re-stat and compare against `want` to catch this class of + # failure before returning success. + post_have = get_have( + module, + become, + dest, + need_content_hash=want.get("content_hash") is not None, + ) + post_diff = diff_want_have(want, post_have) + if post_diff: + module.fail_json( + msg=( + "vyos_file converged but post-check found remaining " + "differences — one or more commands likely failed silently " + "at the OS level (e.g. chown to a nonexistent user/group): " + "{0}".format(post_diff) + ), + ) + + +def have_is_missing(diff): + return diff.get("state") == (None, "present") + + +def validate_dest(module, dest): + # dest is type=path in ARGUMENT_SPEC, which expands ~ and env vars but + # does NOT enforce absoluteness — a relative value would resolve against + # whatever the underlying shell's cwd happens to be, an unintended and + # unpredictable target. And since this module issues raw `rm -rf`, + # `chmod`, `chown` against dest with no config-tree safety net, a + # dest of "/" (or anything that normalizes to it) combined with + # state=absent would attempt to recursively remove the entire + # filesystem. Both must be rejected before any stat/converge runs. + if not os.path.isabs(dest): + module.fail_json( + msg="vyos_file: dest must be an absolute path, got {0!r}".format(dest), + ) + normalized = os.path.normpath(dest) + # normalized == "/" alone is insufficient: os.path.normpath preserves + # "//" as-is (a POSIX quirk permitting implementation-defined behavior + # for exactly two leading slashes), so dest="//" would otherwise bypass + # this check entirely. Stripping all slashes catches "/", "//", "///", + # etc. uniformly. + if normalized.strip("/") == "": + module.fail_json( + msg=( + "vyos_file: refusing to manage the root filesystem path " + "(dest normalized to {0!r}): {1!r}".format(normalized, dest) + ), + ) + + +_MODE_RE = re.compile(r"^[0-7]{3,4}$") + + +def validate_mode(module, mode): + # _normalize_mode() (module_utils) does str(mode).zfill(4)[-4:], which + # for genuinely invalid input silently mangles it into something that + # LOOKS valid rather than rejecting it — e.g. "10640" (5 digits, an + # obvious typo for a 4-digit mode) becomes "0640" by truncation, and + # the module would silently apply permissions the caller never actually + # asked for. Validate strictly here, before that normalization ever + # runs, so malformed input fails loudly instead of being reinterpreted. + if mode is None: + return + if not _MODE_RE.match(mode): + module.fail_json( + msg=( + "vyos_file: mode must be an octal string of 3 or 4 digits " + "(0-7 only), got {0!r}".format(mode) + ), + ) + + +def validate_src(module, src): + # local_content_hash()/read_local_bytes() do plain open(src, "rb") + # calls with no existence/type/permission check. A missing file, a + # directory passed where a file is expected, or an unreadable path + # would otherwise surface as an unhandled Python traceback instead of + # a clean module error — and this happens even under check_mode, since + # content-hashing runs before the check-mode short-circuit. + if src is None: + return + if not os.path.exists(src): + module.fail_json(msg="vyos_file: src not found: {0!r}".format(src)) + if os.path.isdir(src): + module.fail_json( + msg="vyos_file: src is a directory, expected a file: {0!r}".format(src), + ) + if not os.access(src, os.R_OK): + module.fail_json(msg="vyos_file: src is not readable: {0!r}".format(src)) + + +def main(): + module = AnsibleModule( + argument_spec=ARGUMENT_SPEC, + mutually_exclusive=[["src", "content"]], + supports_check_mode=True, + ) + + dest = module.params["dest"] + validate_dest(module, dest) + validate_mode(module, module.params.get("mode")) + validate_src(module, module.params.get("src")) + + become = "sudo " if module.params.get("become", True) else "" + + want = build_want(module.params, local_content_hash(module.params)) + have = get_have( + module, + become, + dest, + need_content_hash=want.get("content_hash") is not None, + ) + diff = diff_want_have(want, have) + + result = {"changed": bool(diff), "diff_fields": list(diff.keys())} + + if module.check_mode or not diff: + module.exit_json(**result) + + converge(module, become, dest, want, diff, module.params) + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/vyos_firewall_global.py b/plugins/modules/vyos_firewall_global.py index e952ae50..4967a564 100644 --- a/plugins/modules/vyos_firewall_global.py +++ b/plugins/modules/vyos_firewall_global.py @@ -28,7 +28,6 @@ The module file for vyos_firewall_global from __future__ import absolute_import, division, print_function - __metaclass__ = type ANSIBLE_METADATA = { @@ -46,7 +45,8 @@ description: VyOS devices. version_added: '1.0.0' notes: -- Tested against VyOS 1.3.8. +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. +- The provided examples of commands are valid for VyOS 1.4+ - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: @@ -280,6 +280,91 @@ options: - notice - info - debug + zone: + description: + - Defines a firewall zone. + type: list + elements: dict + suboptions: + name: + description: + - Name of the firewall zone. + type: str + required: true + description: + description: + - Allows you to specify a brief description for the firewall zone. + type: str + default_log: + description: + - Specifies whether or not to log packets for the firewall zone. + type: bool + local_zone: + description: + - Specifies whether or not the zone is local. + type: bool + default_action: + description: + - Specifies the default action for the zone. + type: str + default: drop + choices: + - drop + - reject + interfaces: + description: + - Specifies the interfaces associated with the zone. + type: list + elements: str + intra_zone_filtering: + description: + - Specifies a policy for intra-zone filtering. + type: dict + suboptions: + action: + description: + - Action for intra-zone traffic. + type: str + choices: + - accept + - drop + firewall: + description: + - Firewall ruleset to apply to intra-zone traffic. + type: dict + suboptions: + name: + description: + - Name of the firewall ruleset to apply to intra-zone traffic. + type: str + ipv6_name: + description: + - Name of the IPv6 firewall ruleset to apply to intra-zone traffic. + type: str + sources: + description: + - Specifies the source zones for the firewall rules. + type: list + elements: dict + suboptions: + zone: + description: + - Name of the source zone. + type: str + required: true + firewall: + description: + - Firewall ruleset to apply to the source zone. + type: dict + suboptions: + name: + description: + - Name of the firewall ruleset to apply to the source zone. + type: str + ipv6_name: + description: + - Name of the IPv6 firewall ruleset to apply to the source zone. + type: str running_config: description: - > @@ -373,7 +458,7 @@ EXAMPLES = """ # "set firewall global-options send-redirects 'enable'", # "set firewall global-options config-trap 'enable'", # "set firewall global-options state-policy established action 'accept'", -# "set firewall global-options state-policy established log 'enable'", +# "set firewall global-options state-policy established log, # "set firewall global-options state-policy established log-level 'emerg'", # "set firewall global-options state-policy invalid action 'reject'", # "set firewall global-options broadcast-ping 'enable'", @@ -1189,7 +1274,7 @@ EXAMPLES = """ # "set firewall global-options send-redirects 'enable'", # "set firewall global-options config-trap 'enable'", # "set firewall global-options state-policy established action 'accept'", -# "set firewall global-options state-policy established log 'enable'", +# "set firewall global-options state-policy established log, # "set firewall global-options state-policy invalid action 'reject'", # "set firewall global-options broadcast-ping 'enable'", # "set firewall global-options all-ping 'enable'", diff --git a/plugins/modules/vyos_firewall_interfaces.py b/plugins/modules/vyos_firewall_interfaces.py index ae17bc13..a3210b65 100644 --- a/plugins/modules/vyos_firewall_interfaces.py +++ b/plugins/modules/vyos_firewall_interfaces.py @@ -28,7 +28,6 @@ The module file for vyos_firewall_interfaces from __future__ import absolute_import, division, print_function - __metaclass__ = type ANSIBLE_METADATA = { diff --git a/plugins/modules/vyos_firewall_rules.py b/plugins/modules/vyos_firewall_rules.py index 850299ff..96cf271b 100644 --- a/plugins/modules/vyos_firewall_rules.py +++ b/plugins/modules/vyos_firewall_rules.py @@ -28,7 +28,6 @@ The module file for vyos_firewall_rules from __future__ import absolute_import, division, print_function - __metaclass__ = type ANSIBLE_METADATA = { @@ -47,7 +46,8 @@ author: - Rohit Thakur (@rohitthakur2590) - Gaige B. Paulsen (@gaige) notes: -- Tested against VyOS 1.3.8. +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. +- The provided examples of commands are valid for VyOS 1.4+ - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). @@ -89,8 +89,10 @@ options: - reject (Drop and notify source if no prior rules are hit) - accept (Accept if no prior rules are hit) - jump (Jump to another rule-set, 1.4+) + - return (Return from the current chain and continue at the next rule of the last chain, 1.4+) + - continue (Continue parsing next rule, 1.4+) type: str - choices: ['drop', 'reject', 'accept', 'jump'] + choices: ['drop', 'reject', 'accept', 'jump', 'return', 'continue'] default_jump_target: description: - Default jump target if the default action is jump. @@ -134,6 +136,7 @@ options: - continue - return - jump + - offload - queue - synproxy destination: @@ -308,6 +311,10 @@ options: - Option to log packets matching rule. type: str choices: ['disable', 'enable'] + offload_target: + description: + - Match flowtable object. + type: str outbound_interface: description: - Match outbound interface. @@ -570,14 +577,14 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall name Downlink default-action 'accept' -# set firewall name Downlink description 'IPv4 INBOUND rule set' -# set firewall name Downlink rule 501 action 'accept' -# set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible' -# set firewall name Downlink rule 501 ipsec 'match-ipsec' -# set firewall name Downlink rule 502 action 'reject' -# set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible' -# set firewall name Downlink rule 502 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink default-action 'accept' +# set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set' +# set firewall ipv4 name Downlink rule 501 action 'accept' +# set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible' +# set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink rule 502 action 'reject' +# set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible' +# set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec' - name: Delete attributes of given firewall rules. vyos.vyos.vyos_firewall_rules: @@ -619,7 +626,7 @@ EXAMPLES = """ # } # ] # "commands": [ -# "delete firewall name Downlink" +# "delete firewall ipv4 name Downlink" # ] # # "after": [] @@ -635,25 +642,25 @@ EXAMPLES = """ # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' # set firewall group address-group 'inbound' -# set firewall name Downlink default-action 'accept' -# set firewall name Downlink description 'IPv4 INBOUND rule set' -# set firewall name Downlink rule 501 action 'accept' -# set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible' -# set firewall name Downlink rule 501 ipsec 'match-ipsec' -# set firewall name Downlink rule 502 action 'reject' -# set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible' -# set firewall name Downlink rule 502 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink default-action 'accept' +# set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set' +# set firewall ipv4 name Downlink rule 501 action 'accept' +# set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible' +# set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink rule 502 action 'reject' +# set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible' +# set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec' - name: Delete attributes of given firewall rules. vyos.vyos.vyos_firewall_rules: @@ -717,23 +724,23 @@ EXAMPLES = """ # } # ] # "commands": [ -# "delete firewall name" +# "delete firewall ipv4 name" # ] # # "after": [] # After state # ------------ # vyos@vyos:~$ show configuration commands| grep firewall -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' # Using deleted to delete all the the firewall rules when provided config is empty @@ -743,14 +750,14 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall name Downlink default-action 'accept' -# set firewall name Downlink description 'IPv4 INBOUND rule set' -# set firewall name Downlink rule 501 action 'accept' -# set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible' -# set firewall name Downlink rule 501 ipsec 'match-ipsec' -# set firewall name Downlink rule 502 action 'reject' -# set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible' -# set firewall name Downlink rule 502 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink default-action 'accept' +# set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set' +# set firewall ipv4 name Downlink rule 501 action 'accept' +# set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible' +# set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink rule 502 action 'reject' +# set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible' +# set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec' # - name: Delete attributes of given firewall rules. vyos.vyos.vyos_firewall_rules: @@ -788,7 +795,7 @@ EXAMPLES = """ # } # ] # "commands": [ -# "delete firewall name" +# "delete firewall ipv4 name" # ] # # "after": [] @@ -860,35 +867,33 @@ EXAMPLES = """ # before": [] # # "commands": [ -# "set firewall ipv6-name UPLINK default-action 'accept'", -# "set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set'", -# "set firewall ipv6-name UPLINK rule 1 action 'accept'", -# "set firewall ipv6-name UPLINK rule 1", -# "set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible'", -# "set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec'", -# "set firewall ipv6-name UPLINK rule 2 action 'accept'", -# "set firewall ipv6-name UPLINK rule 2", -# "set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible'", -# "set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec'", -# "set firewall name INBOUND default-action 'accept'", -# "set firewall name INBOUND description 'IPv4 INBOUND rule set'", -# "set firewall name INBOUND rule 101 action 'accept'", -# "set firewall name INBOUND rule 101", -# "set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", -# "set firewall name INBOUND rule 101 ipsec 'match-ipsec'", -# "set firewall name INBOUND rule 102 action 'reject'", -# "set firewall name INBOUND rule 102", -# "set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible'", -# "set firewall name INBOUND rule 102 ipsec 'match-ipsec'", -# "set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible'", -# "set firewall name INBOUND rule 103 destination group address-group inbound", -# "set firewall name INBOUND rule 103", -# "set firewall name INBOUND rule 103 source address 192.0.2.0", -# "set firewall name INBOUND rule 103 state established enable", -# "set firewall name INBOUND rule 103 state related enable", -# "set firewall name INBOUND rule 103 state invalid disable", -# "set firewall name INBOUND rule 103 state new disable", -# "set firewall name INBOUND rule 103 action 'accept'" +# "set firewall ipv6 name UPLINK default-action 'accept'", +# "set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set'", +# "set firewall ipv6 name UPLINK rule 1 action 'accept'", +# "set firewall ipv6 name UPLINK rule 1", +# "set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible'", +# "set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec'", +# "set firewall ipv6 name UPLINK rule 2 action 'accept'", +# "set firewall ipv6 name UPLINK rule 2", +# "set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible'", +# "set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec'", +# "set firewall ipv4 name INBOUND default-action 'accept'", +# "set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set'", +# "set firewall ipv4 name INBOUND rule 101 action 'accept'", +# "set firewall ipv4 name INBOUND rule 101", +# "set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec'", +# "set firewall ipv4 name INBOUND rule 102 action 'reject'", +# "set firewall ipv4 name INBOUND rule 102", +# "set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec'", +# "set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 103 destination group address-group inbound", +# "set firewall ipv4 name INBOUND rule 103", +# "set firewall ipv4 name INBOUND rule 103 source address 192.0.2.0", +# "set firewall ipv4 name INBOUND rule 103 state established", +# "set firewall ipv4 name INBOUND rule 103 state related", +# "set firewall ipv4 name INBOUND rule 103 action 'accept'" # ] # # "after": [ @@ -966,30 +971,28 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 102 action 'reject' -# set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible' -# set firewall name INBOUND rule 102 ipsec 'match-ipsec' -# set firewall name INBOUND rule 103 action 'accept' -# set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible' -# set firewall name INBOUND rule 103 destination group address-group 'inbound' -# set firewall name INBOUND rule 103 source address '192.0.2.0' -# set firewall name INBOUND rule 103 state established 'enable' -# set firewall name INBOUND rule 103 state invalid 'disable' -# set firewall name INBOUND rule 103 state new 'disable' -# set firewall name INBOUND rule 103 state related 'enable' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 102 action 'reject' +# set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 103 action 'accept' +# set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 103 destination group address-group 'inbound' +# set firewall ipv4 name INBOUND rule 103 source address '192.0.2.0' +# set firewall ipv4 name INBOUND rule 103 state established +# set firewall ipv4 name INBOUND rule 103 state related # Using replaced @@ -999,30 +1002,28 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 102 action 'reject' -# set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible' -# set firewall name INBOUND rule 102 ipsec 'match-ipsec' -# set firewall name INBOUND rule 103 action 'accept' -# set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible' -# set firewall name INBOUND rule 103 destination group address-group 'inbound' -# set firewall name INBOUND rule 103 source address '192.0.2.0' -# set firewall name INBOUND rule 103 state established 'enable' -# set firewall name INBOUND rule 103 state invalid 'disable' -# set firewall name INBOUND rule 103 state new 'disable' -# set firewall name INBOUND rule 103 state related 'enable' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 102 action 'reject' +# set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 103 action 'accept' +# set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 103 destination group address-group 'inbound' +# set firewall ipv4 name INBOUND rule 103 source address '192.0.2.0' +# set firewall ipv4 name INBOUND rule 103 state established +# set firewall ipv4 name INBOUND rule 103 state related # - name: >- Replace device configurations of listed firewall rules with provided @@ -1126,14 +1127,14 @@ EXAMPLES = """ # ] # # "commands": [ -# "delete firewall ipv6-name UPLINK rule 1", -# "delete firewall ipv6-name UPLINK rule 2", -# "delete firewall name INBOUND rule 102", -# "delete firewall name INBOUND rule 103", -# "set firewall name INBOUND rule 104 action 'reject'", -# "set firewall name INBOUND rule 104 description 'Rule 104 is configured by Ansible'", -# "set firewall name INBOUND rule 104", -# "set firewall name INBOUND rule 104 ipsec 'match-none'" +# "delete firewall ipv6 name UPLINK rule 1", +# "delete firewall ipv6 name UPLINK rule 2", +# "delete firewall ipv4 name INBOUND rule 102", +# "delete firewall ipv4 name INBOUND rule 103", +# "set firewall ipv4 name INBOUND rule 104 action 'reject'", +# "set firewall ipv4 name INBOUND rule 104 description 'Rule 104 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 104", +# "set firewall ipv4 name INBOUND rule 104 ipsec 'match-none'" # ] # # "after": [ @@ -1178,16 +1179,16 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 104 action 'reject' -# set firewall name INBOUND rule 104 description 'Rule 104 is configured by Ansible' -# set firewall name INBOUND rule 104 ipsec 'match-none' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 104 action 'reject' +# set firewall ipv4 name INBOUND rule 104 description 'Rule 104 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 104 ipsec 'match-none' # Using overridden @@ -1197,16 +1198,16 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 104 action 'reject' -# set firewall name INBOUND rule 104 description 'Rule 104 is configured by Ansible' -# set firewall name INBOUND rule 104 ipsec 'match-none' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 104 action 'reject' +# set firewall ipv4 name INBOUND rule 104 description 'Rule 104 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 104 ipsec 'match-none' # - name: Overrides all device configuration with provided configuration vyos.vyos.vyos_firewall_rules: @@ -1270,18 +1271,18 @@ EXAMPLES = """ # ] # # "commands": [ -# "delete firewall ipv6-name UPLINK", -# "delete firewall name INBOUND", -# "set firewall name Downlink default-action 'accept'", -# "set firewall name Downlink description 'IPv4 INBOUND rule set'", -# "set firewall name Downlink rule 501 action 'accept'", -# "set firewall name Downlink rule 501", -# "set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible'", -# "set firewall name Downlink rule 501 ipsec 'match-ipsec'", -# "set firewall name Downlink rule 502 action 'reject'", -# "set firewall name Downlink rule 502", -# "set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible'", -# "set firewall name Downlink rule 502 ipsec 'match-ipsec'" +# "delete firewall ipv6 name UPLINK", +# "delete firewall ipv4 name INBOUND", +# "set firewall ipv4 name Downlink default-action 'accept'", +# "set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set'", +# "set firewall ipv4 name Downlink rule 501 action 'accept'", +# "set firewall ipv4 name Downlink rule 501", +# "set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible'", +# "set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec'", +# "set firewall ipv4 name Downlink rule 502 action 'reject'", +# "set firewall ipv4 name Downlink rule 502", +# "set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible'", +# "set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec'" # # # "after": [ @@ -1317,14 +1318,14 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall name Downlink default-action 'accept' -# set firewall name Downlink description 'IPv4 INBOUND rule set' -# set firewall name Downlink rule 501 action 'accept' -# set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible' -# set firewall name Downlink rule 501 ipsec 'match-ipsec' -# set firewall name Downlink rule 502 action 'reject' -# set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible' -# set firewall name Downlink rule 502 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink default-action 'accept' +# set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set' +# set firewall ipv4 name Downlink rule 501 action 'accept' +# set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible' +# set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink rule 502 action 'reject' +# set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible' +# set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec' # Using gathered @@ -1334,30 +1335,28 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 102 action 'reject' -# set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible' -# set firewall name INBOUND rule 102 ipsec 'match-ipsec' -# set firewall name INBOUND rule 103 action 'accept' -# set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible' -# set firewall name INBOUND rule 103 destination group address-group 'inbound' -# set firewall name INBOUND rule 103 source address '192.0.2.0' -# set firewall name INBOUND rule 103 state established 'enable' -# set firewall name INBOUND rule 103 state invalid 'disable' -# set firewall name INBOUND rule 103 state new 'disable' -# set firewall name INBOUND rule 103 state related 'enable' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 102 action 'reject' +# set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 103 action 'accept' +# set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 103 destination group address-group 'inbound' +# set firewall ipv4 name INBOUND rule 103 source address '192.0.2.0' +# set firewall ipv4 name INBOUND rule 103 state established +# set firewall ipv4 name INBOUND rule 103 state related # - name: Gather listed firewall rules with provided configurations vyos.vyos.vyos_firewall_rules: @@ -1445,30 +1444,28 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 102 action 'reject' -# set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible' -# set firewall name INBOUND rule 102 ipsec 'match-ipsec' -# set firewall name INBOUND rule 103 action 'accept' -# set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible' -# set firewall name INBOUND rule 103 destination group address-group 'inbound' -# set firewall name INBOUND rule 103 source address '192.0.2.0' -# set firewall name INBOUND rule 103 state established 'enable' -# set firewall name INBOUND rule 103 state invalid 'disable' -# set firewall name INBOUND rule 103 state new 'disable' -# set firewall name INBOUND rule 103 state related 'enable' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 102 action 'reject' +# set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 103 action 'accept' +# set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 103 destination group address-group 'inbound' +# set firewall ipv4 name INBOUND rule 103 source address '192.0.2.0' +# set firewall ipv4 name INBOUND rule 103 state established +# set firewall ipv4 name INBOUND rule 103 state related # Using rendered @@ -1518,27 +1515,25 @@ EXAMPLES = """ # # # "rendered": [ -# "set firewall ipv6-name UPLINK default-action 'accept'", -# "set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set'", -# "set firewall name INBOUND default-action 'accept'", -# "set firewall name INBOUND description 'IPv4 INBOUND rule set'", -# "set firewall name INBOUND rule 101 action 'accept'", -# "set firewall name INBOUND rule 101", -# "set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", -# "set firewall name INBOUND rule 101 ipsec 'match-ipsec'", -# "set firewall name INBOUND rule 102 action 'reject'", -# "set firewall name INBOUND rule 102", -# "set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible'", -# "set firewall name INBOUND rule 102 ipsec 'match-ipsec'", -# "set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible'", -# "set firewall name INBOUND rule 103 destination group address-group inbound", -# "set firewall name INBOUND rule 103", -# "set firewall name INBOUND rule 103 source address 192.0.2.0", -# "set firewall name INBOUND rule 103 state established enable", -# "set firewall name INBOUND rule 103 state related enable", -# "set firewall name INBOUND rule 103 state invalid disable", -# "set firewall name INBOUND rule 103 state new disable", -# "set firewall name INBOUND rule 103 action 'accept'" +# "set firewall ipv6 name UPLINK default-action 'accept'", +# "set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set'", +# "set firewall ipv4 name INBOUND default-action 'accept'", +# "set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set'", +# "set firewall ipv4 name INBOUND rule 101 action 'accept'", +# "set firewall ipv4 name INBOUND rule 101", +# "set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec'", +# "set firewall ipv4 name INBOUND rule 102 action 'reject'", +# "set firewall ipv4 name INBOUND rule 102", +# "set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec'", +# "set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 103 destination group address-group inbound", +# "set firewall ipv4 name INBOUND rule 103", +# "set firewall ipv4 name INBOUND rule 103 source address 192.0.2.0", +# "set firewall ipv4 name INBOUND rule 103 state established", +# "set firewall ipv4 name INBOUND rule 103 state related", +# "set firewall ipv4 name INBOUND rule 103 action 'accept'" # ] @@ -1549,14 +1544,14 @@ EXAMPLES = """ vyos.vyos.vyos_firewall_rules: running_config: "set firewall group address-group 'inbound' - set firewall name Downlink default-action 'accept' - set firewall name Downlink description 'IPv4 INBOUND rule set' - set firewall name Downlink rule 501 action 'accept' - set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible' - set firewall name Downlink rule 501 ipsec 'match-ipsec' - set firewall name Downlink rule 502 action 'reject' - set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible' - set firewall name Downlink rule 502 ipsec 'match-ipsec'" + set firewall ipv4 name Downlink default-action 'accept' + set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set' + set firewall ipv4 name Downlink rule 501 action 'accept' + set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible' + set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec' + set firewall ipv4 name Downlink rule 502 action 'reject' + set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible' + set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec'" state: parsed # # @@ -1612,21 +1607,21 @@ commands: returned: always type: list sample: - - "set firewall name Downlink default-action 'accept'" - - "set firewall name Downlink description 'IPv4 INBOUND rule set'" - - "set firewall name Downlink rule 501 action 'accept'" - - "set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible'" - - "set firewall name Downlink rule 502 ipsec 'match-ipsec'" + - "set firewall ipv4 name Downlink default-action 'accept'" + - "set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set'" + - "set firewall ipv4 name Downlink rule 501 action 'accept'" + - "set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible'" + - "set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec'" 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 firewall name Downlink default-action 'accept'" - - "set firewall name Downlink description 'IPv4 INBOUND rule set'" - - "set firewall name Downlink rule 501 action 'accept'" - - "set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible'" - - "set firewall name Downlink rule 502 ipsec 'match-ipsec'" + - "set firewall ipv4 name Downlink default-action 'accept'" + - "set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set'" + - "set firewall ipv4 name Downlink rule 501 action 'accept'" + - "set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible'" + - "set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec'" gathered: description: Facts about the network resource gathered from the remote device as structured data. returned: when I(state) is C(gathered) diff --git a/plugins/modules/vyos_ha.py b/plugins/modules/vyos_ha.py new file mode 100644 index 00000000..ddd02b48 --- /dev/null +++ b/plugins/modules/vyos_ha.py @@ -0,0 +1,1327 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2024 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +""" +The module file for vyos_ha module, which manages VRRP and load balancer configuration on VyOS +""" + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +DOCUMENTATION = r""" +--- +module: vyos_ha +author: Evgeny Molotkov (@omnom62) +short_description: Manage VRRP and load balancer configuration on VyOS +version_added: "1.0.0" +description: + - This module configures VRRP groups, global VRRP parameters, VRRP sync groups, + and LVS-style virtual servers on VyOS 1.4+. + - Supports creation, modification, deletion, replacement, rendering, and parsing + of VRRP-related configuration. + +options: + config: + description: + - Full VRRP and virtual server configuration. + type: dict + suboptions: + disable: + description: + - Disable all VRRP and L4-LB configuration under this module. + type: bool + default: false + virtual_servers: + description: + - List of load balancer virtual server (LVS) definitions. + type: list + elements: dict + suboptions: + name: + description: + - Unique identifier for the virtual server. + type: str + required: true + address: + description: + - Virtual IP address for the server. + type: str + algorithm: + description: + - Load balancing algorithm used for dispatching connections. + type: str + delay_loop: + description: + - Delay loop interval in seconds. + type: int + forward_method: + description: + - Forwarding method used by LVS. + type: str + choices: [direct, nat] + fwmark: + description: + - Firewall mark for LVS traffic classification. + type: int + persistence_timeout: + description: + - Client persistence timeout in seconds. + type: int + port: + description: + - TCP/UDP port provided by the virtual service. + type: int + protocol: + description: + - Transport protocol for the virtual server. + type: str + choices: [tcp, udp] + + real_server: + description: + - Backend real servers behind the virtual service. + type: list + elements: dict + suboptions: + address: + description: + - Real server IP address. + type: str + required: true + port: + description: + - Backend server port. + type: int + connection_timeout: + description: + - Backend server connection timeout. + type: int + health_check_script: + description: + - Path to health check script used for backend validation. + type: str + + vrrp: + description: + - VRRP configuration including groups, global parameters, SNMP settings, + and sync-groups. + type: dict + suboptions: + + global_parameters: + description: + - Global VRRP tuning parameters. + type: dict + suboptions: + garp: + description: + - Gratuitous ARP related configuration. + type: dict + suboptions: + interval: + description: + - GARP interval in seconds. + type: int + master_delay: + description: + - Delay before sending GARP as master. + type: int + master_refresh: + description: + - Refresh interval for master GARP announcements. + type: int + master_refresh_repeat: + description: + - Number of times to repeat refresh announcements. + type: int + master_repeat: + description: + - Number of GARP repeats when transitioning to master. + type: int + + startup_delay: + description: + - Delay before VRRP starts after boot. + type: int + + version: + description: + - VRRP protocol version. + type: str + + groups: + description: + - VRRP instance configuration groups. + type: list + elements: dict + suboptions: + name: + description: + - VRRP group name. + type: str + required: true + address: + description: + - Virtual router IP addresses. + type: list + elements: str + + advertise_interval: + description: + - VRRP advertisement interval. + type: int + + authentication: + description: + - VRRP group authentication options. + type: dict + suboptions: + password: + description: + - Authentication password. + type: str + type: + description: + - Authentication type. + type: str + + description: + description: + - Text description for the VRRP group. + type: str + + disable: + description: + - Disable this VRRP group. + type: bool + default: false + + excluded_address: + description: + - IP address excluded from source checks. + type: list + elements: str + + garp: + description: + - GARP-specific settings for this group. + type: dict + suboptions: + interval: + description: GARP interval. + type: int + master_delay: + description: GARP master delay. + type: int + master_refresh: + description: GARP master refresh interval. + type: int + master_refresh_repeat: + description: Repeated refresh sends. + type: int + master_repeat: + description: GARP repeat count. + type: int + + health_check: + description: + - VRRP group health check options. + type: dict + suboptions: + failure_count: + description: Allowed number of failed checks. + type: int + interval: + description: Health check interval. + type: int + ping: + description: Host to ping for checks. + type: str + script: + description: Script to execute for health checking. + type: str + + hello_source_address: + description: + - Source address for VRRP hello packets. + type: str + + interface: + description: + - Interface used by the VRRP group. + type: str + + no_preempt: + description: + - Disable preemption. + type: bool + default: false + + peer_address: + description: + - Peer VRRP router address. + type: str + + preempt_delay: + description: + - Delay before taking master role. + type: int + + priority: + description: + - VRRP priority (higher = preferred master). + type: int + + rfc3768_compatibility: + description: + - Enable or disable RFC3768 compatibility mode. + type: bool + default: false + + track: + description: + - Track interface and VRRP behaviour. + type: dict + suboptions: + exclude_vrrp_interface: + description: + - Exclude VRRP interface from tracking. + type: bool + interface: + description: + - Interface to track. + type: list + elements: str + + transition_script: + description: + - Scripts executed during VRRP state transitions. + type: dict + suboptions: + backup: + description: Path to backup script. + type: str + fault: + description: Path to fault script. + type: str + master: + description: Path to master script. + type: str + stop: + description: Path to stop script. + type: str + + vrid: + description: + - VRRP Virtual Router ID. + type: int + + snmp: + description: + - Enable SNMP support for VRRP. + type: str + choices: ['enabled', 'disabled'] + + sync_groups: + description: + - VRRP sync-groups for coordinated failover. + type: list + elements: dict + suboptions: + name: + description: + - Sync-group name. + type: str + required: true + + health_check: + description: + - Health check options for sync group. + type: dict + suboptions: + failure_count: + description: Allowed number of failures. + type: int + interval: + description: Health check interval. + type: int + ping: + description: Host to ping. + type: str + script: + description: Script to run for health checking. + type: str + + member: + description: + - List of VRRP groups participating in this sync group. + type: list + elements: str + + transition_script: + description: + - Transition scripts for sync group events. + type: dict + suboptions: + backup: + description: Backup state script. + type: str + fault: + description: Fault state script. + type: str + master: + description: Master state script. + type: str + stop: + description: Stop state script. + type: str + + state: + description: + - Desired end state of the VRRP configuration. + type: str + choices: + - deleted + - merged + - purged + - replaced + - gathered + - rendered + - parsed + - overridden + default: merged + + running_config: + description: + - Used only when C(state=parsed). Must contain the output of + C(show configuration commands | grep high-availability). + type: str +""" + +EXAMPLES = """ +# Using merged +# Before state + +# vyos@vyos:~$ show configuration commands | match "set high-availability" +# vyos@vyos:~$ + +- name: Merge provided configuration with device configuration + vyos.vyos.vyos_ha: + config: + disable: true + virtual_servers: + - name: s1 + address: 10.10.10.5 + algorithm: round-robin + real_server: + - address: 10.10.50.2 + port: 8443 + - name: s2 + address: 10.10.10.2 + persistence_timeout: 30 + port: 81 + protocol: tcp + - name: s3 + address: 10.10.10.3 + port: 88 + protocol: udp + vrrp: + snmp: enabled + global_parameters: + startup_delay: 30 + garp: + master_repeat: 6 + groups: + - name: "g1" + peer_address: 192.168.1.3 + priority: 100 + disable: false + no_preempt: false + vrid: 20 + sync_groups: + - name: "sg1" + health_check: + failure_count: 5 + state: merged + +# After State +# vyos@vyos:~$ show configuration commands | match "set high-availability" +# set high-availability disable +# set high-availability virtual-server s1 address '10.10.10.5' +# set high-availability virtual-server s1 algorithm 'round-robin' +# set high-availability virtual-server s1 real-server 10.10.50.2 port '8443' +# set high-availability virtual-server s2 address '10.10.10.2' +# set high-availability virtual-server s2 persistence-timeout '30' +# set high-availability virtual-server s2 port '81' +# set high-availability virtual-server s2 protocol 'tcp' +# set high-availability virtual-server s3 address '10.10.10.3' +# set high-availability virtual-server s3 port '88' +# set high-availability virtual-server s3 protocol 'udp' +# set high-availability vrrp global-parameters garp master-repeat '6' +# set high-availability vrrp global-parameters startup-delay '30' +# set high-availability vrrp group g1 peer-address '192.168.1.3' +# set high-availability vrrp group g1 priority '100' +# set high-availability vrrp group g1 vrid '20' +# set high-availability vrrp snmp +# set high-availability vrrp sync-group sg1 health-check failure-count '5' +# vyos@vyos:~$ +# +# # Module Execution: +# +# "after": { +# "disable": true, +# "virtual_servers": [ +# { +# "address": "10.10.10.5", +# "algorithm": "round-robin", +# "name": "s1", +# "real_server": [ +# { +# "address": "10.10.50.2", +# "port": 8443 +# } +# ] +# }, +# { +# "address": "10.10.10.2", +# "name": "s2", +# "persistence_timeout": 30, +# "port": 81, +# "protocol": "tcp" +# }, +# { +# "address": "10.10.10.3", +# "name": "s3", +# "port": 88, +# "protocol": "udp" +# } +# ], +# "vrrp": { +# "global_parameters": { +# "garp": { +# "master_repeat": 6 +# }, +# "startup_delay": 30 +# }, +# "groups": [ +# { +# "disable": false, +# "name": "g1", +# "no_preempt": false, +# "peer_address": "192.168.1.3", +# "priority": 100, +# "rfc3768_compatibility": false, +# "vrid": 20 +# } +# ], +# "snmp": "enabled", +# "sync_groups": [ +# { +# "health_check": { +# "failure_count": 5 +# }, +# "name": "sg1" +# } +# ] +# } +# }, +# "before": { +# "disable": false +# }, +# "changed": true, +# "commands": [ +# "set high-availability disable", +# "set high-availability virtual-server s1 address 10.10.10.5", +# "set high-availability virtual-server s1 algorithm round-robin", +# "set high-availability virtual-server s1 real-server 10.10.50.2 port 8443", +# "set high-availability virtual-server s2 address 10.10.10.2", +# "set high-availability virtual-server s2 persistence-timeout 30", +# "set high-availability virtual-server s2 port 81", +# "set high-availability virtual-server s2 protocol tcp", +# "set high-availability virtual-server s3 address 10.10.10.3", +# "set high-availability virtual-server s3 port 88", +# "set high-availability virtual-server s3 protocol udp", +# "set high-availability vrrp global-parameters garp master-repeat 6", +# "set high-availability vrrp global-parameters startup-delay 30", +# "set high-availability vrrp group g1 peer-address 192.168.1.3", +# "set high-availability vrrp group g1 priority 100", +# "set high-availability vrrp group g1 vrid 20", +# "set high-availability vrrp snmp", +# "set high-availability vrrp sync-group sg1 health-check failure-count 5" +# ], + +# Using replaced: +# -------------- + +# Before state: +# vyos@vyos:~$ show configuration commands | match "set high-availability" +# set high-availability disable +# set high-availability virtual-server s1 address '10.10.10.5' +# set high-availability virtual-server s1 algorithm 'round-robin' +# set high-availability virtual-server s1 real-server 10.10.50.2 port '8443' +# set high-availability virtual-server s2 address '10.10.10.2' +# set high-availability virtual-server s2 persistence-timeout '30' +# set high-availability virtual-server s2 port '81' +# set high-availability virtual-server s2 protocol 'tcp' +# set high-availability virtual-server s3 address '10.10.10.3' +# set high-availability virtual-server s3 port '88' +# set high-availability virtual-server s3 protocol 'udp' +# set high-availability vrrp global-parameters garp master-repeat '6' +# set high-availability vrrp global-parameters startup-delay '30' +# set high-availability vrrp group g1 peer-address '192.168.1.3' +# set high-availability vrrp group g1 priority '100' +# set high-availability vrrp group g1 vrid '20' +# set high-availability vrrp snmp +# set high-availability vrrp sync-group sg1 health-check failure-count '5' +# vyos@vyos:~$ + +- name: Replace + vyos.vyos.vyos_ha: + config: + disable: false + virtual_servers: + - name: s1 + address: 10.10.10.3 + algorithm: round-robin + port: 8443 + real_server: + - address: 10.10.50.3 + port: 8443 + - name: s2 + address: 10.10.10.2 + persistence_timeout: 300 + port: 81 + protocol: tcp + real_server: + - address: 10.10.50.30 + port: 8443 + - name: s3 + address: 10.10.10.3 + port: 88 + protocol: udp + real_server: + - address: 10.10.50.6 + port: 8443 + vrrp: + snmp: enabled + global_parameters: + startup_delay: 30 + garp: + master_repeat: 6 + groups: + - name: "g1" + peer_address: 192.168.1.13 + priority: 100 + disable: false + no_preempt: true + interface: eth1 + address: 192.168.51.13 + vrid: 20 + sync_groups: + - name: "sg1" + health_check: + failure_count: 3 + state: replaced + +# After state: + +# vyos@vyos:~$ show configuration commands | match "set high-availability" +# set high-availability virtual-server s1 address '10.10.10.3' +# set high-availability virtual-server s1 algorithm 'round-robin' +# set high-availability virtual-server s1 port '8443' +# set high-availability virtual-server s1 real-server 10.10.50.2 port '8443' +# set high-availability virtual-server s1 real-server 10.10.50.3 port '8443' +# set high-availability virtual-server s2 address '10.10.10.2' +# set high-availability virtual-server s2 persistence-timeout '300' +# set high-availability virtual-server s2 port '81' +# set high-availability virtual-server s2 protocol 'tcp' +# set high-availability virtual-server s2 real-server 10.10.50.3 port '8443' +# set high-availability virtual-server s3 address '10.10.10.3' +# set high-availability virtual-server s3 port '88' +# set high-availability virtual-server s3 protocol 'udp' +# set high-availability virtual-server s3 real-server 10.10.50.6 port '8443' +# set high-availability vrrp global-parameters garp master-repeat '6' +# set high-availability vrrp global-parameters startup-delay '30' +# set high-availability vrrp group g1 address 192.168.51.13 +# set high-availability vrrp group g1 interface 'eth1' +# set high-availability vrrp group g1 no-preempt +# set high-availability vrrp group g1 peer-address '192.168.1.3' +# set high-availability vrrp group g1 peer-address '192.168.1.13' +# set high-availability vrrp group g1 priority '100' +# set high-availability vrrp group g1 vrid '20' +# set high-availability vrrp snmp +# set high-availability vrrp sync-group sg1 health-check failure-count '3' +# vyos@vyos:~$ +# +# +# Module Execution: +# +# "after": { +# "disable": false, +# "virtual_servers": [ +# { +# "address": "10.10.10.3", +# "algorithm": "round-robin", +# "name": "s1", +# "port": 8443, +# "real_server": [ +# { +# "address": "10.10.50.2", +# "port": 8443 +# }, +# { +# "address": "10.10.50.3", +# "port": 8443 +# } +# ] +# }, +# { +# "address": "10.10.10.2", +# "name": "s2", +# "persistence_timeout": 300, +# "port": 81, +# "protocol": "tcp", +# "real_server": [ +# { +# "address": "10.10.50.3", +# "port": 8443 +# } +# ] +# }, +# { +# "address": "10.10.10.3", +# "name": "s3", +# "port": 88, +# "protocol": "udp", +# "real_server": [ +# { +# "address": "10.10.50.6", +# "port": 8443 +# } +# ] +# } +# ], +# "vrrp": { +# "global_parameters": { +# "garp": { +# "master_repeat": 6 +# }, +# "startup_delay": 30 +# }, +# "groups": [ +# { +# "address": "192.168.51.13", +# "disable": false, +# "interface": "eth1", +# "name": "g1", +# "no_preempt": true, +# "peer_address": "192.168.1.13", +# "priority": 100, +# "rfc3768_compatibility": false, +# "vrid": 20 +# } +# ], +# "snmp": "enabled", +# "sync_groups": [ +# { +# "health_check": { +# "failure_count": 3 +# }, +# "name": "sg1" +# } +# ] +# } +# }, +# "before": { +# "disable": true, +# "virtual_servers": [ +# { +# "address": "10.10.10.5", +# "algorithm": "round-robin", +# "name": "s1", +# "real_server": [ +# { +# "address": "10.10.50.2", +# "port": 8443 +# } +# ] +# }, +# { +# "address": "10.10.10.2", +# "name": "s2", +# "persistence_timeout": 30, +# "port": 81, +# "protocol": "tcp" +# }, +# { +# "address": "10.10.10.3", +# "name": "s3", +# "port": 88, +# "protocol": "udp" +# } +# ], +# "vrrp": { +# "global_parameters": { +# "garp": { +# "master_repeat": 6 +# }, +# "startup_delay": 30 +# }, +# "groups": [ +# { +# "disable": false, +# "name": "g1", +# "no_preempt": false, +# "peer_address": "192.168.1.3", +# "priority": 100, +# "rfc3768_compatibility": false, +# "vrid": 20 +# } +# ], +# "snmp": "enabled", +# "sync_groups": [ +# { +# "health_check": { +# "failure_count": 5 +# }, +# "name": "sg1" +# } +# ] +# } +# }, +# "changed": true, +# "commands": [ +# "delete high-availability disable", +# "set high-availability virtual-server s1 address 10.10.10.3", +# "set high-availability virtual-server s1 port 8443", +# "set high-availability virtual-server s1 real-server 10.10.50.3 port 8443", +# "set high-availability virtual-server s2 persistence-timeout 300", +# "set high-availability virtual-server s2 real-server 10.10.50.3 port 8443", +# "set high-availability virtual-server s3 real-server 10.10.50.6 port 8443", +# "set high-availability vrrp group g1 address 192.168.51.13", +# "set high-availability vrrp group g1 interface eth1", +# "set high-availability vrrp group g1 no-preempt", +# "set high-availability vrrp group g1 peer-address 192.168.1.13", +# "set high-availability vrrp sync-group sg1 health-check failure-count 3" +# ], + +# Using deleted: +# ------------- + +# Before state: + +# vyos@vyos:~$ show configuration commands | match "set high-availability" +# set high-availability disable +# set high-availability virtual-server s1 address '10.10.10.5' +# set high-availability virtual-server s1 algorithm 'round-robin' +# set high-availability virtual-server s1 real-server 10.10.50.2 port '8443' +# set high-availability virtual-server s2 address '10.10.10.2' +# set high-availability virtual-server s2 persistence-timeout '30' +# set high-availability virtual-server s2 port '81' +# set high-availability virtual-server s2 protocol 'tcp' +# set high-availability virtual-server s3 address '10.10.10.3' +# set high-availability virtual-server s3 port '88' +# set high-availability virtual-server s3 protocol 'udp' +# set high-availability vrrp global-parameters garp master-repeat '6' +# set high-availability vrrp global-parameters startup-delay '30' +# set high-availability vrrp group g1 peer-address '192.168.1.3' +# set high-availability vrrp group g1 priority '100' +# set high-availability vrrp group g1 vrid '20' +# set high-availability vrrp snmp +# set high-availability vrrp sync-group sg1 health-check failure-count '5' +# vyos@vyos:~$ + +- name: Delete configuration + vyos.vyos.vyos_ha: + config: + disable: false + vrrp: + snmp: disabled + global_parameters: + startup_delay: 32 + version: 3 + virtual_servers: + - name: 's1' + address: '10.10.10.1' + algorithm: 'round-robin' + delay_loop: 60 + forward_method: 'direct' + persistence_timeout: 30 + port: 443 + protocol: 'tcp' + real_server: + - address: '10.10.10.1' + connection_timeout: 61 + port: 443 + state: deleted + +# After state: + +# vyos@vyos:~$ show configuration commands | match "set high-availability" +# set high-availability disable +# set high-availability virtual-server s2 address '10.10.10.2' +# set high-availability virtual-server s2 persistence-timeout '30' +# set high-availability virtual-server s2 port '81' +# set high-availability virtual-server s2 protocol 'tcp' +# set high-availability virtual-server s3 address '10.10.10.3' +# set high-availability virtual-server s3 port '88' +# set high-availability virtual-server s3 protocol 'udp' +# set high-availability vrrp global-parameters garp master-repeat '6' +# set high-availability vrrp group g1 peer-address '192.168.1.3' +# set high-availability vrrp group g1 priority '100' +# set high-availability vrrp group g1 vrid '20' +# set high-availability vrrp snmp +# set high-availability vrrp sync-group sg1 health-check failure-count '5' + +# vyos@vyos:~$ +# +# +# Module Execution: +# +# "after": { +# "disable": true, +# "virtual_servers": [ +# { +# "address": "10.10.10.2", +# "name": "s2", +# "persistence_timeout": 30, +# "port": 81, +# "protocol": "tcp" +# }, +# { +# "address": "10.10.10.3", +# "name": "s3", +# "port": 88, +# "protocol": "udp" +# } +# ], +# "vrrp": { +# "global_parameters": { +# "garp": { +# "master_repeat": 6 +# } +# }, +# "groups": [ +# { +# "disable": false, +# "name": "g1", +# "no_preempt": false, +# "peer_address": "192.168.1.3", +# "priority": 100, +# "rfc3768_compatibility": false, +# "vrid": 20 +# } +# ], +# "snmp": "enabled", +# "sync_groups": [ +# { +# "health_check": { +# "failure_count": 5 +# }, +# "name": "sg1" +# } +# ] +# } +# }, +# "before": { +# "disable": true, +# "virtual_servers": [ +# { +# "address": "10.10.10.5", +# "algorithm": "round-robin", +# "name": "s1", +# "real_server": [ +# { +# "address": "10.10.50.2", +# "port": 8443 +# } +# ] +# }, +# { +# "address": "10.10.10.2", +# "name": "s2", +# "persistence_timeout": 30, +# "port": 81, +# "protocol": "tcp" +# }, +# { +# "address": "10.10.10.3", +# "name": "s3", +# "port": 88, +# "protocol": "udp" +# } +# ], +# "vrrp": { +# "global_parameters": { +# "garp": { +# "master_repeat": 6 +# }, +# "startup_delay": 30 +# }, +# "groups": [ +# { +# "disable": false, +# "name": "g1", +# "no_preempt": false, +# "peer_address": "192.168.1.3", +# "priority": 100, +# "rfc3768_compatibility": false, +# "vrid": 20 +# } +# ], +# "snmp": "enabled", +# "sync_groups": [ +# { +# "health_check": { +# "failure_count": 5 +# }, +# "name": "sg1" +# } +# ] +# } +# }, +# "changed": true, +# "commands": [ +# "delete high-availability virtual-server s1", +# "delete high-availability vrrp global-parameters startup-delay" +# ], + +# Using purged: + +# Before state: + +# vyos@vyos:~$ show configuration commands | match "set high-availability" +# set high-availability disable +# set high-availability virtual-server s2 address '10.10.10.2' +# set high-availability virtual-server s2 persistence-timeout '30' +# set high-availability virtual-server s2 port '81' +# set high-availability virtual-server s2 protocol 'tcp' +# set high-availability virtual-server s3 address '10.10.10.3' +# set high-availability virtual-server s3 port '88' +# set high-availability virtual-server s3 protocol 'udp' +# set high-availability vrrp global-parameters garp master-repeat '6' +# set high-availability vrrp group g1 peer-address '192.168.1.3' +# set high-availability vrrp group g1 priority '100' +# set high-availability vrrp group g1 vrid '20' +# set high-availability vrrp snmp +# set high-availability vrrp sync-group sg1 health-check failure-count '5' +# vyos@vyos:~$ + + +- name: Purge configuration + vyos.vyos.vyos_ha: + config: + state: purged + +# After state: + +# vyos@vyos:~$ show configuration commands | match "set high-availability" +# vyos@vyos:~$ +# +# Module Execution: +# +# "after": { +# "disable": false +# }, +# "before": { +# "disable": true, +# "virtual_servers": [ +# { +# "address": "10.10.10.2", +# "name": "s2", +# "persistence_timeout": 30, +# "port": 81, +# "protocol": "tcp" +# }, +# { +# "address": "10.10.10.3", +# "name": "s3", +# "port": 88, +# "protocol": "udp" +# } +# ], +# "vrrp": { +# "global_parameters": { +# "garp": { +# "master_repeat": 6 +# } +# }, +# "groups": [ +# { +# "disable": false, +# "name": "g1", +# "no_preempt": false, +# "peer_address": "192.168.1.3", +# "priority": 100, +# "rfc3768_compatibility": false, +# "vrid": 20 +# } +# ], +# "snmp": "enabled", +# "sync_groups": [ +# { +# "health_check": { +# "failure_count": 5 +# }, +# "name": "sg1" +# } +# ] +# } +# }, +# "changed": true, +# "commands": [ +# "delete high-availability" +# ], + + +# using gathered: +# -------------- + +# Before state: +# vyos@vyos:~$ +# show configuration commands | match "set high-availability" +# set high-availability disable +# set high-availability virtual-server s1 address '10.10.10.5' +# set high-availability virtual-server s1 algorithm 'round-robin' +# set high-availability virtual-server s1 real-server 10.10.50.2 port '8443' +# set high-availability virtual-server s2 address '10.10.10.2' +# set high-availability virtual-server s2 persistence-timeout '30' +# set high-availability virtual-server s2 port '81' +# set high-availability virtual-server s2 protocol 'tcp' +# set high-availability virtual-server s3 address '10.10.10.3' +# set high-availability virtual-server s3 port '88' +# set high-availability virtual-server s3 protocol 'udp' +# set high-availability vrrp global-parameters garp master-repeat '6' +# set high-availability vrrp global-parameters startup-delay '30' +# set high-availability vrrp group g1 peer-address '192.168.1.3' +# set high-availability vrrp group g1 priority '100' +# set high-availability vrrp group g1 vrid '20' +# set high-availability vrrp snmp +# set high-availability vrrp sync-group sg1 health-check failure-count '5' +# vyos@vyos:~$ + +- name: gather configs + vyos.vyos.vyos_ha: + state: gathered + +# Module Execution: +# "changed": false, +# "gathered": { +# "disable": true, +# "virtual_servers": [ +# { +# "address": "10.10.10.5", +# "algorithm": "round-robin", +# "name": "s1", +# "real_server": [ +# { +# "address": "10.10.50.2", +# "port": 8443 +# } +# ] +# }, +# { +# "address": "10.10.10.2", +# "name": "s2", +# "persistence_timeout": 30, +# "port": 81, +# "protocol": "tcp" +# }, +# { +# "address": "10.10.10.3", +# "name": "s3", +# "port": 88, +# "protocol": "udp" +# } +# ], +# "vrrp": { +# "global_parameters": { +# "garp": { +# "master_repeat": 6 +# }, +# "startup_delay": 30 +# }, +# "groups": [ +# { +# "disable": false, +# "name": "g1", +# "no_preempt": false, +# "peer_address": "192.168.1.3", +# "priority": 100, +# "rfc3768_compatibility": false, +# "vrid": 20 +# } +# ], +# "snmp": "enabled", +# "sync_groups": [ +# { +# "health_check": { +# "failure_count": 5 +# }, +# "name": "sg1" +# } +# ] +# } +# }, +# + +# Using parsed: +# ------------ + +# parsed.cfg +# set high-availability vrrp group g1 interface eth2 +# set high-availability vrrp group g1 address 1.1.1.1 +# set high-availability vrrp group g1 disable +# set high-availability vrrp group g1 no-preempt +# set high-availability vrrp group g1 advertise-interval 10 +# set high-availability vrrp group g1 peer-address 2.2.2.2 +# set high-availability vrrp group g1 rfc3768-compatibility +# set high-availability vrrp group g1 vrid 20 + +- name: parse configs + vyos.vyos.vyos_ha: + running_config: "{{ lookup('file', './parsed.cfg') }}" + state: parsed + +# Module execution: +# "parsed": { +# "disable": false, +# "vrrp": { +# "groups": [ +# { +# "address": "1.1.1.1", +# "advertise_interval": 10, +# "disable": true, +# "interface": "eth2", +# "name": "g1", +# "no_preempt": true, +# "peer_address": "2.2.2.2", +# "rfc3768_compatibility": true, +# "vrid": 20 +# } +# ] +# } +# } +# + +# Using rendered: +# -------------- + +- name: Render + vyos.vyos.vyos_ha: + config: + disable: true + vrrp: + snmp: enabled + global_parameters: + startup_delay: 32 + version: 3 + garp: + interval: 30 + master_delay: 11 + master_refresh: 100 + master_refresh_repeat: 200 + master_repeat: 5 + state: rendered + +# Module Execution: +# "rendered": [ +# "set high-availability disable", +# "set high-availability vrrp global-parameters garp interval 30", +# "set high-availability vrrp global-parameters garp master-delay 11", +# "set high-availability vrrp global-parameters garp master-refresh 100", +# "set high-availability vrrp global-parameters garp master-refresh-repeat 200", +# "set high-availability vrrp global-parameters garp master-repeat 5", +# "set high-availability vrrp global-parameters startup-delay 32", +# "set high-availability vrrp global-parameters version 3", +# "set high-availability vrrp snmp" +# ] +""" + +RETURN = """ +before: + 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: > + This output will always be in the same format as the + module argspec. +after: + description: The resulting configuration after module execution. + returned: when changed + type: dict + sample: > + 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: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) + type: list + sample: + - set high-availability vrrp group g1 address '1.1.1.1' + - set high-availability vrrp group g1 advertise-interval '10' + - set high-availability vrrp group g1 description 'Group 1' +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 high-availability vrrp global-parameters garp master-delay '10' + - set high-availability vrrp global-parameters garp master-refresh '100' + - set high-availability vrrp global-parameters garp master-refresh-repeat '200' +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.ha.ha import ( + HaArgs, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.ha.ha import ( + Ha, +) + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + module = AnsibleModule( + argument_spec=HaArgs.argument_spec, + mutually_exclusive=[["config", "running_config"]], + required_if=[ + ["state", "merged", ["config"]], + ["state", "replaced", ["config"]], + ["state", "overridden", ["config"]], + ["state", "rendered", ["config"]], + ["state", "parsed", ["running_config"]], + ], + supports_check_mode=True, + ) + + result = Ha(module).execute_module() + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/vyos_hostname.py b/plugins/modules/vyos_hostname.py index 480b011f..27f2081f 100644 --- a/plugins/modules/vyos_hostname.py +++ b/plugins/modules/vyos_hostname.py @@ -10,7 +10,6 @@ The module file for vyos_hostname from __future__ import absolute_import, division, print_function - __metaclass__ = type DOCUMENTATION = """ diff --git a/plugins/modules/vyos_interfaces.py b/plugins/modules/vyos_interfaces.py index 6125b4b9..98f3aa5a 100644 --- a/plugins/modules/vyos_interfaces.py +++ b/plugins/modules/vyos_interfaces.py @@ -28,7 +28,6 @@ The module file for vyos_interfaces from __future__ import absolute_import, division, print_function - __metaclass__ = type ANSIBLE_METADATA = { @@ -47,7 +46,7 @@ description: - This module supports managing base attributes of Ethernet, Bonding, VXLAN, Loopback and Virtual Tunnel Interfaces. notes: -- Tested against VyOS 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: @@ -129,6 +128,10 @@ options: - MTU for the virtual sub-interface. - Refer to vendor documentation for valid values. type: int + vrf: + description: + - VRF associated with the interface. + type: str running_config: description: - This option is used only with state I(parsed). diff --git a/plugins/modules/vyos_l3_interfaces.py b/plugins/modules/vyos_l3_interfaces.py index 0d2a5dae..1d3dd20c 100644 --- a/plugins/modules/vyos_l3_interfaces.py +++ b/plugins/modules/vyos_l3_interfaces.py @@ -28,7 +28,6 @@ The module file for vyos_l3_interfaces from __future__ import absolute_import, division, print_function - __metaclass__ = type ANSIBLE_METADATA = { diff --git a/plugins/modules/vyos_lag_interfaces.py b/plugins/modules/vyos_lag_interfaces.py index 090021ad..27dc6d0a 100644 --- a/plugins/modules/vyos_lag_interfaces.py +++ b/plugins/modules/vyos_lag_interfaces.py @@ -28,7 +28,6 @@ The module file for vyos_lag_interfaces from __future__ import absolute_import, division, print_function - __metaclass__ = type ANSIBLE_METADATA = { @@ -46,7 +45,7 @@ description: This module manages attributes of link aggregation groups on VyOS n author: - Rohit Thakur (@rohitthakur2590) notes: -- Tested against VyOS 1.3.8. +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: config: diff --git a/plugins/modules/vyos_lldp_global.py b/plugins/modules/vyos_lldp_global.py index 190f4513..a1c01e23 100644 --- a/plugins/modules/vyos_lldp_global.py +++ b/plugins/modules/vyos_lldp_global.py @@ -28,7 +28,6 @@ The module file for vyos_lldp_global from __future__ import absolute_import, division, print_function - __metaclass__ = type ANSIBLE_METADATA = { @@ -45,7 +44,7 @@ short_description: LLDP global resource module description: This module manages link layer discovery protocol (LLDP) attributes on VyOS devices. notes: -- Tested against VyOS 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: - Rohit Thakur (@rohitthakur2590) diff --git a/plugins/modules/vyos_lldp_interfaces.py b/plugins/modules/vyos_lldp_interfaces.py index 0a8f892b..48cb171f 100644 --- a/plugins/modules/vyos_lldp_interfaces.py +++ b/plugins/modules/vyos_lldp_interfaces.py @@ -28,7 +28,6 @@ The module file for vyos_lldp_interfaces from __future__ import absolute_import, division, print_function - __metaclass__ = type ANSIBLE_METADATA = { @@ -44,7 +43,7 @@ version_added: '1.0.0' short_description: LLDP interfaces resource module description: This module manages attributes of lldp interfaces on VyOS network devices. notes: -- Tested against VyOS 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: diff --git a/plugins/modules/vyos_logging_global.py b/plugins/modules/vyos_logging_global.py index 9479e7b2..c9443f6a 100644 --- a/plugins/modules/vyos_logging_global.py +++ b/plugins/modules/vyos_logging_global.py @@ -10,7 +10,6 @@ The module file for vyos_logging_global from __future__ import absolute_import, division, print_function - __metaclass__ = type DOCUMENTATION = """ @@ -20,10 +19,20 @@ short_description: Logging resource module description: This module manages the logging attributes of Vyos network devices author: Sagar Paul (@KB-perByte) notes: - - Tested against vyos 1.3.8+ + - Tested against VyOS 1.3.8, 1.4.2, 1.5.0, and the rolling release of spring 2025. - This module works with connection C(network_cli). - - The Configuration defaults of the Vyos network devices - are supposed to hinder idempotent behavior of plays + - The Configuration defaults of the VyOS network devices + are supposed to hinder idempotent behavior of plays. + - > + B(VyOS 1.5+ breaking changes): The C(files), C(users), and + C(global_params.archive) options are not supported on VyOS 1.5+. + If provided, they will be ignored with a warning. + The C(global_params) facilities now map to C(set system syslog local) + (was C(set system syslog global)). + Remote hosts now map to C(set system syslog remote) + (was C(set system syslog host)). + The C(marker_interval) and C(preserve_fqdn) options moved to top-level + (was under C(global_params) in the CLI, argspec key unchanged). options: config: description: A list containing dictionary of logging options @@ -85,7 +94,9 @@ options: - debug - all files: - description: logging to file + description: > + Logging to file. B(Not supported on VyOS 1.5+.) If provided on a + 1.5+ device, this option will be ignored with a warning. type: list elements: dict suboptions: @@ -111,7 +122,11 @@ options: facility: *facility severity: *severity global_params: - description: logging to serial console + description: > + Global logging parameters. On VyOS 1.5+, facilities map to + C(set system syslog local), and C(marker_interval)/C(preserve_fqdn) + move to top-level CLI paths. The C(archive) suboption is + B(not supported on VyOS 1.5+) and will be ignored with a warning. type: dict suboptions: state: *state_config @@ -124,7 +139,9 @@ options: description: uses FQDN for logging type: bool hosts: - description: logging to serial console + description: > + Logging to remote hosts. On VyOS 1.5+, maps to + C(set system syslog remote) (was C(set system syslog host)). type: list elements: dict suboptions: @@ -159,7 +176,9 @@ options: suboptions: state: *state_config users: - description: logging to file + description: > + Logging to a local user terminal. B(Not supported on VyOS 1.5+.) + If provided on a 1.5+ device, this option will be ignored with a warning. type: list elements: dict suboptions: @@ -699,6 +718,141 @@ EXAMPLES = """ # ] # } # } +# Using state: merged (VyOS 1.5+) + +# Before state: +# ------------- + +# vyos:~$ show configuration commands | grep syslog + +- name: Apply the provided configuration (VyOS 1.5+) + vyos.vyos.vyos_logging_global: + config: + console: + facilities: + - facility: local7 + severity: err + hosts: + - hostname: 172.16.0.1 + facilities: + - facility: local7 + severity: all + port: 514 + protocol: udp + global_params: + facilities: + - facility: cron + severity: debug + marker_interval: 111 + preserve_fqdn: true + state: merged + +# Commands Fired: +# --------------- + +# "commands": [ +# "set system syslog console facility local7 level err", +# "set system syslog remote 172.16.0.1 facility local7 level all", +# "set system syslog remote 172.16.0.1 port 514", +# "set system syslog remote 172.16.0.1 protocol udp", +# "set system syslog local facility cron level debug", +# "set system syslog marker interval 111", +# "set system syslog preserve-fqdn" +# ], + +# After state: +# ------------ + +# vyos:~$ show configuration commands | grep syslog +# set system syslog console facility local7 level 'err' +# set system syslog local facility cron level 'debug' +# set system syslog marker interval '111' +# set system syslog preserve-fqdn +# set system syslog remote 172.16.0.1 facility local7 level 'all' +# set system syslog remote 172.16.0.1 port '514' +# set system syslog remote 172.16.0.1 protocol 'udp' + +# Using state: gathered (VyOS 1.5+) + +- name: Gather logging config (VyOS 1.5+) + vyos.vyos.vyos_logging_global: + state: gathered + +# Module Execution Result: +# ------------------------ + +# "gathered": { +# "console": { +# "facilities": [ +# { +# "facility": "local7", +# "severity": "err" +# } +# ] +# }, +# "global_params": { +# "facilities": [ +# { +# "facility": "cron", +# "severity": "debug" +# } +# ], +# "marker_interval": 111, +# "preserve_fqdn": true +# }, +# "hosts": [ +# { +# "facilities": [ +# { +# "facility": "local7", +# "severity": "all" +# } +# ], +# "hostname": "172.16.0.1", +# "port": 514, +# "protocol": "udp" +# } +# ] +# }, + +# Using state: rendered (VyOS 1.5+) +# Note: files, users, and global_params.archive are not supported on VyOS 1.5+ +# and will be ignored with a warning if provided. + +- name: Render the provided configuration (VyOS 1.5+) + vyos.vyos.vyos_logging_global: + config: + console: + facilities: + - facility: local7 + severity: err + hosts: + - hostname: 172.16.0.1 + facilities: + - facility: local7 + severity: all + port: 514 + protocol: udp + global_params: + facilities: + - facility: cron + severity: debug + marker_interval: 111 + preserve_fqdn: true + state: rendered + +# Module Execution Result: +# ------------------------ + +# "rendered": [ +# "set system syslog console facility local7 level err", +# "set system syslog remote 172.16.0.1 facility local7 level all", +# "set system syslog remote 172.16.0.1 port 514", +# "set system syslog remote 172.16.0.1 protocol udp", +# "set system syslog local facility cron level debug", +# "set system syslog marker interval 111", +# "set system syslog preserve-fqdn" +# ] """ RETURN = """ diff --git a/plugins/modules/vyos_nat.py b/plugins/modules/vyos_nat.py new file mode 100644 index 00000000..7715cb76 --- /dev/null +++ b/plugins/modules/vyos_nat.py @@ -0,0 +1,934 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +""" +The module file for vyos_nat +""" + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +DOCUMENTATION = """ +module: vyos_nat +version_added: 6.0.0 +short_description: NAT resource module +description: +- This module manages NAT configuration on devices running VyOS. +author: +- Evgeny Molotkov (@omnom62) +notes: +- Tested against VyOS 1.4.3 and 1.5.0. +- This module works with connection C(network_cli). +options: + config: + description: + - The desired configuration for the NAT resource represented as a dictionary. + type: dict + suboptions: + nat: + type: dict + description: Configuration for NAT rules. + suboptions: + cgnat: + type: dict + description: Configuration for Carrier Grade NAT (CGNAT). + suboptions: + log_allocation: + type: bool + description: Log CGNAT address allocations. + pool: + type: dict + description: Configuration for CGNAT pools. + suboptions: + external: + type: list + elements: dict + description: List of external NAT pools for CGNAT. + suboptions: + name: + type: str + required: true + description: Name of the external NAT pool. + external_port_range: + type: str + description: Port range to use for NAT translations in this external pool. + per_user_limit: + type: dict + description: Per-user limit configuration for the external pool. + suboptions: + port: + type: str + description: Maximum number of ports allocated per user. + range: + type: list + elements: dict + description: List of external IP address ranges in the pool. + suboptions: + value: + type: str + required: true + description: IP address, prefix, or range (e.g. 203.0.113.0/24 or 203.0.113.1-203.0.113.60). + seq: + type: str + description: Optional sequence number for this range entry. + internal: + type: list + elements: dict + description: List of internal NAT pools for CGNAT. + suboptions: + name: + type: str + required: true + description: Name of the internal NAT pool. + range: + type: list + elements: str + description: List of internal IP addresses or prefixes in the pool. + rule: + type: list + elements: dict + description: List of CGNAT rules. + suboptions: + id: + type: int + required: true + description: Rule number for CGNAT. + source: + type: dict + description: Source pool configuration for CGNAT translation. + suboptions: + pool: + type: str + description: Source pool name to use for CGNAT translation. + translation: + type: dict + description: Translation pool configuration for CGNAT. + suboptions: + pool: + type: str + description: Translation pool name to use for CGNAT translation. + destination: + type: dict + description: Configuration for destination NAT rules. + suboptions: + rule: + type: list + elements: dict + description: List of destination NAT rules. + suboptions: + id: + type: int + required: true + description: Rule number for destination NAT. + description: + type: str + description: User-friendly description of the destination NAT rule. + protocol: + type: str + description: Protocol to NAT (default all). + packet_type: + type: str + description: Packet type to match. + exclude: + type: bool + description: Exclude packets matching this rule from NAT. + log: + type: bool + description: Log packets hitting this rule. + disable: + type: bool + description: Disable this destination NAT rule. + inbound_interface: + type: dict + description: Match inbound interface. + suboptions: + name: + type: str + description: Interface name to match. + group: + type: str + description: Interface group to match. + destination: + type: dict + description: Match criteria for destination NAT. + suboptions: + address: + type: str + description: IP address, subnet, or range to match. + fqdn: + type: str + description: Fully qualified domain name to match. + port: + type: str + description: Port number or range to match. + address_group: + type: str + description: Address group name to match. + domain_group: + type: str + description: Domain group name to match. + mac_group: + type: str + description: MAC address group name to match. + network_group: + type: str + description: Network group name to match. + port_group: + type: str + description: Port group name to match. + translation: + type: dict + description: Translation configuration for destination NAT. + suboptions: + address: + type: str + description: IP address or prefix to translate destination to. + port: + type: str + description: Port number or range to translate destination port to. + redirect_port: + type: str + description: Redirect to local port number. + address_mapping: + type: str + choices: + - random + - persistent + description: Address mapping mode for translation. + port_mapping: + type: str + choices: + - random + - none + description: Port mapping mode for translation. + load_balance: + type: dict + description: Load balancing configuration for this NAT rule. + suboptions: + hash: + type: list + elements: str + description: Fields to hash on for load balancing. Mutually exclusive with I(translation.address). + choices: + - source-address + - destination-address + - source-port + - destination-port + - random + backend: + type: list + elements: dict + description: List of backends to load-balance across. Weights should sum to 100. + suboptions: + ip: + type: str + description: IP address of the backend translation target. + weight: + type: int + description: Relative weight (1-100) for this backend's share of load-balanced traffic. + source: + type: dict + description: Configuration for source NAT rules. + suboptions: + rule: + type: list + elements: dict + description: List of source NAT rules. + suboptions: + id: + type: int + required: true + description: Rule number for source NAT. + description: + type: str + description: User-friendly description of the source NAT rule. + protocol: + type: str + description: Protocol to NAT (default all). + packet_type: + type: str + description: Packet type to match. + exclude: + type: bool + description: Exclude packets matching this rule from NAT. + log: + type: bool + description: Log packets hitting this rule. + disable: + type: bool + description: Disable this source NAT rule. + outbound_interface: + type: dict + description: Match outbound interface. + suboptions: + name: + type: str + description: Interface name to match. + group: + type: str + description: Interface group to match. + destination: + type: dict + description: Destination match criteria for source NAT. + suboptions: + address: + type: str + description: IP address, subnet, or range to match. + fqdn: + type: str + description: Fully qualified domain name to match. + port: + type: str + description: Port number or range to match. + address_group: + type: str + description: Address group name to match. + domain_group: + type: str + description: Domain group name to match. + mac_group: + type: str + description: MAC address group name to match. + network_group: + type: str + description: Network group name to match. + port_group: + type: str + description: Port group name to match. + source: + type: dict + description: Source match criteria for source NAT. + suboptions: + address: + type: str + description: IP address, subnet, or range to match. + fqdn: + type: str + description: Fully qualified domain name to match. + port: + type: str + description: Port number or range to match. + address_group: + type: str + description: Address group name to match. + domain_group: + type: str + description: Domain group name to match. + mac_group: + type: str + description: MAC address group name to match. + network_group: + type: str + description: Network group name to match. + port_group: + type: str + description: Port group name to match. + translation: + type: dict + description: Translation configuration for source NAT. + suboptions: + address: + type: str + description: IP address or prefix to translate source to. Use masquerade to masquerade as the outbound interface address. + port: + type: str + description: Port number or range to translate source port to. + address_mapping: + type: str + choices: + - random + - persistent + description: Address mapping mode for translation. + port_mapping: + type: str + choices: + - random + - none + description: Port mapping mode for translation. + load_balance: + type: dict + description: Load balancing configuration for this NAT rule. + suboptions: + hash: + type: list + elements: str + description: Fields to hash on for load balancing. Mutually exclusive with I(translation.address). + choices: + - source-address + - destination-address + - source-port + - destination-port + - random + backend: + type: list + elements: dict + description: List of backends to load-balance across. Weights should sum to 100. + suboptions: + ip: + type: str + description: IP address of the backend translation target. + weight: + type: int + description: Relative weight (1-100) for this backend's share of load-balanced traffic. + static: + type: dict + description: Configuration for static one-to-one NAT rules. + suboptions: + rule: + type: list + elements: dict + description: List of static NAT rules. + suboptions: + id: + type: int + required: true + description: Rule number for static NAT. + description: + type: str + description: User-friendly description of the static NAT rule. + destination: + type: dict + description: Match criteria for static NAT. + suboptions: + address: + type: str + description: IP address, subnet, or range to match. + inbound_interface: + type: str + description: Inbound interface that this static NAT rule applies to. + log: + type: bool + description: Log packets hitting this static NAT rule. + translation: + type: dict + description: Translation configuration for static NAT. + suboptions: + address: + type: str + description: IP address or prefix to translate to. + nat64: + type: dict + description: Configuration for NAT64 (IPv6-to-IPv4) rules. + suboptions: + source: + type: dict + description: Configuration for NAT64 source rules. + suboptions: + rule: + type: list + elements: dict + description: List of NAT64 source rules. + suboptions: + id: + type: int + required: true + description: Rule number for NAT64 source rule (1-999999). + description: + type: str + description: User-friendly description of the NAT64 source rule. + disable: + type: bool + description: Disable this NAT64 source rule. + match: + type: dict + description: Match criteria for NAT64 source rule. + suboptions: + mark: + type: int + description: Match on firewall mark value (1-2147483647). + source: + type: dict + description: IPv6 source prefix to match for NAT64 translation. + suboptions: + prefix: + type: str + description: IPv6 source prefix to match (h:h:h:h:h:h:h:h/x). + translation: + type: dict + description: Translation configuration for NAT64 source rule. + suboptions: + pool: + type: list + elements: dict + description: List of translation pools for NAT64. + suboptions: + id: + type: int + required: true + description: Pool number (1-999999). + address: + type: str + description: IPv4 address or prefix for translation pool. + description: + type: str + description: User-friendly description of the translation pool. + disable: + type: bool + description: Disable this translation pool. + port: + type: str + description: Port number or range for translation pool. + protocol: + type: str + choices: + - icmp + - tcp + - udp + description: Protocol for this translation pool entry. + nat66: + type: dict + description: Configuration for NAT66 (IPv6-to-IPv6) rules. + suboptions: + destination: + type: dict + description: Configuration for NAT66 destination rules. + suboptions: + rule: + type: list + elements: dict + description: List of NAT66 destination rules. + suboptions: + id: + type: int + required: true + description: Rule number for NAT66 destination rule. + description: + type: str + description: User-friendly description of the NAT66 destination rule. + destination: + type: dict + description: Match criteria for NAT66 destination rule. + suboptions: + address: + type: str + description: IPv6 address or prefix to match. + port: + type: str + description: Port number or range to match. + disable: + type: bool + description: Disable this NAT66 destination rule. + exclude: + type: bool + description: Exclude packets matching this rule from NAT66. + inbound_interface: + type: dict + description: Inbound interface to match for NAT66 destination rule. + suboptions: + name: + type: str + description: Interface name to match. + log: + type: bool + description: Log packets hitting this NAT66 destination rule. + protocol: + type: str + description: Protocol to match. + source: + type: dict + description: Source match criteria for NAT66 destination rule. + suboptions: + address: + type: str + description: IPv6 source address or prefix to match. + port: + type: str + description: Source port number or range to match. + translation: + type: dict + description: Translation configuration for NAT66 destination rule. + suboptions: + address: + type: str + description: IPv6 address or prefix to translate destination to. + port: + type: str + description: Port number or range to translate destination port to. + source: + type: dict + description: Configuration for NAT66 source rules. + suboptions: + rule: + type: list + elements: dict + description: List of NAT66 source rules. + suboptions: + id: + type: int + required: true + description: Rule number for NAT66 source rule. + description: + type: str + description: User-friendly description of the NAT66 source rule. + destination: + type: dict + description: Destination match criteria for NAT66 source rule. + suboptions: + port: + type: str + description: Destination port number or range to match. + prefix: + type: str + description: IPv6 destination prefix to match (h:h:h:h:h:h:h:h/x). + disable: + type: bool + description: Disable this NAT66 source rule. + exclude: + type: bool + description: Exclude packets matching this rule from NAT66. + log: + type: bool + description: Log packets hitting this NAT66 source rule. + outbound_interface: + type: dict + description: Outbound interface to match for NAT66 source rule. + suboptions: + name: + type: str + description: Interface name to match. + protocol: + type: str + description: Protocol to match. + source: + type: dict + description: Source match criteria for NAT66 source rule. + suboptions: + port: + type: str + description: Source port number or range to match. + prefix: + type: str + description: IPv6 source prefix to match (h:h:h:h:h:h:h:h/x). + translation: + type: dict + description: Translation configuration for NAT66 source rule. + suboptions: + address: + type: str + description: IPv6 address or prefix to translate source to. Use masquerade to masquerade as the outbound interface address. + port: + type: str + description: Port number or range to translate source port to. + running_config: + description: + - This option is used only with state I(parsed). + - The value of this option should be the output received from the VyOS device by + executing the command B(show configuration commands | match 'nat'). + - The state I(parsed) reads the configuration from C(show configuration commands | match 'nat') + and transforms it into Ansible structured data as per the module argspec. + The value is then returned in the I(parsed) key within the result. + - The state I(replaced) replaces only the provided configuration, while I(overridden) removes any + existing NAT configuration not specified in I(config). + type: str + state: + description: + - The state the configuration should be left in. + type: str + choices: + - deleted + - merged + - overridden + - replaced + - gathered + - rendered + - parsed + default: merged +""" +EXAMPLES = """ +# Using merged - configure CGNAT +- name: Merge CGNAT configuration + vyos.vyos.vyos_nat: + config: + nat: + cgnat: + log_allocation: true + pool: + external: + - name: ext-pool-1 + external_port_range: "10000-20000" + per_user_limit: + port: "200" + range: + - value: 203.0.113.0/24 + internal: + - name: int-pool-1 + range: + - 10.0.0.0/24 + rule: + - id: 1 + source: + pool: int-pool-1 + translation: + pool: ext-pool-1 + state: merged + +# Using merged - configure destination NAT +- name: Merge destination NAT rule + vyos.vyos.vyos_nat: + config: + nat: + destination: + rule: + - id: 100 + description: "Web server NAT" + protocol: tcp + log: true + destination: + address: 198.51.100.10 + port: "80" + translation: + address: 192.168.1.10 + port: "8080" + state: merged + +# Using merged - configure source NAT +- name: Merge source NAT rule + vyos.vyos.vyos_nat: + config: + nat: + source: + rule: + - id: 200 + description: "Outbound masquerade" + protocol: tcp + log: true + outbound_interface: + name: eth0 + translation: + address: masquerade + state: merged + +# Using merged - configure static NAT +- name: Merge static NAT rule + vyos.vyos.vyos_nat: + config: + nat: + static: + rule: + - id: 300 + description: "Static mapping" + inbound_interface: eth2 + destination: + address: 198.51.100.20 + translation: + address: 192.168.1.20 + log: true + state: merged + +# Using merged - configure NAT64 +- name: Merge NAT64 source rule + vyos.vyos.vyos_nat: + config: + nat64: + source: + rule: + - id: 10 + description: "NAT64 example" + source: + prefix: 2001:db8::/96 + match: + mark: 100 + translation: + pool: + - id: 1 + address: 192.168.100.10 + port: "1-65535" + protocol: udp + state: merged + +# Using merged - configure NAT66 +- name: Merge NAT66 destination rule + vyos.vyos.vyos_nat: + config: + nat66: + destination: + rule: + - id: 20 + description: "NAT66 DNAT" + protocol: tcp + inbound_interface: + name: eth1 + destination: + address: 2001:db8::1 + translation: + address: 2001:db8:1::10 + port: "8443" + state: merged + +# Using replaced - replace specific NAT rules +- name: Replace destination NAT rule + vyos.vyos.vyos_nat: + config: + nat: + destination: + rule: + - id: 100 + description: "Replaced web server NAT" + protocol: tcp + destination: + address: 198.51.100.10 + port: "443" + translation: + address: 192.168.1.10 + port: "8443" + state: replaced + +# Using overridden - override entire NAT configuration +- name: Override entire NAT configuration + vyos.vyos.vyos_nat: + config: + nat: + destination: + rule: + - id: 100 + description: "Only rule after override" + protocol: tcp + destination: + address: 198.51.100.10 + port: "80" + translation: + address: 192.168.1.10 + port: "8080" + state: overridden + +# Using deleted - delete all NAT configuration +- name: Delete all NAT configuration + vyos.vyos.vyos_nat: + state: deleted + +# Using deleted - delete specific NAT rules +- name: Delete specific NAT rules + vyos.vyos.vyos_nat: + config: + nat: + destination: + rule: + - id: 100 + source: + rule: + - id: 200 + nat64: + source: + rule: + - id: 10 + state: deleted + +# Using gathered +- name: Gather NAT configuration from device + vyos.vyos.vyos_nat: + state: gathered + +# Using rendered +- name: Render NAT configuration offline + vyos.vyos.vyos_nat: + config: + nat: + destination: + rule: + - id: 100 + description: "Rendered rule" + protocol: tcp + destination: + address: 198.51.100.10 + port: "80" + translation: + address: 192.168.1.10 + port: "8080" + state: rendered + +# Using parsed +- name: Parse NAT configuration from file + vyos.vyos.vyos_nat: + running_config: "{{ lookup('file', './nat_config.cfg') }}" + state: parsed +""" +RETURN = """ +before: + description: The configuration prior to the module execution. + returned: when I(state) is C(merged), C(replaced), C(overridden) or C(deleted) + type: dict + sample: > + This output will always be in the same format as the + module argspec. +after: + description: The resulting configuration after module execution. + returned: when changed + type: dict + sample: > + 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: when I(state) is C(merged), C(replaced), C(overridden) or C(deleted) + type: list + sample: + - set nat destination rule 100 description 'Web server NAT' + - set nat destination rule 100 protocol tcp + - set nat destination rule 100 inbound-interface name eth2 + - set nat destination rule 100 destination address 198.51.100.10 + - set nat destination rule 100 translation address 192.168.1.10 + - delete nat source rule 200 +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 nat destination rule 100 description 'Web server NAT' + - set nat destination rule 100 protocol tcp + - set nat destination rule 100 inbound-interface name eth2 + - set nat destination rule 100 destination address 198.51.100.10 + - set nat destination rule 100 translation address 192.168.1.10 +gathered: + description: Facts about the network resource gathered from the remote device as structured data. + returned: when I(state) is C(gathered) + type: dict + 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: dict + 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.nat.nat import ( + NatArgs, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.nat.nat import ( + Nat, +) + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + module = AnsibleModule( + argument_spec=NatArgs.argument_spec, + mutually_exclusive=[["config", "running_config"]], + required_if=[ + ["state", "merged", ["config"]], + ["state", "replaced", ["config"]], + ["state", "overridden", ["config"]], + ["state", "rendered", ["config"]], + ["state", "parsed", ["running_config"]], + ], + supports_check_mode=True, + ) + + result = Nat(module).execute_module() + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/vyos_ntp_global.py b/plugins/modules/vyos_ntp_global.py index cad08a68..ae1330ff 100644 --- a/plugins/modules/vyos_ntp_global.py +++ b/plugins/modules/vyos_ntp_global.py @@ -10,7 +10,6 @@ The module file for vyos_ntp_global from __future__ import absolute_import, division, print_function - __metaclass__ = type DOCUMENTATION = """ @@ -22,7 +21,7 @@ description: author: - Varshitha Yataluru (@YVarshitha) notes: -- Tested against vyos 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(network_cli). - "VyOS v.1.4+ uses chronyd, and path changes from `system` to `service`" options: diff --git a/plugins/modules/vyos_ospf_interfaces.py b/plugins/modules/vyos_ospf_interfaces.py index f86acb7a..d49e9d35 100644 --- a/plugins/modules/vyos_ospf_interfaces.py +++ b/plugins/modules/vyos_ospf_interfaces.py @@ -10,7 +10,6 @@ The module file for vyos_ospf_interfaces from __future__ import absolute_import, division, print_function - __metaclass__ = type DOCUMENTATION = """ @@ -19,6 +18,7 @@ version_added: 1.2.0 short_description: OSPF Interfaces Resource Module. description: - This module manages OSPF configuration of interfaces on devices running VYOS. +- The provided examples of commands are valid for VyOS 1.4+ author: Gomathi Selvi Srinivasan (@GomathiselviS) options: config: @@ -173,14 +173,14 @@ EXAMPLES = """ # -------------- # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' # "after": [ # " @@ -244,14 +244,14 @@ EXAMPLES = """ # ], # "changed": true, # "commands": [ -# "set interfaces ethernet eth1 ip ospf transmit-delay 50", -# "set interfaces ethernet eth1 ip ospf priority 26", -# "set interfaces ethernet eth1 ip ospf network point-to-point", -# "set interfaces ethernet eth1 ipv6 ospfv3 dead-interval 39", -# "set interfaces bonding bond2 ip ospf transmit-delay 45", -# "set interfaces bonding bond2 ip ospf bandwidth 70", -# "set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key 1111111111232345", -# "set interfaces bonding bond2 ipv6 ospfv3 passive" +# "set protocols ospf interface eth1 transmit-delay 50", +# "set protocols ospf interface eth1 priority 26", +# "set protocols ospf interface eth1 network point-to-point", +# "set protocols ospfv3 interface eth1 dead-interval 39", +# "set protocols ospf interface bond2 transmit-delay 45", +# "set protocols ospf interface bond2 bandwidth 70", +# "set protocols ospf interface bond2 authentication md5 key-id 10 md5-key 1111111111232345", +# "set protocols ospfv3 interface bond2 passive" # ], # Using replaced: @@ -260,14 +260,14 @@ EXAMPLES = """ # ------------ # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' - name: Replace provided configuration with device configuration vyos.vyos.vyos_ospf_interfaces: @@ -290,10 +290,10 @@ EXAMPLES = """ # ----------- # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf cost '100' -# set interfaces ethernet eth1 ipv6 ospfv3 ifmtu '33' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 cost '100' +# set protocols ospfv3 interface eth1 ifmtu '33' # vyos@vyos:~$ # Module Execution @@ -383,14 +383,14 @@ EXAMPLES = """ # ], # "changed": true, # "commands": [ -# "set interfaces ethernet eth1 ip ospf cost 100", -# "set interfaces ethernet eth1 ipv6 ospfv3 ifmtu 33", -# "delete interfaces ethernet eth1 ip ospf network point-to-point", -# "delete interfaces ethernet eth1 ip ospf priority 26", -# "delete interfaces ethernet eth1 ip ospf transmit-delay 50", -# "delete interfaces ethernet eth1 ipv6 ospfv3 dead-interval 39", -# "delete interfaces bonding bond2 ip ospf authentication", -# "delete interfaces bonding bond2 ip ospf bandwidth 70" +# "set protocols ospf interface eth1 cost 100", +# "set protocols ospfv3 interface eth1 ifmtu 33", +# "delete protocols ospf interface eth1 network point-to-point", +# "delete protocols ospf interface eth1 priority 26", +# "delete protocols ospf interface eth1 transmit-delay 50", +# "delete protocols ospfv3 interface eth1 dead-interval 39", +# "delete protocols ospf interface bond2 authentication", +# "delete protocols ospf interface bond2 bandwidth 70" # ], # @@ -401,16 +401,16 @@ EXAMPLES = """ # ------------ # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf cost '100' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' -# set interfaces ethernet eth1 ipv6 ospfv3 ifmtu '33' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 cost '100' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' +# set protocols ospfv3 interface eth1 ifmtu '33' # vyos@vyos:~$ - name: Override device configuration with provided configuration @@ -429,9 +429,9 @@ EXAMPLES = """ # ----------- # 200~vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces ethernet eth0 ip ospf cost '100' -# set interfaces ethernet eth0 ipv6 ospfv3 ifmtu '33' -# set interfaces ethernet eth0 ipv6 ospfv3 'passive' +# set protocols ospf interface eth0 cost '100' +# set protocols ospfv3 interface eth0 ifmtu '33' +# set protocols ospfv3 interface eth0 'passive' # vyos@vyos:~$ # # @@ -513,13 +513,13 @@ EXAMPLES = """ # ], # "changed": true, # "commands": [ -# "delete interfaces bonding bond2 ip ospf", -# "delete interfaces bonding bond2 ipv6 ospfv3", -# "delete interfaces ethernet eth1 ip ospf", -# "delete interfaces ethernet eth1 ipv6 ospfv3", -# "set interfaces ethernet eth0 ip ospf cost 100", -# "set interfaces ethernet eth0 ipv6 ospfv3 ifmtu 33", -# "set interfaces ethernet eth0 ipv6 ospfv3 passive" +# "delete protocols ospf interface bond2", +# "delete protocols ospfv3 interface bond2", +# "delete protocols ospf interface eth1", +# "delete protocols ospfv3 interface eth1", +# "set protocols ospf interface eth0 cost 100", +# "set protocols ospfv3 interface eth0 ifmtu 33", +# "set protocols ospfv3 interface eth0 passive" # ], # @@ -530,17 +530,17 @@ EXAMPLES = """ # ------------- # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth0 ip ospf cost '100' -# set interfaces ethernet eth0 ipv6 ospfv3 ifmtu '33' -# set interfaces ethernet eth0 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth0 cost '100' +# set protocols ospfv3 interface eth0 ifmtu '33' +# set protocols ospfv3 interface eth0 'passive' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' # vyos@vyos:~$ - name: Delete device configuration @@ -553,14 +553,14 @@ EXAMPLES = """ # ----------- # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' # vyos@vyos:~$ # # @@ -669,25 +669,25 @@ EXAMPLES = """ # ], # "changed": true, # "commands": [ -# "delete interfaces ethernet eth0 ip ospf", -# "delete interfaces ethernet eth0 ipv6 ospfv3" +# "delete protocols ospf interface eth0", +# "delete protocols ospfv3 interface eth0" # ], # # Using parsed: # parsed.cfg: -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth0 ip ospf cost '50' -# set interfaces ethernet eth0 ip ospf priority '26' -# set interfaces ethernet eth0 ipv6 ospfv3 instance-id '33' -# set interfaces ethernet eth0 ipv6 ospfv3 'mtu-ignore' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth0 cost '50' +# set protocols ospf interface eth0 priority '26' +# set protocols ospfv3 interface eth0 instance-id '33' +# set protocols ospfv3 interface eth0 'mtu-ignore' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' # - name: parse configs @@ -782,14 +782,14 @@ EXAMPLES = """ # ---------------- # "rendered": [ -# "set interfaces ethernet eth1 ip ospf transmit-delay 50", -# "set interfaces ethernet eth1 ip ospf priority 26", -# "set interfaces ethernet eth1 ip ospf network point-to-point", -# "set interfaces ethernet eth1 ipv6 ospfv3 dead-interval 39", -# "set interfaces bonding bond2 ip ospf transmit-delay 45", -# "set interfaces bonding bond2 ip ospf bandwidth 70", -# "set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key 1111111111232345", -# "set interfaces bonding bond2 ipv6 ospfv3 passive" +# "set protocols ospf interface eth1 transmit-delay 50", +# "set protocols ospf interface eth1 priority 26", +# "set protocols ospf interface eth1 network point-to-point", +# "set protocols ospfv3 interface eth1 dead-interval 39", +# "set protocols ospf interface bond2 transmit-delay 45", +# "set protocols ospf interface bond2 bandwidth 70", +# "set protocols ospf interface bond2 authentication md5 key-id 10 md5-key 1111111111232345", +# "set protocols ospfv3 interface bond2 passive" # ] # @@ -799,14 +799,14 @@ EXAMPLES = """ # Native Config: # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' # vyos@vyos:~$ - name: gather configs @@ -884,17 +884,17 @@ commands: returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) type: list sample: - - "set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345'" - - "set interfaces bonding bond2 ip ospf bandwidth '70'" - - "set interfaces bonding bond2 ip ospf transmit-delay '45'" + - "set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345'" + - "set protocols ospf interface bond2 bandwidth '70'" + - "set protocols ospf interface bond2 transmit-delay '45'" 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 bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345'" - - "set interfaces bonding bond2 ip ospf bandwidth '70'" - - "set interfaces bonding bond2 ip ospf transmit-delay '45'" + - "set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345'" + - "set protocols ospf interface bond2 bandwidth '70'" + - "set protocols ospf interface bond2 transmit-delay '45'" gathered: description: Facts about the network resource gathered from the remote device as structured data. returned: when I(state) is C(gathered) diff --git a/plugins/modules/vyos_ospfv2.py b/plugins/modules/vyos_ospfv2.py index a72b7fd2..85822e89 100644 --- a/plugins/modules/vyos_ospfv2.py +++ b/plugins/modules/vyos_ospfv2.py @@ -28,7 +28,6 @@ The module file for vyos_ospfv2 from __future__ import absolute_import, division, print_function - __metaclass__ = type ANSIBLE_METADATA = { @@ -45,7 +44,8 @@ short_description: OSPFv2 resource module description: This resource module configures and manages attributes of OSPFv2 routes on VyOS network devices. notes: -- Tested against VyOS 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 +- The provided examples of commands are valid for VyOS 1.4+ - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: @@ -456,8 +456,8 @@ EXAMPLES = """ # "set protocols ospf parameters opaque-lsa", # "set protocols ospf parameters abr-type 'cisco'", # "set protocols ospf parameters rfc1583-compatibility", -# "set protocols ospf passive-interface eth1", -# "set protocols ospf passive-interface eth2", +# "set protocols ospf interface 'eth1' passive", +# "set protocols ospf interface 'eth2' passive", # "set protocols ospf max-metric router-lsa on-shutdown 10", # "set protocols ospf max-metric router-lsa administrative", # "set protocols ospf max-metric router-lsa on-startup 10", @@ -601,8 +601,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' @@ -864,8 +864,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' @@ -901,8 +901,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' # @@ -1059,7 +1059,7 @@ EXAMPLES = """ # } # # "commands": [ -# "delete protocols ospf passive-interface eth2", +# "delete protocols ospf interface 'eth2' passive", # "delete protocols ospf area 3", # "delete protocols ospf area 4 range 192.0.3.0/24 cost", # "delete protocols ospf area 4 range 192.0.3.0/24", @@ -1191,7 +1191,7 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' +# set protocols ospf interface 'eth1' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' @@ -1279,8 +1279,8 @@ EXAMPLES = """ # "set protocols ospf parameters opaque-lsa", # "set protocols ospf parameters abr-type 'cisco'", # "set protocols ospf parameters rfc1583-compatibility", -# "set protocols ospf passive-interface eth1", -# "set protocols ospf passive-interface eth2", +# "set protocols ospf interface 'eth1' passive", +# "set protocols ospf interface 'eth2' passive", # "set protocols ospf max-metric router-lsa on-shutdown 10", # "set protocols ospf max-metric router-lsa administrative", # "set protocols ospf max-metric router-lsa on-startup 10", @@ -1335,8 +1335,8 @@ EXAMPLES = """ set protocols ospf parameters 'opaque-lsa' set protocols ospf parameters 'rfc1583-compatibility' set protocols ospf parameters router-id '192.0.1.1' - set protocols ospf passive-interface 'eth1' - set protocols ospf passive-interface 'eth2' + set protocols ospf interface 'eth1' passive + set protocols ospf interface 'eth2' passive set protocols ospf redistribute bgp metric '10' set protocols ospf redistribute bgp metric-type '2' state: parsed @@ -1472,8 +1472,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' # @@ -1608,8 +1608,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' @@ -1645,8 +1645,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' # @@ -1781,7 +1781,7 @@ commands: type: list sample: - "set protocols ospf parameters router-id 192.0.1.1" - - "set protocols ospf passive-interface 'eth1'" + - "set protocols ospf interface 'eth1' passive" """ diff --git a/plugins/modules/vyos_ospfv3.py b/plugins/modules/vyos_ospfv3.py index 81b26327..89a5ab24 100644 --- a/plugins/modules/vyos_ospfv3.py +++ b/plugins/modules/vyos_ospfv3.py @@ -28,7 +28,6 @@ The module file for vyos_ospfv3 from __future__ import absolute_import, division, print_function - __metaclass__ = type ANSIBLE_METADATA = { @@ -46,7 +45,7 @@ description: This resource module configures and manages attributes of OSPFv3 ro author: - Rohit Thakur (@rohitthakur2590) notes: -- Tested against VyOS 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: @@ -68,6 +67,15 @@ options: import_list: description: Name of import-list. type: str + interface: + description: Enable OSPVv3 on an interface for this area. + aliases: ['interfaces'] + type: list + elements: dict + suboptions: + name: + description: Interface name. + type: str range: description: Summarize routes matching prefix (border routers only). type: list diff --git a/plugins/modules/vyos_ping.py b/plugins/modules/vyos_ping.py index 98619399..1e81111e 100644 --- a/plugins/modules/vyos_ping.py +++ b/plugins/modules/vyos_ping.py @@ -21,7 +21,6 @@ from __future__ import absolute_import, division, print_function - __metaclass__ = type @@ -30,7 +29,7 @@ module: vyos_ping short_description: Tests reachability using ping from VyOS network devices description: - Tests reachability using ping from a VyOS device to a remote destination. -- Tested against VyOS 1.1.8 (helium) +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - For a general purpose network module, see the M(ansible.netcommon.net_ping) module. - For Windows targets, use the M(ansible.windows.win_ping) module instead. - For targets running Python, use the M(ansible.builtin.ping) module instead. @@ -73,7 +72,7 @@ options: - present default: present notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - For a general purpose network module, see the M(ansible.netcommon.net_ping) module. - For Windows targets, use the M(ansible.windows.win_ping) module instead. - For targets running Python, use the M(ansible.builtin.ping) module instead. diff --git a/plugins/modules/vyos_prefix_lists.py b/plugins/modules/vyos_prefix_lists.py index 71d52b32..b9b5ca99 100644 --- a/plugins/modules/vyos_prefix_lists.py +++ b/plugins/modules/vyos_prefix_lists.py @@ -10,7 +10,6 @@ The module file for vyos_prefix_lists from __future__ import absolute_import, division, print_function - __metaclass__ = type DOCUMENTATION = """ @@ -21,7 +20,7 @@ description: version_added: 2.4.0 author: Priyam Sahoo (@priyamsahoo) notes: - - Tested against VyOS 1.1.8 (helium) + - Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(network_cli) options: config: diff --git a/plugins/modules/vyos_route_maps.py b/plugins/modules/vyos_route_maps.py index 67d327a6..8bd55f3d 100644 --- a/plugins/modules/vyos_route_maps.py +++ b/plugins/modules/vyos_route_maps.py @@ -10,7 +10,6 @@ The module file for vyos_route_maps from __future__ import absolute_import, division, print_function - __metaclass__ = type DOCUMENTATION = """ @@ -21,7 +20,7 @@ description: - This module manages route map configurations on devices running VYOS. author: Ashwini Mhatre (@amhatre) notes: -- Tested against vyos 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(network_cli). options: config: @@ -103,6 +102,12 @@ options: extcommunity_soo: type: str description: Set Site of Origin value. ASN:nn_or_IP_address:nn VPN extended community + extcommunity_bandwidth: + type: str + description: Set Bandwidth of Origin value. 1-25600|cumulative|num-multipaths VPN extended community + extcommunity_bandwidth_non_transitive: + type: bool + description: Set the bandwidth extended community encoded as non-transitive True/False VPN extended community ip_next_hop: type: str description: IP address. @@ -146,6 +151,9 @@ options: weight: type: str description: Border Gateway Protocol (BGP) weight attribute. Example <0-4294967295> + table: + type: str + description: Set prefixes to table. Example <1-200> match: description: Route parameters to match. type: dict @@ -226,6 +234,10 @@ options: type: str description: RPKI validation value. choices: [ "notfound", "invalid", "valid" ] + protocol: + type: str + description: Source protocol to match. + choices: [ "babel","bgp","connected","isis","kernel","ospf","ospfv3","rip","ripng","static","table","vnc" ] on_match: type: dict description: Exit policy on matches. diff --git a/plugins/modules/vyos_snmp_server.py b/plugins/modules/vyos_snmp_server.py index f574919a..a72fb266 100644 --- a/plugins/modules/vyos_snmp_server.py +++ b/plugins/modules/vyos_snmp_server.py @@ -10,7 +10,6 @@ The module file for vyos_snmp_server from __future__ import absolute_import, division, print_function - __metaclass__ = type DOCUMENTATION = """ @@ -20,7 +19,7 @@ short_description: Manages snmp_server resource module description: This module manages the snmp server attributes of Vyos network devices author: Gomathi Selvi Srinivasan (@GomathiselviS) notes: - - Tested against vyos 1.3.8, 1.4.1 + - Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025, 1.4.1 - This module works with connection C(network_cli). - The Configuration defaults of the Vyos network devices are supposed to hinder idempotent behavior of plays diff --git a/plugins/modules/vyos_static_routes.py b/plugins/modules/vyos_static_routes.py index 0629a8bd..37593ffa 100644 --- a/plugins/modules/vyos_static_routes.py +++ b/plugins/modules/vyos_static_routes.py @@ -28,7 +28,6 @@ The module file for vyos_static_routes from __future__ import absolute_import, division, print_function - __metaclass__ = type ANSIBLE_METADATA = { @@ -44,7 +43,7 @@ version_added: '1.0.0' short_description: Static routes resource module description: This module manages attributes of static routes on VyOS network devices. notes: -- Tested against VyOS 1.3.8. +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: diff --git a/plugins/modules/vyos_system.py b/plugins/modules/vyos_system.py index 96a0e9bc..25b32dd7 100644 --- a/plugins/modules/vyos_system.py +++ b/plugins/modules/vyos_system.py @@ -16,8 +16,8 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function __metaclass__ = type @@ -33,7 +33,7 @@ version_added: 1.0.0 extends_documentation_fragment: - vyos.vyos.vyos notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: host_name: @@ -94,21 +94,27 @@ EXAMPLES = """ - sub1.example.com - sub2.example.com """ +from re import M, findall from ansible.module_utils.basic import AnsibleModule +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.version import ( + LooseVersion, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( get_config, + get_os_version, load_config, ) -def spec_key_to_device_key(key): +def spec_key_to_device_key(key, module): device_key = key.replace("_", "-") - # domain-search is longer than just it's key + # domain-search differs in 1.3- and 1.4+ if device_key == "domain-search": - device_key += " domain" + if LooseVersion(get_os_version(module)) <= LooseVersion("1.3"): + device_key += " domain" return device_key @@ -119,19 +125,20 @@ def config_to_dict(module): config = {"domain_search": [], "name_server": []} for line in data.split("\n"): - if line.startswith("set system host-name"): - config["host_name"] = line[22:-1] - elif line.startswith("set system domain-name"): - config["domain_name"] = line[24:-1] - elif line.startswith("set system domain-search domain"): - config["domain_search"].append(line[33:-1]) - elif line.startswith("set system name-server"): - config["name_server"].append(line[24:-1]) - + config_line = findall(r"^set system\s+(\S+)(?:\s+domain)?\s+'([^']+)'", line, M) + if config_line: + if config_line[0][0] == "host-name": + config["host_name"] = config_line[0][1] + elif config_line[0][0] == "domain-name": + config["domain_name"] = config_line[0][1] + elif config_line[0][0] == "domain-search": + config["domain_search"].append(config_line[0][1]) + elif config_line[0][0] == "name-server": + config["name_server"].append(config_line[0][1]) return config -def spec_to_commands(want, have): +def spec_to_commands(want, have, module): commands = [] state = want.pop("state") @@ -140,7 +147,7 @@ def spec_to_commands(want, have): if state == "absent" and all(v is None for v in want.values()): # Clear everything for key in have: - commands.append("delete system %s" % spec_key_to_device_key(key)) + commands.append("delete system %s" % spec_key_to_device_key(key, module)) for key in want: if want[key] is None: @@ -148,7 +155,7 @@ def spec_to_commands(want, have): current = have.get(key) proposed = want[key] - device_key = spec_key_to_device_key(key) + device_key = spec_key_to_device_key(key, module) # These keys are lists which may need to be reconciled with the device if key in ["domain_search", "name_server"]: @@ -201,7 +208,7 @@ def main(): want = map_param_to_obj(module) have = config_to_dict(module) - commands = spec_to_commands(want, have) + commands = spec_to_commands(want, have, module) result["commands"] = commands if commands: diff --git a/plugins/modules/vyos_user.py b/plugins/modules/vyos_user.py index 5aebf943..7c21b074 100644 --- a/plugins/modules/vyos_user.py +++ b/plugins/modules/vyos_user.py @@ -2,7 +2,6 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, division, print_function - __metaclass__ = type # (c) 2017, Ansible by Red Hat, inc @@ -37,7 +36,7 @@ version_added: 1.0.0 extends_documentation_fragment: - vyos.vyos.vyos notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: aggregate: @@ -55,7 +54,7 @@ options: description: - The username to be configured on the VyOS device. This argument accepts a string value and is mutually exclusive with the C(aggregate) argument. - required: True + required: true type: str full_name: description: @@ -118,6 +117,8 @@ options: - ecdsa-sha2-nistp384 - ssh-ed25519 - ecdsa-sha2-nistp521 + - sk-ecdsa-sha2-nistp256@openssh.com + - sk-ssh-ed25519@openssh.com name: description: @@ -205,12 +206,12 @@ commands: """ import re +import shlex from copy import deepcopy from functools import partial from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( remove_default_spec, ) @@ -277,7 +278,8 @@ def spec_to_commands(updates, module): add( commands, want, - "authentication plaintext-password %s" % want["configured_password"], + "authentication plaintext-password %s" + % shlex.quote(want["configured_password"]), ) return commands @@ -364,6 +366,8 @@ def get_param_value(key, item, module): # if key doesn't exist in the item, get it from module.params if not item.get(key): value = module.params[key] + else: + value = item.get(key) # validate the param value (if validator func exists) validator = globals().get("validate_%s" % key) @@ -424,7 +428,7 @@ def update_objects(want, have): if item is None: updates.append((entry, {})) elif item: - for key, value in iteritems(entry): + for key, value in entry.items(): if value and value != item[key]: updates.append((entry, item)) return updates @@ -445,6 +449,8 @@ def main(): "ecdsa-sha2-nistp384", "ssh-ed25519", "ecdsa-sha2-nistp521", + "sk-ecdsa-sha2-nistp256@openssh.com", + "sk-ssh-ed25519@openssh.com", ], ), ) @@ -453,7 +459,8 @@ def main(): full_name=dict(), configured_password=dict(no_log=True), encrypted_password=dict(no_log=False), - update_password=dict(default="always", choices=["on_create", "always"]), + # Explicit no_log=False: unset no_log triggers Ansible PASSWORD_MATCH on *password* names. + update_password=dict(default="always", choices=["on_create", "always"], no_log=False), state=dict(default="present", choices=["present", "absent"]), public_keys=dict(type="list", elements="dict", options=public_key_spec), ) diff --git a/plugins/modules/vyos_vlan.py b/plugins/modules/vyos_vlan.py index 49cc1258..d2e004f8 100644 --- a/plugins/modules/vyos_vlan.py +++ b/plugins/modules/vyos_vlan.py @@ -6,7 +6,6 @@ from __future__ import absolute_import, division, print_function - __metaclass__ = type @@ -18,7 +17,7 @@ description: - This module provides declarative management of VLANs on VyOS network devices. version_added: 1.0.0 notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: name: @@ -279,15 +278,11 @@ def map_config_to_obj(module): obj = {} eth = splitted_line[0].strip("'") - if eth.startswith("eth"): + if eth.startswith("eth") and "." in eth: obj["interfaces"] = [] - if "." in eth: - interface = eth.split(".")[0] - obj["interfaces"].append(interface) - obj["vlan_id"] = eth.split(".")[-1] - else: - obj["interfaces"].append(eth) - obj["vlan_id"] = None + interface = eth.split(".")[0] + obj["interfaces"].append(interface) + obj["vlan_id"] = eth.split(".")[-1] if splitted_line[1].strip("'") != "-": obj["address"] = splitted_line[1].strip("'") diff --git a/plugins/modules/vyos_vpn_ipsec.py b/plugins/modules/vyos_vpn_ipsec.py new file mode 100644 index 00000000..9af12ff7 --- /dev/null +++ b/plugins/modules/vyos_vpn_ipsec.py @@ -0,0 +1,454 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2026 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +""" +The module file for vyos_vpn_ipsec +""" + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +DOCUMENTATION = """ +module: vyos_vpn_ipsec +short_description: Manages global IPsec (ike-group, esp-group, profile, authentication, options) attributes of VyOS network devices. +description: This module manages global VPN IPsec configuration on VyOS devices + -- IKE groups, ESP groups, PSK/PPK authentication, IPsec profiles, and global + options. Site-to-site peers and IKEv2 remote-access connections are handled by + separate modules. +version_added: 1.0.0 +author: Evgeny Molotkov (@omnom62) +extends_documentation_fragment: + - vyos.vyos.vyos +notes: + - Tested against VyOS 1.4 and 1.5. + - "Source of truth for field types/choices: device node.def templates under /opt/vyatta/share/vyatta-cfg/templates/vpn/ipsec/." +options: + config: + description: IPsec global configuration. + type: dict + suboptions: + ike_group: + description: List of IKE groups. + type: list + elements: dict + suboptions: + name: + description: The name of the IKE group. + type: str + required: true + close_action: + description: Action to take if a child SA is unexpectedly closed. + type: str + choices: [none, trap, start] + dead_peer_detection: + description: Dead Peer Detection (DPD). + type: dict + suboptions: + action: + description: Keep-alive failure action. + type: str + choices: [trap, clear, restart] + interval: + description: Keep-alive interval in seconds. + type: int + timeout: + description: Dead Peer Detection keep-alive timeout (IKEv1 only), in seconds. + type: int + disable_mobike: + description: Disable MOBIKE support (IKEv2 only). + type: bool + ikev2_reauth: + description: Re-authentication of the remote peer during an IKE re-key (IKEv2 only). + type: bool + key_exchange: + description: IKE version. + type: str + choices: [ikev1, ikev2] + lifetime: + description: IKE lifetime in seconds. + type: int + mode: + description: IKEv1 phase 1 mode. + type: str + choices: [main, aggressive] + proposal: + description: List of IKE proposals. + type: list + elements: dict + suboptions: + proposal_id: + description: The proposal identifier. + type: int + dh_group: + description: Diffie-Hellman group. See VyOS/strongSwan documentation for the + full set of valid values -- validated device-side, not enumerated here since + the set is version-dependent. + type: int + encryption: + description: Encryption algorithm. See VyOS/strongSwan documentation for the + full set of valid values -- validated device-side, not enumerated here since + the set is version-dependent. + type: str + hash: + description: Hash algorithm. See VyOS/strongSwan documentation for the + full set of valid values -- validated device-side. + type: str + prf: + description: Pseudo-Random Function. See VyOS/strongSwan documentation for the + full set of valid values -- validated device-side. + type: str + esp_group: + description: List of ESP groups. + type: list + elements: dict + suboptions: + name: + description: The name of the ESP group. + type: str + required: true + compression: + description: Enable ESP compression. + type: bool + disable_rekey: + description: Do not locally initiate a re-key of the SA; remote peer must re-key before expiration. + type: bool + life_bytes: + description: Security Association byte count to expire. + type: int + life_packets: + description: Security Association packet count to expire. + type: int + lifetime: + description: Security Association time to expire, in seconds. + type: int + mode: + description: ESP mode. + type: str + choices: [tunnel, transport] + pfs: + description: ESP Perfect Forward Secrecy. See VyOS/strongSwan documentation for the + full set of valid values -- validated device-side, not enumerated here since + the set is version-dependent. + type: str + proposal: + description: List of ESP proposals. + type: list + elements: dict + suboptions: + proposal_id: + description: The proposal identifier. + type: int + encryption: + description: Encryption algorithm. See VyOS/strongSwan documentation for the + full set of valid values -- validated device-side, not enumerated here since + the set is version-dependent. + type: str + hash: + description: Hash algorithm. See VyOS/strongSwan documentation for the + full set of valid values -- validated device-side. + type: str + authentication: + description: Global pre-shared-key and post-quantum pre-shared-key definitions. + type: dict + suboptions: + psk: + description: List of pre-shared keys. + type: list + elements: dict + suboptions: + name: + description: Pre-shared key name. + type: str + required: true + id: + description: ID(s) for authentication. + type: list + elements: str + dhcp_interface: + description: DHCP interface(s) supplying next-hop IP address. + type: list + elements: str + secret: + description: IKE pre-shared secret key. + type: str + secret_type: + description: Secret encoding type. + type: str + choices: [base64, hex, plaintext] + ppk: + description: List of post-quantum pre-shared keys. + type: list + elements: dict + suboptions: + name: + description: Post-quantum pre-shared key name. + type: str + required: true + id: + description: ID(s) for PPK. + type: list + elements: str + secret: + description: Post-quantum pre-shared secret key. + type: str + secret_type: + description: Secret encoding type. + type: str + choices: [base64, hex, plaintext] + profile: + description: List of VPN IPsec profiles (used for e.g. DMVPN/GRE tunnel binding). + type: list + elements: dict + suboptions: + name: + description: Profile name. + type: str + required: true + authentication: + description: Authentication settings for this profile. + type: dict + suboptions: + mode: + description: Authentication mode. + type: str + choices: [pre-shared-secret] + pre_shared_secret: + description: Pre-shared secret key. + type: str + bind_tunnel: + description: Tunnel interface(s) associated with this profile. + type: list + elements: str + disable: + description: Disable this profile. + type: bool + esp_group: + description: ESP group name to use for this profile. + type: str + ike_group: + description: IKE group name to use for this profile. + type: str + interface: + description: Interface(s) IPsec listens on. If omitted, listens on all interfaces. + type: list + elements: str + log: + description: IPsec logging settings. + type: dict + suboptions: + level: + description: Global IPsec logging level. + type: int + subsystem: + description: Per-subsystem logging levels to enable. + type: list + elements: str + options: + description: Global IPsec options. + type: dict + suboptions: + disable_route_autoinstall: + description: Do not automatically install routes to remote networks. + type: bool + flexvpn: + description: Allow FlexVPN vendor ID payload (IKEv2 only). + type: bool + interface: + description: Single interface for IPsec options scope (distinct from top-level interface list). + type: str + retransmission: + description: IPsec retransmission settings. + type: dict + suboptions: + attempts: + description: Maximum number of retransmissions. + type: int + base: + description: Base of exponential backoff. + type: float + timeout: + description: Timeout in seconds before the first retransmission. + type: int + virtual_ip: + description: Allow install of virtual-ip addresses. + type: bool + disable_uniqreqids: + description: Disable requirement for unique IDs in the Security Database. + type: bool + running_config: + description: + - This option is used only with state I(parsed). + - The value of this option should be the output received from the VyOS device by + executing the command B(show configuration commands | match "vpn ipsec"). + - The states I(replaced) and I(overridden) have identical behaviour for this module + with respect to named collections (ike_group, esp_group, profile, authentication), + but differ in scope -- see the module description for detail. + - The state I(parsed) reads the configuration from the C(running_config) option and + transforms it into Ansible structured data as per the resource module's argspec, + returned in the I(parsed) key within the result. + type: str + state: + description: The state the configuration should be left in. + type: str + choices: [merged, replaced, overridden, deleted, gathered, rendered, parsed] + default: merged +""" + +EXAMPLES = """ +- name: Merge provided configuration with device configuration + vyos.vyos.vyos_vpn_ipsec: + config: + esp_group: + - name: ESP-TEST + proposal: + - proposal_id: 1 + encryption: aes256 + hash: sha256 + ike_group: + - name: IKE-TEST + key_exchange: ikev2 + proposal: + - proposal_id: 1 + encryption: aes256 + hash: sha256 + dh_group: 14 + state: merged + +- name: Replace one named esp-group, leaving all other groups untouched + vyos.vyos.vyos_vpn_ipsec: + config: + esp_group: + - name: ESP-TEST + proposal: + - proposal_id: 1 + encryption: aes128 + hash: sha256 + state: replaced + +- name: Override the whole configuration -- anything not listed here is removed + vyos.vyos.vyos_vpn_ipsec: + config: + esp_group: + - name: ESP-TEST + proposal: + - proposal_id: 1 + encryption: aes256 + hash: sha256 + state: overridden + +- name: Delete one named esp-group, leaving all other groups untouched + vyos.vyos.vyos_vpn_ipsec: + config: + esp_group: + - name: ESP-TEST + state: deleted + +- name: Remove all vpn_ipsec configuration + vyos.vyos.vyos_vpn_ipsec: + state: deleted + +- name: Gather current vpn_ipsec configuration + vyos.vyos.vyos_vpn_ipsec: + state: gathered + +- name: Render configuration without touching the device + vyos.vyos.vyos_vpn_ipsec: + config: + esp_group: + - name: ESP-TEST + proposal: + - proposal_id: 1 + encryption: aes256 + hash: sha256 + state: rendered + +- name: Parse raw config text into structured facts + vyos.vyos.vyos_vpn_ipsec: + running_config: "{{ lookup('file', './vpn_ipsec.cfg') }}" + state: parsed +""" + +RETURN = """ +before: + description: The configuration prior to the module execution. + returned: when I(state) is C(merged), C(replaced), C(overridden) or C(deleted) + type: dict + sample: > + This output will always be in the same format as the + module argspec. +after: + description: The resulting configuration after module execution. + returned: when changed + type: dict + sample: > + 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: when I(state) is C(merged), C(replaced), C(overridden) or C(deleted) + type: list + sample: + - set vpn ipsec esp-group ESP-TEST proposal 1 encryption aes256 + - set vpn ipsec ike-group IKE-TEST key-exchange ikev2 +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 vpn ipsec esp-group ESP-TEST proposal 1 encryption aes256 +gathered: + description: Facts about the network resource gathered from the remote device as structured data. + returned: when I(state) is C(gathered) + type: dict + 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: dict + 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.vpn_ipsec.vpn_ipsec import ( + Vpn_ipsecArgs, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.vpn_ipsec.vpn_ipsec import ( + Vpn_ipsec, +) + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + module = AnsibleModule( + argument_spec=Vpn_ipsecArgs.argument_spec, + mutually_exclusive=[["config", "running_config"]], + required_if=[ + ["state", "merged", ["config"]], + ["state", "replaced", ["config"]], + ["state", "overridden", ["config"]], + ["state", "rendered", ["config"]], + ["state", "parsed", ["running_config"]], + ], + supports_check_mode=True, + ) + + result = Vpn_ipsec(module).execute_module() + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/vyos_vpn_ipsec_s2s.py b/plugins/modules/vyos_vpn_ipsec_s2s.py new file mode 100644 index 00000000..7458381e --- /dev/null +++ b/plugins/modules/vyos_vpn_ipsec_s2s.py @@ -0,0 +1,337 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2026 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +""" +The module file for vyos_vpn_ipsec_s2s +""" + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +DOCUMENTATION = """ +module: vyos_vpn_ipsec_s2s +short_description: Manages IPsec site-to-site VPN peers on VyOS network devices. +description: This module manages VPN IPsec site-to-site peer configuration on VyOS + devices -- policy-based tunnels and route-based (VTI) connections. IKE/ESP groups, + PSK/PPK authentication, and IPsec profiles are managed by the separate vyos_vpn_ipsec + module; peers here reference those by name. +version_added: 1.0.0 +author: Evgeny Molotkov (@omnom62) +extends_documentation_fragment: + - vyos.vyos.vyos +notes: + - Tested against VyOS 1.4 and 1.5. + - "Source of truth: vyos-1x's interface-definitions/vpn_ipsec.xml.in, resolved and + drafted via this collection's fetch_vyos_xml_definition.py / parse_xml_definitions.py + helper scripts, then hand-reviewed." + - "The argspec only requires I(name) on a peer, but VyOS itself enforces + several more requirements at commit time -- confirmed via real device + testing, not visible in the argspec: every peer needs C(authentication), + a real C(remote_address) (not just omitted), a C(local_address) or + C(dhcp_interface), and at least one of C(tunnel) or C(vti). A peer + missing any of these will pass Ansible's own argument validation but + fail the device commit with a specific error naming what's missing." +options: + config: + description: IPsec site-to-site configuration. + type: dict + suboptions: + peer: + description: List of site-to-site peers. + type: list + elements: dict + suboptions: + name: + description: Connection name of the peer. + type: str + required: true + disable: + description: Disable this peer. + type: bool + authentication: + description: Peer authentication settings. + type: dict + suboptions: + local_id: + description: Local ID for peer authentication. + type: str + remote_id: + description: ID for remote authentication. + type: str + mode: + description: Authentication mode. + type: str + choices: [pre-shared-secret, rsa, x509] + use_x509_id: + description: Use certificate common name as ID. + type: bool + ppk: + description: Post-quantum preshared key reference for this peer. + type: dict + suboptions: + id: + description: Post-quantum preshared key ID for this connection. + type: str + required: + description: Require a valid PPK for the connection to establish. + type: bool + rsa: + description: RSA key authentication. + type: dict + suboptions: + local_key: + description: Name of the PKI key-pair with the local private key. + type: str + remote_key: + description: Name of the PKI key-pair with the remote public key. + type: str + passphrase: + description: Local private key passphrase. + type: str + x509: + description: X.509 certificate authentication. + type: dict + suboptions: + certificate: + description: Certificate in PKI configuration. + type: str + passphrase: + description: Private key passphrase. + type: str + ca_certificate: + description: Certificate Authority chain in PKI configuration. + type: list + elements: str + childless: + description: Childless IKE SA initiation support. + type: str + choices: [allow, prefer, force, never] + connection_type: + description: Connection type. + type: str + choices: [initiate, trap, none] + default_esp_group: + description: Default ESP group name for tunnels under this peer that + don't specify their own. + type: str + description: + description: Description. + type: str + dhcp_interface: + description: DHCP interface supplying the next-hop IP address. + type: str + force_udp_encapsulation: + description: Force UDP encapsulation. + type: bool + ike_group: + description: IKE group name. + type: str + ikev2_reauth: + description: Re-authentication of the remote peer during an IKE re-key + (IKEv2 only). + type: str + choices: ["yes", "no", inherit] + local_address: + description: IPv4 or IPv6 address of a local interface to use for the + VPN, or "any". + type: str + remote_address: + description: IPv4 or IPv6 address(es) of the remote peer, or "any". + type: list + elements: str + replay_window: + description: IPsec replay window to configure for this CHILD_SA. + type: int + virtual_address: + description: Initiator-requested virtual address(es) from the peer. + type: list + elements: str + tunnel: + description: Policy-based tunnel definitions for this peer. + type: list + elements: dict + suboptions: + tunnel_id: + description: The tunnel identifier. + type: int + required: true + disable: + description: Disable this tunnel. + type: bool + esp_group: + description: ESP group name for this tunnel (overrides the peer's + default_esp_group). + type: str + protocol: + description: Protocol to match for this tunnel's traffic selector. + type: str + priority: + description: Priority for this IPsec policy (lowest value is most + preferred). + type: int + local: + description: Local traffic selector for this tunnel. + type: dict + suboptions: + port: + description: Local port to match. + type: int + prefix: + description: Local IPv4 or IPv6 prefix(es) to match. + type: list + elements: str + remote: + description: Remote traffic selector for this tunnel. + type: dict + suboptions: + port: + description: Remote port to match. + type: int + prefix: + description: Remote IPv4 or IPv6 prefix(es) to match. + type: list + elements: str + vti: + description: Route-based (VTI) connection settings for this peer. + type: dict + suboptions: + bind: + description: VTI tunnel interface associated with this connection. + type: str + esp_group: + description: ESP group name for this VTI connection. + type: str + traffic_selector: + description: Traffic selector for the VTI connection. + type: dict + suboptions: + local: + description: Local traffic-selector parameters. + type: dict + suboptions: + prefix: + description: Local IPv4 or IPv6 prefix(es). + type: list + elements: str + remote: + description: Remote traffic-selector parameters. + type: dict + suboptions: + prefix: + description: Remote IPv4 or IPv6 prefix(es). + type: list + elements: str + running_config: + description: + - This option is used only with state I(parsed). + - The value of this option should be the output received from the VyOS device + by executing the command B(show configuration commands | match "vpn ipsec + site-to-site"). + - The state I(parsed) reads the configuration from the C(running_config) option + and transforms it into Ansible structured data as per the resource module's + argspec, returned in the I(parsed) key within the result. + type: str + state: + description: The state the configuration should be left in. + type: str + choices: [merged, replaced, overridden, deleted, gathered, rendered, parsed] + default: merged +""" + +EXAMPLES = """ +- name: Merge a site-to-site peer + vyos.vyos.vyos_vpn_ipsec_s2s: + config: + peer: + - name: PEER-TEST + ike_group: IKE-TEST + default_esp_group: ESP-TEST + remote_address: + - 203.0.113.1 + state: merged +""" + +RETURN = """ +before: + description: The configuration prior to the module execution. + returned: when I(state) is C(merged), C(replaced), C(overridden) or C(deleted) + type: dict + sample: > + This output will always be in the same format as the + module argspec. +after: + description: The resulting configuration after module execution. + returned: when changed + type: dict + sample: > + 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: when I(state) is C(merged), C(replaced), C(overridden) or C(deleted) + type: list + sample: + - set vpn ipsec site-to-site peer PEER-TEST ike-group 'IKE-TEST' + - set vpn ipsec site-to-site peer PEER-TEST default-esp-group 'ESP-TEST' +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 vpn ipsec site-to-site peer PEER-TEST ike-group 'IKE-TEST' +gathered: + description: Facts about the network resource gathered from the remote device as structured data. + returned: when I(state) is C(gathered) + type: dict + 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: dict + 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.vpn_ipsec_s2s.vpn_ipsec_s2s import ( + Vpn_ipsec_s2sArgs, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.vpn_ipsec_s2s.vpn_ipsec_s2s import ( + Vpn_ipsec_s2s, +) + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + module = AnsibleModule( + argument_spec=Vpn_ipsec_s2sArgs.argument_spec, + mutually_exclusive=[["config", "running_config"]], + required_if=[ + ["state", "merged", ["config"]], + ["state", "replaced", ["config"]], + ["state", "overridden", ["config"]], + ["state", "rendered", ["config"]], + ["state", "parsed", ["running_config"]], + ], + supports_check_mode=True, + ) + + result = Vpn_ipsec_s2s(module).execute_module() + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/vyos_vrf.py b/plugins/modules/vyos_vrf.py new file mode 100644 index 00000000..3f7ae10e --- /dev/null +++ b/plugins/modules/vyos_vrf.py @@ -0,0 +1,1542 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +""" +The module file for vyos_vrf +""" + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = """ +module: vyos_vrf +version_added: 1.0.0 +short_description: VRF resource module +description: +- This module manages vrf configuration on devices running Vyos +author: +- Evgeny Molotkov (@omnom62) +notes: +- Tested against vyos 1.4.2 and 1.5-stream-2025-Q1 +- This module works with connection C(network_cli). +options: + config: + description: List of vrf configuration. + type: dict + suboptions: + bind_to_all: + default: false + description: Enable binding services to all VRFs + type: bool + instances: + description: Virtual Routing and Forwarding instance + type: list + elements: dict + suboptions: + name: + description: VRF instance name + required: true + type: str + description: + description: Description + type: str + disable: + default: false + description: Administratively disable interface + type: bool + aliases: ['disabled'] + table_id: + description: Routing table associated with this instance + type: int + vni: + description: Virtual Network Identifier + type: int + address_family: + type: list + elements: dict + description: Address family configuration + suboptions: + afi: + description: Address family identifier + type: str + choices: ['ipv4', 'ipv6'] + disable_forwarding: + default: false + description: Disable forwarding for this address family + type: bool + nht_no_resolve_via_default: + default: false + description: Disable next-hop resolution via default route + type: bool + route_maps: + description: List of route maps for this address family + type: list + elements: dict + suboptions: + rm_name: + description: Route map name + type: str + required: true + protocol: + description: Protocol to which the route map applies + type: str + choices: + - any + - babel + - bgp + - eigrp + - isis + - ospf + - rip + - static + protocols: + # type: list # sanity + # elements: dict + type: dict + description: Protocol configuration + suboptions: + bgp: + type: dict + description: BGP configuration + suboptions: + as_number: + description: + - AS number. + type: int + #maximum_paths: --> moved to address-family before 1.3 + neighbor: + description: BGP neighbor + type: list + elements: dict + suboptions: + address: + description: + - BGP neighbor address (v4/v6). + type: str + advertisement_interval: + description: + - Minimum interval for sending routing updates. + type: int + capability: + description: + - Advertise capabilities to this neighbor. + type: dict + suboptions: + dynamic: + description: + - Advertise dynamic capability to this neighbor. + type: bool + extended_nexthop: + description: + - Advertise extended nexthop capability to this neighbor. + type: bool + default_originate: + description: + - Send default route to this neighbor + type: str + description: + description: + - Description of the neighbor + type: str + disable_capability_negotiation: + description: + - Disbale capability negotiation with the neighbor + type: bool + disable_connected_check: + description: + - Disable check to see if EBGP peer's address is a connected route. + type: bool + disable_send_community: + description: + - Disable sending community attributes to this neighbor. + type: str + choices: ['extended', 'standard'] + ebgp_multihop: + description: + - Allow this EBGP neighbor to not be on a directly connected network. Specify + the number hops. + type: int + local_as: + description: local as number not to be prepended to updates from EBGP peers + type: int + override_capability: + description: Ignore capability negotiation with specified neighbor. + type: bool + passive: + description: Do not initiate a session with this neighbor + type: bool + password: + description: BGP MD5 password + type: str + peer_group_name: + description: IPv4 peer group for this peer + type: str + peer_group: + description: True if all the configs under this neighbor key is for peer group template. + type: bool + port: + description: Neighbor's BGP port + type: int + remote_as: + description: Neighbor BGP AS number + type: int + shutdown: + description: Administratively shut down neighbor + type: bool + solo: # <-- added in 1.3 + description: Do not send back prefixes learned from the neighbor + type: bool + strict_capability_match: + description: Enable strict capability negotiation + type: bool + timers: + description: Neighbor timers + type: dict + suboptions: + connect: + description: BGP connect timer for this neighbor. + type: int + holdtime: + description: BGP hold timer for this neighbor + type: int + keepalive: + description: BGP keepalive interval for this neighbor + type: int + ttl_security: + description: Number of the maximum number of hops to the BGP peer + type: int + update_source: + description: Source IP of routing updates + type: str + timers: + description: BGP protocol timers + type: dict + suboptions: + keepalive: + description: Keepalive interval + type: int + holdtime: + description: Hold time interval + type: int + bgp_params: + description: BGP parameters + type: dict + suboptions: + always_compare_med: + description: Always compare MEDs from different neighbors + type: bool + bestpath: + description: Default bestpath selection mechanism + type: dict + suboptions: + as_path: + description: AS-path attribute comparison parameters + type: str + choices: ['confed', 'ignore'] + compare_routerid: + description: Compare the router-id for identical EBGP paths + type: bool + med: + description: MED attribute comparison parameters + type: str + choices: ['confed', 'missing-as-worst'] + cluster_id: + description: Route-reflector cluster-id + type: str + confederation: + description: AS confederation parameters + type: list + elements: dict + suboptions: + identifier: + description: Confederation AS identifier + type: int + peers: + description: Peer ASs in the BGP confederation + type: int + dampening: + description: Enable route-flap dampening + type: dict + suboptions: + half_life: + description: Half-life penalty in seconds + type: int + max_suppress_time: + description: Maximum duration to suppress a stable route + type: int + re_use: + description: Time to start reusing a route + type: int + start_suppress_time: + description: When to start suppressing a route + type: int + default: + description: BGP defaults + type: dict + suboptions: + local_pref: + description: Default local preference + type: int + no_ipv4_unicast: + description: | + Deactivate IPv4 unicast for a peer by default + Deprecated: Unavailable after 1.4 + type: bool + deterministic_med: + description: Compare MEDs between different peers in the same AS + type: bool + disable_network_import_check: + description: Disable IGP route check for network statements + type: bool + distance: + description: Administrative distances for BGP routes + type: list + elements: dict + suboptions: + type: + description: Type of route + type: str + choices: ['external', 'internal', 'local'] + value: + description: distance + type: int + prefix: + description: Administrative distance for a specific BGP prefix + type: int + enforce_first_as: + description: Require first AS in the path to match peer's AS + type: bool + graceful_restart: + description: Maximum time to hold onto restarting peer's stale paths + type: int + log_neighbor_changes: + description: Log neighbor up/down changes and reset reason + type: bool + no_client_to_client_reflection: + description: Disable client to client route reflection + type: bool + no_fast_external_failover: + description: Disable immediate session reset if peer's connected link goes down + type: bool + router_id: + description: BGP router-id + type: str + scan_time: + description: BGP route scanner interval + type: int + ospf: + type: dict + description: OSPFv2 configuration + suboptions: + areas: + description: OSPFv2 area. + type: list + elements: dict + suboptions: + area_id: + description: OSPFv2 area identity. + type: str + area_type: + description: Area type. + type: dict + suboptions: + normal: + description: Normal OSPFv2 area. + type: bool + nssa: + description: NSSA OSPFv2 area. + type: dict + suboptions: + set: + description: Enabling NSSA. + type: bool + default_cost: + description: Summary-default cost of NSSA area. + type: int + no_summary: + description: Do not inject inter-area routes into stub. + type: bool + translate: + description: NSSA-ABR. + type: str + choices: [always, candidate, never] + stub: + description: Stub OSPFv2 area. + type: dict + suboptions: + set: + description: Enabling stub. + type: bool + default_cost: + description: Summary-default cost of stub area. + type: int + no_summary: + description: Do not inject inter-area routes into stub. + type: bool + authentication: + description: OSPFv2 area authentication type. + type: str + choices: [plaintext-password, md5] + network: + description: OSPFv2 network. + type: list + elements: dict + suboptions: + address: + required: true + description: OSPFv2 IPv4 network address. + type: str + range: + description: Summarize routes matching prefix (border routers only). + type: list + elements: dict + suboptions: + address: + description: border router IPv4 address. + type: str + cost: + description: Metric for this range. + type: int + not_advertise: + description: Don't advertise this range. + type: bool + substitute: + description: Announce area range (IPv4 address) as another prefix. + type: str + shortcut: + description: Area's shortcut mode. + type: str + choices: [default, disable, enable] + virtual_link: + description: Virtual link address. + type: list + elements: dict + suboptions: + address: + description: virtual link address. + type: str + authentication: + description: OSPFv2 area authentication type. + type: dict + suboptions: + md5: + description: MD5 key id based authentication. + type: list + elements: dict + suboptions: + key_id: + description: MD5 key id. + type: int + md5_key: + description: MD5 key. + type: str + plaintext_password: + description: Plain text password. + type: str + dead_interval: + description: Interval after which a neighbor is declared dead. + type: int + hello_interval: + description: Interval between hello packets. + type: int + retransmit_interval: + description: Interval between retransmitting lost link state advertisements. + type: int + transmit_delay: + description: Link state transmit delay. + type: int + log_adjacency_changes: + description: Log changes in adjacency state. + type: str + choices: [detail] + max_metric: + description: OSPFv2 maximum/infinite-distance metric. + type: dict + suboptions: + router_lsa: + description: Advertise own Router-LSA with infinite distance (stub router). + type: dict + suboptions: + administrative: + description: Administratively apply, for an indefinite period. + type: bool + on_shutdown: + description: Time to advertise self as stub-router. + type: int + on_startup: + description: Time to advertise self as stub-router + type: int + auto_cost: + description: Calculate OSPFv2 interface cost according to bandwidth. + type: dict + suboptions: + reference_bandwidth: + description: Reference bandwidth cost in Mbits/sec. + type: int + default_information: + description: Control distribution of default information. + type: dict + suboptions: + originate: + description: Distribute a default route. + type: dict + suboptions: + always: + description: Always advertise default route. + type: bool + metric: + description: OSPFv2 default metric. + type: int + metric_type: + description: OSPFv2 Metric types for default routes. + type: int + route_map: + description: Route map references. + type: str + default_metric: + description: Metric of redistributed routes + type: int + distance: + description: Administrative distance. + type: dict + suboptions: + global: + description: Global OSPFv2 administrative distance. + type: int + ospf: + description: OSPFv2 administrative distance. + type: dict + suboptions: + external: + description: Distance for external routes. + type: int + inter_area: + description: Distance for inter-area routes. + type: int + intra_area: + description: Distance for intra-area routes. + type: int + mpls_te: + description: MultiProtocol Label Switching-Traffic Engineering (MPLS-TE) parameters. + type: dict + suboptions: + enabled: + description: Enable MPLS-TE functionality. + type: bool + router_address: + description: Stable IP address of the advertising router. + type: str + neighbor: + description: Neighbor IP address. + type: list + elements: dict + suboptions: + neighbor_id: + description: Identity (number/IP address) of neighbor. + type: str + poll_interval: + description: Seconds between dead neighbor polling interval. + type: int + priority: + description: Neighbor priority. + type: int + parameters: + description: OSPFv2 specific parameters. + type: dict + suboptions: + abr_type: + description: OSPFv2 ABR Type. + type: str + choices: [cisco, ibm, shortcut, standard] + opaque_lsa: + description: Enable the Opaque-LSA capability (rfc2370). + type: bool + rfc1583_compatibility: + description: Enable rfc1583 criteria for handling AS external routes. + type: bool + router_id: + description: Override the default router identifier. + type: str + passive_interface: + description: Suppress routing updates on an interface. + type: list + elements: str + passive_interface_exclude: + description: Interface to exclude when using passive-interface default. + type: list + elements: str + redistribute: + description: Redistribute information from another routing protocol. + type: list + elements: dict + suboptions: + route_type: + description: Route type to redistribute. + type: str + choices: [bgp, connected, kernel, rip, static] + metric: + description: Metric for redistribution routes. + type: int + metric_type: + description: OSPFv2 Metric types. + type: int + route_map: + description: Route map references. + type: str + route_map: + description: Filter routes installed in local route map. + type: list + elements: str + timers: + description: Adjust routing timers. + type: dict + suboptions: + refresh: + description: Adjust refresh parameters. + type: dict + suboptions: + timers: + description: refresh timer. + type: int + throttle: + description: Throttling adaptive timers. + type: dict + suboptions: + spf: + description: OSPFv2 SPF timers. + type: dict + suboptions: + delay: + description: Delay (msec) from first change received till SPF + calculation. + type: int + initial_holdtime: + description: Initial hold time(msec) between consecutive SPF calculations. + type: int + max_holdtime: + description: maximum hold time (sec). + type: int + ospfv3: + type: dict + description: OSPFv3 configuration + suboptions: + areas: + description: OSPFv3 area. + type: list + elements: dict + suboptions: + area_id: + description: OSPFv3 Area name/identity. + type: str + export_list: + description: Name of export-list. + type: str + import_list: + description: Name of import-list. + type: str + interface: + description: Enable OSPVv3 on an interface for this area. + aliases: ['interfaces'] + type: list + elements: dict + suboptions: + name: + description: Interface name. + type: str + range: + description: Summarize routes matching prefix (border routers only). + type: list + elements: dict + suboptions: + address: + description: border router IPv4 address. + type: str + advertise: + description: Advertise this range. + type: bool + not_advertise: + description: Don't advertise this range. + type: bool + parameters: + description: OSPFv3 specific parameters. + type: dict + suboptions: + router_id: + description: Override the default router identifier. + type: str + redistribute: + description: Redistribute information from another routing protocol. + type: list + elements: dict + suboptions: + route_type: + description: Route type to redistribute. + type: str + choices: + - bgp + - connected + - kernel + - ripng + - static + route_map: + description: Route map references. + type: str + static: + type: list + description: Static routes configuration + elements: dict + suboptions: + address_families: + description: A dictionary specifying the address family to which the static + route(s) belong. + type: list + elements: dict + suboptions: + afi: + description: + - Specifies the type of route. + type: str + choices: + - ipv4 + - ipv6 + required: true + routes: + description: A dictionary that specify the static route configurations. + type: list + elements: dict + suboptions: + dest: + description: + - An IPv4/v6 address in CIDR notation that specifies the destination + network for the static route. + type: str + required: true + blackhole_config: + description: + - Configured to silently discard packets. + type: dict + suboptions: + type: + description: + - This is to configure only blackhole. + type: str + distance: + description: + - Distance for the route. + type: int + next_hops: + description: + - Next hops to the specified destination. + type: list + elements: dict + suboptions: + forward_router_address: + description: + - The IP address of the next hop that can be used to reach the + destination network. + type: str + enabled: + description: + - Disable IPv4/v6 next-hop static route. + type: bool + admin_distance: + description: + - Distance value for the route. + type: int + interface: + description: + - Name of the outgoing interface. + type: str + running_config: + description: + - This option is used only with state I(parsed). + - The value of this option should be the output received from the VYOS device by + executing the command B(show configuration commands | match "set vrf"). + - The states I(replaced) and I(overridden) have identical + behaviour for this module. + - The state I(parsed) reads the configuration from C(show configuration commands | match "set vrf") option and + transforms it into Ansible structured data as per the resource module's argspec + and the value is then returned in the I(parsed) key within the result. + type: str + state: + description: + - The state the configuration should be left in. + type: str + choices: + - deleted + - merged + - overridden + - replaced + - gathered + - rendered + - parsed + default: merged +""" + +EXAMPLES = """ +# # ------------------- +# # 1. Using merged +# # ------------------- + +# # Before state: +# # ------------- +# vyos@vyos:~$ show configuration commands | match 'set vrf' +# set vrf name vrf-blue description 'blue-vrf' +# set vrf name vrf-blue disable +# set vrf name vrf-blue table '100' +# set vrf name vrf-blue vni '1000' +# vyos@vyos:~$ + +# # Task +# # ------------- + # - name: Merge provided configuration with device configuration + # vyos.vyos.vyos_vrf: + # config: + # instances: + # - name: "vrf-green" + # description: "green-vrf" + # table_id: 110 + # vni: 1010 + +# Task output: +# ------------- + # "after": { + # "bind_to_all": false, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": true, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1000 + # }, + # { + # "description": "green-vrf", + # "disable": false, + # "name": "vrf-green", + # "table_id": 110, + # "vni": 1010 + # } + # ] + # }, + # "before": { + # "bind_to_all": false, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": true, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1000 + # } + # ] + # }, + # "changed": true, + # "commands": [ + # "set vrf name vrf-green table 110", + # "set vrf name vrf-green vni 1010", + # "set vrf name vrf-green description green-vrf" + # ] + +# After state: +# # ------------- +# vyos@vyos:~$ show configuration commands | match 'set vrf' +# set vrf name vrf-blue description 'blue-vrf' +# set vrf name vrf-blue disable +# set vrf name vrf-blue table '100' +# set vrf name vrf-blue vni '1000' +# set vrf name vrf-green description 'green-vrf' +# set vrf name vrf-green table '110' +# set vrf name vrf-green vni '1010' +# vyos@vyos:~$ + +# # ------------------- +# # 2. Using replaced +# # ------------------- + +# # Before state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + + +# # Task +# # ------------- + # - name: Merge provided configuration with device configuration + # vyos.vyos.vyos_vrf: + # config: + # bind_to_all: true + # instances: + # - name: "vrf-blue" + # description: "blue-vrf" + # disable: false + # table_id: 100 + # vni: 1002 + # - name: "vrf-red" + # description: "red-vrf" + # disable: false + # table_id: 101 + # vni: 1001 + # address_family: + # - afi: "ipv4" + # disable_forwarding: false + # route_maps: + # - rm_name: "rm1" + # protocol: "ospf" + # - afi: "ipv6" + # nht_no_resolve_via_default: true + # state: replaced + +# # Task output: +# # ------------- + # "after": { + # "bind_to_all": true, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": false, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1002 + # }, + # { + # "address_family": [ + # { + # "afi": "ipv4", + # "disable_forwarding": false, + # "nht_no_resolve_via_default": false, + # "route_maps": [ + # { + # "protocol": "ospf", + # "rm_name": "rm1" + # }, + # { + # "protocol": "rip", + # "rm_name": "rm1" + # } + # ] + # }, + # { + # "afi": "ipv6", + # "disable_forwarding": false, + # "nht_no_resolve_via_default": true + # } + # ], + # "description": "red-vrf", + # "disable": false, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "before": { + # "bind_to_all": true, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": false, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1000 + # }, + # { + # "address_family": [ + # { + # "afi": "ipv4", + # "disable_forwarding": true, + # "nht_no_resolve_via_default": false, + # "route_maps": [ + # { + # "protocol": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "changed": true, + # "commands": [ + # "set vrf name vrf-blue vni 1002", + # "delete vrf name vrf-red disable", + # "set vrf name vrf-red ip protocol ospf route-map rm1", + # "delete vrf name vrf-red ip disable-forwarding", + # "set vrf name vrf-red ipv6 nht no-resolve-via-default" + # ] + +# After state: +# # ------------- + # vyos@vyos:~$ + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1002' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red ip protocol ospf route-map 'rm1' + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red ipv6 nht no-resolve-via-default + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + + +# # ------------------- +# # 3. Using overridden +# # ------------------- + +# # Before state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# Task +# ------------- + # - name: Overridden provided configuration with device configuration + # vyos.vyos.vyos_vrf: + # config: + # bind_to_all: true + # instances: + # - name: "vrf-blue" + # description: "blue-vrf" + # disable: true + # table_id: 100 + # vni: 1000 + # - name: "vrf-red" + # description: "red-vrf" + # disable: true + # table_id: 101 + # vni: 1001 + # address_family: + # - afi: "ipv4" + # disable_forwarding: false + # route_maps: + # - rm_name: "rm1" + # protocol: "rip" + # - afi: "ipv6" + # nht_no_resolve_via_default: false + # state: overridden + +# # Task output: +# # ------------- + # "after": { + # "bind_to_all": true, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": true, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1000 + # }, + # { + # "address_family": [ + # { + # "afi": "ipv4", + # "disable_forwarding": false, + # "nht_no_resolve_via_default": false, + # "route_maps": [ + # { + # "protocol": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "before": { + # "bind_to_all": true, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": false, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1000 + # }, + # { + # "address_family": [ + # { + # "afi": "ipv4", + # "disable_forwarding": true, + # "nht_no_resolve_via_default": false, + # "route_maps": [ + # { + # "protocol": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "changed": true, + # "commands": [ + # "delete vrf name vrf-blue", + # "commit", + # "delete vrf name vrf-red", + # "commit", + # "set vrf name vrf-blue table 100", + # "set vrf name vrf-blue vni 1000", + # "set vrf name vrf-blue description blue-vrf", + # "set vrf name vrf-blue disable", + # "set vrf name vrf-red table 101", + # "set vrf name vrf-red vni 1001", + # "set vrf name vrf-red description red-vrf", + # "set vrf name vrf-red disable", + # "set vrf name vrf-red ip protocol rip route-map rm1" + # ] + +# After state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue disable + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# 4. Using gathered +# ------------------- + +# # Before state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# Task +# ------------- +# - name: Gather provided configuration with device configuration +# vyos.vyos.vyos_vrf: +# config: +# state: gathered + +# # Task output: +# # ------------- + # "gathered": { + # "bind_to_all": true, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": false, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1000 + # }, + # { + # "address_family": [ + # { + # "afi": "ipv4", + # "disable_forwarding": true, + # "nht_no_resolve_via_default": false, + # "route_maps": [ + # { + # "protocol": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # } + +# After state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + + +# # ------------------- +# # 5. Using deleted +# # ------------------- + +# # Before state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# # Task +# # ------------- +# - name: Replace provided configuration with device configuration +# vyos.vyos.vyos_vrf: +# config: +# bind_to_all: false +# instances: +# - name: "vrf-blue" +# state: deleted + + +# # Task output: +# # ------------- + # "after": { + # "bind_to_all": false, + # "instances": [ + # { + # "address_family": [ + # { + # "afi": "ipv4", + # "disable_forwarding": true, + # "nht_no_resolve_via_default": false, + # "route_maps": [ + # { + # "protocol": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "before": { + # "bind_to_all": true, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": false, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1000 + # }, + # { + # "address_family": [ + # { + # "afi": "ipv4", + # "disable_forwarding": true, + # "nht_no_resolve_via_default": false, + # "route_maps": [ + # { + # "protocol": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "changed": true, + # "commands": [ + # "delete vrf bind-to-all", + # "delete vrf name vrf-blue" + # ] + +# After state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# # ------------------- +# # 6. Using rendered +# # ------------------- + +# # Before state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# Task +# ------------- + # - name: Render provided configuration with device configuration + # vyos.vyos.vyos_vrf: + # config: + # bind_to_all: true + # instances: + # - name: "vrf-green" + # description: "green-vrf" + # disabled: true + # table_id: 105 + # vni: 1000 + # - name: "vrf-amber" + # description: "amber-vrf" + # disable: false + # table_id: 111 + # vni: 1001 + # address_family: + # - afi: "ipv4" + # disable_forwarding: true + # route_maps: + # - rm_name: "rm1" + # protocol: "ospf" + # - afi: "ipv6" + # nht_no_resolve_via_default: false + # state: rendered + +# # Task output: +# # ------------- + # "rendered": [ + # "set vrf bind-to-all", + # "set vrf name vrf-green table 105", + # "set vrf name vrf-green vni 1000", + # "set vrf name vrf-green description green-vrf", + # "set vrf name vrf-green disable", + # "set vrf name vrf-amber table 111", + # "set vrf name vrf-amber vni 1001", + # "set vrf name vrf-amber description amber-vrf", + # "set vrf name vrf-amber ip protocol ospf route-map rm1", + # "set vrf name vrf-amber ip disable-forwarding" + # ] + +# # ------------------- +# # 7. Using parsed +# # ------------------- + +# # vrf_parsed.cfg: +# # ------------- +# set vrf bind-to-all +# set vrf name vrf1 description 'red' +# set vrf name vrf1 disable +# set vrf name vrf1 table 101 +# set vrf name vrf1 vni 501 +# set vrf name vrf2 description 'blah2' +# set vrf name vrf2 disable +# set vrf name vrf2 table 102 +# set vrf name vrf2 vni 102 +# set vrf name vrf1 ip disable-forwarding +# set vrf name vrf1 ip nht no-resolve-via-default +# set vrf name vrf-red ip protocol ospf route-map 'rm1' +# set vrf name vrf-red ipv6 nht no-resolve-via-default + +# Task: +# ------------- +# - name: Parse provided configuration with device configuration +# vyos.vyos.vyos_vrf: +# running_config: "{{ lookup('file', './vrf_parsed.cfg') }}" +# state: parsed + + +# # Task output: +# # ------------- +# "parsed": { +# "bind_to_all": true, +# "instances": [ +# { +# "address_family": [ +# { +# "afi": "ipv4", +# "disable_forwarding": true, +# "nht_no_resolve_via_default": true +# } +# ], +# "description": "red", +# "disable": true, +# "name": "vrf1" +# }, +# { +# "description": "blah2", +# "disable": true, +# "name": "vrf2" +# }, +# { +# "address_family": [ +# { +# "afi": "ipv4", +# "disable_forwarding": false, +# "nht_no_resolve_via_default": false, +# "route_maps": [ +# { +# "protocol": "ospf", +# "rm_name": "rm1" +# } +# ] +# }, +# { +# "afi": "ipv6", +# "disable_forwarding": false, +# "nht_no_resolve_via_default": true +# } +# ], +# "disable": false, +# "name": "vrf-red" +# } +# ] +# } +""" + +RETURN = """ +before: + 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: > + This output will always be in the same format as the + module argspec. +after: + description: The resulting configuration after module execution. + returned: when changed + type: dict + sample: > + 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: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) + type: list + sample: + - set system ntp server server1 dynamic + - set system ntp server server1 prefer + - set system ntp server server2 noselect + - set system ntp server server2 preempt + - set system ntp server server_add preempt +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 system ntp server server1 dynamic + - set system ntp server server1 prefer + - set system ntp server server2 noselect + - set system ntp server server2 preempt + - set system ntp server server_add preempt +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.vrf.vrf import VrfArgs +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.vrf.vrf import Vrf + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + module = AnsibleModule( + argument_spec=VrfArgs.argument_spec, + mutually_exclusive=[["config", "running_config"]], + required_if=[ + ["state", "merged", ["config"]], + ["state", "replaced", ["config"]], + ["state", "overridden", ["config"]], + ["state", "rendered", ["config"]], + ["state", "parsed", ["running_config"]], + ], + supports_check_mode=True, + ) + + result = Vrf(module).execute_module() + module.exit_json(**result) + + +if __name__ == "__main__": + main() |
