diff --git a/tests/junipernetworks.junos/README.md b/tests/junipernetworks.junos/README.md
new file mode 100644
index 00000000..bdc6e87a
--- /dev/null
+++ b/tests/junipernetworks.junos/README.md
@@ -0,0 +1,97 @@
+Functional Tests for Juniper Ansible Collection (junipernetworks.junos)
+
+This directory contains a complete suite of functional tests for the modules in the junipernetworks.junos Ansible collection.
+
+These playbooks verify behavior for each supported module using real Junos devices or virtual environments, following official module documentation examples. This ensures compatibility, schema adherence, and correctness across configuration states like merged, replaced, overridden, deleted, rendered, gathered, and parsed.
+
+๐ง Directory Structure
+
+All functional test playbooks are located under:
+
+tests/junipernetworks.junos/
+
+Each playbook corresponds to one Ansible module, for example:
+
+pb.juniper_junos_system.yml
+
+pb.juniper_junos_lag_interfaces.yml
+
+pb.juniper_junos_bgp_global.yml
+
+etc.
+
+Any required configuration files (e.g., parsed_configs/*.cfg) are also included.
+
+๐งช Steps to Execute Functional Test Playbooks
+
+1. Clone the Repository
+
+git clone https://github.com/Juniper/ansible-junos-stdlib.git
+cd ansible-junos-stdlib/tests/junipernetworks.junos
+
+2. Ensure ansible.cfg is configured correctly
+
+[defaults]
+hash_behaviour = merge
+inventory = inventory
+host_key_checking = False
+log_path = ./ansible.log
+
+[persistent_connection]
+command_timeout = 300
+
+3. Inventory Setup (inventory)
+
+The inventory file defines three connection types:
+
+a. NETCONF (default)
+
+[netconf_connection_testcases]
+junos_device ansible_host=xx.xx.xx.xx
+
+b. Local connection
+
+[local_connection_testcases]
+localhost ansible_connection=local ansible_network_os=none
+
+c. Network CLI
+
+[network_cli_testcases]
+junos_netconf_device ansible_host=xx.xx.xx.xx ansible_connection=network_cli ansible_network_os=junipernetworks.junos.junos ansible_user=xx ansible_password=xx
+
+Global variables:
+
+[all:vars]
+ansible_python_interpreter=/path/to/venv/bin/python
+ansible_connection=netconf
+ansible_network_os=junipernetworks.junos.junos
+ansible_user=xx
+ansible_password=xx
+
+
+4. Run a Functional Test
+
+ansible-playbook pb.juniper_junos_l3_interfaces.yml
+
+You can use -v or -vvv for verbose output and troubleshooting.
+
+5. Run All Tests Automatically
+
+To run all 38 functional tests in sequence, use the provided script:
+
+./run_all_tests.sh
+
+
+This script will:
+
+Execute every test playbook under junipernetworks.junos/
+
+Log results to ansible.log
+
+Ensure a complete functional regression pass
+
+Make sure the script is executable:
+
+chmod +x run_all_tests.sh
+
+
diff --git a/tests/junipernetworks.junos/ansible.cfg b/tests/junipernetworks.junos/ansible.cfg
new file mode 100644
index 00000000..27b4e8e3
--- /dev/null
+++ b/tests/junipernetworks.junos/ansible.cfg
@@ -0,0 +1,9 @@
+[defaults]
+hash_behaviour=merge
+inventory = inventory
+host_key_checking = False
+log_path = ./ansible.log
+
+
+[persistent_connection]
+command_timeout = 300
diff --git a/tests/junipernetworks.junos/inventory b/tests/junipernetworks.junos/inventory
new file mode 100644
index 00000000..a5fccefd
--- /dev/null
+++ b/tests/junipernetworks.junos/inventory
@@ -0,0 +1,15 @@
+[netconf_connection_testcases]
+junos_device ansible_host=xx.xx.xx.xx
+
+[local_connection_testcases]
+localhost ansible_connection=local ansible_network_os=none
+
+[network_cli_testcases]
+junos_netconf_device ansible_host=xx.xx.xx.xx ansible_connection=network_cli ansible_network_os=junipernetworks.junos.junos ansible_user=xx ansible_password=xx
+
+[all:vars]
+ansible_python_interpreter=/path/to/venv/bin/python
+ansible_connection=netconf
+ansible_network_os=junipernetworks.junos.junos
+ansible_user=xx
+ansible_password=xx
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_bgp_address_family.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_bgp_address_family.cfg
new file mode 100644
index 00000000..027160f5
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_bgp_address_family.cfg
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+ 20
+
+ 98
+
+ 2001
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+
+
+ 9.9.9.9
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 20
+
+ 99
+
+
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+ 20
+
+ 99
+
+ 2000
+
+
+
+
+
+
+ 23000
+ 32000
+
+
+ 20
+ 32000
+
+
+
+ 2
+
+
+ from-fib
+
+
+
+
+
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_bgp_global.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_bgp_global.cfg
new file mode 100644
index 00000000..7a8f93f4
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_bgp_global.cfg
@@ -0,0 +1,16 @@
+
+
+
+
+ external-peers
+ external
+ 192.0.2.1
+
+ bgp-keychain
+
+ 65100
+
+ 65000
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_junos_vlans.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_junos_vlans.cfg
new file mode 100644
index 00000000..d4d690cb
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_junos_vlans.cfg
@@ -0,0 +1,16 @@
+
+
+
+
+
+ vlan1
+ 1
+
+
+ vlan2
+ 2
+ irb.12
+
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_logging_global.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_logging_global.cfg
new file mode 100644
index 00000000..04a189d4
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_logging_global.cfg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+ messages
+
+ any
+
+
+
+ authorization
+
+
+
+
+ interactive-commands
+
+ interactive-commands
+
+
+
+
+ *
+
+ any
+
+
+
+
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_ntp_global.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_ntp_global.cfg
new file mode 100644
index 00000000..4bca659d
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_ntp_global.cfg
@@ -0,0 +1,60 @@
+
+
+
+ 78.46.194.186
+
+ 172.16.255.255
+ 50
+ 200
+ 3
+ rt1
+
+
+ 192.16.255.255
+ 50
+ 200
+ 3
+ rt2
+
+
+ 2
+ 224.0.0.1
+
+ 78.44.194.186
+
+
+ 172.44.194.186
+ 10000
+
+ 3
+
+
+ 48.46.194.186
+ 34
+
+ 2
+ rt1
+
+
+ 48.45.194.186
+ 34
+
+ 2
+
+
+ 172.45.194.186
+ rt1
+
+
+ 171.45.194.186
+ rt2
+
+
+ 300
+ accept
+
+ 3000
+ 2000
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_ospf_interfaces.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_ospf_interfaces.cfg
new file mode 100644
index 00000000..847c78dc
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_ospf_interfaces.cfg
@@ -0,0 +1,18 @@
+
+
+
+
+ 0.0.0.0
+
+ ge-0/0/0.0
+ 5
+ 10
+
+
+ ge-0/0/1.0
+
+
+
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_ospfv2.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_ospfv2.cfg
new file mode 100644
index 00000000..5dff43df
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_ospfv2.cfg
@@ -0,0 +1,53 @@
+
+
+
+
+
+ 10g
+
+
+ 0.0.0.100
+
+ 100
+
+
+ 10.200.16.0/24
+
+ 10000
+
+
+ 10.200.11.0/24
+
+
+
+
+ so-0/0/0.0
+
+
+
+ 1g
+ 5
+
+
+ 10g
+ 40
+
+
+ 5
+ 3
+ 2
+ 2
+ 4
+ 2
+
+
+
+
+
+ 10.200.16.75
+
+ 65432
+
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_ospfv3.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_ospfv3.cfg
new file mode 100644
index 00000000..55292b7d
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_ospfv3.cfg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+ 0.0.0.100
+
+ 200
+
+
+ so-0/0/0.0
+
+ 5
+ 3
+
+
+
+
+ 0.0.0.200
+
+ ge-1/1/0.0
+
+
+ ge-2/2/0.0
+
+
+
+
+
+ 10.200.16.75
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_routing_instances.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_routing_instances.cfg
new file mode 100644
index 00000000..0acea602
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_routing_instances.cfg
@@ -0,0 +1,25 @@
+
+
+
+ test
+ vrf
+ 10.58.255.1:37
+ test-policy
+ test-policy
+ test-policy-1
+ sp-0/0/0.0
+ gr-0/0/0.0
+
+
+
+ forwardinst
+ forwarding
+ Configured by Ansible Content Team
+
+
+ vtest1
+ virtual-router
+ ge-0/0/0.0
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_routing_options.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_routing_options.cfg
new file mode 100644
index 00000000..e3e4d4ad
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_routing_options.cfg
@@ -0,0 +1,9 @@
+
+
+
+
+ 2
+
+ 2.2.2.2
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_security_policies.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_security_policies.cfg
new file mode 100644
index 00000000..50fbe124
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_security_policies.cfg
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ test_glob_1
+
+ any-ipv6
+ any-ipv6
+ any
+
+
+
+
+
+
+ test_glob_2
+
+ any-ipv6
+ any-ipv6
+ any
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_security_policies_global.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_security_policies_global.cfg
new file mode 100644
index 00000000..af26beca
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_security_policies_global.cfg
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+ 10k
+ 3
+
+ /[A-Z]*/gm
+
+
+ all
+
+
+
+
+
+
+
+
+
+ enable
+
+
+
+
+
+
+
+ 10
+ 10
+
+
+
+
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_security_zones.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_security_zones.cfg
new file mode 100644
index 00000000..640e69c2
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_security_zones.cfg
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ trust
+ Trusted zone
+
+ ge-0/0/1.0
+
+
+ ssh
+
+
+ ping
+
+
+
+
+
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_snmp.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_snmp.cfg
new file mode 100644
index 00000000..3ba55e02
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_snmp.cfg
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ cl1
+ 192.16.1.0/24
+ 192.16.2.0/24
+ 11.11.11.11/32
+
+
+ cl2
+ 192.16.4.0/24
+
+
+ clv1
+ clv2
+
+
+
+
+
+
diff --git a/tests/junipernetworks.junos/parsed_configs/parsed_static_routes.cfg b/tests/junipernetworks.junos/parsed_configs/parsed_static_routes.cfg
new file mode 100644
index 00000000..9b0f576e
--- /dev/null
+++ b/tests/junipernetworks.junos/parsed_configs/parsed_static_routes.cfg
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ 192.168.16.0/24
+ 172.16.1.2
+ 172.16.1.3
+
+
+ 192.168.47.0/24
+ 10.200.16.2
+
+
+
+
+
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_acl_interfaces.yml b/tests/junipernetworks.junos/pb.juniper_junos_acl_interfaces.yml
new file mode 100644
index 00000000..f051f1aa
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_acl_interfaces.yml
@@ -0,0 +1,126 @@
+
+- name: Functional Test - junos_acl_interfaces module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ vars:
+ interface_name: "ge-1/0/0"
+ inbound_acl_name: "inbound_acl"
+ outbound_acl_name: "outbound_acl"
+
+ tasks:
+
+ - name: Setup - Ensure initial ACL config is absent (clean slate)
+ junos_acl_interfaces:
+ config:
+ - name: "{{ interface_name }}"
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: "{{ inbound_acl_name }}"
+ direction: in
+ - name: "{{ outbound_acl_name }}"
+ direction: out
+ state: deleted
+ register: cleanup_result
+
+ - name: Assert cleanup before test
+ assert:
+ that:
+ - cleanup_result.changed in [true, false]
+
+ - name: Pre-config - Create inbound and outbound ACL filters
+ junipernetworks.junos.junos_config:
+ lines:
+ - set firewall family inet filter {{ inbound_acl_name }} term 1 from source-address 10.0.0.0/8
+ - set firewall family inet filter {{ inbound_acl_name }} term 1 then accept
+ - set firewall family inet filter {{ outbound_acl_name }} term 1 from destination-address 192.168.0.0/16
+ - set firewall family inet filter {{ outbound_acl_name }} term 1 then accept
+ comment: "Test ACL filters for junos_acl_interfaces FT"
+
+
+ - name: Test - Merge ACL config into interface
+ junos_acl_interfaces:
+ config:
+ - name: "{{ interface_name }}"
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: "{{ inbound_acl_name }}"
+ direction: in
+ - name: "{{ outbound_acl_name }}"
+ direction: out
+ state: merged
+ register: merge_result
+
+ - name: Assert merge operation
+ assert:
+ that:
+ - merge_result.changed == true
+ - merge_result.after is defined
+ - merge_result.commands | length > 0
+
+
+ - name: Test - Replace ACL config with only input filter
+ junos_acl_interfaces:
+ config:
+ - name: "{{ interface_name }}"
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: "{{ inbound_acl_name }}"
+ direction: in
+ state: overridden
+ register: replace_result
+
+ - name: Assert override operation
+ assert:
+ that:
+ - replace_result.changed == true
+ - outbound_acl_name not in (replace_result.after | to_json)
+
+
+ - name: Test - Override ACL config with both directions
+ junos_acl_interfaces:
+ config:
+ - name: "{{ interface_name }}"
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: "{{ inbound_acl_name }}"
+ direction: in
+ - name: "{{ outbound_acl_name }}"
+ direction: out
+ state: overridden
+ register: override_result
+
+ - name: Assert override operation
+ assert:
+ that:
+ - override_result.changed == true
+
+
+ - name: Test - Delete ACL config
+ junos_acl_interfaces:
+ config:
+ - name: "{{ interface_name }}"
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: "{{ inbound_acl_name }}"
+ direction: in
+ - name: "{{ outbound_acl_name }}"
+ direction: out
+ state: deleted
+ register: delete_result
+
+ - name: Assert delete operation
+ assert:
+ that:
+ - delete_result.changed == true
+ - delete_result.after is defined
+
+
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_acls.yml b/tests/junipernetworks.junos/pb.juniper_junos_acls.yml
new file mode 100644
index 00000000..0ee9e576
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_acls.yml
@@ -0,0 +1,64 @@
+- name: Functional Test - junos_acls module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ vars:
+ acl_name: "allow_ssh_acl"
+ term_name: "ssh_rule"
+
+ tasks:
+
+ - name: Pre-clean - Delete test ACL if it exists
+ junos_acls:
+ config:
+ - afi: ipv4
+ acls:
+ - name: "{{ acl_name }}"
+ state: deleted
+ register: pre_cleanup
+
+ - name: Assert pre-clean success
+ assert:
+ that:
+ - pre_cleanup.changed in [true, false]
+
+
+ - name: Apply ACL with state merged
+ junos_acls:
+ config:
+ - afi: ipv4
+ acls:
+ - name: "{{ acl_name }}"
+ aces:
+ - name: "{{ term_name }}"
+ source:
+ port_protocol:
+ eq: ssh
+ protocol: tcp
+ state: merged
+ register: merge_result
+
+ - name: Assert merged config applied
+ assert:
+ that:
+ - merge_result.changed == true
+ - merge_result.after is defined
+ - merge_result.commands | length > 0
+
+
+ - name: Post-clean - Remove ACL
+ junos_acls:
+ config:
+ - afi: ipv4
+ acls:
+ - name: "{{ acl_name }}"
+ state: deleted
+ register: post_cleanup
+
+ - name: Assert ACL was cleaned up
+ assert:
+ that:
+ - post_cleanup.changed == true
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_banner.yml b/tests/junipernetworks.junos/pb.juniper_junos_banner.yml
new file mode 100644
index 00000000..7799536b
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_banner.yml
@@ -0,0 +1,74 @@
+- name: Functional Test - junos_banner module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ vars:
+ login_banner_text: |
+ this is my login banner
+ used for testing purposes
+
+ tasks:
+ - name: Pre-clean - Remove login banner if exists
+ junipernetworks.junos.junos_banner:
+ banner: login
+ state: absent
+ register: preclean_result
+
+ - name: Assert pre-clean successful
+ assert:
+ that:
+ - preclean_result.changed in [true, false]
+
+ - name: Apply login banner with state present
+ junipernetworks.junos.junos_banner:
+ banner: login
+ text: "{{ login_banner_text }}"
+ state: present
+ register: present_result
+
+ - name: Assert login banner applied
+ assert:
+ that:
+ - present_result.changed == true
+
+ - name: Deactivate the login banner
+ junipernetworks.junos.junos_banner:
+ banner: login
+ text: "{{ login_banner_text }}"
+ state: present
+ active: false
+ register: deactivate_result
+
+ - name: Assert login banner deactivated
+ assert:
+ that:
+ - deactivate_result.changed == true
+
+ - name: Reactivate the login banner
+ junipernetworks.junos.junos_banner:
+ banner: login
+ state: present
+ active: true
+ text: |
+ this is my login banner
+ used for testing purpose
+ register: reactivate_result
+
+ - name: Assert login banner reactivated
+ assert:
+ that:
+ - reactivate_result.changed == true
+
+ - name: Post-clean - Remove login banner
+ junipernetworks.junos.junos_banner:
+ banner: login
+ state: absent
+ register: postclean_result
+
+ - name: Assert login banner removed
+ assert:
+ that:
+ - postclean_result.changed == true
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_bgp_address_family.yml b/tests/junipernetworks.junos/pb.juniper_junos_bgp_address_family.yml
new file mode 100644
index 00000000..b7eb1b9c
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_bgp_address_family.yml
@@ -0,0 +1,151 @@
+- name: Functional Test - junos_bgp_address_family
+ hosts: junos_device
+ gather_facts: no
+ connection: ansible.netcommon.netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+ - name: MERGED - Full BGP address family config
+ junipernetworks.junos.junos_bgp_address_family:
+ config:
+ address_family:
+ - afi: 'evpn'
+ af_type:
+ - type: 'signaling'
+ accepted_prefix_limit:
+ maximum: 20
+ limit_threshold: 98
+ idle_timeout_value: 2001
+ damping: true
+ defer_initial_multipath_build:
+ maximum_delay: 2
+ - afi: 'inet'
+ af_type:
+ - type: 'flow'
+ legacy_redirect_ip_action:
+ send: true
+ receive: true
+ loops: 4
+ no_install: true
+ output_queue_priority_expedited: true
+ secondary_independent_resolution: true
+
+ - type: 'unicast'
+ extended_nexthop: true
+ extended_nexthop_color: true
+ local_ipv4_address: '9.9.9.9'
+
+ - type: 'labeled-unicast'
+ entropy_label:
+ no_next_hop_validation: true
+ explicit_null:
+ connected_only: true
+ per_prefix_label: true
+ per_group_label: true
+ prefix_limit:
+ maximum: 20
+ limit_threshold: 99
+ forever: true
+ resolve_vpn: true
+ rib: 'inet.3'
+ route_refresh_priority_expedited: true
+ route_refresh_priority_priority: 3
+
+ - type: 'any'
+ accepted_prefix_limit:
+ maximum: 20
+ limit_threshold: 99
+ idle_timeout_value: 2000
+ damping: true
+ defer_initial_multipath_build:
+ maximum_delay: 2
+ delay_route_advertisements:
+ max_delay_route_age: 20
+ max_delay_routing_uptime: 32000
+ min_delay_inbound_convergence: 32000
+ min_delay_routing_uptime: 23000
+ graceful_restart_forwarding_state_bit: 'from-fib'
+ state: merged
+
+ - name: REPLACED - Replace BGP config with simplified evpn
+ junipernetworks.junos.junos_bgp_address_family:
+ config:
+ address_family:
+ - afi: 'evpn'
+ af_type:
+ - type: 'signaling'
+ accepted_prefix_limit:
+ maximum: 21
+ limit_threshold: 99
+ idle_timeout_value: 2002
+ delay_route_advertisements:
+ max_delay_route_age: 20
+ max_delay_routing_uptime: 32000
+ min_delay_inbound_convergence: 32000
+ min_delay_routing_uptime: 23000
+ damping: true
+ state: replaced
+
+ - name: OVERRIDDEN - Override with same evpn config
+ junipernetworks.junos.junos_bgp_address_family:
+ config:
+ address_family:
+ - afi: 'evpn'
+ af_type:
+ - type: 'signaling'
+ accepted_prefix_limit:
+ maximum: 21
+ limit_threshold: 99
+ idle_timeout_value: 2002
+ delay_route_advertisements:
+ max_delay_route_age: 20
+ max_delay_routing_uptime: 32000
+ min_delay_inbound_convergence: 32000
+ min_delay_routing_uptime: 23000
+ damping: true
+ state: overridden
+
+ - name: DELETED - Delete AFI inet only
+ junipernetworks.junos.junos_bgp_address_family:
+ config:
+ address_family:
+ - afi: 'inet'
+ state: deleted
+
+ - name: DELETED - Delete all address-family configuration
+ junipernetworks.junos.junos_bgp_address_family:
+ config: {}
+ state: deleted
+
+ - name: GATHERED - Gather current BGP AF config
+ junipernetworks.junos.junos_bgp_address_family:
+ config: {}
+ state: gathered
+ register: gathered_output
+
+ - name: Assert BGP config gathered
+ assert:
+ that:
+ - gathered_output.gathered is defined
+
+ - name: RENDERED - Render BGP config
+ junipernetworks.junos.junos_bgp_address_family:
+ config:
+ address_family:
+ - afi: 'evpn'
+ af_type:
+ - type: 'signaling'
+ accepted_prefix_limit:
+ maximum: 20
+ limit_threshold: 98
+ idle_timeout_value: 2001
+ damping: true
+ defer_initial_multipath_build:
+ maximum_delay: 2
+ state: rendered
+
+ - name: PARSED - Parse provided BGP config
+ junipernetworks.junos.junos_bgp_address_family:
+ running_config: "{{ lookup('file', './parsed_configs/parsed_bgp_address_family.cfg') }}"
+ state: parsed
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_bgp_global.yml b/tests/junipernetworks.junos/pb.juniper_junos_bgp_global.yml
new file mode 100644
index 00000000..2aa9a467
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_bgp_global.yml
@@ -0,0 +1,124 @@
+- name: Functional Test - junos_bgp_global
+ hosts: junos_device
+ connection: netconf
+ gather_facts: false
+
+ tasks:
+
+ - name: MERGED - Merge provided bgp config
+ junipernetworks.junos.junos_bgp_global:
+ config:
+ as_number: "65534"
+ loops: 3
+ asdot_notation: true
+ accept_remote_nexthop: true
+ add_path_display_ipv4_address: true
+ advertise_from_main_vpn_tables: true
+ advertise_inactive: true
+ bgp_error_tolerance:
+ malformed_route_limit: 20000000
+ bmp:
+ monitor: true
+ damping: true
+ description: "This is configured with Junos_bgp resource module"
+ egress_te_sid_stats: true
+ hold_time: 5
+ holddown_all_stale_labels: true
+ include_mp_next_hop: true
+ log_updown: true
+ no_advertise_peer_as: true
+ no_aggregator_id: true
+ no_client_reflect: true
+ out_delay: 10
+ precision_timers: true
+ preference: 2
+ state: merged
+
+ - name: REPLACED - Replace bgp config
+ junipernetworks.junos.junos_bgp_global:
+ config:
+ advertise_inactive: true
+ bfd_liveness_detection:
+ minimum_receive_interval: 8
+ multiplier: 30
+ no_adaptation: true
+ transmit_interval:
+ minimum_interval: 4
+ version: "automatic"
+ bgp_error_tolerance:
+ malformed_route_limit: 40000000
+ description: "Replace running bgp config"
+ egress_te_sid_stats: true
+ hold_time: 5
+ out_delay: 10
+ preference: "2"
+ state: replaced
+
+ - name: OVERRIDDEN - Override running config
+ junipernetworks.junos.junos_bgp_global:
+ config:
+ advertise_inactive: true
+ bfd_liveness_detection:
+ minimum_receive_interval: 8
+ multiplier: 30
+ no_adaptation: true
+ transmit_interval:
+ minimum_interval: 4
+ version: "automatic"
+ bgp_error_tolerance:
+ malformed_route_limit: 40000000
+ description: "Replace running bgp config"
+ egress_te_sid_stats: true
+ hold_time: 5
+ out_delay: 10
+ preference: "2"
+ state: overridden
+
+ - name: GATHERED - Gather bgp global facts
+ junipernetworks.junos.junos_bgp_global:
+ config:
+ state: gathered
+
+ - name: RENDERED - Render configuration into XML
+ junipernetworks.junos.junos_bgp_global:
+ config:
+ as_number: "65534"
+ loops: 3
+ asdot_notation: true
+ accept_remote_nexthop: true
+ add_path_display_ipv4_address: true
+ advertise_from_main_vpn_tables: true
+ advertise_inactive: true
+ bgp_error_tolerance:
+ malformed_route_limit: 20000000
+ bmp:
+ monitor: true
+ damping: true
+ description: "This is configured with Junos_bgp resource module"
+ egress_te_sid_stats: true
+ hold_time: 5
+ holddown_all_stale_labels: true
+ include_mp_next_hop: true
+ log_updown: true
+ no_advertise_peer_as: true
+ no_aggregator_id: true
+ no_client_reflect: true
+ out_delay: 10
+ precision_timers: true
+ preference: 2
+ state: rendered
+
+ - name: PARSED - Parse the device config into facts
+ junipernetworks.junos.junos_bgp_global:
+ running_config: "{{ lookup('file', './parsed_configs/parsed_bgp_global.cfg') }}"
+ state: parsed
+
+ - name: DELETED - Delete the bgp config
+ junipernetworks.junos.junos_bgp_global:
+ config:
+ state: deleted
+
+ - name: PURGED - Purge the bgp config
+ junipernetworks.junos.junos_bgp_global:
+ config:
+ state: purged
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_command.yml b/tests/junipernetworks.junos/pb.juniper_junos_command.yml
new file mode 100644
index 00000000..14e7271c
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_command.yml
@@ -0,0 +1,68 @@
+
+
+- name: Functional Test - junos_command module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+ - name: Run show version
+ junipernetworks.junos.junos_command:
+ commands: show version
+ register: version_output
+
+ - name: Assert show version output is returned
+ assert:
+ that:
+ - version_output.stdout is defined
+ - "'Junos' in version_output.stdout[0]"
+
+ - name: Run show version with wait_for condition (positive match)
+ junipernetworks.junos.junos_command:
+ commands: show version
+ wait_for:
+ - result[0] contains Hostname
+ register: show_version_wait_positive
+
+ - name: Assert wait_for with positive match passed
+ assert:
+ that:
+ - show_version_wait_positive.stdout is defined
+ - show_version_wait_positive.failed_conditions is not defined
+
+ - name: Run multiple commands
+ junipernetworks.junos.junos_command:
+ commands:
+ - show version
+ - show interfaces terse
+ register: multi_output
+
+ - name: Assert multiple commands worked
+ assert:
+ that:
+ - multi_output.stdout | length == 2
+ - "'Interface' in multi_output.stdout[1]"
+
+ - name: Run show version with json output
+ junipernetworks.junos.junos_command:
+ commands: show version
+ display: json
+ register: json_output
+
+ - name: Assert json output is returned
+ assert:
+ that:
+ - json_output.stdout is defined
+
+ - name: Run RPC get-software-information
+ junipernetworks.junos.junos_command:
+ rpcs: get-software-information
+ register: rpc_output
+
+ - name: Assert RPC output
+ assert:
+ that:
+ - rpc_output.stdout is defined
+ - rpc_output.stdout[0] is string
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_config.yml b/tests/junipernetworks.junos/pb.juniper_junos_config.yml
new file mode 100644
index 00000000..43a61133
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_config.yml
@@ -0,0 +1,67 @@
+- name: Functional Test - junos_config module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Pre-clean - Remove existing test interface description
+ junos_config:
+ lines:
+ - delete interfaces ge-0/0/1 unit 0 description
+ comment: "Clean up test interface config"
+ register: preclean_result
+
+ - name: Assert pre-clean successful
+ assert:
+ that:
+ - preclean_result.changed in [true, false]
+
+ - name: Apply test config - set interface description
+ junipernetworks.junos.junos_config:
+ lines:
+ - set interfaces ge-0/0/1 unit 0 description "FT Test interface"
+ comment: "Apply test config"
+ register: apply_result
+
+ - name: Assert interface config applied
+ assert:
+ that:
+ - apply_result.changed == true
+
+ - name: Confirm commit test with timer
+ junos_config:
+ lines:
+ - set system host-name ft-test-host
+ confirm: 3
+ comment: "Test commit confirmation"
+ # Intentionally allowing commit to rollback to test confirm
+
+ - name: Rollback config to rollback 0
+ junos_config:
+ rollback: 0
+
+ - name: Backup config to custom path
+ junos_config:
+ lines:
+ - set system services ssh
+ backup: true
+ backup_options:
+ filename: ssh_backup.cfg
+ dir_path: ./backup
+ register: backup_result
+
+ - name: Assert backup created
+ assert:
+ that:
+ - backup_result.backup_path is defined
+
+ - name: Post-clean - delete test configuration
+ junos_config:
+ lines:
+ - delete interfaces ge-0/0/1 unit 0 description
+ - delete system host-name
+ - delete system services ssh
+ comment: "Post-clean"
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_facts.yml b/tests/junipernetworks.junos/pb.juniper_junos_facts.yml
new file mode 100644
index 00000000..a40a534a
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_facts.yml
@@ -0,0 +1,44 @@
+- name: Functional Test - junos_facts module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+ - name: Collect default set of facts (min)
+ junipernetworks.junos.junos_facts:
+ register: default_facts
+
+ - name: Assert default facts gathered
+ assert:
+ that:
+ - default_facts.ansible_facts is defined
+ - default_facts.ansible_facts.ansible_net_model is defined
+ - default_facts.ansible_facts.ansible_net_hostname is defined
+
+ - name: Collect full facts including config and interfaces
+ junipernetworks.junos.junos_facts:
+ gather_subset:
+ - all
+ register: full_facts
+
+ - name: Assert full facts gathered
+ assert:
+ that:
+ - full_facts.ansible_facts.ansible_net_interfaces is defined
+ - full_facts.ansible_facts.ansible_net_config is defined
+
+ - name: Collect hardware and config with text format
+ junipernetworks.junos.junos_facts:
+ gather_subset:
+ - hardware
+ - config
+ config_format: text
+ register: hw_config_facts
+
+ - name: Assert hardware and config facts gathered
+ assert:
+ that:
+ - hw_config_facts.ansible_facts.ansible_net_config is defined
+ - "'system' in hw_config_facts.ansible_facts.ansible_net_config"
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_hostname.yml b/tests/junipernetworks.junos/pb.juniper_junos_hostname.yml
new file mode 100644
index 00000000..afe3c26f
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_hostname.yml
@@ -0,0 +1,57 @@
+- name: Functional Test - junos_hostname module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ vars:
+ test_hostname: "ft-host-20250424084647"
+
+ tasks:
+
+ - name: Pre-clean - Delete existing hostname
+ junipernetworks.junos.junos_hostname:
+ config: {}
+ state: deleted
+ register: delete_result
+
+ - name: Assert pre-clean success
+ assert:
+ that:
+ - delete_result.changed == true or delete_result.changed == false
+
+ - name: Apply hostname config with state merged
+ junipernetworks.junos.junos_hostname:
+ config:
+ hostname: "{{ test_hostname }}"
+ state: merged
+ register: merged_result
+
+ - name: Assert hostname was set
+ assert:
+ that:
+ - merged_result.changed == true
+ - merged_result.after.hostname == test_hostname
+
+ - name: Gather hostname config
+ junipernetworks.junos.junos_hostname:
+ state: gathered
+ register: gather_result
+
+ - name: Assert gathered hostname is correct
+ assert:
+ that:
+ - gather_result.changed == false
+ - gather_result.gathered.hostname == test_hostname
+
+ - name: Delete test hostname (post-clean)
+ junipernetworks.junos.junos_hostname:
+ config: {}
+ state: deleted
+ register: cleanup_result
+
+ - name: Assert hostname deleted
+ assert:
+ that:
+ - cleanup_result.changed == true
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_interfaces.yml b/tests/junipernetworks.junos/pb.juniper_junos_interfaces.yml
new file mode 100644
index 00000000..8aa9b620
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_interfaces.yml
@@ -0,0 +1,64 @@
+- name: Functional Test - junos_interfaces module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+ - name: Pre-clean - Delete test configuration if present
+ junipernetworks.junos.junos_interfaces:
+ config:
+ - name: ge-0/0/1
+ units:
+ - name: 0
+ state: deleted
+ ignore_errors: true
+
+ - name: Apply test config with state merged
+ junipernetworks.junos.junos_interfaces:
+ config:
+ - name: ge-0/0/1
+ description: "FT updated interface"
+ enabled: true
+ mtu: 1800
+ units:
+ - name: 0
+ description: "FT logical unit"
+ state: merged
+ register: merge_result
+
+ - name: Gather current interface config
+ junipernetworks.junos.junos_interfaces:
+ state: gathered
+ register: gathered_result
+
+ - name: Assert merged interface config applied
+ assert:
+ that:
+ - merge_result.changed is defined
+ - gathered_result.gathered is defined
+ - gathered_result.gathered | selectattr("name", "equalto", "ge-0/0/1") | list | length > 0
+
+ - name: Render config offline (no connection to device)
+ junipernetworks.junos.junos_interfaces:
+ config:
+ - name: ge-0/0/1
+ description: Render test
+ state: rendered
+ register: render_result
+
+ - name: Assert rendered config returned
+ assert:
+ that:
+ - render_result.rendered is defined
+ - render_result.rendered | length > 0
+
+ - name: Post-clean - Delete test configuration
+ junipernetworks.junos.junos_interfaces:
+ config:
+ - name: ge-0/0/1
+ units:
+ - name: 0
+ state: deleted
+ ignore_errors: true
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_l2_interfaces.yml b/tests/junipernetworks.junos/pb.juniper_junos_l2_interfaces.yml
new file mode 100644
index 00000000..78d9c90c
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_l2_interfaces.yml
@@ -0,0 +1,86 @@
+# Note: This functional test requires switching to be enabled on interfaces.
+
+- name: Functional Test - junos_l2_interfaces module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+ - name: Pre-define required VLANs
+ junipernetworks.junos.junos_vlans:
+ config:
+ - name: v101
+ vlan_id: 101
+ - name: vlan30
+ vlan_id: 30
+ - name: vlan50
+ vlan_id: 50
+ state: merged
+
+ - name: Pre-clean - Delete existing L2 config
+ junipernetworks.junos.junos_l2_interfaces:
+ config:
+ - name: ge-0/0/3
+ - name: ge-0/0/4
+ state: deleted
+ ignore_errors: true
+
+ - name: Apply L2 config - merge access and trunk modes
+ junipernetworks.junos.junos_l2_interfaces:
+ config:
+ - name: ge-0/0/3
+ access:
+ vlan: v101
+ - name: ge-0/0/4
+ trunk:
+ allowed_vlans: [ vlan30 ]
+ native_vlan: "50"
+ state: merged
+ register: merge_result
+
+ - name: Assert L2 config merged
+ assert:
+ that:
+ - merge_result is defined
+ - merge_result.changed is defined
+ - merge_result.changed | bool == true
+
+ - name: Gather current L2 interface config
+ junipernetworks.junos.junos_l2_interfaces:
+ state: gathered
+ register: gathered_result
+
+ - name: Assert L2 config gathered
+ assert:
+ that:
+ - gathered_result.gathered | selectattr("name", "equalto", "ge-0/0/3") | list | length > 0
+ - gathered_result.gathered | selectattr("name", "equalto", "ge-0/0/4") | list | length > 0
+
+ - name: Render L2 config offline
+ junipernetworks.junos.junos_l2_interfaces:
+ config:
+ - name: ge-0/0/3
+ access:
+ vlan: v101
+ - name: ge-0/0/4
+ trunk:
+ allowed_vlans: [ vlan30 ]
+ native_vlan: 50
+ state: rendered
+ register: render_result
+
+ - name: Assert rendered L2 config
+ assert:
+ that:
+ - render_result.rendered is defined
+ - render_result.rendered | length > 0
+
+ - name: Post-clean - Delete L2 config
+ junipernetworks.junos.junos_l2_interfaces:
+ config:
+ - name: ge-0/0/3
+ - name: ge-0/0/4
+ state: deleted
+ ignore_errors: true
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_l3_interfaces.yml b/tests/junipernetworks.junos/pb.juniper_junos_l3_interfaces.yml
new file mode 100644
index 00000000..f83b6d2e
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_l3_interfaces.yml
@@ -0,0 +1,73 @@
+- name: Functional Test - junos_l3_interfaces module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Pre-clean - Delete L3 logical interfaces if present
+ junos_l3_interfaces:
+ config:
+ - name: ge-0/0/1
+ - name: ge-0/0/2
+ state: deleted
+ ignore_errors: true
+
+ - name: Apply L3 configuration (merge)
+ junos_l3_interfaces:
+ config:
+ - name: ge-0/0/1
+ ipv4:
+ - address: 192.168.1.10/24
+ ipv6:
+ - address: 2001:db8::1/64
+ - name: ge-0/0/2
+ ipv4:
+ - address: dhcp
+ state: merged
+ register: merge_result
+
+ - name: Assert L3 config applied
+ assert:
+ that:
+ - merge_result.changed is defined
+ - merge_result.after | selectattr("name", "equalto", "ge-0/0/1") | list | length > 0
+ - merge_result.after | selectattr("name", "equalto", "ge-0/0/2") | list | length > 0
+
+ - name: Gather L3 interfaces
+ junos_l3_interfaces:
+ state: gathered
+ register: gathered_result
+
+ - name: Assert L3 interfaces gathered
+ assert:
+ that:
+ - gathered_result.gathered | selectattr("name", "equalto", "ge-0/0/1") | list | length > 0
+ - gathered_result.gathered | selectattr("name", "equalto", "ge-0/0/2") | list | length > 0
+
+ - name: Render L3 config (offline)
+ junos_l3_interfaces:
+ config:
+ - name: ge-0/0/1
+ ipv4:
+ - address: 192.168.1.10/24
+ ipv6:
+ - address: 2001:db8::1/64
+ state: rendered
+ register: render_result
+
+ - name: Assert rendered config is present
+ assert:
+ that:
+ - render_result.rendered is defined
+ - render_result.rendered | length > 0
+
+ - name: Post-clean - Delete test L3 configuration
+ junos_l3_interfaces:
+ config:
+ - name: ge-0/0/1
+ - name: ge-0/0/2
+ state: deleted
+ ignore_errors: true
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_lacp.yml b/tests/junipernetworks.junos/pb.juniper_junos_lacp.yml
new file mode 100644
index 00000000..51717b28
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_lacp.yml
@@ -0,0 +1,55 @@
+- name: Functional Test - junos_lacp module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Pre-clean - Delete existing global LACP config
+ junos_lacp:
+ state: deleted
+ ignore_errors: true
+
+ - name: Merge global LACP attributes
+ junos_lacp:
+ config:
+ system_priority: 63
+ # link_protection: revertive
+ state: merged
+ register: merge_result
+
+ - name: Assert LACP config merged
+ assert:
+ that:
+ - merge_result.changed is defined
+
+ - name: Gather global LACP config
+ junos_lacp:
+ state: gathered
+ register: gather_result
+
+ - name: Assert gathered global LACP config
+ assert:
+ that:
+ - gather_result.gathered.system_priority == 63
+
+ - name: Render LACP config (offline)
+ junos_lacp:
+ config:
+ system_priority: 63
+ link_protection: revertive
+ state: rendered
+ register: render_result
+
+ - name: Assert rendered config is returned
+ assert:
+ that:
+ - render_result.rendered is defined
+ - render_result.rendered | length > 0
+
+ - name: Post-clean - Delete global LACP config
+ junos_lacp:
+ state: deleted
+ ignore_errors: true
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_lacp_interfaces.yml b/tests/junipernetworks.junos/pb.juniper_junos_lacp_interfaces.yml
new file mode 100644
index 00000000..126abf23
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_lacp_interfaces.yml
@@ -0,0 +1,71 @@
+---
+- name: Functional Test - junos_lacp_interfaces module
+ hosts: netconf_connection_testcases
+ gather_facts: false
+ connection: netconf
+
+ tasks:
+
+ - name: Pre-clean - Delete LACP attributes on ae0
+ junipernetworks.junos.junos_lacp_interfaces:
+ config:
+ - name: ae0
+ state: deleted
+ ignore_errors: true
+
+ - name: Merge LACP configuration onto ae0
+ junipernetworks.junos.junos_lacp_interfaces:
+ config:
+ - name: ae0
+ period: fast
+ sync_reset: enable
+ system:
+ priority: 100
+ mac:
+ address: 00:00:00:00:00:02
+ state: merged
+
+ - name: Replace LACP configuration on ae0
+ junipernetworks.junos.junos_lacp_interfaces:
+ config:
+ - name: ae0
+ period: slow
+ state: replaced
+
+ - name: Override all LACP configuration on ae0
+ junipernetworks.junos.junos_lacp_interfaces:
+ config:
+ - name: ae0
+ system:
+ priority: 300
+ mac:
+ address: 00:00:00:00:00:03
+ state: overridden
+
+ - name: Gather LACP interfaces
+ junipernetworks.junos.junos_lacp_interfaces:
+ state: gathered
+ register: gather_result
+
+ - name: Extract gathered interface names
+ set_fact:
+ gathered_names: "{{ gather_result.gathered | map(attribute='name') | list }}"
+
+ - name: Assert ae0 is present in gathered result
+ ansible.builtin.assert:
+ that:
+ - "'ae0' in gathered_names"
+ fail_msg: "Expected interface ae0 not found in gathered result"
+ success_msg: "Successfully found ae0 in gathered result"
+
+ - name: Render platform-specific XML from input config
+ junipernetworks.junos.junos_lacp_interfaces:
+ config:
+ - name: ae0
+ period: fast
+ sync_reset: enable
+ system:
+ priority: 100
+ mac:
+ address: 00:00:00:00:00:02
+ state: rendered
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_lag_interfaces.yml b/tests/junipernetworks.junos/pb.juniper_junos_lag_interfaces.yml
new file mode 100644
index 00000000..05ef71cf
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_lag_interfaces.yml
@@ -0,0 +1,45 @@
+- name: Functional Test - junos_lag_interfaces
+ hosts: junos_device
+ connection: ansible.netcommon.netconf
+ gather_facts: false
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: GATHERED - Retrieve existing LAG configuration
+ junipernetworks.junos.junos_lag_interfaces:
+ state: gathered
+ register: result_gathered
+
+ - name: Assert gathered LAG config is returned
+ assert:
+ that:
+ - result_gathered.gathered is defined
+ - result_gathered.gathered | type_debug == 'list'
+
+ - name: RENDERED - Generate platform-specific XML config
+ junipernetworks.junos.junos_lag_interfaces:
+ state: rendered
+ config:
+ - name: ae1
+ members:
+ - member: ge-0/0/1
+ - member: ge-0/0/2
+ mode: active
+
+ - name: ae2
+ link_protection: true
+ members:
+ - member: ge-0/0/3
+ link_type: primary
+ - member: ge-0/0/4
+ link_type: backup
+ mode: passive
+ register: result_rendered
+
+ - name: Assert rendered LAG config is valid
+ assert:
+ that:
+ - result_rendered.rendered is defined
+ - result_rendered.rendered | length > 0
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_lldp_global.yml b/tests/junipernetworks.junos/pb.juniper_junos_lldp_global.yml
new file mode 100644
index 00000000..9d72de12
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_lldp_global.yml
@@ -0,0 +1,75 @@
+- name: Functional Test - junos_lldp_global module
+ hosts: netconf_connection_testcases
+ connection: ansible.netcommon.netconf
+ gather_facts: false
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Merge LLDP global configuration
+ junipernetworks.junos.junos_lldp_global:
+ config:
+ interval: 10000
+ address: 10.1.1.1
+ transmit_delay: 400
+ hold_multiplier: 10
+ state: merged
+ register: merge_result
+
+ - name: Assert LLDP global merge applied
+ assert:
+ that:
+ - merge_result.changed == true
+
+ - name: Replace LLDP global configuration
+ junipernetworks.junos.junos_lldp_global:
+ config:
+ address: 20.2.2.2
+ hold_multiplier: 5
+ enabled: false
+ state: replaced
+ register: replace_result
+
+ - name: Assert LLDP global replace applied
+ assert:
+ that:
+ - replace_result.changed == true
+
+ - name: Gather LLDP global configuration
+ junipernetworks.junos.junos_lldp_global:
+ state: gathered
+ register: gather_result
+
+ - name: Assert LLDP address is correctly configured
+ assert:
+ that:
+ - gather_result.gathered.address == "20.2.2.2"
+ - gather_result.gathered.hold_multiplier == 5
+ - gather_result.gathered.enabled == false
+
+ - name: Render LLDP global configuration to XML
+ junipernetworks.junos.junos_lldp_global:
+ config:
+ interval: 10000
+ address: 10.1.1.1
+ transmit_delay: 400
+ hold_multiplier: 10
+ state: rendered
+ register: render_result
+
+ - name: Assert rendered LLDP config is valid
+ assert:
+ that:
+ - render_result.rendered is defined
+ - render_result.rendered | length > 0
+
+ - name: Delete LLDP global configuration
+ junipernetworks.junos.junos_lldp_global:
+ state: deleted
+ register: delete_result
+
+ - name: Assert LLDP global config deleted
+ assert:
+ that:
+ - delete_result.changed == true
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_lldp_interfaces.yml b/tests/junipernetworks.junos/pb.juniper_junos_lldp_interfaces.yml
new file mode 100644
index 00000000..8b36ea22
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_lldp_interfaces.yml
@@ -0,0 +1,61 @@
+- name: Functional Test - junos_lldp_interfaces module
+ hosts: netconf_connection_testcases
+ connection: ansible.netcommon.netconf
+ gather_facts: false
+ tasks:
+
+ - name: Pre-clean LLDP interface config
+ junipernetworks.junos.junos_lldp_interfaces:
+ config:
+ - name: ge-0/0/1
+ - name: ge-0/0/2
+ - name: ge-0/0/3
+ state: deleted
+ ignore_errors: true
+
+ - name: Merge LLDP interface configuration
+ junipernetworks.junos.junos_lldp_interfaces:
+ config:
+ - name: ge-0/0/1
+ - name: ge-0/0/2
+ enabled: false
+ state: merged
+
+ - name: Replace LLDP interface configuration
+ junipernetworks.junos.junos_lldp_interfaces:
+ config:
+ - name: ge-0/0/2
+ enabled: true
+ - name: ge-0/0/3
+ enabled: false
+ state: replaced
+
+ - name: Override LLDP interface configuration
+ junipernetworks.junos.junos_lldp_interfaces:
+ config:
+ - name: ge-0/0/3
+ enabled: false
+ state: overridden
+
+ - name: Gather current LLDP interface configuration
+ junipernetworks.junos.junos_lldp_interfaces:
+ state: gathered
+ register: lldp_interface_gather
+
+ - name: Assert ge-0/0/3 is in gathered LLDP interfaces and disabled
+ ansible.builtin.assert:
+ that:
+ - lldp_interface_gather.gathered | selectattr("name", "equalto", "ge-0/0/3") | selectattr("enabled", "equalto", false) | list | length > 0
+ fail_msg: "ge-0/0/3 with enabled: false not found in gathered result"
+ success_msg: "ge-0/0/3 is correctly disabled in LLDP interfaces"
+
+ - name: Render LLDP interface configuration for offline validation
+ junipernetworks.junos.junos_lldp_interfaces:
+ config:
+ - name: ge-0/0/1
+ - name: ge-0/0/2
+ enabled: false
+ state: rendered
+ register: rendered_lldp
+
+
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_logging_global.yml b/tests/junipernetworks.junos/pb.juniper_junos_logging_global.yml
new file mode 100644
index 00000000..76b47f18
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_logging_global.yml
@@ -0,0 +1,195 @@
+- name: Functional Test - junos_logging_global
+ hosts: junos_device
+ gather_facts: no
+ connection: ansible.netcommon.netconf
+
+ vars:
+ routing_instance_name: inst11
+ logging_source_address: "{{ source_address }}"
+ logging_host_address: "{{ host_address }}"
+
+ tasks:
+
+ - name: Ensure routing instance exists
+ junipernetworks.junos.junos_config:
+ lines:
+ - "set routing-instances {{ routing_instance_name }} instance-type virtual-router"
+ comment: "Pre-create routing instance required for syslog"
+ update: merge
+
+ - name: MERGED - Full logging configuration
+ junipernetworks.junos.junos_logging_global:
+ config:
+ allow_duplicates: true
+ archive:
+ set: true
+ no_binary_data: true
+ files: 10
+ file_size: 65578
+ no_world_readable: true
+ console:
+ any:
+ level: "info"
+ authorization:
+ level: "any"
+ change_log:
+ level: "critical"
+ ftp:
+ level: "none"
+ files:
+ - name: "file101"
+ allow_duplicates: true
+ - name: "file102"
+ allow_duplicates: true
+ any:
+ level: "any"
+ structured_data:
+ set: true
+ - name: "file103"
+ archive:
+ set: true
+ no_binary_data: true
+ files: 10
+ file_size: 65578
+ no_world_readable: true
+ explicit_priority: true
+ match: "^set*"
+ match_strings:
+ - "^delete"
+ - "^prompt"
+ hosts:
+ - name: host111
+ exclude_hostname: true
+ allow_duplicates: true
+ any:
+ level: "any"
+ structured_data:
+ set: true
+ brief: true
+ facility_override: "ftp"
+ log_prefix: "field"
+ match: "^set*"
+ match_strings:
+ - "^delete"
+ - "^prompt"
+ port: 1231
+ routing_instance: "{{ routing_instance_name }}"
+ source_address: "{{ logging_host_address }}"
+ routing_instance: "{{ routing_instance_name }}"
+ log_rotate_frequency: 45
+ source_address: "{{ logging_source_address }}"
+ time_format:
+ millisecond: true
+ year: true
+ users:
+ - name: "user1"
+ allow_duplicates: true
+ - name: "user2"
+ allow_duplicates: true
+ any:
+ level: "any"
+ user:
+ level: info
+ state: merged
+
+ - name: REPLACED - Replace logging configuration
+ junipernetworks.junos.junos_logging_global:
+ config:
+ files:
+ - name: "file104"
+ allow_duplicates: true
+ - name: "file102"
+ allow_duplicates: true
+ any:
+ level: "any"
+ structured_data:
+ set: true
+ hosts:
+ - name: host222
+ exclude_hostname: true
+ allow_duplicates: true
+ any:
+ level: "any"
+ structured_data:
+ set: true
+ brief: true
+ facility_override: "ftp"
+ log_prefix: "field"
+ match: "^set*"
+ match_strings:
+ - "^delete"
+ - "^prompt"
+ port: 1231
+ routing_instance: "{{ routing_instance_name }}"
+ source_address: "{{ logging_host_address }}"
+ users:
+ - name: "user1"
+ allow_duplicates: true
+ - name: "user2"
+ allow_duplicates: true
+ any:
+ level: "any"
+ user:
+ level: info
+ state: replaced
+
+ - name: OVERRIDDEN - Override entire logging config
+ junipernetworks.junos.junos_logging_global:
+ config:
+ files:
+ - name: "file104"
+ allow_duplicates: true
+ - name: "file102"
+ allow_duplicates: true
+ any:
+ level: "any"
+ structured_data:
+ set: true
+ hosts:
+ - name: host222
+ exclude_hostname: true
+ allow_duplicates: true
+ any:
+ level: "any"
+ structured_data:
+ set: true
+ brief: true
+ facility_override: "ftp"
+ log_prefix: "field"
+ match: "^set*"
+ match_strings:
+ - "^delete"
+ - "^prompt"
+ port: 1231
+ routing_instance: "{{ routing_instance_name }}"
+ source_address: "{{ logging_host_address }}"
+ users:
+ - name: "user1"
+ allow_duplicates: true
+ - name: "user2"
+ allow_duplicates: true
+ any:
+ level: "any"
+ user:
+ level: info
+ state: overridden
+
+ - name: GATHERED - Gather current logging config
+ junipernetworks.junos.junos_logging_global:
+ state: gathered
+ register: gathered_output
+
+ - name: RENDERED - Render config into XML
+ junipernetworks.junos.junos_logging_global:
+ config: "{{ gathered_output.gathered }}"
+ state: rendered
+
+ - name: PARSED - Load from parsed.cfg
+ junipernetworks.junos.junos_logging_global:
+ running_config: "{{ lookup('file', './parsed_configs/parsed_logging_global.cfg') }}"
+ state: parsed
+
+ - name: DELETED - Delete all logging config
+ junipernetworks.junos.junos_logging_global:
+ config: {}
+ state: deleted
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_netconf.yml b/tests/junipernetworks.junos/pb.juniper_junos_netconf.yml
new file mode 100644
index 00000000..862dab57
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_netconf.yml
@@ -0,0 +1,30 @@
+- name: Functional Test - junos_netconf module
+ hosts: network_cli_testcases
+ gather_facts: false
+ connection: network_cli
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+ - name: Enable NETCONF service on port 830
+ junipernetworks.junos.junos_netconf:
+ netconf_port: 830
+ state: present
+ register: enable_result
+
+ - name: Assert NETCONF service was enabled
+ assert:
+ that:
+ - enable_result.changed is defined
+ - enable_result.commands | length > 0
+
+ - name: Disable NETCONF service
+ junipernetworks.junos.junos_netconf:
+ state: absent
+ register: disable_result
+
+ - name: Assert NETCONF service was disabled
+ assert:
+ that:
+ - disable_result.changed is defined
+ - disable_result.commands | length > 0
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_ntp_global.yml b/tests/junipernetworks.junos/pb.juniper_junos_ntp_global.yml
new file mode 100644
index 00000000..6593c1c0
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_ntp_global.yml
@@ -0,0 +1,217 @@
+- name: Functional Test - junos_ntp_global module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Pre-clean - Delete existing NTP global config
+ junipernetworks.junos.junos_ntp_global:
+ config: {}
+ state: deleted
+ register: preclean_result
+ - name: Pre-create required routing instances
+ junipernetworks.junos.junos_routing_instances:
+ config:
+ - name: "rt1"
+ type: "virtual-router"
+ - name: "rt2"
+ type: "virtual-router"
+ state: merged
+
+ - name: Apply NTP global config using merged
+ junipernetworks.junos.junos_ntp_global:
+ config:
+ boot_server: '78.46.194.186'
+ broadcasts:
+ - address: '172.16.255.255'
+ key: '50'
+ ttl: 200
+ version: 3
+ routing_instance_name: 'rt1'
+ - address: '192.16.255.255'
+ key: '50'
+ ttl: 200
+ version: 3
+ routing_instance_name: 'rt2'
+ broadcast_client: true
+ interval_range: 2
+ multicast_client: "224.0.0.1"
+ peers:
+ - peer: "78.44.194.186"
+ - peer: "172.44.194.186"
+ key_id: 10000
+ prefer: true
+ version: 3
+ servers:
+ - server: "48.46.194.186"
+ key_id: 34
+ prefer: true
+ version: 2
+ routing_instance: 'rt1'
+ - server: "48.45.194.186"
+ key_id: 34
+ prefer: true
+ version: 2
+ source_addresses:
+ - source_address: "172.45.194.186"
+ routing_instance: 'rt1'
+ - source_address: "171.45.194.186"
+ routing_instance: 'rt2'
+ threshold:
+ value: 300
+ action: "accept"
+ trusted_keys:
+ - key_id: 3000
+ - key_id: 2000
+ state: merged
+ register: merged_result
+
+ - name: Assert merged result
+ assert:
+ that:
+ - merged_result.changed == true
+
+ - name: Gather NTP global config
+ junipernetworks.junos.junos_ntp_global:
+ state: gathered
+ register: gathered_result
+
+ - name: Assert gathered result
+ assert:
+ that:
+ - gathered_result.gathered is defined
+
+ - name: Replace running NTP global config
+ junipernetworks.junos.junos_ntp_global:
+ config:
+ authentication_keys:
+ - id: 2
+ algorithm: 'md5'
+ key: 'asdfghd'
+ - id: 5
+ algorithm: 'sha1'
+ key: 'aasdad'
+ servers:
+ - server: "48.46.194.186"
+ key_id: 34
+ prefer: true
+ version: 2
+ routing_instance: 'rt1'
+ - server: "48.45.194.186"
+ key_id: 34
+ prefer: true
+ version: 2
+ state: replaced
+ register: replaced_result
+
+ - name: Assert replaced result
+ assert:
+ that:
+ - replaced_result.changed == true
+
+ - name: Override running NTP global config
+ junipernetworks.junos.junos_ntp_global:
+ config:
+ authentication_keys:
+ - id: 2
+ algorithm: 'md5'
+ key: 'asdfghd'
+ - id: 5
+ algorithm: 'sha1'
+ key: 'aasdad'
+ servers:
+ - server: "48.46.194.186"
+ key_id: 34
+ prefer: true
+ version: 2
+ routing_instance: 'rt1'
+ - server: "48.45.194.186"
+ key_id: 34
+ prefer: true
+ version: 2
+ state: overridden
+ register: overridden_result
+
+ - name: Assert overridden result
+ assert:
+ that:
+ - overridden_result.changed == true
+
+ - name: Delete NTP global configuration
+ junipernetworks.junos.junos_ntp_global:
+ config: {}
+ state: deleted
+ register: deleted_result
+
+ - name: Assert deleted result
+ assert:
+ that:
+ - deleted_result.changed == true
+
+ - name: Render NTP global configuration
+ junipernetworks.junos.junos_ntp_global:
+ config:
+ boot_server: '78.46.194.186'
+ broadcasts:
+ - address: '172.16.255.255'
+ key: '50'
+ ttl: 200
+ version: 3
+ routing_instance_name: 'rt1'
+ - address: '192.16.255.255'
+ key: '50'
+ ttl: 200
+ version: 3
+ routing_instance_name: 'rt2'
+ broadcast_client: true
+ interval_range: 2
+ multicast_client: "224.0.0.1"
+ peers:
+ - peer: "78.44.194.186"
+ - peer: "172.44.194.186"
+ key_id: 10000
+ prefer: true
+ version: 3
+ servers:
+ - server: "48.46.194.186"
+ key_id: 34
+ prefer: true
+ version: 2
+ routing_instance: 'rt1'
+ - server: "48.45.194.186"
+ key_id: 34
+ prefer: true
+ version: 2
+ source_addresses:
+ - source_address: "172.45.194.186"
+ routing_instance: 'rt1'
+ - source_address: "171.45.194.186"
+ routing_instance: 'rt2'
+ threshold:
+ value: 300
+ action: "accept"
+ trusted_keys:
+ - key_id: 3000
+ - key_id: 2000
+ state: rendered
+ register: rendered_result
+
+ - name: Assert rendered result
+ assert:
+ that:
+ - rendered_result.rendered is defined
+
+ - name: Parse NTP global config
+ junipernetworks.junos.junos_ntp_global:
+ running_config: "{{ lookup('file', 'parsed_configs/parsed_ntp_global.cfg') }}"
+ state: parsed
+ register: parsed_result
+
+ - name: Assert parsed result
+ assert:
+ that:
+ - parsed_result is defined
+ - parsed_result.parsed is defined
\ No newline at end of file
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_ospf_interfaces.yml b/tests/junipernetworks.junos/pb.juniper_junos_ospf_interfaces.yml
new file mode 100644
index 00000000..82d667a9
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_ospf_interfaces.yml
@@ -0,0 +1,141 @@
+- name: Functional Test - junos_ospf_interfaces module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+ - name: Pre-clean - Delete existing OSPF interface config
+ junipernetworks.junos.junos_ospf_interfaces:
+ config:
+ - name: "ge-0/0/2.0"
+ state: deleted
+ register: deleted_result
+
+ - name: Assert deleted result
+ assert:
+ that:
+ - deleted_result is succeeded
+
+ - name: Apply OSPF interface config using merged
+ junipernetworks.junos.junos_ospf_interfaces:
+ config:
+ - name: "ge-0/0/2.0"
+ address_family:
+ - afi: "ipv4"
+ processes:
+ area:
+ area_id: "0.0.0.2"
+ metric: 5
+ priority: 3
+ state: merged
+ register: merged_result
+
+ - name: Assert merged result
+ assert:
+ that:
+ - merged_result.changed == true
+
+ - name: Replace OSPF interface config
+ junipernetworks.junos.junos_ospf_interfaces:
+ config:
+ - name: "ge-0/0/2.0"
+ address_family:
+ - afi: "ipv4"
+ processes:
+ area:
+ area_id: "0.0.0.1"
+ metric: 6
+ priority: 6
+ state: replaced
+ register: replaced_result
+
+ - name: Assert replaced result
+ assert:
+ that:
+ - replaced_result.changed == true
+
+ - name: Override OSPF interface config
+ junipernetworks.junos.junos_ospf_interfaces:
+ config:
+ - name: so-0/0/0.0
+ router_id: 10.200.16.75
+ address_family:
+ - afi: ipv4
+ processes:
+ area:
+ area_id: 0.0.0.110
+ bandwidth_based_metrics:
+ - bandwidth: 1g
+ metric: 5
+ - bandwidth: 10g
+ metric: 40
+ metric: 5
+ priority: 3
+ passive: true
+ - name: ge-0/0/2.0
+ router_id: 10.200.16.75
+ address_family:
+ - afi: ipv4
+ processes:
+ area:
+ area_id: 0.0.0.3
+ metric: 7
+ priority: 4
+ state: overridden
+ register: overridden_result
+
+
+ - name: Assert overridden result
+ assert:
+ that:
+ - overridden_result.changed == true
+
+ - name: Delete specific OSPF interface config
+ junipernetworks.junos.junos_ospf_interfaces:
+ config:
+ - name: "ge-0/0/1.0"
+ state: deleted
+ register: deleted_specific_result
+
+ - name: Gather OSPF interfaces config
+ junipernetworks.junos.junos_ospf_interfaces:
+ state: gathered
+ register: gathered_result
+
+ - name: Assert gathered result
+ assert:
+ that:
+ - gathered_result.gathered is defined
+
+ - name: Render OSPF interfaces config
+ junipernetworks.junos.junos_ospf_interfaces:
+ config:
+ - name: "ge-0/0/2.0"
+ address_family:
+ - afi: "ipv4"
+ processes:
+ area:
+ area_id: "0.0.0.2"
+ metric: 5
+ priority: 3
+ state: rendered
+ register: rendered_result
+
+ - name: Assert rendered output
+ assert:
+ that:
+ - rendered_result.rendered is defined
+
+
+ - name: Parse OSPF interfaces running config
+ junipernetworks.junos.junos_ospf_interfaces:
+ running_config: "{{ lookup('file', 'parsed_configs/parsed_ospf_interfaces.cfg') }}"
+ state: parsed
+ register: parsed_result
+
+ - name: Assert parsed output
+ assert:
+ that:
+ - parsed_result.parsed is defined
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_ospfv2.yml b/tests/junipernetworks.junos/pb.juniper_junos_ospfv2.yml
new file mode 100644
index 00000000..d3b8c810
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_ospfv2.yml
@@ -0,0 +1,181 @@
+- name: Functional Test - junos_ospfv2 module
+ hosts: junos_device
+ gather_facts: false
+ connection: ansible.netcommon.netconf
+
+ tasks:
+
+ - name: DELETE - Reset before MERGED
+ junipernetworks.junos.junos_ospfv2:
+ config: []
+ state: deleted
+
+ - name: MERGED - Configure OSPFv2 instance
+ junipernetworks.junos.junos_ospfv2:
+ config:
+ - reference_bandwidth: 10g
+ areas:
+ - area_id: 0.0.0.100
+ area_ranges:
+ - address: 10.200.17.0/24
+ exact: true
+ restrict: true
+ override_metric: 2000
+ - address: 10.200.15.0/24
+ exact: true
+ restrict: true
+ override_metric: 2000
+ stub:
+ default_metric: 100
+ set: true
+ interfaces:
+ - name: so-0/0/0.0
+ priority: 3
+ metric: 5
+ flood_reduction: false
+ passive: true
+ bandwidth_based_metrics:
+ - bandwidth: 1g
+ metric: 5
+ - bandwidth: 10g
+ metric: 40
+ timers:
+ dead_interval: 4
+ hello_interval: 2
+ poll_interval: 2
+ retransmit_interval: 2
+ rfc1583compatibility: false
+ state: merged
+
+ - name: DELETE - Reset before REPLACED
+ junipernetworks.junos.junos_ospfv2:
+ config: []
+ state: deleted
+
+ - name: REPLACED - Replace OSPFv2 instance
+ junipernetworks.junos.junos_ospfv2:
+ config:
+ - reference_bandwidth: 10g
+ areas:
+ - area_id: 0.0.0.100
+ area_ranges:
+ - address: 10.200.17.0/24
+ exact: true
+ restrict: true
+ - address: 10.200.16.0/24
+ exact: true
+ restrict: true
+ override_metric: 1000
+ stub:
+ default_metric: 100
+ set: true
+ interfaces:
+ - name: so-0/0/0.0
+ priority: 3
+ metric: 5
+ flood_reduction: false
+ passive: true
+ bandwidth_based_metrics:
+ - bandwidth: 1g
+ metric: 5
+ - bandwidth: 10g
+ metric: 40
+ timers:
+ dead_interval: 4
+ hello_interval: 2
+ poll_interval: 2
+ retransmit_interval: 2
+ rfc1583compatibility: false
+ state: replaced
+
+ - name: DELETE - Reset before OVERRIDDEN
+ junipernetworks.junos.junos_ospfv2:
+ config: []
+ state: deleted
+
+ - name: OVERRIDDEN - Override OSPFv2 instance
+ junipernetworks.junos.junos_ospfv2:
+ config:
+ - reference_bandwidth: 10g
+ areas:
+ - area_id: 0.0.0.110
+ area_ranges:
+ - address: 20.200.17.0/24
+ exact: true
+ restrict: true
+ override_metric: 2000
+ - address: 20.200.15.0/24
+ exact: true
+ restrict: true
+ override_metric: 2000
+ stub:
+ default_metric: 200
+ set: true
+ interfaces:
+ - name: so-0/0/0.0
+ priority: 3
+ metric: 5
+ flood_reduction: false
+ passive: true
+ bandwidth_based_metrics:
+ - bandwidth: 1g
+ metric: 5
+ - bandwidth: 10g
+ metric: 40
+ state: overridden
+
+ - name: RENDERED - Render OSPFv2 config
+ junipernetworks.junos.junos_ospfv2:
+ config:
+ - reference_bandwidth: 10g
+ areas:
+ - area_id: 0.0.0.100
+ area_ranges:
+ - address: 10.200.17.0/24
+ exact: true
+ restrict: true
+ override_metric: 2000
+ - address: 10.200.15.0/24
+ exact: true
+ restrict: true
+ override_metric: 2000
+ stub:
+ default_metric: 100
+ set: true
+ interfaces:
+ - name: so-0/0/0.0
+ priority: 3
+ metric: 5
+ flood_reduction: false
+ passive: true
+ bandwidth_based_metrics:
+ - bandwidth: 1g
+ metric: 5
+ - bandwidth: 10g
+ metric: 40
+ timers:
+ dead_interval: 4
+ hello_interval: 2
+ poll_interval: 2
+ retransmit_interval: 2
+ state: rendered
+
+ - name: GATHERED - Get current OSPFv2 config
+ junipernetworks.junos.junos_ospfv2:
+ config: []
+ state: gathered
+ register: ospf_gather
+
+ - name: Show GATHERED
+ ansible.builtin.debug:
+ var: ospf_gather.gathered
+
+ - name: PARSED - Parsed ospfv2 config from XML
+ junipernetworks.junos.junos_ospfv2:
+ running_config: "{{ lookup('file', './parsed_configs/parsed_ospfv2.cfg') }}"
+ state: parsed
+ register: ospf_parsed
+
+ - name: Show PARSED
+ ansible.builtin.debug:
+ var: ospf_parsed.parsed
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_ospfv3.yml b/tests/junipernetworks.junos/pb.juniper_junos_ospfv3.yml
new file mode 100644
index 00000000..20ed913f
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_ospfv3.yml
@@ -0,0 +1,88 @@
+- name: Functional Test - junos_ospfv3 module
+ hosts: junos_device
+ gather_facts: false
+ connection: ansible.netcommon.netconf
+
+ tasks:
+ - name: DELETE - Reset before test
+ junipernetworks.junos.junos_ospfv3:
+ config: []
+ state: deleted
+
+ - name: MERGED - Merge Junos OSPFv3 config
+ junipernetworks.junos.junos_ospfv3:
+ config:
+ - router_id: 10.200.16.75
+ areas:
+ - area_id: 0.0.0.100
+ interfaces:
+ - metric: 5
+ name: so-0/0/0.0
+ priority: 3
+ - metric: 6
+ name: so-0/0/1.0
+ priority: 2
+ stub:
+ default_metric: 200
+ set: true
+ state: merged
+
+ - name: REPLACED - Replace Junos OSPFv3 config
+ junipernetworks.junos.junos_ospfv3:
+ config:
+ - router_id: 10.200.16.75
+ areas:
+ - area_id: 0.0.0.100
+ interfaces:
+ - name: so-0/0/0.0
+ state: replaced
+
+ - name: OVERRIDDEN - Override Junos OSPFv3 config
+ junipernetworks.junos.junos_ospfv3:
+ config:
+ - router_id: 10.200.16.75
+ areas:
+ - area_id: 0.0.0.100
+ stub:
+ default_metric: 200
+ set: true
+ interfaces:
+ - name: so-0/0/0.0
+ priority: 3
+ metric: 5
+ flood_reduction: true
+ passive: true
+ - area_id: 0.0.0.200
+ interfaces:
+ - name: ge-1/1/0.0
+ - name: ge-2/2/0.0
+ state: overridden
+
+ - name: GATHERED - Get current OSPFv3 configuration
+ junipernetworks.junos.junos_ospfv3:
+ config: []
+ state: gathered
+ register: gathered_ospfv3
+
+ - name: PARSED - Parse structured config from XML file
+ junipernetworks.junos.junos_ospfv3:
+ running_config: "{{ lookup('file', './parsed_configs/parsed_ospfv3.cfg') }}"
+ state: parsed
+
+ - name: RENDERED - Render OSPFv3 config into XML
+ junipernetworks.junos.junos_ospfv3:
+ config:
+ - router_id: 10.200.16.75
+ areas:
+ - area_id: 0.0.0.100
+ interfaces:
+ - metric: 5
+ name: so-0/0/0.0
+ priority: 3
+ - metric: 6
+ name: so-0/0/1.0
+ priority: 2
+ stub:
+ default_metric: 200
+ set: true
+ state: rendered
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_package.yml b/tests/junipernetworks.junos/pb.juniper_junos_package.yml
new file mode 100644
index 00000000..9c508742
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_package.yml
@@ -0,0 +1,63 @@
+- name: Functional Test - junos_package module
+ hosts: localhost
+ gather_facts: false
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Install local package on remote device
+ junipernetworks.junos.junos_package:
+ src: "{{ package_src }}"
+ reboot: true
+ provider:
+ host: xx.xx.xx.xx
+ username: xx
+ password: xx
+ port: 830
+ transport: netconf
+ register: result_install
+
+ - name: Wait for device to come back online after reboot (TCP check)
+ wait_for:
+ host: xx.xx.xx.xx
+ port: 830
+ delay: 30
+ timeout: 300
+
+ - name: Wait until NETCONF service is ready (SSH banner check)
+ wait_for:
+ host: xx.xx.xx.xx
+ port: 830
+ search_regex: "SSH"
+ timeout: 300
+ delay: 10
+ sleep: 5
+ register: wait_result
+ until: wait_result is succeeded
+ retries: 10
+ delay: 10
+
+ - name: Assert install task ran
+ assert:
+ that:
+ - result_install is defined
+
+ - name: Install local package without reboot
+ junipernetworks.junos.junos_package:
+ src: /tmp/junos-vsrx-12.1X46-D10.2-domestic.tgz
+ reboot: false
+ provider:
+ host: xx.xx.xx.xx
+ username: xxx
+ password: xxx
+ port: 830
+ transport: netconf
+ register: result_noreboot
+
+ - name: Assert no-reboot task ran
+ assert:
+ that:
+ - result_noreboot is defined
+
+
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_ping.yml b/tests/junipernetworks.junos/pb.juniper_junos_ping.yml
new file mode 100644
index 00000000..315571b8
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_ping.yml
@@ -0,0 +1,67 @@
+- name: Functional Test - junos_ping module
+ hosts: network_cli_testcases
+ gather_facts: false
+ connection: network_cli
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Test reachability to target
+ junipernetworks.junos.junos_ping:
+ dest: xx.xx.xx.xx
+ register: ping_default
+
+ - name: Assert default ping worked
+ assert:
+ that:
+ - ping_default.packet_loss is defined
+
+ - name: Test reachability to target using source and size set
+ junipernetworks.junos.junos_ping:
+ dest: xx.xx.xx.xx
+ size: 1024
+ ttl: 128
+ register: ping_source_ttl
+
+ - name: Assert source TTL ping worked
+ assert:
+ that:
+ - ping_source_ttl.packet_loss is defined
+
+ - name: Test unreachability to target using interval
+ junipernetworks.junos.junos_ping:
+ dest: xx.xx.xx.xx
+ interval: 3
+ state: present
+ register: ping_absent
+
+ - name: "Assert unreachable ping worked (state: absent)"
+ assert:
+ that:
+ - ping_absent.packet_loss is defined
+
+ - name: Test reachability to target setting count and interface
+ junipernetworks.junos.junos_ping:
+ dest: xx.xx.xx.xx
+ interface: fxp0
+ count: 20
+ size: 512
+ register: ping_iface
+
+ - name: Assert ping with count/interface worked
+ assert:
+ that:
+ - ping_iface.packet_loss is defined
+
+ - name: Test reachability to target using do-not-fragment and rapid
+ junipernetworks.junos.junos_ping:
+ dest: xx.xx.xx.xx
+ df_bit: true
+ rapid: true
+ register: ping_df_rapid
+
+ - name: Assert ping with DF bit and rapid worked
+ assert:
+ that:
+ - ping_df_rapid.packet_loss is defined
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_prefix_lists.yml b/tests/junipernetworks.junos/pb.juniper_junos_prefix_lists.yml
new file mode 100644
index 00000000..95fca784
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_prefix_lists.yml
@@ -0,0 +1,118 @@
+- name: Functional Test - junos_prefix_lists module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+ - name: Pre-clean - Delete all prefix-lists if present
+ junos_prefix_lists:
+ state: deleted
+ ignore_errors: true
+
+ - name: Apply prefix-lists using merged
+ junos_prefix_lists:
+ config:
+ - name: Internal
+ address_prefixes:
+ - 172.16.1.32
+ - 172.16.3.32
+ - name: Test1
+ dynamic_db: true
+ - name: Test2
+ address_prefixes:
+ - 172.16.2.32
+ - 172.16.7.32
+ - 172.16.9.32
+ state: merged
+ register: merged_result
+
+ - name: Assert merged result
+ assert:
+ that:
+ - merged_result.changed == true
+
+ - name: Gather prefix-lists
+ junos_prefix_lists:
+ state: gathered
+ register: gathered_result
+
+ - name: Assert gathered prefix-lists
+ assert:
+ that:
+ - gathered_result.gathered is defined
+ - gathered_result.gathered | length > 0
+
+ - name: Replace prefix-list Test2 with new prefixes
+ junos_prefix_lists:
+ config:
+ - name: Test2
+ address_prefixes:
+ - 172.16.4.32
+ - 172.16.8.32
+ - 172.16.9.32
+ state: replaced
+ register: replaced_result
+
+ - name: Assert replaced result
+ assert:
+ that:
+ - replaced_result.changed == true
+
+ - name: Override prefix-lists with only Test2 entries
+ junos_prefix_lists:
+ config:
+ - name: Test2
+ address_prefixes:
+ - 172.16.4.32/28
+ - 172.16.8.32/28
+ - 172.16.9.32/28
+ state: overridden
+ register: overridden_result
+
+ - name: Assert overridden result
+ assert:
+ that:
+ - overridden_result.changed == true
+
+ - name: Render prefix-lists offline
+ junos_prefix_lists:
+ config:
+ - name: Internal
+ address_prefixes:
+ - 172.16.1.32
+ - 172.16.3.32
+ - name: Test1
+ dynamic_db: true
+ - name: Test2
+ address_prefixes:
+ - 172.16.2.32
+ - 172.16.7.32
+ - 172.16.9.32
+ state: rendered
+ register: rendered_result
+
+ - name: Assert rendered output
+ assert:
+ that:
+ - rendered_result.rendered is defined
+ - rendered_result.rendered | length > 0
+
+ - name: Post-clean - Delete specific prefix-lists
+ junos_prefix_lists:
+ config:
+ - name: Test1
+ - name: Test2
+ state: deleted
+ register: deleted_result
+
+ - name: Assert deleted specific prefix-lists
+ assert:
+ that:
+ - deleted_result.changed == true
+
+ - name: Final clean - Delete all prefix-lists
+ junos_prefix_lists:
+ state: deleted
+ ignore_errors: true
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_routing_instances.yml b/tests/junipernetworks.junos/pb.juniper_junos_routing_instances.yml
new file mode 100644
index 00000000..710e7f53
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_routing_instances.yml
@@ -0,0 +1,146 @@
+- name: Functional Test - junos_routing_instances module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Pre-clean - Create required policy statements
+ junipernetworks.junos.junos_config:
+ lines:
+ - set policy-options policy-statement test-policy term t1 then reject
+ - set policy-options policy-statement test-policy-1 term t1 then reject
+ comment: "Pre-create dummy policies needed for routing instances FT"
+
+ - name: Pre-clean - Delete test routing instances
+ junipernetworks.junos.junos_routing_instances:
+ config:
+ - name: "test"
+ - name: "forwardinst"
+ - name: "vtest1"
+ state: deleted
+
+ - name: Apply routing instances using merged
+ junipernetworks.junos.junos_routing_instances:
+ config:
+ - name: "test"
+ type: "vrf"
+ route_distinguisher: "10.58.255.1:37"
+ vrf_imports:
+ - "test-policy"
+ vrf_exports:
+ - "test-policy"
+ - "test-policy-1"
+ interfaces:
+ - name: "sp-0/0/0.0"
+ - name: "gr-0/0/0.0"
+ connector_id_advertise: true
+ - name: "forwardinst"
+ type: "forwarding"
+ description: "Configured by Ansible Content Team"
+ state: merged
+ register: merged_result
+
+ - name: Assert merged result
+ assert:
+ that:
+ - merged_result.changed == true
+
+ - name: Gather routing instances
+ junipernetworks.junos.junos_routing_instances:
+ state: gathered
+ register: gathered_result
+
+ - name: Assert gathered result
+ assert:
+ that:
+ - gathered_result.gathered is defined
+
+ - name: Replace routing instance configuration
+ junipernetworks.junos.junos_routing_instances:
+ config:
+ - name: "test"
+ type: "vrf"
+ route_distinguisher: "10.57.255.1:37"
+ vrf_imports:
+ - "test-policy"
+ vrf_exports:
+ - "test-policy"
+ interfaces:
+ - name: "sp-0/0/0.0"
+ - name: "gr-0/0/0.0"
+ connector_id_advertise: false
+ description: "Configured by Ansible Content Team"
+ state: replaced
+ register: replaced_result
+
+ - name: Assert replaced result
+ assert:
+ that:
+ - replaced_result.changed == true
+
+
+
+ - name: Delete specific routing instance
+ junipernetworks.junos.junos_routing_instances:
+ config:
+ - name: "test"
+ state: deleted
+ register: delete_specific_result
+
+ - name: Assert specific routing instance deleted
+ assert:
+ that:
+ - delete_specific_result.changed == true
+
+ - name: Final clean - Delete test routing instances only
+ junipernetworks.junos.junos_routing_instances:
+ config:
+ - name: "forwardinst"
+ - name: "vtest1"
+ state: deleted
+ register: delete_all_result
+
+ - name: Assert all routing instances deleted
+ assert:
+ that:
+ - delete_all_result.changed == true
+
+ - name: Render routing instances configuration
+ junipernetworks.junos.junos_routing_instances:
+ config:
+ - name: "test"
+ type: "vrf"
+ route_distinguisher: "10.58.255.1:37"
+ vrf_imports:
+ - "test-policy"
+ vrf_exports:
+ - "test-policy"
+ - "test-policy-1"
+ interfaces:
+ - name: "sp-0/0/0.0"
+ - name: "gr-0/0/0.0"
+ connector_id_advertise: true
+ - name: "forwardinst"
+ type: "forwarding"
+ description: "Configured by Ansible Content Team"
+ state: rendered
+ register: rendered_result
+
+ - name: Assert rendered configuration
+ assert:
+ that:
+ - rendered_result.rendered is defined
+
+ - name: Parse routing instance running configuration
+ junipernetworks.junos.junos_routing_instances:
+ running_config: "{{ lookup('file', 'parsed_configs/parsed_routing_instances.cfg') }}"
+ state: parsed
+ register: parsed_result
+
+ - name: Assert parsed result
+ assert:
+ that:
+ - parsed_result.parsed is defined
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_routing_options.yml b/tests/junipernetworks.junos/pb.juniper_junos_routing_options.yml
new file mode 100644
index 00000000..71e4157b
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_routing_options.yml
@@ -0,0 +1,105 @@
+- name: Functional Test - junos_routing_options module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Pre-clean - Delete existing routing options
+ junipernetworks.junos.junos_routing_options:
+ config: {}
+ state: deleted
+
+ - name: Apply routing options using merged
+ junipernetworks.junos.junos_routing_options:
+ config:
+ autonomous_system:
+ as_number: 2
+ asdot_notation: true
+ state: merged
+ register: merged_result
+
+ - name: Assert merged result
+ assert:
+ that:
+ - merged_result.changed == true
+
+ - name: Gather routing options
+ junipernetworks.junos.junos_routing_options:
+ state: gathered
+ register: gathered_result
+
+ - name: Assert gathered result
+ assert:
+ that:
+ - gathered_result.gathered is defined
+
+ - name: Replace routing options configuration
+ junipernetworks.junos.junos_routing_options:
+ config:
+ autonomous_system:
+ as_number: 2
+ asdot_notation: true
+ router_id: "1.1.1.1"
+ state: replaced
+ register: replaced_result
+
+ - name: Assert replaced result
+ assert:
+ that:
+ - replaced_result.changed == true
+
+ - name: Override routing options configuration
+ junipernetworks.junos.junos_routing_options:
+ config:
+ autonomous_system:
+ as_number: 2
+ asdot_notation: true
+ router_id: "2.2.2.2"
+ state: overridden
+ register: overridden_result
+
+ - name: Assert overridden result
+ assert:
+ that:
+ - overridden_result.changed == true
+
+ - name: Render routing options configuration
+ junipernetworks.junos.junos_routing_options:
+ config:
+ autonomous_system:
+ as_number: 2
+ asdot_notation: true
+ loops: 4
+ router_id: "12.12.12.12"
+ state: rendered
+ register: rendered_result
+
+ - name: Assert rendered configuration
+ assert:
+ that:
+ - rendered_result.rendered is defined
+
+ - name: Parse routing options running configuration
+ junipernetworks.junos.junos_routing_options:
+ running_config: "{{ lookup('file', 'parsed_configs/parsed_routing_options.cfg') }}"
+ state: parsed
+ register: parsed_result
+
+ - name: Assert parsed result
+ assert:
+ that:
+ - parsed_result.parsed is defined
+
+ - name: Final clean - Delete all routing options
+ junipernetworks.junos.junos_routing_options:
+ config: {}
+ state: deleted
+ register: delete_result
+
+ - name: Assert routing options deleted
+ assert:
+ that:
+ - delete_result.changed == true
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_rpc.yml b/tests/junipernetworks.junos/pb.juniper_junos_rpc.yml
new file mode 100644
index 00000000..956f13e8
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_rpc.yml
@@ -0,0 +1,48 @@
+- name: Functional Test - junos_rpc module
+ hosts: netconf_connection_testcases
+ gather_facts: false
+ connection: ansible.netcommon.netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Collect interface information using RPC
+ junipernetworks.junos.junos_rpc:
+ rpc: get-interface-information
+ args:
+ interface-name: em0
+ media: true
+ register: interface_info
+
+ - name: Assert interface information RPC returned XML
+ assert:
+ that:
+ - interface_info.xml is defined
+
+ - name: Get system information using RPC
+ junipernetworks.junos.junos_rpc:
+ rpc: get-system-information
+ register: system_info
+
+ - name: Assert system information RPC returned XML
+ assert:
+ that:
+ - system_info.xml is defined
+
+ - name: Load configuration using RPC (requires file on device)
+ junipernetworks.junos.junos_rpc:
+ rpc: load-configuration
+ attrs:
+ action: override
+ format: text
+ url: /tmp/config.conf
+ register: config_load
+ when: false
+
+ - name: Assert load configuration RPC executed
+ assert:
+ that:
+ - config_load.xml is defined
+ when: false
+
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_security_policies.yml b/tests/junipernetworks.junos/pb.juniper_junos_security_policies.yml
new file mode 100644
index 00000000..bf1b3ca7
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_security_policies.yml
@@ -0,0 +1,27 @@
+- name: Functional Test - junos_security_policies (parsed and rendered only)
+ hosts: junos_device
+ gather_facts: no
+ connection: ansible.netcommon.netconf
+
+ tasks:
+ - name: Render security policy config
+ junipernetworks.junos.junos_security_policies:
+ config:
+ global:
+ policies:
+ - name: test_glob_1
+ match:
+ application:
+ any: true
+ source_address:
+ any_ipv6: true
+ destination_address:
+ any_ipv6: true
+ then:
+ deny: true
+ state: rendered
+
+ - name: Parse from saved running config
+ junipernetworks.junos.junos_security_policies:
+ running_config: "{{ lookup('file', './parsed_configs/parsed_security_policies.cfg') }}"
+ state: parsed
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_security_policies_global.yml b/tests/junipernetworks.junos/pb.juniper_junos_security_policies_global.yml
new file mode 100644
index 00000000..ec835f3f
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_security_policies_global.yml
@@ -0,0 +1,37 @@
+- name: Functional Test - junos_security_policies_global (parsed, rendered, gathered)
+ hosts: junos_device
+ gather_facts: no
+ connection: netconf
+
+ tasks:
+
+ - name: PARSED - Parse running config from local file
+ junipernetworks.junos.junos_security_policies_global:
+ running_config: "{{ lookup('file', './parsed_configs/parsed_security_policies_global.cfg') }}"
+ state: parsed
+
+ - name: RENDERED - Render the provided config
+ junipernetworks.junos.junos_security_policies_global:
+ config:
+ default_policy: deny-all
+ policy_rematch:
+ enable: true
+ policy_stats:
+ enable: true
+ pre_id_default_policy_action:
+ log:
+ session_init: true
+ session_timeout:
+ icmp: 10
+ others: 10
+ traceoptions:
+ file:
+ files: 4
+ match: /[A-Z]*/gm
+ size: 10k
+ no_world_readable: true
+ flag: all
+ no_remote_trace: true
+ state: rendered
+
+
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_security_zones.yml b/tests/junipernetworks.junos/pb.juniper_junos_security_zones.yml
new file mode 100644
index 00000000..919e8314
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_security_zones.yml
@@ -0,0 +1,41 @@
+- name: Functional Test - junos_security_zones module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Render Security Zone config to XML
+ junipernetworks.junos.junos_security_zones:
+ config:
+ zones:
+ - name: trust
+ description: "Trusted zone"
+ interfaces:
+ - ge-0/0/1.0
+ host_inbound_traffic:
+ system_services:
+ - name: ssh
+ - name: ping
+ state: rendered
+ register: result_rendered
+
+ - name: Assert rendered output
+ assert:
+ that:
+ - result_rendered.rendered is defined
+ - result_rendered.changed == false
+
+ - name: Parse Security Zone config from file
+ junipernetworks.junos.junos_security_zones:
+ running_config: "{{ lookup('file', 'parsed_configs/parsed_security_zones.cfg') }}"
+ state: parsed
+ register: result_parsed
+
+ - name: Assert parsed zone config
+ assert:
+ that:
+ - result_parsed.parsed is defined
+ - result_parsed.changed == false
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_snmp_server.yml b/tests/junipernetworks.junos/pb.juniper_junos_snmp_server.yml
new file mode 100644
index 00000000..94543acb
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_snmp_server.yml
@@ -0,0 +1,130 @@
+- name: Functional Test - junos_snmp_server (all states)
+ hosts: netconf_connection_testcases
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+ - name: Render SNMP server configuration (dry-run XML)
+ junipernetworks.junos.junos_snmp_server:
+ config:
+ arp:
+ set: true
+ host_name_resolution: true
+ routing_instance_access:
+ set: true
+ access_lists:
+ - clv1
+ - clv2
+ state: rendered
+ register: result_rendered
+
+ - name: Assert rendered SNMP config
+ assert:
+ that:
+ - result_rendered.rendered is defined
+ - result_rendered.changed == false
+
+ - name: Parse SNMP server config from XML
+ junipernetworks.junos.junos_snmp_server:
+ running_config: "{{ lookup('file', 'parsed_configs/parsed_snmp.cfg') }}"
+ state: parsed
+ register: result_parsed
+
+ - name: Assert parsed SNMP config
+ assert:
+ that:
+ - result_parsed.parsed is defined
+ - result_parsed.changed == false
+
+ - name: Merge SNMP server configuration (may fail if RI clv1/clv2 don't exist)
+ junipernetworks.junos.junos_snmp_server:
+ config:
+ arp:
+ set: true
+ host_name_resolution: true
+ client_lists:
+ - name: cl1
+ addresses:
+ - address: "192.16.1.0/24"
+ - address: "192.16.2.0/24"
+ - address: "11.11.11.11"
+ restrict: true
+ - name: cl2
+ addresses:
+ - address: "192.16.4.0/24"
+ routing_instance_access:
+ set: true
+ access_lists:
+ - clv1
+ - clv2
+ state: merged
+ register: result_merge
+ ignore_errors: true # Skip if routing instances clv1/clv2 are not present
+
+ - name: Replace SNMP server configuration
+ junipernetworks.junos.junos_snmp_server:
+ config:
+ contact: "ansiblesupport11@redhat.com"
+ customization:
+ ether_stats_ifd_only: true
+ description: "Local SNMP Server"
+ engine_id:
+ local: "local1"
+ use_default_ip_address: true
+ use_mac_address: true
+ filter_duplicates: true
+ filter_interfaces:
+ set: true
+ all_internal_interfaces: true
+ interfaces:
+ - eth1
+ - eth2
+ state: replaced
+ register: result_replaced
+
+ - name: Override SNMP server configuration
+ junipernetworks.junos.junos_snmp_server:
+ config:
+ contact: "ansiblesupport11@redhat.com"
+ customization:
+ ether_stats_ifd_only: true
+ description: "Local SNMP Server"
+ engine_id:
+ local: "local1"
+ use_default_ip_address: true
+ use_mac_address: true
+ filter_duplicates: true
+ filter_interfaces:
+ set: true
+ all_internal_interfaces: true
+ interfaces:
+ - eth1
+ - eth2
+ state: overridden
+ register: result_overridden
+
+ - name: Gather SNMP server configuration from device
+ junipernetworks.junos.junos_snmp_server:
+ state: gathered
+ register: result_gathered
+
+ - name: Assert gathered SNMP config
+ assert:
+ that:
+ - result_gathered.gathered is defined
+ - result_gathered.changed == false
+
+ - name: Delete SNMP server configuration
+ junipernetworks.junos.junos_snmp_server:
+ config: {}
+ state: deleted
+ register: result_deleted
+
+ - name: Assert config states
+ assert:
+ that:
+ - result_replaced.changed is defined
+ - result_overridden.changed is defined
+ - result_deleted.changed is defined
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_static_routes.yml b/tests/junipernetworks.junos/pb.juniper_junos_static_routes.yml
new file mode 100644
index 00000000..373e6326
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_static_routes.yml
@@ -0,0 +1,33 @@
+- name: Functional Test - junos_static_routes (safe states only)
+ hosts: netconf_connection_testcases
+ connection: netconf
+ gather_facts: no
+
+ tasks:
+
+ - name: 1. Render static route config for 192.168.16.0/24 โ 172.16.1.2
+ junipernetworks.junos.junos_static_routes:
+ config:
+ - vrf: default
+ address_families:
+ - afi: ipv4
+ routes:
+ - dest: 192.168.16.0/24
+ next_hop:
+ - forward_router_address: 172.16.1.2
+ state: rendered
+ register: rendered_output
+
+ - name: Debug rendered config
+ debug:
+ var: rendered_output.rendered
+
+ - name: 2. Parse running config from parsed_static_routes.cfg
+ junipernetworks.junos.junos_static_routes:
+ running_config: "{{ lookup('file', 'parsed_configs/parsed_static_routes.cfg') }}"
+ state: parsed
+ register: parsed_output
+
+ - name: Debug parsed output
+ debug:
+ var: parsed_output.parsed
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_system.yml b/tests/junipernetworks.junos/pb.juniper_junos_system.yml
new file mode 100644
index 00000000..ad001c8f
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_system.yml
@@ -0,0 +1,73 @@
+- name: Functional Test - junos_system module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Pre-clean - Remove system configuration
+ junipernetworks.junos.junos_system:
+ hostname: junos01
+ domain_name: test.example.com
+ domain_search:
+ - ansible.com
+ - redhat.com
+ - juniper.net
+ name_servers:
+ - 8.8.8.8
+ - 8.8.4.4
+ state: absent
+ register: preclean_result
+
+ - name: Assert pre-clean result
+ assert:
+ that:
+ - preclean_result is not failed
+
+ - name: Configure hostname, domain name, and domain search
+ junipernetworks.junos.junos_system:
+ hostname: junos01
+ domain_name: test.example.com
+ domain_search:
+ - ansible.com
+ - redhat.com
+ - juniper.net
+ register: configure_hostname_domain
+
+ - name: Assert hostname and domain name configured
+ assert:
+ that:
+ - configure_hostname_domain.changed == true
+
+ - name: Configure name servers
+ junipernetworks.junos.junos_system:
+ name_servers:
+ - 8.8.8.8
+ - 8.8.4.4
+ register: configure_nameservers
+
+ - name: Assert name servers configured
+ assert:
+ that:
+ - configure_nameservers.changed == true
+
+ - name: Cleanup - Remove system configuration
+ junipernetworks.junos.junos_system:
+ hostname: junos01
+ domain_name: test.example.com
+ domain_search:
+ - ansible.com
+ - redhat.com
+ - juniper.net
+ name_servers:
+ - 8.8.8.8
+ - 8.8.4.4
+ state: absent
+ register: cleanup_result
+
+ - name: Assert final clean-up
+ assert:
+ that:
+ - cleanup_result.changed == true
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_user.yml b/tests/junipernetworks.junos/pb.juniper_junos_user.yml
new file mode 100644
index 00000000..5ef05200
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_user.yml
@@ -0,0 +1,46 @@
+---
+- name: Functional Test - junos_user module
+ hosts: netconf_connection_testcases
+ gather_facts: false
+ connection: ansible.netcommon.netconf
+
+ tasks:
+ - name: Ensure test user is absent before test
+ junipernetworks.junos.junos_user:
+ name: ansible_test_user
+ state: absent
+ ignore_errors: true
+
+ - name: Create a new user account with optional SSH key
+ junipernetworks.junos.junos_user:
+ name: ansible_test_user
+ role: super-user
+ sshkey: "{{ user_ssh_key | default(omit) }}"
+ full_name: "Ansible Test User"
+ state: present
+ # Note: Provide SSH key using:
+ # ansible-playbook pb.juniper_junos_user.yml -e "user_ssh_key={{ lookup('file', '~/.ssh/id_rsa.pub') }}"
+
+ - name: Set user password (SHA-512 hashed)
+ junipernetworks.junos.junos_user:
+ name: ansible_test_user
+ role: super-user
+ encrypted_password: "{{ 'testpass123' | password_hash('sha512') }}"
+ state: present
+
+ - name: Create a list of additional users
+ junipernetworks.junos.junos_user:
+ aggregate:
+ - { name: test_user1, full_name: "Operator User", role: operator, state: present }
+ - { name: test_user2, full_name: "ReadOnly User", role: read-only, state: present }
+
+ - name: Delete additional users
+ junipernetworks.junos.junos_user:
+ aggregate:
+ - { name: test_user1, full_name: "Operator User", role: operator, state: absent }
+ - { name: test_user2, full_name: "ReadOnly User", role: read-only, state: absent }
+
+ - name: Remove the test user account
+ junipernetworks.junos.junos_user:
+ name: ansible_test_user
+ state: absent
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_vlans.yml b/tests/junipernetworks.junos/pb.juniper_junos_vlans.yml
new file mode 100644
index 00000000..6e331a3f
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_vlans.yml
@@ -0,0 +1,49 @@
+
+- name: Functional Test - junos_vlans (read-only states)
+ hosts: netconf_connection_testcases
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+
+ - name: Render VLAN configuration (dry-run XML)
+ junipernetworks.junos.junos_vlans:
+ config:
+ - name: vlan1
+ vlan_id: 1
+ - name: vlan2
+ vlan_id: 2
+ l3_interface: irb.12
+ state: rendered
+ register: result_rendered
+
+ - name: Assert rendered VLAN config
+ assert:
+ that:
+ - result_rendered.rendered is defined
+ - result_rendered.changed == false
+
+ - name: Gather VLAN configuration from device
+ junipernetworks.junos.junos_vlans:
+ state: gathered
+ register: result_gathered
+
+ - name: Assert gathered VLAN config
+ assert:
+ that:
+ - result_gathered.gathered is defined
+ - result_gathered.changed == false
+
+ - name: Parse VLAN config from XML file
+ junipernetworks.junos.junos_vlans:
+ running_config: "{{ lookup('file', 'parsed_configs/parsed_junos_vlans.cfg') }}"
+ state: parsed
+ register: result_parsed
+
+ - name: Assert parsed VLAN config
+ assert:
+ that:
+ - result_parsed.parsed is defined
+ - result_parsed.changed == false
diff --git a/tests/junipernetworks.junos/pb.juniper_junos_vrf.yml b/tests/junipernetworks.junos/pb.juniper_junos_vrf.yml
new file mode 100644
index 00000000..1af69e1a
--- /dev/null
+++ b/tests/junipernetworks.junos/pb.juniper_junos_vrf.yml
@@ -0,0 +1,69 @@
+- name: Functional Test - junos_vrf module
+ hosts: junos_device
+ gather_facts: false
+ connection: netconf
+ collections:
+ - junipernetworks.junos
+
+ tasks:
+ - name: Pre-clean conflicting routing-instances
+ junipernetworks.junos.junos_config:
+ lines:
+ - delete routing-instances test-1
+ - delete routing-instances test-2
+ comment: "Cleanup existing VRFs"
+
+ - name: Preconfigure required interfaces
+ junipernetworks.junos.junos_config:
+ lines:
+ - set interfaces ge-0/0/2.0 family inet address 192.0.2.2/24
+ - set interfaces ge-0/0/3.0 family inet address 192.0.2.3/24
+ - set interfaces ge-0/0/4.0 family inet address 192.0.2.4/24
+ - set interfaces ge-0/0/5.0 family inet address 192.0.2.5/24
+ comment: "Ensure full logical units configured"
+
+ - name: Deactivate VRF test-1
+ junipernetworks.junos.junos_vrf:
+ name: test-1
+ active: false
+ rd: 192.0.2.1:10
+ target: target:65514:113
+ interfaces:
+ - ge-0/0/3.0
+ - ge-0/0/2.0
+ description: test-vrf-1
+ register: deactivate_result
+
+ - name: Assert VRF test-1 deactivated
+ assert:
+ that: deactivate_result.changed == true
+
+ - name: Remove VRF test-1
+ junipernetworks.junos.junos_vrf:
+ name: test-1
+ description: test-vrf-1
+ interfaces:
+ - ge-0/0/3.0
+ - ge-0/0/2.0
+ rd: 192.0.2.1:10
+ target: target:65514:113
+ state: absent
+ register: remove_test1
+
+ - name: Assert VRF test-1 removed
+ assert:
+ that: remove_test1.changed == true
+
+ - name: Remove VRF test-2
+ junipernetworks.junos.junos_vrf:
+ name: test-2
+ description: test-vrf-2
+ interfaces:
+ - ge-0/0/4.0
+ - ge-0/0/5.0
+ rd: 192.0.2.2:10
+ target: target:65515:114
+ state: absent
+ register: remove_test2
+
+
diff --git a/tests/junipernetworks.junos/run_all_tests.sh b/tests/junipernetworks.junos/run_all_tests.sh
new file mode 100755
index 00000000..70a09558
--- /dev/null
+++ b/tests/junipernetworks.junos/run_all_tests.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+echo "Starting execution of all Ansible Junos playbooks..."
+echo "-----------------------------------------------------"
+
+# File to store passed test logs
+PASS_LOG="junos_passed_tests.log"
+> "$PASS_LOG" # Clear previous contents
+
+# Loop through all *.yml playbooks
+for file in pb.juniper_junos_*.yml; do
+ echo "Running $file"
+ ansible-playbook -i inventory "$file"
+ status=$?
+
+ if [ $status -ne 0 ]; then
+ echo "โ $file failed with status $status"
+ else
+ echo "โ
$file completed successfully"
+ echo "$file PASSED at $(date)" >> "$PASS_LOG"
+ fi
+
+ echo "-----------------------------------------------------"
+done
+
+echo "All playbooks processed."
+echo "Passed test results saved to $PASS_LOG"