diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 16:03:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 16:03:42 +0000 |
commit | 66cec45960ce1d9c794e9399de15c138acb18aed (patch) | |
tree | 59cd19d69e9d56b7989b080da7c20ef1a3fe2a5a /ansible_collections/cisco/iosxr/tests | |
parent | Initial commit. (diff) | |
download | ansible-66cec45960ce1d9c794e9399de15c138acb18aed.tar.xz ansible-66cec45960ce1d9c794e9399de15c138acb18aed.zip |
Adding upstream version 7.3.0+dfsg.upstream/7.3.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/cisco/iosxr/tests')
591 files changed, 34739 insertions, 0 deletions
diff --git a/ansible_collections/cisco/iosxr/tests/.gitignore b/ansible_collections/cisco/iosxr/tests/.gitignore new file mode 100644 index 00000000..ea1472ec --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/.gitignore @@ -0,0 +1 @@ +output/ diff --git a/ansible_collections/cisco/iosxr/tests/integration/target-prefixes.network b/ansible_collections/cisco/iosxr/tests/integration/target-prefixes.network new file mode 100644 index 00000000..c61a1902 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/target-prefixes.network @@ -0,0 +1 @@ +iosxr diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/_populate.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/_populate.yaml new file mode 100644 index 00000000..968b356d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/_populate.yaml @@ -0,0 +1,16 @@ +--- +- name: Populate the device with acls + cisco.iosxr.iosxr_config: + lines: + "ipv4 access-list acl_1\n10 permit ipv4 any any\nipv4 access-list acl_2\n10 permit ipv4 any any\nipv4 access-list acl_3\n10 permit ipv4 any any\nipv6 access-list\ + \ acl6_1\n10 permit ipv6 any any\nipv6 access-list acl6_2\n10 permit ipv6 any any\nipv6 access-list acl6_3\n10 permit ipv6 any any\n" + +- name: Setup ACL interfaces configuration for gigabitethernet0/0/0/0 + cisco.iosxr.iosxr_config: + lines: "ipv4 access-group acl_1 ingress\nipv4 access-group acl_2 egress\nipv6 access-group acl6_1 ingress\nipv6 access-group acl6_2 egress\n" + parents: interface GigabitEthernet0/0/0/0 + +- name: Setup ACL interfaces configuration for gigabitethernet0/0/0/1 + cisco.iosxr.iosxr_config: + lines: ipv4 access-group acl_1 egress + parents: interface GigabitEthernet0/0/0/1 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..b86f3d84 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/_remove_config.yaml @@ -0,0 +1,27 @@ +--- +- name: Remove/default resources + vars: + lines: + "default interface GigabitEthernet0/0/0/0\ndefault interface GigabitEthernet0/0/0/1\nno ipv4 access-list acl_1\nno ipv4 access-list acl_2\nno ipv6 access-list\ + \ acl6_1\nno ipv6 access-list acl6_2\nno ipv6 access-list acl6_3\n" + ansible.netcommon.cli_config: + config: "{{ lines }}" + +- name: Initialize interfaces + loop: + - interface GigabitEthernet0/0/0/0 + - interface GigabitEthernet0/0/0/1 + cisco.iosxr.iosxr_config: + lines: shutdown + parents: "{{ item }}" + +- name: Remove unwanted interfaces from configuration + loop: + - 0/0/0/2 + - 0/0/0/3 + - 0/0/0/4 + - 0/0/0/5 + ignore_errors: true + cisco.iosxr.iosxr_config: + lines: + - no interface GigabitEthernet{{ item }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/deleted.yaml new file mode 100644 index 00000000..5dfe512b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/deleted.yaml @@ -0,0 +1,31 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_acl_interfaces deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Delete ACL attributes of gigabitethernet0/0/0/1 + register: result + cisco.iosxr.iosxr_acl_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/1 + state: deleted + + - ansible.builtin.assert: + that: + - "'interface GigabitEthernet0/0/0/1' in result.commands" + - "'no ipv4 access-group acl_1 egress' in result.commands" + - result.commands|length == 2 + + - name: Delete ACL attributes of gigabitethernet0/0/0/1 (idempotent) + register: result + cisco.iosxr.iosxr_acl_interfaces: *id001 + - ansible.builtin.assert: + that: + - result.changed == False + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/deleted_all.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/deleted_all.yaml new file mode 100644 index 00000000..16f5195a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/deleted_all.yaml @@ -0,0 +1,44 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_acl_interfaces deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Delete all ACL interfaces configuration from the device + register: result + cisco.iosxr.iosxr_acl_interfaces: &id001 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Delete ACL attributes of all interfaces (idempotent) + register: result + cisco.iosxr.iosxr_acl_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + - result.commands|length == 0 + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/empty_config.yaml new file mode 100644 index 00000000..24723a9d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acl_interfaces empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_acl_interfaces: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_acl_interfaces: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_acl_interfaces: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_acl_interfaces: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_acl_interfaces: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/fixtures/parsed.cfg new file mode 100644 index 00000000..f2f4eea7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/fixtures/parsed.cfg @@ -0,0 +1,14 @@ +interface MgmtEth0/RP0/CPU0/0 + ipv4 address dhcp +! +interface GigabitEthernet0/0/0/0 + shutdown + ipv4 access-group acl_1 ingress + ipv4 access-group acl_2 egress + ipv6 access-group acl6_1 ingress + ipv6 access-group acl6_2 egress +! +interface GigabitEthernet0/0/0/1 + shutdown + ipv4 access-group acl_1 egress +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/gathered.yaml new file mode 100644 index 00000000..aaa2982d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/gathered.yaml @@ -0,0 +1,53 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acl_interfaces gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- name: Populate the device with acls + cisco.iosxr.iosxr_config: + lines: + "ipv4 access-list acl_1\n10 permit ipv4 any any\nipv4 access-list acl_2\n10 permit ipv4 any any\nipv6 access-list acl6_1\n10 permit ipv6 any any\nipv6\ + \ access-list acl6_2\n10 permit ipv6 any any\n" + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_acl_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + access_groups: + - afi: ipv4 + acls: + - name: acl_1 + direction: in + + - name: acl_2 + direction: out + + - afi: ipv6 + acls: + - name: acl6_1 + direction: in + + - name: acl6_2 + direction: out + + - name: GigabitEthernet0/0/0/1 + access_groups: + - afi: ipv4 + acls: + - name: acl_1 + direction: out + state: merged + + - name: Gather ACL interfaces facts using gathered state + register: result + cisco.iosxr.iosxr_acl_interfaces: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] | symmetric_difference(result['gathered']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/merged.yaml new file mode 100644 index 00000000..5d2708a3 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/merged.yaml @@ -0,0 +1,110 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acl_interfaces merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- name: Populate the device with acls + cisco.iosxr.iosxr_config: + lines: + "ipv4 access-list acl_1\n10 permit ipv4 any any\nipv4 access-list acl_2\n10 permit ipv4 any any\nipv6 access-list acl6_1\n10 permit ipv6 any any\nipv6\ + \ access-list acl6_2\n10 permit ipv6 any any\n" + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_acl_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + access_groups: + - afi: ipv4 + acls: + - name: acl_1 + direction: in + + - name: acl_2 + direction: out + + - afi: ipv6 + acls: + - name: acl6_1 + direction: in + + - name: acl6_2 + direction: out + + - name: GigabitEthernet0/0/0/1 + access_groups: + - afi: ipv4 + acls: + - name: acl_1 + direction: out + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['before'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_acl_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Update acl_interfaces configuration using merged + register: result + cisco.iosxr.iosxr_acl_interfaces: &id002 + config: + - name: GigabitEthernet0/0/0/1 + access_groups: + - afi: ipv4 + acls: + - name: acl_2 + direction: out + + - name: acl_1 + direction: in + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['update_before'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['update_commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['update_after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Update acl_interfaces configuration using merged (idempotent) + register: result + cisco.iosxr.iosxr_acl_interfaces: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/overridden.yaml new file mode 100644 index 00000000..80dac14c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/overridden.yaml @@ -0,0 +1,63 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acl_interfaces overridden integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Overridde all interface ACL configuration with provided configuration + register: result + cisco.iosxr.iosxr_acl_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + access_groups: + - afi: ipv6 + acls: + - name: acl6_3 + direction: in + + - name: GigabitEthernet0/0/0/1 + access_groups: + - afi: ipv4 + acls: + - name: acl_2 + direction: in + + - afi: ipv6 + acls: + - name: acl6_3 + direction: out + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Overridde all interface ACL configuration with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_acl_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/parsed.yaml new file mode 100644 index 00000000..7e091090 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acl_interfaces parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided ACL interfaces configuration to agnostic model + register: result + cisco.iosxr.iosxr_acl_interfaces: + running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['parsed']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/rendered.yaml new file mode 100644 index 00000000..7d84155f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/rendered.yaml @@ -0,0 +1,38 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acl_interfaces rendered integration tests on connection={{ ansible_connection }} + +- name: Render platform specific commands from task input using rendered state + register: result + cisco.iosxr.iosxr_acl_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + access_groups: + - afi: ipv4 + acls: + - name: acl_1 + direction: in + + - name: acl_2 + direction: out + + - afi: ipv6 + acls: + - name: acl6_1 + direction: in + + - name: acl6_2 + direction: out + + - name: GigabitEthernet0/0/0/1 + access_groups: + - afi: ipv4 + acls: + - name: acl_1 + direction: out + state: rendered + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['rendered']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/replaced.yaml new file mode 100644 index 00000000..dc480ce5 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/replaced.yaml @@ -0,0 +1,51 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acl_interfaces replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Replace device configurations of listed interface with provided configurations + register: result + cisco.iosxr.iosxr_acl_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + access_groups: + - afi: ipv6 + acls: + - name: acl6_3 + direction: in + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Replace device configurations of listed interfaces with provided configurarions (idempotent) + register: result + cisco.iosxr.iosxr_acl_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/rtt.yaml new file mode 100644 index 00000000..a87c7df6 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/tests/cli/rtt.yaml @@ -0,0 +1,95 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acl_interfaces round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Populate the device with acls + cisco.iosxr.iosxr_config: + lines: + "ipv4 access-list acl_1\n10 permit ipv4 any any\nipv4 access-list acl_2\n10 permit ipv4 any any\nipv4 access-list acl_3\n10 permit ipv4 any any\nipv6\ + \ access-list acl6_1\n10 permit ipv6 any any\nipv6 access-list acl6_2\n10 permit ipv6 any any\nipv6 access-list acl6_3\n10 permit ipv6 any any\n" + + - name: Apply the provided configuration (base config) + cisco.iosxr.iosxr_acl_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + access_groups: + - afi: ipv4 + acls: + - name: acl_1 + direction: in + + - name: acl_2 + direction: out + + - afi: ipv6 + acls: + - name: acl6_1 + direction: in + + - name: acl6_2 + direction: out + + - name: GigabitEthernet0/0/0/1 + access_groups: + - afi: ipv4 + acls: + - name: acl_1 + direction: out + state: merged + + - name: Gather interfaces facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - acl_interfaces + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_acl_interfaces: + config: + - name: GigabitEthernet0/0/0/1 + access_groups: + - afi: ipv4 + acls: + - name: acl_1 + direction: in + + - name: acl_2 + direction: out + + - afi: ipv6 + acls: + - name: acl6_1 + direction: in + + - name: acl6_2 + direction: out + + - name: GigabitEthernet0/0/0/0 + access_groups: + - afi: ipv4 + acls: + - name: acl_1 + direction: out + state: overridden + + - name: Assert that changes were applied + ansible.builtin.assert: + that: "{{ round_trip['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_acl_interfaces: + config: "{{ ansible_facts['network_resources']['acl_interfaces'] }}" + state: overridden + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: "{{ merged['after'] | symmetric_difference(revert['after']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/vars/main.yaml new file mode 100644 index 00000000..f5f138d8 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acl_interfaces/vars/main.yaml @@ -0,0 +1,172 @@ +--- +merged: + before: + - name: MgmtEth0/RP0/CPU0/0 + - name: GigabitEthernet0/0/0/0 + - name: GigabitEthernet0/0/0/1 + commands: + - interface GigabitEthernet0/0/0/0 + - ipv4 access-group acl_1 ingress + - ipv4 access-group acl_2 egress + - ipv6 access-group acl6_1 ingress + - ipv6 access-group acl6_2 egress + - interface GigabitEthernet0/0/0/1 + - ipv4 access-group acl_1 egress + update_commands: + - interface GigabitEthernet0/0/0/1 + - ipv4 access-group acl_2 egress + - ipv4 access-group acl_1 ingress + after: + - name: MgmtEth0/RP0/CPU0/0 + - name: GigabitEthernet0/0/0/0 + access_groups: + - acls: + - name: acl_1 + direction: in + - name: acl_2 + direction: out + afi: ipv4 + - acls: + - name: acl6_1 + direction: in + - name: acl6_2 + direction: out + afi: ipv6 + - name: GigabitEthernet0/0/0/1 + access_groups: + - acls: + - name: acl_1 + direction: out + afi: ipv4 + update_before: + - name: MgmtEth0/RP0/CPU0/0 + - access_groups: + - acls: + - direction: in + name: acl_1 + - direction: out + name: acl_2 + afi: ipv4 + - acls: + - direction: in + name: acl6_1 + - direction: out + name: acl6_2 + afi: ipv6 + name: GigabitEthernet0/0/0/0 + - access_groups: + - acls: + - direction: out + name: acl_1 + afi: ipv4 + name: GigabitEthernet0/0/0/1 + update_after: + - name: MgmtEth0/RP0/CPU0/0 + - access_groups: + - acls: + - direction: in + name: acl_1 + - direction: out + name: acl_2 + afi: ipv4 + - acls: + - direction: in + name: acl6_1 + - direction: out + name: acl6_2 + afi: ipv6 + name: GigabitEthernet0/0/0/0 + - access_groups: + - acls: + - direction: in + name: acl_1 + - direction: out + name: acl_2 + afi: ipv4 + name: GigabitEthernet0/0/0/1 +replaced: + commands: + - interface GigabitEthernet0/0/0/0 + - no ipv4 access-group acl_1 ingress + - no ipv4 access-group acl_2 egress + - no ipv6 access-group acl6_2 egress + - ipv6 access-group acl6_3 ingress + after: + - name: MgmtEth0/RP0/CPU0/0 + - name: GigabitEthernet0/0/0/0 + access_groups: + - afi: ipv6 + acls: + - name: acl6_3 + direction: in + - name: GigabitEthernet0/0/0/1 + access_groups: + - acls: + - name: acl_1 + direction: out + afi: ipv4 +overridden: + commands: + - interface GigabitEthernet0/0/0/0 + - no ipv4 access-group acl_1 ingress + - no ipv4 access-group acl_2 egress + - no ipv6 access-group acl6_2 egress + - ipv6 access-group acl6_3 ingress + - interface GigabitEthernet0/0/0/1 + - no ipv4 access-group acl_1 egress + - ipv4 access-group acl_2 ingress + - ipv6 access-group acl6_3 egress + after: + - name: MgmtEth0/RP0/CPU0/0 + - name: GigabitEthernet0/0/0/0 + access_groups: + - afi: ipv6 + acls: + - name: acl6_3 + direction: in + - name: GigabitEthernet0/0/0/1 + access_groups: + - acls: + - name: acl_2 + direction: in + afi: ipv4 + - acls: + - name: acl6_3 + direction: out + afi: ipv6 +deleted: + commands: + - interface GigabitEthernet0/0/0/0 + - no ipv4 access-group acl_1 ingress + - no ipv4 access-group acl_2 egress + - no ipv6 access-group acl6_1 ingress + - no ipv6 access-group acl6_2 egress + - interface GigabitEthernet0/0/0/1 + - no ipv4 access-group acl_1 egress + after: + - name: MgmtEth0/RP0/CPU0/0 + - name: GigabitEthernet0/0/0/0 + - name: GigabitEthernet0/0/0/1 +round_trip: + after: + - name: MgmtEth0/RP0/CPU0/0 + - access_groups: + - acls: + - direction: out + name: acl_1 + afi: ipv4 + name: GigabitEthernet0/0/0/0 + - access_groups: + - acls: + - direction: in + name: acl_1 + - direction: out + name: acl_2 + afi: ipv4 + - acls: + - direction: in + name: acl6_1 + - direction: out + name: acl6_2 + afi: ipv6 + name: GigabitEthernet0/0/0/1 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/_populate_config.yaml new file mode 100644 index 00000000..423b8f2b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/_populate_config.yaml @@ -0,0 +1,10 @@ +--- +- name: Setup + cisco.iosxr.iosxr_config: + lines: + "ipv6 access-list acl6_1\n10 deny tcp 2001:db8:1234::/48 range ftp telnet\ + \ any syn ttl range 180 250 authen routing log\n20 permit icmpv6 any any router-advertisement\ + \ precedence network destopts\nipv4 access-list acl_1\n16 remark TEST_ACL_1_REMARK\n\ + 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst\n23\ + \ deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12\nipv4\ + \ access-list acl_2\n10 remark TEST_ACL_2_REMARK" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..2585c995 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/_remove_config.yaml @@ -0,0 +1,9 @@ +--- +- name: Remove acls + vars: + lines: + "no ipv4 access-list acl_1\nno ipv4 access-list acl_2\nno ipv4 access-list acl_3\nno ipv4 access-list acl_3\nno ipv6 access-list acl6_1\nno ipv6 access-list\ + \ acl6_2\nno ipv6 access-list acl6_3\n" + ignore_errors: true + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/deleted.yaml new file mode 100644 index 00000000..2c7c5ab4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/deleted.yaml @@ -0,0 +1,87 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_lag_interfaces deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete a single ACL + register: result + cisco.iosxr.iosxr_acls: &id001 + config: + - afi: ipv6 + acls: + - name: acl6_1 + state: deleted + + - ansible.builtin.assert: + that: + - '"no ipv6 access-list acl6_1" in result.commands' + - result.commands|length == 1 + + - name: Delete a single ACL (idempotent) + register: result + cisco.iosxr.iosxr_acls: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: &id003 + that: + - result.changed == false + - result.commands|length == 0 + + - name: Delete all acls under one AFI + register: result + cisco.iosxr.iosxr_acls: &id002 + config: + - afi: ipv4 + state: deleted + + - ansible.builtin.assert: + that: + - '"no ipv4 access-list acl_1" in result.commands' + - '"no ipv4 access-list acl_2" in result.commands' + - result.commands|length == 2 + + - name: Delete all acls under one AFI (idempotent) + register: result + cisco.iosxr.iosxr_acls: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: *id003 + - ansible.builtin.include_tasks: _populate_config.yaml + + - name: Delete all acls from the device + register: result + cisco.iosxr.iosxr_acls: &id004 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Delete all acls from the device (idempotent) + register: result + cisco.iosxr.iosxr_acls: *id004 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + - result.commands|length == 0 + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/empty_config.yaml new file mode 100644 index 00000000..ac6fa61b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acls empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_acls: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_acls: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_acls: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_acls: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_acls: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/fixtures/parsed.cfg new file mode 100644 index 00000000..f1da89bb --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/fixtures/parsed.cfg @@ -0,0 +1,8 @@ +ipv4 access-list acl_1 + 10 remark TEST_ACL_2_REMARK +ipv4 access-list acl_2 + 11 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 authen routing log + 21 permit icmpv6 any any router-advertisement precedence network packet-length eq 576 destopts +ipv6 access-list acl6_1 + 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log + 20 permit icmpv6 any any router-advertisement precedence network packet-length eq 576 destopts diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/gathered.yaml new file mode 100644 index 00000000..7abdcc24 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/gathered.yaml @@ -0,0 +1,19 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acls gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Gather ACL interfaces facts using gathered state + register: result + cisco.iosxr.iosxr_acls: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] | symmetric_difference(result['gathered']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/merged.yaml new file mode 100644 index 00000000..d1bfdfc0 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/merged.yaml @@ -0,0 +1,165 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acls merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_acls: &id001 + config: + - afi: ipv6 + acls: + - name: acl6_1 + aces: + - sequence: 10 + grant: deny + protocol: tcp + source: + prefix: 2001:db8:1234::/48 + port_protocol: + range: + start: ftp + end: telnet + destination: + any: true + protocol_options: + tcp: + syn: true + ttl: + range: + start: 180 + end: 250 + routing: true + authen: true + log: true + + - sequence: 20 + grant: permit + protocol: icmpv6 + source: + any: true + destination: + any: true + protocol_options: + icmpv6: + router_advertisement: true + precedence: network + destopts: true + + - afi: ipv4 + acls: + - name: acl_1 + aces: + - sequence: 16 + remark: TEST_ACL_1_REMARK + + - sequence: 21 + grant: permit + protocol: tcp + source: + host: 192.0.2.10 + port_protocol: + range: + start: pop3 + end: 121 + destination: + address: 198.51.100.0 + wildcard_bits: 0.0.0.15 + protocol_options: + tcp: + rst: true + + - sequence: 23 + grant: deny + protocol: icmp + source: + any: true + destination: + prefix: 198.51.100.0/28 + protocol_options: + icmp: + reassembly_timeout: true + dscp: + lt: af12 + + - name: acl_2 + aces: + - sequence: 10 + remark: TEST_ACL_2_REMARK + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['before'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_acls: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Update existing aces + register: result + cisco.iosxr.iosxr_acls: &id002 + config: + - afi: ipv4 + acls: + - name: acl_1 + aces: + - sequence: 21 + source: + prefix: 198.51.100.32/28 + port_protocol: + range: + start: pop3 + end: 121 + protocol_options: + tcp: + syn: true + + - sequence: 23 + protocol_options: + icmp: + router_advertisement: true + dscp: + eq: af23 + state: merged + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - '"ipv4 access-list acl_1" in result.commands' + - '"21 permit tcp 198.51.100.32 0.0.0.15 range pop3 121 198.51.100.0 0.0.0.15 syn" in result.commands' + - '"23 deny icmp any 198.51.100.0 0.0.0.15 router-advertisement dscp eq af23" in result.commands' + - result.commands|length == 3 + + - name: Update existing aces (idempotent) + register: result + cisco.iosxr.iosxr_acls: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/overridden.yaml new file mode 100644 index 00000000..c73c1ff5 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/overridden.yaml @@ -0,0 +1,66 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acls overridden integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Overridde all acls configuration with provided configuration + register: result + cisco.iosxr.iosxr_acls: &id001 + config: + - afi: ipv4 + acls: + - name: acl_1 + aces: + - sequence: 10 + grant: permit + source: + any: true + destination: + any: true + protocol: tcp + + - name: acl_2 + aces: + - sequence: 20 + grant: permit + source: + any: true + destination: + any: true + protocol: igmp + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Overridde all interface lag interface configuration with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_acls: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/parsed.yaml new file mode 100644 index 00000000..ce3bbfe4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acls parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided ACL configuration to agnostic model + register: result + cisco.iosxr.iosxr_acls: + running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ parsed | symmetric_difference(result['parsed']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/rendered.yaml new file mode 100644 index 00000000..559de6c0 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/rendered.yaml @@ -0,0 +1,93 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acls rendered integration tests on connection={{ ansible_connection }} + +- name: Render platform specific commands from task input using rendered state + register: result + cisco.iosxr.iosxr_acls: + config: + - afi: ipv6 + acls: + - name: acl6_1 + aces: + - sequence: 10 + grant: deny + protocol: tcp + source: + prefix: 2001:db8:1234::/48 + port_protocol: + range: + start: ftp + end: telnet + destination: + any: true + protocol_options: + tcp: + syn: true + ttl: + range: + start: 180 + end: 250 + routing: true + authen: true + log: true + + - sequence: 20 + grant: permit + protocol: icmpv6 + source: + any: true + destination: + any: true + protocol_options: + icmpv6: + router_advertisement: true + precedence: network + destopts: true + + - afi: ipv4 + acls: + - name: acl_1 + aces: + - sequence: 16 + remark: TEST_ACL_1_REMARK + + - sequence: 21 + grant: permit + protocol: tcp + source: + host: 192.0.2.10 + port_protocol: + range: + start: pop3 + end: 121 + destination: + address: 198.51.100.0 + wildcard_bits: 0.0.0.15 + protocol_options: + tcp: + rst: true + + - sequence: 23 + grant: deny + protocol: icmp + source: + any: true + destination: + prefix: 198.51.100.0/28 + protocol_options: + icmp: + reassembly_timeout: true + dscp: + lt: af12 + + - name: acl_2 + aces: + - sequence: 10 + remark: TEST_ACL_2_REMARK + state: rendered + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['rendered']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/replaced.yaml new file mode 100644 index 00000000..14c1137a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/replaced.yaml @@ -0,0 +1,66 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acl_interfaces replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replace device configurations of listed ACL with provided configurations + register: result + cisco.iosxr.iosxr_acls: &id001 + config: + - afi: ipv4 + acls: + - name: acl_2 + aces: + - sequence: 11 + grant: permit + protocol: igmp + source: + host: 198.51.100.130 + destination: + any: true + ttl: + eq: 100 + + - sequence: 12 + grant: deny + source: + any: true + destination: + any: true + protocol: icmp + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Replace device configurations of listed interfaces with provided configurarions (idempotent) + register: result + cisco.iosxr.iosxr_acls: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/rtt.yaml new file mode 100644 index 00000000..34e09675 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/tests/cli/rtt.yaml @@ -0,0 +1,84 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_acls round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Apply the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_acls: + config: + - afi: ipv4 + acls: + - name: acl_2 + aces: + - sequence: 11 + grant: permit + protocol: igmp + source: + host: 198.51.100.130 + destination: + any: true + ttl: + eq: 100 + + - sequence: 12 + grant: deny + source: + any: true + destination: + any: true + protocol: icmp + state: merged + + - name: Gather interfaces facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - acls + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_acls: + config: + - afi: ipv4 + acls: + - name: acl_1 + aces: + - sequence: 10 + grant: permit + source: + any: true + destination: + any: true + protocol: tcp + + - name: acl_2 + aces: + - sequence: 20 + grant: permit + source: + any: true + destination: + any: true + protocol: igmp + state: overridden + + - name: Assert that changes were applied + ansible.builtin.assert: + that: "{{ overridden['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_acls: + config: "{{ ansible_facts['network_resources']['acls'] }}" + state: overridden + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: "{{ base_config['after'] | symmetric_difference(revert['after']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/vars/main.yaml new file mode 100644 index 00000000..41e4b0fc --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_acls/vars/main.yaml @@ -0,0 +1,317 @@ +--- +merged: + before: [] + commands: + - ipv6 access-list acl6_1 + - 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 authen + routing log + - 20 permit icmpv6 any any router-advertisement precedence network destopts + - ipv4 access-list acl_1 + - 16 remark TEST_ACL_1_REMARK + - 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst + - 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12 + - ipv4 access-list acl_2 + - 10 remark TEST_ACL_2_REMARK + after: + - acls: + - aces: + - remark: TEST_ACL_1_REMARK + sequence: 16 + - destination: + address: 198.51.100.0 + wildcard_bits: 0.0.0.15 + grant: permit + protocol: tcp + protocol_options: + tcp: + rst: true + sequence: 21 + source: + host: 192.0.2.10 + port_protocol: + range: + end: "121" + start: pop3 + - destination: + address: 198.51.100.0 + wildcard_bits: 0.0.0.15 + dscp: + lt: af12 + grant: deny + protocol: icmp + protocol_options: + icmp: + reassembly_timeout: true + sequence: 23 + source: + any: true + name: acl_1 + - aces: + - remark: TEST_ACL_2_REMARK + sequence: 10 + name: acl_2 + afi: ipv4 + - acls: + - aces: + - authen: true + destination: + any: true + grant: deny + log: true + protocol: tcp + protocol_options: + tcp: + syn: true + routing: true + sequence: 10 + source: + port_protocol: + range: + end: telnet + start: ftp + prefix: 2001:db8:1234::/48 + ttl: + range: + end: 250 + start: 180 + - destination: + any: true + destopts: true + grant: permit + precedence: network + protocol: icmpv6 + protocol_options: + icmpv6: + router_advertisement: true + sequence: 20 + source: + any: true + name: acl6_1 + afi: ipv6 +replaced: + commands: + - ipv4 access-list acl_2 + - no 10 + - 11 permit igmp host 198.51.100.130 any ttl eq 100 + - 12 deny icmp any any + after: + - acls: + - aces: + - remark: TEST_ACL_1_REMARK + sequence: 16 + - destination: + address: 198.51.100.0 + wildcard_bits: 0.0.0.15 + grant: permit + protocol: tcp + protocol_options: + tcp: + rst: true + sequence: 21 + source: + host: 192.0.2.10 + port_protocol: + range: + end: "121" + start: pop3 + - destination: + address: 198.51.100.0 + wildcard_bits: 0.0.0.15 + dscp: + lt: af12 + grant: deny + protocol: icmp + protocol_options: + icmp: + reassembly_timeout: true + sequence: 23 + source: + any: true + name: acl_1 + - aces: + - destination: + any: true + grant: permit + protocol: igmp + sequence: 11 + source: + host: 198.51.100.130 + ttl: + eq: 100 + - destination: + any: true + grant: deny + protocol: icmp + sequence: 12 + source: + any: true + name: acl_2 + afi: ipv4 + - acls: + - aces: + - authen: true + destination: + any: true + grant: deny + log: true + protocol: tcp + protocol_options: + tcp: + syn: true + routing: true + sequence: 10 + source: + port_protocol: + range: + end: telnet + start: ftp + prefix: 2001:db8:1234::/48 + ttl: + range: + end: 250 + start: 180 + - destination: + any: true + destopts: true + grant: permit + precedence: network + protocol: icmpv6 + protocol_options: + icmpv6: + router_advertisement: true + sequence: 20 + source: + any: true + name: acl6_1 + afi: ipv6 +overridden: + commands: + - no ipv6 access-list acl6_1 + - ipv4 access-list acl_1 + - no 16 + - no 21 + - no 23 + - 10 permit tcp any any + - ipv4 access-list acl_2 + - no 10 + - 20 permit igmp any any + after: + - acls: + - aces: + - destination: + any: true + grant: permit + protocol: tcp + sequence: 10 + source: + any: true + name: acl_1 + - aces: + - destination: + any: true + grant: permit + protocol: igmp + sequence: 20 + source: + any: true + name: acl_2 + afi: ipv4 +deleted: + commands: + - no ipv4 access-list acl_1 + - no ipv4 access-list acl_2 + - no ipv6 access-list acl6_1 + after: [] +parsed: + - acls: + - aces: + - remark: TEST_ACL_2_REMARK + sequence: 10 + name: acl_1 + - aces: + - authen: true + destination: + any: true + grant: deny + log: true + protocol: tcp + protocol_options: + tcp: + syn: true + routing: true + sequence: 11 + source: + port_protocol: + range: + end: telnet + start: ftp + prefix: 2001:db8:1234::/48 + ttl: + range: + end: 250 + start: 180 + - destination: + any: true + destopts: true + grant: permit + packet_length: + eq: 576 + precedence: network + protocol: icmpv6 + protocol_options: + icmpv6: + router_advertisement: true + sequence: 21 + source: + any: true + name: acl_2 + afi: ipv4 + - acls: + - aces: + - authen: true + destination: + any: true + grant: deny + log: true + protocol: tcp + protocol_options: + tcp: + syn: true + routing: true + sequence: 10 + source: + port_protocol: + range: + end: telnet + start: ftp + prefix: 2001:db8:1234::/48 + ttl: + range: + end: 250 + start: 180 + - destination: + any: true + destopts: true + grant: permit + packet_length: + eq: 576 + precedence: network + protocol: icmpv6 + protocol_options: + icmpv6: + router_advertisement: true + sequence: 20 + source: + any: true + name: acl6_1 + afi: ipv6 +round_trip: + after: + - members: + - member: GigabitEthernet0/0/0/8 + mode: passive + - member: GigabitEthernet0/0/0/9 + mode: active + name: Bundle-Ether10 + - mode: active + name: Bundle-Ether11 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/defaults/main.yaml new file mode 100644 index 00000000..9ef5ba51 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/meta/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/meta/main.yaml new file mode 100644 index 00000000..be631e5d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_iosxr_tests diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tasks/cli.yaml new file mode 100644 index 00000000..59a889b4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tasks/main.yaml new file mode 100644 index 00000000..419a6cde --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tasks/main.yaml @@ -0,0 +1,6 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + +- name: Include the netconf tasks + ansible.builtin.include_tasks: netconf.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tasks/netconf.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tasks/netconf.yaml new file mode 100644 index 00000000..8ff2ae68 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tasks/netconf.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all netconf test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/netconf" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test cases (connection=ansible.netcommon.netconf) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.netconf + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - netconf diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/cli/basic-login.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/cli/basic-login.yaml new file mode 100644 index 00000000..6a15c6b6 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/cli/basic-login.yaml @@ -0,0 +1,37 @@ +--- +- name: Pause for 1 min + ansible.builtin.pause: + minutes: 1 + +- name: Setup - remove login + cisco.iosxr.iosxr_banner: + banner: login + state: absent + +- name: Set login + register: result + cisco.iosxr.iosxr_banner: + banner: login + text: "@this is my login banner\nthat has a multiline\nstring\n@" + state: present + +- ansible.builtin.debug: + msg: "{{ result }}" + +- ansible.builtin.assert: + that: + - result.changed == true + - "'this is my login banner' in result.commands[0]" + - "'that has a multiline' in result.commands[0]" + +- name: Set login again (idempotent) + register: result + cisco.iosxr.iosxr_banner: + banner: login + text: "@this is my login banner\nthat has a multiline\nstring\n@" + state: present + +- ansible.builtin.assert: + that: + - result.changed == false + - result.commands | length == 0 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/cli/basic-motd.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/cli/basic-motd.yaml new file mode 100644 index 00000000..3117ad79 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/cli/basic-motd.yaml @@ -0,0 +1,37 @@ +--- +- name: Pause for 1 min + ansible.builtin.pause: + minutes: 1 + +- name: Setup - remove MOTD + cisco.iosxr.iosxr_banner: + banner: motd + state: absent + +- name: Set MOTD + register: result + cisco.iosxr.iosxr_banner: + banner: motd + text: "@this is my motd banner\nthat has a multiline\nstring\n@" + state: present + +- ansible.builtin.debug: + msg: "{{ result }}" + +- ansible.builtin.assert: + that: + - result.changed == true + - "'this is my motd banner' in result.commands[0]" + - "'that has a multiline' in result.commands[0]" + +- name: Set MOTD again (idempotent) + register: result + cisco.iosxr.iosxr_banner: + banner: motd + text: "@this is my motd banner\nthat has a multiline\nstring\n@" + state: present + +- ansible.builtin.assert: + that: + - result.changed == false + - result.commands | length == 0 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/cli/basic-no-login.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/cli/basic-no-login.yaml new file mode 100644 index 00000000..ce30de3f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/cli/basic-no-login.yaml @@ -0,0 +1,35 @@ +--- +- name: Pause for 1 min + ansible.builtin.pause: + minutes: 1 + +- name: Setup + cisco.iosxr.iosxr_banner: + banner: login + text: "@Junk login banner\nover multiple lines\n@" + state: present + +- name: Remove login + register: result + cisco.iosxr.iosxr_banner: + banner: login + state: absent + +- ansible.builtin.debug: + msg: "{{ result }}" + +- ansible.builtin.assert: + that: + - result.changed == true + - "'no banner login' in result.commands[0]" + +- name: Remove login (idempotent) + register: result + cisco.iosxr.iosxr_banner: + banner: login + state: absent + +- ansible.builtin.assert: + that: + - result.changed == false + - result.commands | length == 0 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/netconf/basic-login.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/netconf/basic-login.yaml new file mode 100644 index 00000000..f1262c45 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/netconf/basic-login.yaml @@ -0,0 +1,37 @@ +--- +- name: Sleep for 30 seconds and continue with play + ansible.builtin.wait_for: + timeout: 30 + +- name: Setup - remove login + cisco.iosxr.iosxr_banner: + banner: login + state: absent + +- name: Set login + register: result + cisco.iosxr.iosxr_banner: + banner: login + text: "@this is my login banner\nthat has a multiline\nstring\n@" + state: present + +- ansible.builtin.debug: + msg: "{{ result }}" + +- ansible.builtin.assert: + that: + - result.changed == true + - "'this is my login banner' in result.xml" + - "'that has a multiline' in result.xml" + +- name: Set login again (idempotent) + register: result + cisco.iosxr.iosxr_banner: + banner: login + text: "@this is my login banner\nthat has a multiline\nstring\n@" + state: present + +- ansible.builtin.assert: + that: + - result.changed == false + - result.xml | length == 0 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/netconf/basic-motd.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/netconf/basic-motd.yaml new file mode 100644 index 00000000..6fe84dea --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/netconf/basic-motd.yaml @@ -0,0 +1,37 @@ +--- +- name: Sleep for 30 seconds and continue with play + ansible.builtin.wait_for: + timeout: 30 + +- name: Setup - remove MOTD + cisco.iosxr.iosxr_banner: + banner: motd + state: absent + +- name: Set MOTD + register: result + cisco.iosxr.iosxr_banner: + banner: motd + text: "@this is my motd banner\nthat has a multiline\nstring\n@" + state: present + +- ansible.builtin.debug: + msg: "{{ result }}" + +- ansible.builtin.assert: + that: + - result.changed == true + - "'this is my motd banner' in result.xml" + - "'that has a multiline' in result.xml" + +- name: Set MOTD again (idempotent) + register: result + cisco.iosxr.iosxr_banner: + banner: motd + text: "@this is my motd banner\nthat has a multiline\nstring\n@" + state: present + +- ansible.builtin.assert: + that: + - result.changed == false + - result.xml | length == 0 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/netconf/basic-no-login.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/netconf/basic-no-login.yaml new file mode 100644 index 00000000..9c2d06ed --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_banner/tests/netconf/basic-no-login.yaml @@ -0,0 +1,34 @@ +--- +- name: Sleep for 30 seconds and continue with play + ansible.builtin.wait_for: + timeout: 30 + +- name: Setup + cisco.iosxr.iosxr_banner: + banner: login + text: "@Junk login banner\nover multiple lines\n@" + state: present + +- name: Remove login + register: result + cisco.iosxr.iosxr_banner: + banner: login + state: absent +- ansible.builtin.debug: + msg: "{{ result }}" + +- ansible.builtin.assert: + that: + - result.changed == true + - '''xc:operation="delete"'' in result.xml' + +- name: Remove login (idempotent) + register: result + cisco.iosxr.iosxr_banner: + banner: login + state: absent + +- ansible.builtin.assert: + that: + - result.changed == false + - result.xml | length == 0 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/defaults/main.yaml new file mode 100644 index 00000000..9ef5ba51 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/meta/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/meta/main.yaml new file mode 100644 index 00000000..be631e5d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_iosxr_tests diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/tasks/cli.yaml new file mode 100644 index 00000000..29e7f60c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/tasks/cli.yaml @@ -0,0 +1,19 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/tests/cli/basic.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/tests/cli/basic.yaml new file mode 100644 index 00000000..608a4400 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp/tests/cli/basic.yaml @@ -0,0 +1,239 @@ +--- +- ansible.builtin.debug: msg="START iosxr cli/iosxr_bgp.yaml on connection={{ ansible_connection }}" + +- name: Check ios-xr version + register: facts + cisco.iosxr.iosxr_facts: + gather_subset: default + +- block: + - name: Clear existing BGP configuration + ignore_errors: true + cisco.iosxr.iosxr_bgp: + operation: delete + + - name: Configure BGP with as 64496 and a router-id + register: result + cisco.iosxr.iosxr_bgp: &id001 + operation: merge + config: + bgp_as: 64496 + router_id: 192.0.2.2 + + - ansible.builtin.assert: + that: + - result.changed == true + - "'router bgp 64496' in result.commands" + - "'bgp router-id 192.0.2.2' in result.commands" + + - name: Configure BGP with as 64496 and a router-id (idempotent) + register: result + cisco.iosxr.iosxr_bgp: *id001 + - ansible.builtin.assert: + that: + - result.changed == false + + - name: Configure BGP neighbors + register: result + cisco.iosxr.iosxr_bgp: &id002 + operation: merge + config: + bgp_as: 64496 + neighbors: + - neighbor: 192.0.2.10 + remote_as: 64496 + description: IBGP_NBR_1 + advertisement_interval: 120 + timers: + keepalive: 300 + holdtime: 360 + + - neighbor: 192.0.2.15 + remote_as: 64496 + description: IBGP_NBR_2 + tcp_mss: 1500 + + - ansible.builtin.assert: + that: + - result.changed == true + - "'router bgp 64496' in result.commands" + - "'neighbor 192.0.2.10' in result.commands" + - "'remote-as 64496' in result.commands" + - "'description IBGP_NBR_1' in result.commands" + - "'timers 300 360' in result.commands" + - "'advertisement-interval 120' in result.commands" + - "'neighbor 192.0.2.15' in result.commands" + - "'remote-as 64496' in result.commands" + - "'description IBGP_NBR_2' in result.commands" + - "'tcp mss 1500' in result.commands" + + - name: Configure BGP neighbors (idempotent) + register: result + cisco.iosxr.iosxr_bgp: *id002 + - ansible.builtin.assert: + that: + - result.changed == false + + - name: Configure BGP neighbors with operation replace + register: result + cisco.iosxr.iosxr_bgp: &id003 + operation: replace + config: + bgp_as: 64496 + neighbors: + - neighbor: 192.0.2.15 + remote_as: 64496 + description: IBGP_NBR_2 + tcp_mss: 1500 + + - neighbor: 203.0.113.10 + remote_as: 64511 + description: EBGP_NBR_1 + + - ansible.builtin.assert: + that: + - result.changed == true + - "'neighbor 203.0.113.10' in result.commands" + - "'remote-as 64511' in result.commands" + - "'description EBGP_NBR_1' in result.commands" + - "'no neighbor 192.0.2.10' in result.commands" + + - name: Configure BGP neighbors with operation replace (idempotent) + register: result + cisco.iosxr.iosxr_bgp: *id003 + - ansible.builtin.assert: + that: + - result.changed == false + + - name: Create route-policy as prerequisite for BGP configuration + register: result + cisco.iosxr.iosxr_config: + lines: + - no route-policy RMAP_1 + - route-policy RMAP_1 + - exit + + - name: Configure networks under address family + register: result + cisco.iosxr.iosxr_bgp: &id004 + operation: merge + config: + bgp_as: 64496 + address_family: + - afi: ipv4 + networks: + - prefix: 198.51.100.48 + masklen: 28 + route_map: RMAP_1 + + - prefix: 192.0.2.64 + masklen: 27 + + - prefix: 203.0.113.160 + masklen: 27 + + - afi: ipv4 + safi: multicast + networks: + - prefix: 198.51.100.64 + masklen: 28 + + - ansible.builtin.assert: + that: + - result.changed == true + - "'router bgp 64496' in result.commands" + - "'address-family ipv4 unicast' in result.commands" + - "'network 198.51.100.48/28 route-policy RMAP_1' in result.commands" + - "'network 192.0.2.64/27' in result.commands" + - "'network 203.0.113.160/27' in result.commands" + - "'address-family ipv4 multicast' in result.commands" + - "'network 198.51.100.64/28' in result.commands" + + - name: Configure networks under address family (idempotent) + register: result + cisco.iosxr.iosxr_bgp: *id004 + - ansible.builtin.assert: + that: + - result.changed == false + + - name: Configure networks under address family with operation replace + register: result + cisco.iosxr.iosxr_bgp: &id005 + operation: replace + config: + bgp_as: 64496 + address_family: + - afi: ipv4 + safi: unicast + networks: + - prefix: 198.51.100.80 + masklen: 28 + + - prefix: 192.0.2.64 + masklen: 27 + + - prefix: 203.0.113.192 + masklen: 27 + + - afi: ipv4 + safi: multicast + networks: + - prefix: 198.51.100.64 + masklen: 28 + + - ansible.builtin.assert: + that: + - result.changed == true + - '"router bgp 64496" in result.commands' + - '"address-family ipv4 unicast" in result.commands' + - '"network 198.51.100.80/28" in result.commands' + - '"network 203.0.113.192/27" in result.commands' + - '"no network 198.51.100.48/28" in result.commands' + - '"no network 203.0.113.160/27" in result.commands' + + - name: Configure networks under address family with operation replace (idempotent) + register: result + cisco.iosxr.iosxr_bgp: *id005 + - ansible.builtin.assert: + that: + - result.changed == false + + - name: Override all the existing BGP configuration + register: result + cisco.iosxr.iosxr_bgp: + operation: override + config: + bgp_as: 64497 + router_id: 192.0.2.10 + log_neighbor_changes: true + + - ansible.builtin.assert: + that: + - result.changed == true + - "'router bgp 64497' in result.commands" + - "'bgp router-id 192.0.2.10' in result.commands" + - "'bgp log neighbor changes detail' in result.commands" + + - name: Teardown + register: result + cisco.iosxr.iosxr_bgp: &id006 + operation: delete + + - ansible.builtin.assert: + that: + - result.changed == true + - "'no router bgp 64497' in result.commands" + + - name: Teardown again (idempotent) + register: result + cisco.iosxr.iosxr_bgp: *id006 + - ansible.builtin.assert: + that: + - result.changed == false + + - name: Delete route-policy configures as prerequisite for BGP configuration (teardown) + cisco.iosxr.iosxr_config: + lines: no route-policy RMAP_1 + when: facts['ansible_facts']['ansible_net_version'].split('[')[0] == '6.1.3' + +- ansible.builtin.debug: msg="END iosxr cli/iosxr_bgp.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/defaults/main.yaml new file mode 100644 index 00000000..871ea460 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "[^_].*" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/meta/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/meta/main.yaml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/meta/main.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tasks/cli.yaml new file mode 100644 index 00000000..a1b57ab4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tasks/cli.yaml @@ -0,0 +1,21 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tasks/main.yaml new file mode 100644 index 00000000..f75f2f03 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_parsed.cfg new file mode 100644 index 00000000..7de77196 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_parsed.cfg @@ -0,0 +1,10 @@ +router bgp 65536 + address-family ipv4 unicast + bgp attribute-download + advertise best-external + dynamic-med interval 10 + bgp scan-time 20 + redistribute application test1 metric 10 + allocate-label all + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_base_vrf.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_base_vrf.yaml new file mode 100644 index 00000000..626e0fee --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_base_vrf.yaml @@ -0,0 +1,15 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "address-family ipv4 unicast" + - "address-family vpnv4 unicast" + - "bgp router-id 10.0.0.1" + - "vrf vrf1" + - " rd auto" + - "vrf vrf2" + - " rd auto" + parents: "router bgp 65536" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_config.yaml new file mode 100644 index 00000000..f83b5aa7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_config.yaml @@ -0,0 +1,16 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "address-family ipv4 unicast" + - " bgp attribute-download" + - " advertise best-external" + - " dynamic-med interval 10" + - " redistribute connected metric 10" + - " redistribute isis test3 metric 4" + - " redistribute application test1 metric 10" + - " allocate-label all" + parents: "router bgp 65536" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_config1.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_config1.yaml new file mode 100644 index 00000000..f44b0af6 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_config1.yaml @@ -0,0 +1,17 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "address-family ipv4 unicast" + - " bgp attribute-download" + - " advertise best-external" + - " dynamic-med interval 10" + - " redistribute connected metric 10" + - " redistribute isis test3 metric 4" + - " redistribute application test1 metric 10" + - " allocate-label all" + - "address-family ipv4 mvpn" + parents: "router bgp 65536" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_vrf.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_vrf.yaml new file mode 100644 index 00000000..71292b54 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_populate_vrf.yaml @@ -0,0 +1,16 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "vrf vrf1" + - " address-family ipv4 unicast" + - " redistribute connected metric 10" + - " dynamic-med interval 9" + - "vrf vrf2" + - " address-family ipv4 unicast" + - " redistribute connected metric 10" + - " dynamic-med interval 10" + parents: "router bgp 65536" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_remove_config.yaml new file mode 100644 index 00000000..812cd1bd --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/_remove_config.yaml @@ -0,0 +1,8 @@ +--- +- name: Remove pre-existing BGP configurations + cisco.iosxr.iosxr_config: + lines: + - no router bgp 65536 + ignore_errors: true + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/deleted.yaml new file mode 100644 index 00000000..90039f6f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/deleted.yaml @@ -0,0 +1,64 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_bgp_address_family deleted integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete given bgp_address_family configuration + become: true + register: result + cisco.iosxr.iosxr_bgp_address_family: &deleted + config: + state: deleted + + - ansible.builtin.assert: + that: + - result.commands|length == 2 + - result.changed == true + - "'no router bgp 65536' not in result.commands" + - result.after == deleted.after + + - name: Idempotency check + become: true + register: result + cisco.iosxr.iosxr_bgp_address_family: *deleted + - ansible.builtin.assert: + that: + - result.commands|length == 0 + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.debug: + msg: Start iosxr_bgp_address_family deleted integration tests with multiple afs connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _populate_base_vrf.yaml + +- ansible.builtin.include_tasks: _populate_vrf.yaml + +- block: + - name: Deleted given bgp_address_family configuration + become: true + register: result + cisco.iosxr.iosxr_bgp_address_family: + config: + as_number: "65536" + address_family: + - afi: "ipv4" + safi: "unicast" + vrf: vrf1 + dynamic_med: 9 + state: deleted + + - ansible.builtin.assert: + that: + - result.commands|length == 3 + - result.changed == true + - "'no router bgp 65536' not in result.commands" + - deleted['vrf']['commands'] == result['commands'] + + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/empty_config.yaml new file mode 100644 index 00000000..4ab7f8fb --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/empty_config.yaml @@ -0,0 +1,50 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_address_family empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_address_family: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_address_family: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_address_family: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_address_family: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' + +- ansible.builtin.debug: + msg: END nxos_bgp_global empty_config integration tests on connection={{ ansible_connection }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/gathered.yaml new file mode 100644 index 00000000..81afdcca --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/gathered.yaml @@ -0,0 +1,31 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_address_family gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "address-family ipv4 unicast" + - " bgp attribute-download" + - " advertise best-external" + - " dynamic-med interval 10" + - " redistribute application test1 metric 10" + - " allocate-label all" + parents: "router bgp 65536" + + - name: Gathered the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_bgp_address_family: + config: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: + - "{{ gathered['after']['address_family'] | symmetric_difference(result['gathered']['address_family']) |length == 0 }}" + - gathered['after']['as_number'] == result['gathered']['as_number'] + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/merged.yaml new file mode 100644 index 00000000..0ffa6e4b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/merged.yaml @@ -0,0 +1,90 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_bgp_address-family merged integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + cisco.iosxr.iosxr_bgp_address_family: &id001 + config: + as_number: "65536" + address_family: + - afi: "ipv4" + safi: "unicast" + dynamic_med: 10 + redistribute: + - protocol: application + id: test1 + metric: 10 + bgp: + scan_time: 20 + attribute_download: true + advertise_best_external: true + allocate_label: + all: true + + register: result + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ result['before'] == {} }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts were correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['after'] + + - name: Merge the provided configuration with the existing running configuration (idempotent) + cisco.iosxr.iosxr_bgp_address_family: *id001 + register: result + + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.debug: + msg: Start iosxr_bgp_address-family merged integration tests for af under vrf connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _populate_base_vrf.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration(vrf) + cisco.iosxr.iosxr_bgp_address_family: &id002 + config: + as_number: "65536" + address_family: + - afi: "ipv4" + safi: "unicast" + vrf: vrf1 + dynamic_med: 9 + redistribute: + - protocol: connected + metric: 10 + + register: result + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['vrf']['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + cisco.iosxr.iosxr_bgp_address_family: *id002 + register: result + + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + +- ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/overridden.yaml new file mode 100644 index 00000000..482b2859 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/overridden.yaml @@ -0,0 +1,44 @@ +--- +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config1.yaml + +- block: + - name: Override given bgp_address_family configuration + become: true + register: result + cisco.iosxr.iosxr_bgp_address_family: &overridden + config: + as_number: "65536" + address_family: + - afi: "ipv4" + safi: "unicast" + dynamic_med: 4 + redistribute: + - protocol: application + id: test1 + metric: 10 + - protocol: connected + metric: 10 + - protocol: isis + id: test3 + metric: 4 + state: overridden + + - ansible.builtin.assert: + that: + - result.commands|length == 7 + - result.changed == true + - "'no router bgp 65536' not in result.commands" + - overridden['commands'] == result['commands'] + + - name: Idempotency check + become: true + register: result + cisco.iosxr.iosxr_bgp_address_family: *overridden + - ansible.builtin.assert: + that: + - result.commands|length == 0 + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/parsed.yaml new file mode 100644 index 00000000..2f0d5b5c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_address_family parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided BGP configuration + register: result + cisco.iosxr.iosxr_bgp_address_family: + running_config: "{{ lookup('file', './_parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['parsed']}}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/rendered.yaml new file mode 100644 index 00000000..1f412d09 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/rendered.yaml @@ -0,0 +1,46 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_global rendered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- name: Render platform specific configuration lines with state rendered (without connecting to the device) + cisco.iosxr.iosxr_bgp_address_family: + config: + as_number: "65536" + address_family: + - afi: "ipv4" + safi: "unicast" + dynamic_med: 10 + redistribute: + - protocol: application + id: test1 + metric: 10 + - protocol: connected + metric: 10 + - protocol: isis + id: test3 + metric: 4 + bgp: + scan_time: 20 + attribute_download: true + advertise_best_external: true + allocate_label: + all: true + state: rendered + register: result + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - rendered['commands'] == result['rendered'] + +- name: Gather BGP facts + cisco.iosxr.iosxr_bgp_address_family: + state: gathered + register: result + +- name: Ensure that no configuration changes were made + ansible.builtin.assert: + that: + - result.gathered == {} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/replaced.yaml new file mode 100644 index 00000000..f30405e7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/tests/common/replaced.yaml @@ -0,0 +1,86 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_bgp_address-family replaced integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config1.yaml + +- block: + - name: Replaced given bgp_address_family configuration + become: true + register: result + cisco.iosxr.iosxr_bgp_address_family: &replaced + config: + as_number: "65536" + address_family: + - afi: "ipv4" + safi: "unicast" + dynamic_med: 4 + redistribute: + - protocol: application + id: test1 + metric: 10 + - protocol: connected + metric: 10 + - protocol: isis + id: test3 + metric: 4 + state: replaced + + - ansible.builtin.assert: + that: + - result.commands|length == 6 + - result.changed == true + - "'no router bgp 65536' not in result.commands" + - replaced['commands'] == result['commands'] + + - name: Idempotency check + become: true + register: result + cisco.iosxr.iosxr_bgp_address_family: *replaced + - ansible.builtin.assert: + that: + - result.commands|length == 0 + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.debug: + msg: Start iosxr_bgp_address-family replaced integration tests(VRF) connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _populate_base_vrf.yaml + +- ansible.builtin.include_tasks: _populate_vrf.yaml + +- block: + - name: Replaced given bgp_address_family configuration + become: true + register: result + cisco.iosxr.iosxr_bgp_address_family: &replaced1 + config: + as_number: "65536" + address_family: + - afi: "ipv4" + safi: "unicast" + vrf: vrf1 + dynamic_med: 8 + state: replaced + + - ansible.builtin.assert: + that: + - result.commands|length == 5 + - result.changed == true + - "'no router bgp 65536' not in result.commands" + - replaced['vrf']['commands'] == result['commands'] + + - name: Idempotency check + become: true + register: result + cisco.iosxr.iosxr_bgp_address_family: *replaced1 + - ansible.builtin.assert: + that: + - result.commands|length == 0 + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/vars/main.yaml new file mode 100644 index 00000000..1227d06b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_address_family/vars/main.yaml @@ -0,0 +1,99 @@ +--- +merged: + commands: + - router bgp 65536 + - address-family ipv4 unicast + - advertise best-external + - allocate-label all + - bgp attribute-download + - bgp scan-time 20 + - dynamic-med interval 10 + - redistribute application test1 metric 10 + after: + as_number: "65536" + address_family: + - afi: "ipv4" + safi: "unicast" + dynamic_med: 10 + redistribute: + - protocol: application + id: "test1" + metric: 10 + bgp: + scan_time: 20 + attribute_download: true + advertise_best_external: true + allocate_label: + all: true + vrf: + commands: + - router bgp 65536 + - vrf vrf1 + - address-family ipv4 unicast + - dynamic-med interval 9 + - redistribute connected metric 10 + +deleted: + after: + as_number: "65536" + vrf: + commands: + - router bgp 65536 + - vrf vrf1 + - no address-family ipv4 unicast + +overridden: + commands: + - router bgp 65536 + - address-family ipv4 unicast + - no advertise best-external + - no allocate-label all + - no bgp attribute-download + - dynamic-med interval 4 + - no address-family ipv4 mvpn + +replaced: + commands: + - router bgp 65536 + - address-family ipv4 unicast + - no advertise best-external + - no allocate-label all + - no bgp attribute-download + - dynamic-med interval 4 + + vrf: + commands: + - router bgp 65536 + - vrf vrf1 + - address-family ipv4 unicast + - dynamic-med interval 8 + - no redistribute connected metric 10 + +rendered: + commands: + - router bgp 65536 + - address-family ipv4 unicast + - advertise best-external + - allocate-label all + - bgp attribute-download + - bgp scan-time 20 + - dynamic-med interval 10 + - redistribute application test1 metric 10 + - redistribute connected metric 10 + - redistribute isis test3 metric 4 +gathered: + after: + as_number: "65536" + address_family: + - afi: "ipv4" + safi: "unicast" + dynamic_med: 10 + redistribute: + - protocol: application + id: "test1" + metric: 10 + bgp: + attribute_download: true + advertise_best_external: true + allocate_label: + all: true diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/defaults/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/defaults/main.yml new file mode 100644 index 00000000..871ea460 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/defaults/main.yml @@ -0,0 +1,2 @@ +--- +testcase: "[^_].*" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/meta/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/meta/main.yml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/meta/main.yml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tasks/cli.yaml new file mode 100644 index 00000000..1b019a5a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tasks/cli.yaml @@ -0,0 +1,21 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + vars: + ansible_connection: ansible.netcommon.network_cli + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tasks/main.yaml new file mode 100644 index 00000000..f75f2f03 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_parsed.cfg new file mode 100644 index 00000000..6e19cdb2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_parsed.cfg @@ -0,0 +1,19 @@ +router bgp 65536 + bgp confederation identifier 4 + bgp router-id 192.0.2.10 + bgp cluster-id 5 + default-metric 4 + socket send-buffer-size 4098 + bgp bestpath med confed + socket receive-buffer-size 514 + neighbor 192.0.2.11 + remote-as 65537 + cluster-id 3 + ! + neighbor 192.0.2.14 + remote-as 65538 + bfd fast-detect strict-mode + bfd multiplier 6 + bfd minimum-interval 20 + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_populate_af.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_populate_af.yml new file mode 100644 index 00000000..0265308a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_populate_af.yml @@ -0,0 +1,15 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "bgp cluster-id 5" + - "address-family ipv4 unicast" + - "bgp router-id 192.0.2.10" + - " neighbor 192.0.2.11" + - " address-family ipv4 unicast" + - " next-hop-self" + - " remote-as 65537" + parents: "router bgp 65536" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_populate_config.yaml new file mode 100644 index 00000000..c164070b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_populate_config.yaml @@ -0,0 +1,23 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "router bgp 65536" + - "bgp cluster-id 5" + - "bgp router-id 192.0.2.10" + - "bgp bestpath med confed" + - "bgp confederation identifier 4" + - "default-metric 4" + - "socket receive-buffer-size 514" + - "socket send-buffer-size 4098" + - "neighbor 192.0.2.11" + - "cluster-id 3" + - "remote-as 65537" + - "neighbor 192.0.2.14" + - "bfd fast-detect strict-mode" + - "bfd minimum-interval 20" + - "bfd multiplier 6" + - "remote-as 65538" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_populate_vrf.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_populate_vrf.yaml new file mode 100644 index 00000000..73dae4c1 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_populate_vrf.yaml @@ -0,0 +1,16 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "bgp cluster-id 5" + - "address-family ipv4 unicast" + - "address-family vpnv4 unicast" + - "bgp router-id 192.0.2.10" + - " vrf vrf1" + - " rd auto" + - " address-family ipv4 unicast" + + parents: "router bgp 65536" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_remove_config.yaml new file mode 100644 index 00000000..812cd1bd --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_remove_config.yaml @@ -0,0 +1,8 @@ +--- +- name: Remove pre-existing BGP configurations + cisco.iosxr.iosxr_config: + lines: + - no router bgp 65536 + ignore_errors: true + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_replaced_af.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_replaced_af.yaml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/_replaced_af.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/deleted.yaml new file mode 100644 index 00000000..f209a31b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/deleted.yaml @@ -0,0 +1,39 @@ +--- +- ansible.builtin.debug: + msg: Start nxos_bgp_global deleted integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete given bgp_global configuration + become: true + register: result + cisco.iosxr.iosxr_bgp_global: &deleted + config: + as_number: "65536" + state: deleted + + - become: true + cisco.iosxr.iosxr_facts: + gather_network_resources: bgp_global + + - ansible.builtin.assert: + that: + - result.commands|length == 10 + - result.changed == true + - "'no router bgp 65536' not in result.commands" + - ansible_facts.network_resources.bgp_global == result.after + - result.after == deleted.after + + - name: Idempotency check + become: true + register: result + cisco.iosxr.iosxr_bgp_global: *deleted + - ansible.builtin.assert: + that: + - result.commands|length == 0 + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/deleted_af.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/deleted_af.yaml new file mode 100644 index 00000000..34a820ba --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/deleted_af.yaml @@ -0,0 +1,25 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_bgp_global deleted_af integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_af.yml + +- block: + - name: Remove a neighbor having AF configurations (should fail) + cisco.iosxr.iosxr_bgp_global: + config: + as_number: "65536" + state: deleted + register: result + ignore_errors: true + + - name: Assert that the task failed + ansible.builtin.assert: + that: + - result.failed == True + - "'Neighbor 192.0.2.11 has address-family configurations.' in result.msg" + + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/deleted_af_with_vrf.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/deleted_af_with_vrf.yaml new file mode 100644 index 00000000..30caebe2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/deleted_af_with_vrf.yaml @@ -0,0 +1,25 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_bgp_global deleted_af integration tests for vrfs connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_vrf.yaml + +- block: + - name: Remove a neighbor having AF configurations (should fail) + cisco.iosxr.iosxr_bgp_global: + config: + as_number: "65536" + state: deleted + register: result + ignore_errors: true + + - name: Assert that the task failed + ansible.builtin.assert: + that: + - result.failed == True + - "'VRF vrf1 has address-family configurations.' in result.msg" + + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/empty_config.yaml new file mode 100644 index 00000000..bdd5e071 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/empty_config.yaml @@ -0,0 +1,50 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_global empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_global: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_global: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_global: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_global: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' + +- ansible.builtin.debug: + msg: END nxos_bgp_global empty_config integration tests on connection={{ ansible_connection }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/gathered.yaml new file mode 100644 index 00000000..dfbc0d53 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/gathered.yaml @@ -0,0 +1,22 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_global gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Gathered the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_bgp_global: + config: + state: gathered + + - name: Assert + ansible.builtin.assert: + that: + - merged.after == result.gathered + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/merged.yaml new file mode 100644 index 00000000..34f1a62b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/merged.yaml @@ -0,0 +1,61 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_bgp_global merged integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + cisco.iosxr.iosxr_bgp_global: &id001 + config: + as_number: 65536 + default_metric: 4 + socket: + receive_buffer_size: 514 + send_buffer_size: 4098 + bgp: + confederation: + identifier: 4 + bestpath: + med: + confed: true + cluster_id: 5 + router_id: 192.0.2.10 + neighbors: + - neighbor: 192.0.2.11 + remote_as: 65537 + cluster_id: 3 + - neighbor: 192.0.2.14 + remote_as: 65538 + bfd: + fast_detect: + strict_mode: true + multiplier: 6 + minimum_interval: 20 + register: result + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ result['before'] == {} }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts were correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['after'] + + - name: Merge the provided configuration with the existing running configuration (idempotent) + cisco.iosxr.iosxr_bgp_global: *id001 + register: result + + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/parsed.yaml new file mode 100644 index 00000000..7cd8e234 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_global parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided BGP configuration + register: result + cisco.iosxr.iosxr_bgp_global: + running_config: "{{ lookup('file', './_parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - merged['after'] == result['parsed'] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/purged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/purged.yaml new file mode 100644 index 00000000..dd3b9591 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/purged.yaml @@ -0,0 +1,41 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_bgp_global purged integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete all BGP configuration from the device + cisco.iosxr.iosxr_bgp_global: &id001 + state: purged + register: result + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['before'] + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "'no router bgp 65536' in result.commands" + - result.commands|length == 1 + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - result['after'] == {} + + - name: Delete all BGP configuration from the device (idempotent) + register: result + cisco.iosxr.iosxr_bgp_global: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/rendered.yaml new file mode 100644 index 00000000..f45236df --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/rendered.yaml @@ -0,0 +1,43 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_global rendered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- name: Render platform specific configuration lines with state rendered (without connecting to the device) + cisco.iosxr.iosxr_bgp_global: + config: + as_number: 65536 + default_metric: 4 + socket: + receive_buffer_size: 514 + send_buffer_size: 4098 + bgp: + confederation: + identifier: 4 + bestpath: + med: + confed: true + cluster_id: 5 + router_id: 192.0.2.10 + neighbors: + - neighbor: 192.0.2.11 + remote_as: 65537 + cluster_id: 3 + state: rendered + register: result + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - rendered['commands'] == result['rendered'] + +- name: Gather BGP facts + cisco.iosxr.iosxr_bgp_global: + state: gathered + register: result + +- name: Ensure that no configuration changes were made + ansible.builtin.assert: + that: + - result.gathered == {} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/replaced.yaml new file mode 100644 index 00000000..b4f98180 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/replaced.yaml @@ -0,0 +1,64 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_bgp_global replaced integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replace BGP configuration with provided configuration + cisco.iosxr.iosxr_bgp_global: &id001 + config: + as_number: 65536 + default_metric: 5 + socket: + receive_buffer_size: 514 + send_buffer_size: 4098 + bgp: + bestpath: + med: + confed: true + cluster_id: 5 + router_id: 192.0.2.10 + neighbors: + - neighbor: 192.0.2.13 + remote_as: 65538 + bfd: + fast_detect: + set: true + multiplier: 6 + minimum_interval: 20 + state: replaced + register: result + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - replaced['after'] == result['after'] + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['before'] + + - name: Replace device configurations of BGP global module (idempotent) + register: result + cisco.iosxr.iosxr_bgp_global: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - replaced['after'] == result['before'] + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/replaced_af.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/replaced_af.yaml new file mode 100644 index 00000000..6cb3f6fb --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/tests/common/replaced_af.yaml @@ -0,0 +1,40 @@ +--- +- ansible.builtin.debug: + msg: Start nxos_bgp_global deleted_af integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_af.yml + +- block: + - name: Replace BGP configuration with provided configuration + cisco.iosxr.iosxr_bgp_global: + config: + as_number: 65536 + default_metric: 5 + socket: + receive_buffer_size: 514 + send_buffer_size: 4098 + bgp: + bestpath: + med: + confed: true + cluster_id: 5 + router_id: 192.0.2.10 + neighbors: + - neighbor: 192.0.2.13 + remote_as: 65538 + bfd: + fast_detect: + strict_mode: true + multiplier: 6 + minimum_interval: 20 + state: replaced + register: result + ignore_errors: true + + - name: Assert that the task failed + ansible.builtin.assert: + that: + - result.failed == True + - "'Neighbor 192.0.2.11 has address-family configurations.' in result.msg" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/vars/main.yaml new file mode 100644 index 00000000..ef656a41 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_global/vars/main.yaml @@ -0,0 +1,94 @@ +--- +merged: + commands: + - router bgp 65536 + - bgp cluster-id 5 + - bgp router-id 192.0.2.10 + - bgp bestpath med confed + - bgp confederation identifier 4 + - default-metric 4 + - socket receive-buffer-size 514 + - socket send-buffer-size 4098 + - neighbor 192.0.2.11 + - cluster-id 3 + - remote-as 65537 + - neighbor 192.0.2.14 + - bfd fast-detect strict-mode + - bfd minimum-interval 20 + - bfd multiplier 6 + - remote-as 65538 + after: + as_number: "65536" + default_metric: 4 + socket: + receive_buffer_size: 514 + send_buffer_size: 4098 + bgp: + confederation: + identifier: 4 + bestpath: + med: + confed: true + cluster_id: "5" + router_id: "192.0.2.10" + neighbors: + - neighbor_address: 192.0.2.11 + remote_as: 65537 + cluster_id: "3" + - neighbor_address: "192.0.2.14" + remote_as: 65538 + bfd: + fast_detect: + strict_mode: true + multiplier: 6 + minimum_interval: 20 + +deleted: + after: + as_number: "65536" + +replaced: + commands: + - router bgp 65536 + - no bgp confederation identifier 4 + - default-metric 5 + - no neighbor 192.0.2.11 + - no neighbor 192.0.2.14 + - neighbor 192.0.2.13 + - bfd fast-detect + - bfd minimum-interval 20 + - bfd multiplier 6 + - remote-as 65538 + after: + as_number: "65536" + default_metric: 5 + socket: + receive_buffer_size: 514 + send_buffer_size: 4098 + bgp: + bestpath: + med: + confed: true + cluster_id: "5" + router_id: "192.0.2.10" + neighbors: + - neighbor_address: "192.0.2.13" + remote_as: 65538 + bfd: + fast_detect: + set: true + multiplier: 6 + minimum_interval: 20 +rendered: + commands: + - router bgp 65536 + - bgp cluster-id 5 + - bgp router-id 192.0.2.10 + - bgp bestpath med confed + - bgp confederation identifier 4 + - default-metric 4 + - socket receive-buffer-size 514 + - socket send-buffer-size 4098 + - neighbor 192.0.2.11 + - cluster-id 3 + - remote-as 65537 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/defaults/main.yaml new file mode 100644 index 00000000..871ea460 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "[^_].*" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/meta/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/meta/main.yaml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/meta/main.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tasks/cli.yaml new file mode 100644 index 00000000..1b019a5a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tasks/cli.yaml @@ -0,0 +1,21 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + vars: + ansible_connection: ansible.netcommon.network_cli + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tasks/main.yaml new file mode 100644 index 00000000..f75f2f03 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_parsed.cfg new file mode 100644 index 00000000..4e2b4c71 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_parsed.cfg @@ -0,0 +1,26 @@ +router bgp 65536 + address-family ipv4 unicast + ! + neighbor 192.0.2.2 + remote-as 5 + address-family ipv4 unicast + origin-as validation disable + bestpath origin-as allow invalid + weight 5 + send-community-ebgp + multipath + allowas-in 4 + maximum-prefix 10 20 restart 10 + as-override + capability orf prefix both + send-extended-community-ebgp + default-originate + next-hop-self + send-community-gshut-ebgp + soft-reconfiguration inbound always + send-multicast-attributes + route-policy test1 in + route-policy test1 out + ! + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_base_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_base_config.yaml new file mode 100644 index 00000000..606bcba7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_base_config.yaml @@ -0,0 +1,23 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "address-family ipv4 unicast" + - "address-family ipv6 unicast" + - "neighbor 192.0.2.2" + - " remote-as 65537" + parents: "router bgp 65536" + vars: + ansible_connection: ansible.netcommon.network_cli + +- name: "Setup route-policy test1 for referance" + cisco.iosxr.iosxr_config: + commands: + - route-policy test1 + - end-policy + +- name: "Setup route-policy test2 for referance" + cisco.iosxr.iosxr_config: + commands: + - route-policy test2 + - end-policy diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_config.yaml new file mode 100644 index 00000000..c01eebb0 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_config.yaml @@ -0,0 +1,27 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "neighbor 192.0.2.2" + - " address-family ipv4 unicast" + - " origin-as validation disable" + - " bestpath origin-as allow invalid" + - " weight 5" + - " send-community-ebgp" + - " multipath" + - " allowas-in 4" + - " maximum-prefix 10 20 restart 10" + - " as-override" + - " capability orf prefix both" + - " send-extended-community-ebgp" + - " default-originate" + - " next-hop-self" + - " send-community-gshut-ebgp" + - " soft-reconfiguration inbound always" + - " send-multicast-attributes" + - " route-policy test1 in" + - " route-policy test1 out" + parents: "router bgp 65536" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_vrf_base_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_vrf_base_config.yaml new file mode 100644 index 00000000..a54158ae --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_vrf_base_config.yaml @@ -0,0 +1,25 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "bgp router-id 192.0.2.1" + - "address-family vpnv4 unicast" + - "address-family ipv4 unicast" + - "neighbor 192.0.2.2" + - " remote-as 65537" + - "neighbor 192.0.2.3" + - " remote-as 65538" + - "vrf vrf1" + - " rd auto" + - " address-family ipv4 unicast" + - " neighbor 192.0.2.4" + - " remote-as 65539" + - "vrf vrf2" + - " rd auto" + - " address-family ipv4 unicast" + - " neighbor 192.0.2.5" + - " remote-as 65540" + parents: "router bgp 65536" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_vrf_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_vrf_config.yaml new file mode 100644 index 00000000..a3fa9d72 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_populate_vrf_config.yaml @@ -0,0 +1,26 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "neighbor 192.0.2.2" + - " address-family ipv4 unicast" + - " weight 5" + - "neighbor 192.0.2.3" + - " address-family ipv4 unicast" + - " bestpath origin-as allow invalid" + - " weight 4" + - "vrf vrf1" + - " neighbor 192.0.2.4" + - " address-family ipv4 unicast" + - " multipath" + - " capability orf prefix both" + - " default-originate" + - "vrf vrf2" + - " neighbor 192.0.2.5" + - " address-family ipv4 unicast" + - " multipath" + - " capability orf prefix both" + parents: "router bgp 65536" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_remove_config.yaml new file mode 100644 index 00000000..6954b2d2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_remove_config.yaml @@ -0,0 +1,10 @@ +--- +- name: Remove pre-existing BGP configurations + cisco.iosxr.iosxr_config: + lines: + - no router bgp 65536 + - no route-policy test1 + - no route-policy test2 + ignore_errors: true + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_route_policy.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_route_policy.cfg new file mode 100644 index 00000000..d2352c9b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/_route_policy.cfg @@ -0,0 +1,6 @@ +route-policy test1 +end-policy +! +route-policy test2 +end-policy +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/deleted.yaml new file mode 100644 index 00000000..3c70df5e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/deleted.yaml @@ -0,0 +1,71 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_bgp_nbr_address_family deleted integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_base_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete given bgp_nbr_address_family configuration + become: true + register: result + cisco.iosxr.iosxr_bgp_neighbor_address_family: &deleted + config: + state: deleted + + - ansible.builtin.assert: + that: + - result.commands|length == 3 + - result.changed == true + - "'no router bgp 65536' not in result.commands" + - result.after == deleted.after + + - name: Idempotency check + become: true + register: result + cisco.iosxr.iosxr_bgp_neighbor_address_family: *deleted + - ansible.builtin.assert: + that: + - result.commands|length == 0 + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.debug: + msg: Start iosxr_bgp_nbr_address_family deleted integration tests (for multipale af) connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_vrf_base_config.yaml + +- ansible.builtin.include_tasks: _populate_vrf_config.yaml + +- block: + - name: Delete only one AF between multiple AF present on device. + cisco.iosxr.iosxr_bgp_neighbor_address_family: + state: deleted + config: + as_number: 65536 + vrfs: + - vrf: vrf1 + neighbors: + - neighbor_address: 192.0.2.4 + address_family: + - afi: "ipv4" + safi: "unicast" + weight: 4 + default_originate: + set: true + capability_orf_prefix: both + register: result + + - ansible.builtin.assert: + that: + - result.commands|length == 4 + - result.changed == true + - "'no router bgp 65536' not in result.commands" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/empty_config.yaml new file mode 100644 index 00000000..9461281b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/empty_config.yaml @@ -0,0 +1,50 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_neighbor_address_family empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_neighbor_address_family: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_neighbor_address_family: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_neighbor_address_family: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_bgp_neighbor_address_family: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' + +- ansible.builtin.debug: + msg: END nxos_bgp_global empty_config integration tests on connection={{ ansible_connection }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/gathered.yaml new file mode 100644 index 00000000..5edb90e9 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/gathered.yaml @@ -0,0 +1,24 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_neighbor_address_family gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_base_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Gathered the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_bgp_neighbor_address_family: + config: + state: gathered + + - name: Assert + ansible.builtin.assert: + that: + - "{{ merged['after']['neighbors'] | symmetric_difference(result['gathered']['neighbors']) |length == 0 }}" + - merged['after']['as_number'] == result['gathered']['as_number'] + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/merged.yaml new file mode 100644 index 00000000..59da323f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/merged.yaml @@ -0,0 +1,138 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_bgp_nbr_address_family merged integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_base_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + cisco.iosxr.iosxr_bgp_neighbor_address_family: &id001 + config: + as_number: 65536 + neighbors: + - neighbor_address: 192.0.2.2 + address_family: + - afi: "ipv4" + safi: "unicast" + multipath: true + default_originate: + set: true + weight: 5 + capability_orf_prefix: both + send_multicast_attributes: + set: true + soft_reconfiguration: + inbound: + always: true + send_community_gshut_ebgp: + set: true + route_policy: + inbound: test1 + outbound: test1 + send_extended_community_ebgp: + set: true + send_community_ebgp: + set: true + origin_as: + validation: + disable: true + maximum_prefix: + max_limit: 10 + threshold_value: 20 + restart: 10 + next_hop_self: + set: true + as_override: + set: true + allowas_in: + value: 4 + bestpath_origin_as_allow_invalid: true + register: result + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts were correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['after'] + + - name: Merge the provided configuration with the existing running configuration (idempotent) + cisco.iosxr.iosxr_bgp_neighbor_address_family: *id001 + register: result + + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_vrf_base_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration(vrf and multiple afs) + cisco.iosxr.iosxr_bgp_neighbor_address_family: &id002 + config: + as_number: 65536 + neighbors: + - neighbor_address: 192.0.2.2 + address_family: + - afi: "ipv4" + safi: "unicast" + multipath: true + default_originate: + set: true + weight: 5 + - neighbor_address: 192.0.2.3 + address_family: + - afi: "ipv4" + safi: "unicast" + multipath: true + default_originate: + set: true + weight: 4 + vrfs: + - vrf: vrf1 + neighbors: + - neighbor_address: 192.0.2.4 + address_family: + - afi: "ipv4" + safi: "unicast" + multipath: true + default_originate: + set: true + capability_orf_prefix: both + - vrf: vrf2 + neighbors: + - neighbor_address: 192.0.2.5 + address_family: + - afi: "ipv4" + safi: "unicast" + multipath: true + default_originate: + set: true + capability_orf_prefix: both + register: result + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['vrf']['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + cisco.iosxr.iosxr_bgp_neighbor_address_family: *id002 + register: result + + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/overridden.yaml new file mode 100644 index 00000000..86ddac62 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/overridden.yaml @@ -0,0 +1,45 @@ +--- +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_base_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Override given bgp_address_family configuration + become: true + register: result + cisco.iosxr.iosxr_bgp_neighbor_address_family: &overridden + config: + as_number: 65536 + neighbors: + - neighbor_address: 192.0.2.2 + address_family: + - afi: "ipv6" + safi: "unicast" + multipath: true + default_originate: + set: true + weight: 5 + route_policy: + inbound: test2 + outbound: test2 + state: overridden + + - ansible.builtin.assert: + that: + - result.commands|length == 9 + - result.changed == true + - "'no router bgp 65536' not in result.commands" + - overridden['commands'] == result['commands'] + + - name: Idempotency check + become: true + register: result + cisco.iosxr.iosxr_bgp_neighbor_address_family: *overridden + - ansible.builtin.assert: + that: + - result.commands|length == 0 + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/parsed.yaml new file mode 100644 index 00000000..50e6fcef --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_address_family parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided BGP configuration + register: result + cisco.iosxr.iosxr_bgp_neighbor_address_family: + running_config: "{{ lookup('file', './_parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['parsed']}}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/rendered.yaml new file mode 100644 index 00000000..851dcf1e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/rendered.yaml @@ -0,0 +1,54 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_bgp_neighbor_af rendered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_base_config.yaml + +- name: Render platform specific configuration lines with state rendered (without connecting to the device) + cisco.iosxr.iosxr_bgp_neighbor_address_family: + config: + as_number: 65536 + neighbors: + - neighbor_address: 192.0.2.2 + address_family: + - afi: "ipv4" + safi: "unicast" + multipath: true + default_originate: + set: true + weight: 5 + capability_orf_prefix: both + send_multicast_attributes: + set: true + soft_reconfiguration: + inbound: + always: true + send_community_gshut_ebgp: + set: true + send_extended_community_ebgp: + set: true + send_community_ebgp: + set: true + origin_as: + validation: + disable: true + maximum_prefix: + max_limit: 10 + threshold_value: 20 + restart: 10 + next_hop_self: + set: true + as_override: + set: true + allowas_in: + value: 4 + bestpath_origin_as_allow_invalid: true + state: rendered + register: result + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - rendered['commands'] == result['rendered'] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/replaced.yaml new file mode 100644 index 00000000..81b5e50b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/tests/common/replaced.yaml @@ -0,0 +1,105 @@ +--- +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_base_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replaced given bgp_nbr_address_family configuration + become: true + register: result + cisco.iosxr.iosxr_bgp_neighbor_address_family: &replaced + config: + as_number: 65536 + neighbors: + - neighbor_address: 192.0.2.2 + address_family: + - afi: "ipv4" + safi: "unicast" + multipath: true + default_originate: + set: true + weight: 4 + capability_orf_prefix: both + send_multicast_attributes: + set: true + soft_reconfiguration: + inbound: + always: true + send_community_gshut_ebgp: + set: true + send_extended_community_ebgp: + set: true + send_community_ebgp: + set: true + maximum_prefix: + max_limit: 10 + threshold_value: 20 + restart: 10 + next_hop_self: + set: true + as_override: + set: true + allowas_in: + value: 4 + bestpath_origin_as_allow_invalid: true + state: replaced + + - ansible.builtin.assert: + that: + - result.commands|length == 7 + - result.changed == true + - "'no router bgp 65536' not in result.commands" + - replaced['commands'] == result['commands'] + + - name: Idempotency check + become: true + register: result + cisco.iosxr.iosxr_bgp_neighbor_address_family: *replaced + - ansible.builtin.assert: + that: + - result.commands|length == 0 + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_vrf_base_config.yaml + +- ansible.builtin.include_tasks: _populate_vrf_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + cisco.iosxr.iosxr_bgp_neighbor_address_family: &id001 + state: replaced + config: + as_number: 65536 + vrfs: + - vrf: vrf1 + neighbors: + - neighbor_address: 192.0.2.4 + address_family: + - afi: "ipv4" + safi: "unicast" + weight: 4 + default_originate: + set: true + capability_orf_prefix: both + register: result + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['vrf']['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + cisco.iosxr.iosxr_bgp_neighbor_address_family: *id001 + register: result + + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/vars/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/vars/main.yml new file mode 100644 index 00000000..0be96b26 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_bgp_neighbor_address_family/vars/main.yml @@ -0,0 +1,145 @@ +--- +merged: + commands: + - router bgp 65536 + - neighbor 192.0.2.2 + - address-family ipv4 unicast + - allowas-in 4 + - as-override + - bestpath origin-as allow invalid + - capability orf prefix both + - default-originate + - maximum-prefix 10 20 restart 10 + - multipath + - next-hop-self + - origin-as validation disable + - send-community-ebgp + - send-community-gshut-ebgp + - send-extended-community-ebgp + - route-policy test1 in + - route-policy test1 out + - send-multicast-attributes + - soft-reconfiguration inbound always + - weight 5 + vrf: + commands: + - router bgp 65536 + - neighbor 192.0.2.2 + - address-family ipv4 unicast + - default-originate + - multipath + - weight 5 + - neighbor 192.0.2.3 + - address-family ipv4 unicast + - default-originate + - multipath + - weight 4 + - vrf vrf1 + - neighbor 192.0.2.4 + - address-family ipv4 unicast + - capability orf prefix both + - default-originate + - multipath + - vrf vrf2 + - neighbor 192.0.2.5 + - address-family ipv4 unicast + - capability orf prefix both + - default-originate + - multipath + + after: + as_number: "65536" + neighbors: + - neighbor_address: "192.0.2.2" + address_family: + - afi: "ipv4" + safi: "unicast" + multipath: true + default_originate: + set: true + weight: 5 + capability_orf_prefix: "both" + send_multicast_attributes: + set: true + soft_reconfiguration: + inbound: + always: true + send_community_gshut_ebgp: + set: true + send_extended_community_ebgp: + set: true + send_community_ebgp: + set: true + origin_as: + validation: + disable: true + route_policy: + inbound: "test1" + outbound: "test1" + maximum_prefix: + max_limit: 10 + threshold_value: 20 + restart: 10 + next_hop_self: + set: true + as_override: + set: true + allowas_in: + value: 4 + bestpath_origin_as_allow_invalid: true + +deleted: + after: + as_number: "65536" + +overridden: + commands: + - router bgp 65536 + - neighbor 192.0.2.2 + - address-family ipv6 unicast + - default-originate + - multipath + - weight 5 + - route-policy test2 in + - route-policy test2 out + - no address-family ipv4 unicast + +replaced: + commands: + - router bgp 65536 + - neighbor 192.0.2.2 + - address-family ipv4 unicast + - no origin-as validation disable + - weight 4 + - no route-policy test1 in + - no route-policy test1 out + + vrf: + commands: + - router bgp 65536 + - vrf vrf1 + - neighbor 192.0.2.4 + - address-family ipv4 unicast + - no multipath + - weight 4 + +rendered: + commands: + - router bgp 65536 + - neighbor 192.0.2.2 + - address-family ipv4 unicast + - allowas-in 4 + - as-override + - bestpath origin-as allow invalid + - capability orf prefix both + - default-originate + - maximum-prefix 10 20 restart 10 + - multipath + - next-hop-self + - origin-as validation disable + - send-community-ebgp + - send-community-gshut-ebgp + - send-extended-community-ebgp + - send-multicast-attributes + - soft-reconfiguration inbound always + - weight 5 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/defaults/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/defaults/main.yml new file mode 100644 index 00000000..871ea460 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/defaults/main.yml @@ -0,0 +1,2 @@ +--- +testcase: "[^_].*" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/meta/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/meta/main.yml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/meta/main.yml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/tasks/cli.yaml new file mode 100644 index 00000000..a1b57ab4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/tasks/cli.yaml @@ -0,0 +1,21 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/tasks/main.yaml new file mode 100644 index 00000000..f75f2f03 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/tests/common/commit_conf.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/tests/common/commit_conf.yaml new file mode 100644 index 00000000..05ddfd8e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/tests/common/commit_conf.yaml @@ -0,0 +1,33 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_cliconf integration tests on connection={{ ansible_connection }} + +- name: Apply interface description + register: result + cisco.iosxr.iosxr_interfaces: + state: merged + config: + - name: GigabitEthernet0/0/0/2 + description: TestCommitConfirmed + +- name: Do commit confirmed + cisco.iosxr.iosxr_command: + commands: + - commit confirmed + when: result["changed"] == true + +- name: Sleep for 35 sec. + ansible.builtin.wait_for: + timeout: 35 + when: result["changed"] == true + +- name: Get interface description + register: get_desc + iosxr_command: + commands: + - "show interfaces GigabitEthernet 0/0/0/2 | include Description" + ignore_errors: true + +- ansible.builtin.assert: + that: + - "'TestCommitConfirmed' in get_desc.stdout[0]" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/vars/main.yaml new file mode 100644 index 00000000..8ff6db3c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_cliconf/vars/main.yaml @@ -0,0 +1,3 @@ +--- +ansible_iosxr_commit_confirmed: true +ansible_iosxr_commit_confirmed_timeout: 30 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/defaults/main.yaml new file mode 100644 index 00000000..871ea460 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "[^_].*" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/meta/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/meta/main.yml new file mode 100644 index 00000000..be631e5d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_iosxr_tests diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tasks/cli.yaml new file mode 100644 index 00000000..fd2202fa --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tasks/cli.yaml @@ -0,0 +1,21 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/bad_operator.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/bad_operator.yaml new file mode 100644 index 00000000..f5379f00 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/bad_operator.yaml @@ -0,0 +1,19 @@ +--- +- ansible.builtin.debug: msg="START cli/bad_operator.yaml on connection={{ ansible_connection }}" + +- name: Test bad operator + register: result + ignore_errors: true + cisco.iosxr.iosxr_command: + commands: + - show version + - show interfaces GigabitEthernet 0/0 + wait_for: + - "result[0] contains 'Description: Foo'" + +- ansible.builtin.assert: + that: + - result.failed == true + - result.msg is defined + +- ansible.builtin.debug: msg="END cli/bad_operator.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/cli_command.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/cli_command.yaml new file mode 100644 index 00000000..ec0a2567 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/cli_command.yaml @@ -0,0 +1,45 @@ +--- +- ansible.builtin.debug: + msg: START cli/cli_command.yaml on connection={{ ansible_connection }} + +- name: Get output for single command + register: result + ansible.netcommon.cli_command: + command: show version + +- ansible.builtin.assert: + that: + - result.changed == false + - result.stdout is defined + +- name: Send invalid command + register: result + ignore_errors: true + ansible.netcommon.cli_command: + command: show foo + +- ansible.builtin.assert: + that: + - result.failed == true + - result.msg is defined + +- name: Delete configuration file on disk to prevent failure of copy task for duplicate + ignore_errors: true + ansible.netcommon.cli_command: + command: delete harddisk:ansible_tmp.txt + prompt: Delete harddisk\:/?ansible_tmp\.txt\[confirm\] + answer: "" + +- name: Run command with prompt + register: result + ansible.netcommon.cli_command: + command: copy running-config harddisk:ansible_tmp.txt + prompt: "Destination file name \\(control-c to abort\\)\\: \\[\\/ansible_tmp.txt\\]\\?" + answer: ansible_tmp.txt + +- ansible.builtin.assert: + that: + - result.stdout is defined + - "'ansible_tmp' in result.stdout" + +- ansible.builtin.debug: msg="END cli/cli_command.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/contains.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/contains.yaml new file mode 100644 index 00000000..c87e082a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/contains.yaml @@ -0,0 +1,19 @@ +--- +- ansible.builtin.debug: msg="START cli/contains.yaml on connection={{ ansible_connection }}" + +- name: Test contains operator + register: result + cisco.iosxr.iosxr_command: + commands: + - show version + - show interfaces Loopback 888 + wait_for: + - result[0] contains 'Cisco IOS XR Software' + - result[1] contains 'Hardware is Loopback interface' + +- ansible.builtin.assert: + that: + - result.changed == false + - result.stdout is defined + +- ansible.builtin.debug: msg="END cli/contains.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/invalid.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/invalid.yaml new file mode 100644 index 00000000..3ba25aec --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/invalid.yaml @@ -0,0 +1,32 @@ +--- +- ansible.builtin.debug: msg="START cli/invalid.yaml on connection={{ ansible_connection }}" + +- name: Run invalid command + register: result + ignore_errors: true + cisco.iosxr.iosxr_command: + commands: + command: show foo + prompt: fooprompt + answer: "yes" + +- ansible.builtin.assert: + that: + - result.failed + +- name: Run commands that include invalid command + register: result + ignore_errors: true + cisco.iosxr.iosxr_command: + commands: + - show version + + - command: show foo + prompt: fooprompt + answer: "yes" + +- ansible.builtin.assert: + that: + - result.failed + +- ansible.builtin.debug: msg="END cli/invalid.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/output.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/output.yaml new file mode 100644 index 00000000..20862223 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/output.yaml @@ -0,0 +1,28 @@ +--- +- ansible.builtin.debug: msg="START cli/output.yaml on connection={{ ansible_connection }}" + +- name: Get output for single command + register: result + cisco.iosxr.iosxr_command: + commands: + - show version + +- ansible.builtin.assert: + that: + - result.changed == false + - result.stdout is defined + +- name: Get output for multiple commands + register: result + cisco.iosxr.iosxr_command: + commands: + - show version + - show interfaces + +- ansible.builtin.assert: + that: + - result.changed == false + - result.stdout is defined + - result.stdout | length == 2 + +- ansible.builtin.debug: msg="END cli/output.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/prompt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/prompt.yaml new file mode 100644 index 00000000..09f14686 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/prompt.yaml @@ -0,0 +1,26 @@ +--- +- ansible.builtin.debug: + msg: START cli/prompt.yaml on connection={{ ansible_connection }} + +- name: Delete configuration file on disk to prevent failure of copy task for duplicate + ignore_errors: true + cisco.iosxr.iosxr_command: + commands: + - command: delete harddisk:ansible_tmp.txt + prompt: Delete harddisk\:/?ansible_tmp\.txt\[confirm\] + answer: "" + +- name: Copy + register: result + cisco.iosxr.iosxr_command: + commands: + - command: copy running-config harddisk:ansible_tmp.txt + prompt: "Destination file name \\(control-c to abort\\)\\: \\[\\/ansible_tmp.txt\\]\\?" + answer: ansible_tmp.txt + +- ansible.builtin.assert: + that: + - result.stdout is defined + - "'ansible_tmp' in result.stdout[0]" + +- ansible.builtin.debug: msg="END cli/prompt.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/timeout.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/timeout.yaml new file mode 100644 index 00000000..8e4397b9 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_command/tests/cli/timeout.yaml @@ -0,0 +1,18 @@ +--- +- ansible.builtin.debug: msg="START cli/timeout.yaml on connection={{ ansible_connection }}" + +- name: Test bad condition + register: result + ignore_errors: true + cisco.iosxr.iosxr_command: + commands: + - show version + wait_for: + - result[0] contains bad_value_string + +- ansible.builtin.assert: + that: + - result.failed == true + - result.msg is defined + +- ansible.builtin.debug: msg="END cli/timeout.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/defaults/main.yaml new file mode 100644 index 00000000..9ef5ba51 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/fixtures/config_add_interface.txt b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/fixtures/config_add_interface.txt new file mode 100644 index 00000000..c63e3f92 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/fixtures/config_add_interface.txt @@ -0,0 +1,42 @@ +hostname iosxr-7.0.2 +username admin + group root-lr + group cisco-support + secret 10 $6$xWjtz/sPyTaz5z/.$2jQ3Ihs8/qvcTn0MT9IxW3egRWRFYJ6Rgk3Q.K7QYgrke7QE5.tUHLc19qCjnKhdgJlVU6SRrjBaO1HP0HkQx1 +! +username zuul + group root-lr + group cisco-support + password 7 082C555C0C1E101B13191C053938 +! +tpa + vrf default + address-family ipv4 + update-source dataports MgmtEth0/RP0/CPU0/0 + ! + ! +! +call-home + service active + contact smart-licensing + profile CiscoTAC-1 + active + destination transport-method http + ! +! +interface Loopback888 + description test for ansible + shutdown +! +interface MgmtEth0/RP0/CPU0/0 + ipv4 address dhcp +! +interface preconfigure GigabitEthernet0/0/0/3 + description test-interface-3 + mtu 256 + speed 100 + duplex full +! +ssh server v2 +ssh server vrf default +end diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/fixtures/config_del_interface.txt b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/fixtures/config_del_interface.txt new file mode 100644 index 00000000..eb006870 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/fixtures/config_del_interface.txt @@ -0,0 +1,36 @@ +hostname iosxr-7.0.2 +username admin + group root-lr + group cisco-support + secret 10 $6$xWjtz/sPyTaz5z/.$2jQ3Ihs8/qvcTn0MT9IxW3egRWRFYJ6Rgk3Q.K7QYgrke7QE5.tUHLc19qCjnKhdgJlVU6SRrjBaO1HP0HkQx1 +! +username zuul + group root-lr + group cisco-support + password 7 082C555C0C1E101B13191C053938 +! +tpa + vrf default + address-family ipv4 + update-source dataports MgmtEth0/RP0/CPU0/0 + ! + ! +! +call-home + service active + contact smart-licensing + profile CiscoTAC-1 + active + destination transport-method http + ! +! +interface Loopback888 + description test for ansible + shutdown +! +interface MgmtEth0/RP0/CPU0/0 + ipv4 address dhcp +! +ssh server v2 +ssh server vrf default +end diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/meta/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/meta/main.yml new file mode 100644 index 00000000..be631e5d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_iosxr_tests diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/cli.yaml new file mode 100644 index 00000000..59a889b4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/cli_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/cli_config.yaml new file mode 100644 index 00000000..0b6332e9 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/cli_config.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli_config" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/main.yaml new file mode 100644 index 00000000..3bf9ffdf --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/main.yaml @@ -0,0 +1,10 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + +- name: Include the cli_config tasks + ansible.builtin.include_tasks: cli_config.yaml + +- name: Include the redirection task + ansible.builtin.include_tasks: redirection.yaml + when: ansible_version.full is version('2.10.0', '>=') diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/redirection.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/redirection.yaml new file mode 100644 index 00000000..bc4b47e2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tasks/redirection.yaml @@ -0,0 +1,18 @@ +--- +- name: Collect all redirection CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/redirection" + patterns: "{{ testcase }}.yaml" + register: shortname_test_cases + delegate_to: localhost + +- name: Set test_items for redirection + ansible.builtin.set_fact: test_items="{{ shortname_test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/change_prefix_set.j2 b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/change_prefix_set.j2 new file mode 100644 index 00000000..3dd5beef --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/change_prefix_set.j2 @@ -0,0 +1,5 @@ +interface Loopback999 + description this is a test interface for prefix-set +prefix-set ebpg_filter + 192.168.0.0/16 ge 15 le 30 +end-set diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/config.j2 b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/config.j2 new file mode 100644 index 00000000..a1272530 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/config.j2 @@ -0,0 +1,3 @@ +interface Loopback999 + description this is a test + shutdown diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/configuration.j2 b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/configuration.j2 new file mode 100644 index 00000000..73c98879 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/configuration.j2 @@ -0,0 +1,3 @@ +interface Loopback888 + description test for ansible automation + shutdown diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/init_prefix_set.j2 b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/init_prefix_set.j2 new file mode 100644 index 00000000..d1170b02 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/init_prefix_set.j2 @@ -0,0 +1,3 @@ +prefix-set ebpg_filter + 192.168.0.0/16 ge 17 le 30 +end-set diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/route_policy.j2 b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/route_policy.j2 new file mode 100644 index 00000000..ecc68e81 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/route_policy.j2 @@ -0,0 +1,121 @@ +router ospf 1 + area 0 +! +prefix-set EBGP-PEER-BOGONS + 0.0.0.0/0, + 0.0.0.0/8 le 32, + 10.0.0.0/8 le 32, + 127.0.0.0/8 le 32, + 169.254.0.0/16 le 32, + 172.16.0.0/12 le 32, + 192.0.0.0/24 le 32, + 192.0.2.0/24 le 32, + 192.168.0.0/16 le 32, + 198.18.0.0/15 le 32, + 224.0.0.0/4 le 32, + 240.0.0.0/4 le 32 +end-set +! +prefix-set cust-ddos-DDOS +end-set +! +prefix-set cust-no-export +end-set +! +prefix-set acme_DC_Internal + 137.1.0.0/16, + 137.1.16.0/24, + 137.1.18.0/24, + 137.1.20.0/24, + 137.1.22.0/24, + 137.1.23.0/24, + 137.1.24.0/24, + 137.1.29.0/24, + 137.1.30.0/24, + 137.1.31.0/24, + 137.1.32.0/21, + 137.1.40.0/22, + 209.1.0.0/16 +end-set +! +as-path-set EBGP-PEER-AS16509-403-PERMIT-PATHS + ios-regex '^11164_8075_', + ios-regex '^11164_16509$', + ios-regex '^1116_16509_[0-9]+$', + ios-regex '^8075_', + ios-regex '^16509$', + ios-regex '^16509_[0-9]+$' +end-set +! +community-set cust-announce + 1525:65298, + 1525:65436, + 1525:65438, + 1525:65439, + 1525:65498, + 1525:65511, + 1523:65418, + 1523:65436, + 1523:65438 +end-set +! +community-set cust-no-export + 1525:65439, + 1525:65511, + 1525:65535 +end-set +! + +route-policy POLICY2 +end-policy +! +route-policy cust2bgp + set origin igp + set next-hop 137.1.16.12 +end-policy +! +rd-set ebpg-1 +end-set +! +rd-set EBGP_INCOMING_RD_SET + 172.16.0.0/16:*, + 172.17.0.0/16:100, + 192:*, + 192:100 +end-set +! +extcommunity-set rt EBGP_INCOMIG_RT_SET + 10:615, + 10:6150, + 15.15.15.15:15 +end-set +! +extcommunity-set rt ebpg-1 +end-set +! +route-policy static-to-bgp + if destination in cust-no-export then + apply cust2bgp + set community cust-no-export additive + elseif destination in cust-announce then + apply cust2bgp + set community cust-announce additive + elseif destination in cust-announce-backup then + apply cust2bgp + set local-preference 100 + set weight 0 + set community cust-announce additive + elseif destination in cust-no-export-backup then + apply cust2bgp + set local-preference 98 + set weight 0 + set community cust-no-export additive + else + drop + endif +end-policy +! +class-map match-any data + match precedence ipv4 0 1 + end-class-map +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/route_policy_change.j2 b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/route_policy_change.j2 new file mode 100644 index 00000000..4f04f384 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/route_policy_change.j2 @@ -0,0 +1,68 @@ +router ospf 1 + area 0 +! +prefix-set EBGP-PEER-BOGONS + 192.0.2.0/24 le 32, + 192.168.0.0/16 le 32, + 198.18.0.0/16 le 32, + 224.0.0.0/4 le 32, + 240.0.0.0/4 le 32 +end-set +! +as-path-set EBGP-PEER-AS16509-403-PERMIT-PATHS + ios-regex '^11164_8075_', + ios-regex '^1164_16509$', + ios-regex '^1116_16409_[0-9]+$', + ios-regex '^8075_' +end-set +! +community-set cust-announce + 1525:65298, + 1525:6546, + 1525:6438, + 1525:65439, + 1525:65498 +end-set +! +rd-set EBGP_INCOMING_RD_SET + 172.16.0.0/16:*, + 172.14.0.0/16:100, + 192:*, + 192:100 +end-set +! +extcommunity-set rt EBGP_INCOMIG_RT_SET + 10:615, + 10:6120, + 15.15.15.15:15 +end-set +! +route-policy POLICY2 +end-policy +! +route-policy static-to-bgp + if destination in cust-no-export then + apply cust2bgp + set community cust-no-export additive + elseif destination in cust-announce then + apply cust2bgp + set community cust-announce additive + elseif destination in cust-announce-backup then + apply cust2bgp + set local-preference 100 + set weight 23 + set community cust-announce additive + elseif destination in cust-no-export-backup then + apply cust2bgp + set local-preference 98 + set weight 0 + set community cust-no-export additive + else + drop + endif +end-policy +! +class-map match-any data + match precedence ipv4 0 1 2 + end-class-map +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/route_policy_clean.j2 b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/route_policy_clean.j2 new file mode 100644 index 00000000..87152680 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/basic/route_policy_clean.j2 @@ -0,0 +1,32 @@ +no router ospf 1 +! +no prefix-set EBGP-PEER-BOGONS +! +no prefix-set cust-ddos-DDOS +! +no prefix-set cust-no-export +! +no prefix-set acme_DC_Internal +! +no as-path-set EBGP-PEER-AS16509-403-PERMIT-PATHS +! +no community-set cust-announce +! +no community-set cust-no-export +! +no rd-set ebpg-1 +! +no rd-set EBGP_INCOMING_RD_SET +! +no extcommunity-set rt EBGP_INCOMIG_RT_SET +! +no extcommunity-set rt ebpg-1 +! +no route-policy POLICY2 +! +no route-policy cust2bgp +! +no route-policy static-to-bgp +! +no class-map match-any data +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/defaults/config.j2 b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/defaults/config.j2 new file mode 100644 index 00000000..92f35da8 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/templates/defaults/config.j2 @@ -0,0 +1,3 @@ +interface Loopback999 + description this is a test + no shutdown diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/backup.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/backup.yaml new file mode 100644 index 00000000..f33fedff --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/backup.yaml @@ -0,0 +1,69 @@ +--- +- ansible.builtin.debug: msg="START cli/backup.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - no description + - no shutdown + parents: + - interface Loopback999 + match: none + +- name: Configure device with configuration + register: result + cisco.iosxr.iosxr_config: + src: basic/config.j2 + backup: true + +- ansible.builtin.assert: + that: + - result.changed == true + - result.updates is not defined + +- name: Delete configurable backup file path + ansible.builtin.file: + path: "{{ item }}" + state: absent + with_items: + - "{{ role_path }}/backup_test_dir/" + - "{{ role_path }}/backup/backup.cfg" + +- name: Take configuration backup in custom filename and directory path + become: true + register: result + cisco.iosxr.iosxr_config: + backup: true + backup_options: + filename: backup.cfg + dir_path: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}" + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Take configuration backup in custom filename + become: true + register: result + cisco.iosxr.iosxr_config: + backup: true + backup_options: + filename: backup.cfg + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Take configuration backup in custom path and default filename + become: true + register: result + cisco.iosxr.iosxr_config: + backup: true + backup_options: + dir_path: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}" + +- ansible.builtin.assert: + that: + - result.changed == true + +- ansible.builtin.debug: msg="END cli/backup.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/comment-too-long.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/comment-too-long.yaml new file mode 100644 index 00000000..cbb59f6e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/comment-too-long.yaml @@ -0,0 +1,26 @@ +--- +- ansible.builtin.debug: msg="START cli/comment-too-long.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - no description + - no shutdown + parents: + - interface Loopback999 + match: none + +- name: Commit message too long + register: result + ignore_errors: true + cisco.iosxr.iosxr_config: + src: basic/config.j2 + comment: this is a really long message aaaaabbbbbbcdde end-of-message + +- ansible.builtin.assert: + that: + - result.changed == false + - result.updates is not defined + - "'comment argument cannot be more than 60 characters' in result.msg" + +- ansible.builtin.debug: msg="END cli/comment-too-long.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/comment.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/comment.yaml new file mode 100644 index 00000000..dcbbe78a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/comment.yaml @@ -0,0 +1,76 @@ +--- +- ansible.builtin.debug: msg="START cli/comment.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - no description + - no shutdown + parents: + - interface Loopback999 + match: none + +- name: Configure device with comment + register: result + cisco.iosxr.iosxr_config: + src: basic/config.j2 + comment: this is sensible commit message + exclusive: true + +- ansible.builtin.assert: + that: + - result.changed == true + - result.updates is not defined + +- name: Check device with configuration + register: result + cisco.iosxr.iosxr_config: + src: basic/config.j2 + exclusive: true + +- ansible.builtin.assert: + that: + - result.changed == false + - result.updates is not defined + +- name: Assert accurately report configuration failure during pseudo-atomic operation + register: result + ignore_errors: true + cisco.iosxr.iosxr_config: + lines: + - router bgp 65111 + - neighbor 10.1.1.1 + - update-source Loopback0 + +- ansible.builtin.assert: + that: + - result.changed == false + - result.failed == true + +- name: Run show configuration failed + register: result + cisco.iosxr.iosxr_config: + lines: + - show configuration failed + +- ansible.builtin.assert: + that: + - result.failed == false + +- name: Configure device without default comment + register: result + cisco.iosxr.iosxr_config: + lines: hostname iosxr1 + disable_default_comment: true + +- name: Check details of latest commit + iosxr_command: + commands: + - show configuration commit list 1 detail + register: result + +- ansible.builtin.assert: + that: + - "'configured by iosxr_config' not in result.stdout[0]" + +- ansible.builtin.debug: msg="END cli/comment.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/commit_confirmed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/commit_confirmed.yaml new file mode 100644 index 00000000..f9d672d2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/commit_confirmed.yaml @@ -0,0 +1,35 @@ +--- +- ansible.builtin.debug: msg="START cli/commit_confirmed.yaml on connection={{ ansible_connection }}" + +- name: Test commit confirmed functionality + vars: + ansible_iosxr_commit_confirmed: true + ansible_iosxr_commit_confirmed_timeout: 60 + cisco.iosxr.iosxr_config: + lines: + - hostname iosxr_commit_confirmed + +- name: "Get hostname" + vars: + ansible_iosxr_commit_confirmed: true + register: get_hostname1 + iosxr_command: + commands: + - "show running-config hostname" + ignore_errors: true + +- name: Sleep for 90 secs as rollback to happen. + ansible.builtin.wait_for: + timeout: 90 + +- name: "Get hostname" + register: get_hostname2 + iosxr_command: + commands: + - "show running-config hostname" + ignore_errors: true + +- ansible.builtin.assert: + that: + - "'iosxr_commit_confirmed' in get_hostname1.stdout[0]" + - "'iosxr_commit_confirmed' not in get_hostname2.stdout[0]" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/commit_label.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/commit_label.yaml new file mode 100644 index 00000000..f4926bae --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/commit_label.yaml @@ -0,0 +1,70 @@ +--- +- ansible.builtin.debug: msg="START cli/commit_label.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - no description + - no shutdown + parents: + - interface Loopback999 + match: none + +- name: Get a unique and valid label + ansible.builtin.set_fact: + label: ansible_{{ 1001 | random | to_uuid | truncate(20, true, '_') }} + +- name: Configure device with a label and a comment + register: result + cisco.iosxr.iosxr_config: + src: basic/config.j2 + comment: this is sensible commit message + label: "{{ label }}" + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - no description + - no shutdown + parents: + - interface Loopback999 + match: none + +- name: Try to commit with old label, fail with a msg that label is alreay used + register: result + ignore_errors: true + cisco.iosxr.iosxr_config: + src: basic/config.j2 + label: "{{ label }}" + +- ansible.builtin.assert: + that: + - result.changed == false + - "'already used' in result.msg" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - no description + - no shutdown + parents: + - interface Loopback999 + match: none + +- name: Try to commit with invalid chars($) in label + register: result + ignore_errors: true + cisco.iosxr.iosxr_config: + src: basic/config.j2 + label: ansible_iosxr_config_$ + +- ansible.builtin.assert: + that: + - result.changed == false + - "'only contain alphabets' in result.msg" + +- ansible.builtin.debug: msg="END cli/commit_label.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/extcommunity_set_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/extcommunity_set_config.yaml new file mode 100644 index 00000000..225f6b1c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/extcommunity_set_config.yaml @@ -0,0 +1,26 @@ +--- +- ansible.builtin.debug: msg="START cli/extcommunity_set_config.yaml on connection={{ ansible_connection }}" + +- name: Pre-setup cleanup + cisco.iosxr.iosxr_config: + commands: + - no extcommunity-set rt test_set + +- name: Setup + register: result + cisco.iosxr.iosxr_config: + lines: + - 6667:1234 + - end-set + parents: extcommunity-set rt test_set + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Post-setup cleanup + cisco.iosxr.iosxr_config: + commands: + - no extcommunity-set rt test_set + +- ansible.builtin.debug: msg="END cli/ on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/misplaced_sublevel.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/misplaced_sublevel.yaml new file mode 100644 index 00000000..23069211 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/misplaced_sublevel.yaml @@ -0,0 +1,27 @@ +--- +- ansible.builtin.debug: msg="START cli/misplaced_sublevel.yaml on connection={{ ansible_connection }}" + +- name: Setup + ignore_errors: true + cisco.iosxr.iosxr_config: + src: basic/init_prefix_set.j2 + +- name: Change prefix-set and new command after prefix-set + register: result + cisco.iosxr.iosxr_config: + src: basic/change_prefix_set.j2 + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Play same configuration again to verify no diff in prefix-set also works + register: result + cisco.iosxr.iosxr_config: + src: basic/change_prefix_set.j2 + +- ansible.builtin.assert: + that: + - result.changed == false + +- ansible.builtin.debug: msg="END cli/misplaced_sublevel.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/prefix_set_remark.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/prefix_set_remark.yaml new file mode 100644 index 00000000..d6909db1 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/prefix_set_remark.yaml @@ -0,0 +1,28 @@ +--- +- ansible.builtin.debug: msg="START cli/prefix_set_remark.yaml on connection={{ ansible_connection }}" + +- name: Pre-setup cleanup + cisco.iosxr.iosxr_config: + commands: + - no prefix-set test_set + +- name: Setup + register: result + cisco.iosxr.iosxr_config: + lines: + - "## testremark" + - 192.168.1.0/20 le 24 + - end-set + parents: prefix-set test_set + +- ansible.builtin.assert: + that: + - result.changed == true + - "'## testremark' in result.commands" + +- name: Post-setup cleanup + cisco.iosxr.iosxr_config: + commands: + - no prefix-set test_set + +- ansible.builtin.debug: msg="END cli/prefix_set_remark.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/replace_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/replace_config.yaml new file mode 100644 index 00000000..6cd72dba --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/replace_config.yaml @@ -0,0 +1,40 @@ +--- +- ansible.builtin.debug: msg="START cli/replace_config.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - no interface GigabitEthernet0/0/0/3 + +- name: Replace configuration (add preconfigured interface) + register: result + cisco.iosxr.iosxr_config: &id001 + src: "{{ role_path }}/fixtures/config_add_interface.txt" + replace: config + +- ansible.builtin.assert: + that: + - '"load harddisk:/ansible_config.txt" in result.commands' + +- name: Replace configuration (add preconfigured interface)(idempotence) + register: result + cisco.iosxr.iosxr_config: *id001 +- ansible.builtin.assert: &id003 + that: + - result.changed == false + +- name: Replace configuration (del preconfigured interface) + register: result + cisco.iosxr.iosxr_config: &id002 + src: "{{ role_path }}/fixtures/config_del_interface.txt" + replace: config + +- ansible.builtin.assert: + that: + - '"load harddisk:/ansible_config.txt" in result.commands' + +- name: Replace configuration (del preconfigured interface)(idempotence) + register: result + cisco.iosxr.iosxr_config: *id002 +- ansible.builtin.assert: *id003 +- ansible.builtin.debug: msg="END cli/replace_config.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/route_policy.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/route_policy.yaml new file mode 100644 index 00000000..e5f374be --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/route_policy.yaml @@ -0,0 +1,53 @@ +--- +- ansible.builtin.debug: msg="START cli/route_policy.yaml on connection={{ ansible_connection }}" + +- name: Cleanup + cisco.iosxr.iosxr_config: + src: basic/route_policy_clean.j2 + +- name: Config setup route-policy/prefix-set/as-path-set/community-set + register: result + cisco.iosxr.iosxr_config: + src: basic/route_policy.j2 + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Configure same route-policy/prefix-set ... verify change=0 + register: result + cisco.iosxr.iosxr_config: + src: basic/route_policy.j2 + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Do a change in multi-sublevel route-policy/prefix-set/community-set + register: result + cisco.iosxr.iosxr_config: + src: basic/route_policy_change.j2 + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Configure same route-policy/prefix-set ... verify change=0 + register: result + cisco.iosxr.iosxr_config: + src: basic/route_policy_change.j2 + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Cleanup + register: result + cisco.iosxr.iosxr_config: + src: basic/route_policy_clean.j2 + +- ansible.builtin.assert: + that: + - result.changed == true + +- ansible.builtin.debug: msg="END cli/route_policy.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/src_basic.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/src_basic.yaml new file mode 100644 index 00000000..dd79ebe0 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/src_basic.yaml @@ -0,0 +1,33 @@ +--- +- ansible.builtin.debug: msg="START cli/src_basic.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - no description + - no shutdown + parents: + - interface Loopback999 + match: none + +- name: Configure device with configuration + register: result + cisco.iosxr.iosxr_config: + src: basic/config.j2 + +- ansible.builtin.assert: + that: + - result.changed == true + - result.updates is not defined + +- name: Check device with configuration + register: result + cisco.iosxr.iosxr_config: + src: basic/config.j2 + +- ansible.builtin.assert: + that: + - result.changed == false + - result.updates is not defined + +- ansible.builtin.debug: msg="END cli/src_basic.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/src_invalid.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/src_invalid.yaml new file mode 100644 index 00000000..4b02dbf3 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/src_invalid.yaml @@ -0,0 +1,16 @@ +--- +- ansible.builtin.debug: msg="START cli/src_invalid.yaml on connection={{ ansible_connection }}" + +- name: Configure with invalid src + register: result + ignore_errors: true + cisco.iosxr.iosxr_config: + src: basic/foobar.j2 + +- ansible.builtin.assert: + that: + - result.changed == false + - result.failed == true + - result.msg == 'path specified in src not found' + +- ansible.builtin.debug: msg="END cli/src_invalid.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/src_match_none.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/src_match_none.yaml new file mode 100644 index 00000000..7794ab37 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/src_match_none.yaml @@ -0,0 +1,34 @@ +--- +- ansible.builtin.debug: msg="START cli/src_match_none.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - no description + - no shutdown + parents: + - interface Loopback999 + match: none + +- name: Configure device with configuration + register: result + cisco.iosxr.iosxr_config: + src: basic/config.j2 + match: none + +- ansible.builtin.assert: + that: + - result.changed == true + - result.updates is not defined + +- name: Check device with configuration + register: result + cisco.iosxr.iosxr_config: + src: basic/config.j2 + +- ansible.builtin.assert: + that: + - result.changed == false + - result.updates is not defined + +- ansible.builtin.debug: msg="END cli/src_match_none.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel.yaml new file mode 100644 index 00000000..536db642 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel.yaml @@ -0,0 +1,43 @@ +--- +- ansible.builtin.debug: msg="START cli/sublevel.yaml on connection={{ ansible_connection }}" + +- name: Setup + ignore_errors: true + cisco.iosxr.iosxr_config: + commands: + - no ipv4 access-list test + match: none + +- name: Configure sub level command + register: result + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 any any log + parents: + - ipv4 access-list test + +- ansible.builtin.assert: + that: + - result.changed == true + - "'ipv4 access-list test' in result.commands" + - "'10 permit ipv4 any any log' in result.commands" + +- name: Configure sub level command idempotent check + register: result + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 any any log + parents: + - ipv4 access-list test + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + commands: + - no ipv4 access-list test + match: none + +- ansible.builtin.debug: msg="END cli/sublevel.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_block.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_block.yaml new file mode 100644 index 00000000..2bbb2f6d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_block.yaml @@ -0,0 +1,59 @@ +--- +- ansible.builtin.debug: msg="START cli/sublevel_block.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.2 any log + - 30 permit ipv4 host 192.0.2.3 any log + parents: + - ipv4 access-list test + before: + - no ipv4 access-list test + match: none + +- name: Configure sub level command using block resplace + register: result + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.2 any log + - 30 permit ipv4 host 192.0.2.3 any log + - 40 permit ipv4 host 192.0.2.4 any log + parents: + - ipv4 access-list test + replace: block + +- ansible.builtin.assert: + that: + - result.changed == true + - "'ipv4 access-list test' in result.commands" + - "'10 permit ipv4 host 192.0.2.1 any log' in result.commands" + - "'20 permit ipv4 host 192.0.2.2 any log' in result.commands" + - "'30 permit ipv4 host 192.0.2.3 any log' in result.commands" + - "'40 permit ipv4 host 192.0.2.4 any log' in result.commands" + +- name: Check sub level command using block replace + register: result + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.2 any log + - 30 permit ipv4 host 192.0.2.3 any log + - 40 permit ipv4 host 192.0.2.4 any log + parents: + - ipv4 access-list test + replace: block + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + commands: + - no ipv4 access-list test + match: none + +- ansible.builtin.debug: msg="END cli/sublevel_block.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_exact.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_exact.yaml new file mode 100644 index 00000000..1413a86b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_exact.yaml @@ -0,0 +1,63 @@ +--- +- ansible.builtin.debug: msg="START cli/sublevel_exact.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.2 any log + - 30 permit ipv4 host 192.0.2.3 any log + - 40 permit ipv4 host 192.0.2.4 any log + - 50 permit ipv4 host 192.0.2.5 any log + parents: + - ipv4 access-list test + before: + - no ipv4 access-list test + match: none + +- name: Configure sub level command using exact match + register: result + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.2 any log + - 30 permit ipv4 host 192.0.2.3 any log + - 40 permit ipv4 host 192.0.2.4 any log + parents: + - ipv4 access-list test + match: exact + +- ansible.builtin.assert: + that: + - result.changed == true + - "'ipv4 access-list test' in result.commands" + - "'10 permit ipv4 host 192.0.2.1 any log' in result.commands" + - "'20 permit ipv4 host 192.0.2.2 any log' in result.commands" + - "'30 permit ipv4 host 192.0.2.3 any log' in result.commands" + - "'40 permit ipv4 host 192.0.2.4 any log' in result.commands" + - "'50 permit ipv4 host 192.0.2.5 any log' not in result.commands" + +- name: Check sub level command using exact match + register: result + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.2 any log + - 30 permit ipv4 host 192.0.2.3 any log + - 40 permit ipv4 host 192.0.2.4 any log + - 50 permit ipv4 host 192.0.2.5 any log + parents: + - ipv4 access-list test + match: exact + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + commands: + - no ipv4 access-list test + match: none + +- ansible.builtin.debug: msg="END cli/sublevel_exact.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_strict.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_strict.yaml new file mode 100644 index 00000000..78ede704 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_strict.yaml @@ -0,0 +1,65 @@ +--- +- ansible.builtin.debug: msg="START cli/sublevel_strict.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.3 any log + - 30 permit ipv4 host 192.0.2.2 any log + - 40 permit ipv4 host 192.0.2.4 any log + - 50 permit ipv4 host 192.0.2.5 any log + parents: + - ipv4 access-list test + before: + - no ipv4 access-list test + match: none + +- name: Configure sub level command using strict match + register: result + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.2 any log + - 30 permit ipv4 host 192.0.2.3 any log + - 40 permit ipv4 host 192.0.2.4 any log + parents: + - ipv4 access-list test + before: + - no ipv4 access-list test + match: strict + replace: block + +- ansible.builtin.assert: + that: + - result.changed == true + - "'ipv4 access-list test' in result.commands" + - "'10 permit ipv4 host 192.0.2.1 any log' in result.commands" + - "'20 permit ipv4 host 192.0.2.2 any log' in result.commands" + - "'30 permit ipv4 host 192.0.2.3 any log' in result.commands" + - "'40 permit ipv4 host 192.0.2.4 any log' in result.commands" + - "'50 permit ipv4 host 192.0.2.5 any log' not in result.commands" + +- name: Check sub level command using strict match + register: result + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.2 any log + - 30 permit ipv4 host 192.0.2.3 any log + - 40 permit ipv4 host 192.0.2.4 any log + parents: + - ipv4 access-list test + match: strict + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + commands: + - no ipv4 access-list test + match: none + +- ansible.builtin.debug: msg="END cli/sublevel_strict.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_strict_mul_parents.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_strict_mul_parents.yaml new file mode 100644 index 00000000..54d91adb --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/sublevel_strict_mul_parents.yaml @@ -0,0 +1,73 @@ +--- +- ansible.builtin.debug: msg="START cli/sublevel_strict_mul_parents.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + lines: + - class-map match-any c1 + - match precedence 7 + - policy-map p1 + - class c1 + - set precedence 2 + before: + - no policy-map p1 + - no class-map match-any c1 + match: none + +- name: Configure sub level command using strict match + register: result + cisco.iosxr.iosxr_config: + lines: + - set precedence 5 + - police rate percent 10 + parents: + - policy-map p1 + - class c1 + match: strict + +- ansible.builtin.assert: + that: + - result.changed == true + - "'set precedence 5' in result.commands" + - "'police rate percent 10' in result.commands" + +- name: Change sub level command order and configuration with strict match + register: result + cisco.iosxr.iosxr_config: + lines: + - police rate percent 10 + - set precedence 5 + parents: + - policy-map p1 + - class c1 + match: strict + +- ansible.builtin.assert: + that: + - result.changed == true + - "'set precedence 5' in result.commands" + - "'police rate percent 10' in result.commands" + +- name: Config sub level command with strict match (idempotency) + register: result + cisco.iosxr.iosxr_config: + lines: + - set precedence 5 + - police rate percent 10 + parents: + - policy-map p1 + - class c1 + match: strict + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + lines: + - no policy-map p1 + - no class-map match-any c1 + match: none + +- ansible.builtin.debug: msg="END cli/sublevel_strict_mul_parents.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel.yaml new file mode 100644 index 00000000..b548d561 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel.yaml @@ -0,0 +1,37 @@ +--- +- ansible.builtin.debug: msg="START cli/toplevel.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - hostname {{ inventory_hostname_short }} + match: none + +- name: Configure top level command + register: result + cisco.iosxr.iosxr_config: + commands: + - hostname foo + +- ansible.builtin.assert: + that: + - result.changed == true + - "'hostname foo' in result.commands" + +- name: Configure top level command idempotent check + register: result + cisco.iosxr.iosxr_config: + commands: + - hostname foo + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + commands: + - hostname {{ inventory_hostname_short }} + match: none + +- ansible.builtin.debug: msg="END cli/toplevel.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel_after.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel_after.yaml new file mode 100644 index 00000000..f41fd461 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel_after.yaml @@ -0,0 +1,44 @@ +--- +- ansible.builtin.debug: msg="START cli/toplevel_after.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - no cdp + - hostname {{ inventory_hostname_short }} + match: none + +- name: Configure top level command with before + register: result + cisco.iosxr.iosxr_config: + commands: + - hostname foo + after: + - cdp + +- ansible.builtin.assert: + that: + - result.changed == true + - "'hostname foo' in result.commands" + - "'cdp' in result.commands" + +- name: Configure top level command with before idempotent check + register: result + cisco.iosxr.iosxr_config: + commands: + - hostname foo + after: + - no cdp + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + commands: + - no cdp + - hostname {{ inventory_hostname_short }} + match: none + +- ansible.builtin.debug: msg="END cli/toplevel_after.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel_before.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel_before.yaml new file mode 100644 index 00000000..95ce1fb5 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel_before.yaml @@ -0,0 +1,44 @@ +--- +- ansible.builtin.debug: msg="START cli/toplevel_before.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - no cdp + - hostname {{ inventory_hostname_short }} + match: none + +- name: Configure top level command with before + register: result + cisco.iosxr.iosxr_config: + commands: + - hostname foo + before: + - cdp + +- ansible.builtin.assert: + that: + - result.changed == true + - "'hostname foo' in result.commands" + - "'cdp' in result.commands" + +- name: Configure top level command with before idempotent check + register: result + cisco.iosxr.iosxr_config: + commands: + - hostname foo + before: + - cdp + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + commands: + - no cdp + - hostname {{ inventory_hostname_short }} + match: none + +- ansible.builtin.debug: msg="END cli/toplevel_before.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel_nonidempotent.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel_nonidempotent.yaml new file mode 100644 index 00000000..498f5f91 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli/toplevel_nonidempotent.yaml @@ -0,0 +1,42 @@ +--- +- ansible.builtin.debug: msg="START cli/toplevel_nonidempotent.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - hostname {{ inventory_hostname_short }} + match: none + +- name: Configure top level command + register: result + cisco.iosxr.iosxr_config: + commands: + - banner motd "hello world" + - hostname foo + match: strict + +- ansible.builtin.assert: + that: + - result.changed == true + - "'hostname foo' in result.commands" + - '''banner motd "hello world"'' in result.commands' + +- name: Configure top level command idempotent check + register: result + cisco.iosxr.iosxr_config: + commands: + - banner motd "hello world" + - hostname foo + match: strict + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Teardown + cisco.iosxr.iosxr_config: + commands: + - hostname {{ inventory_hostname_short }} + match: none + +- ansible.builtin.debug: msg="END cli/toplevel_nonidempotent.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli_config/cli_backup.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli_config/cli_backup.yaml new file mode 100644 index 00000000..acfa2cc3 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli_config/cli_backup.yaml @@ -0,0 +1,59 @@ +--- +- ansible.builtin.debug: msg="END cli_config/backup.yaml on connection={{ ansible_connection }}" + +- name: Delete configurable backup file path + ansible.builtin.file: + path: "{{ item }}" + state: absent + with_items: + - "{{ role_path }}/backup_test_dir/" + - "{{ role_path }}/backup/backup.cfg" + +- name: Take configuration backup + become: true + register: result + ansible.netcommon.cli_config: + backup: true + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Take configuration backup in custom filename and directory path + become: true + register: result + ansible.netcommon.cli_config: + backup: true + backup_options: + filename: backup.cfg + dir_path: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}" + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Take configuration backup in custom filename + become: true + register: result + ansible.netcommon.cli_config: + backup: true + backup_options: + filename: backup.cfg + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Take configuration backup in custom path and default filename + become: true + register: result + ansible.netcommon.cli_config: + backup: true + backup_options: + dir_path: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}" + +- ansible.builtin.assert: + that: + - result.changed == true + +- ansible.builtin.debug: msg="END cli_config/backup.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli_config/cli_basic.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli_config/cli_basic.yaml new file mode 100644 index 00000000..18ffd2bc --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/cli_config/cli_basic.yaml @@ -0,0 +1,28 @@ +--- +- ansible.builtin.debug: msg="START cli_config/cli_basic.yaml on connection={{ ansible_connection }}" + +- name: Setup + become: true + ansible.netcommon.cli_config: &id002 + config: "interface Loopback999\n no description\n no shutdown\n" + +- name: Configure device with configuration + register: result + become: true + ansible.netcommon.cli_config: &id001 + config: "{{ lookup('template', 'basic/config.j2') }}" + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Idempotence + register: result + ansible.netcommon.cli_config: *id001 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + ansible.netcommon.cli_config: *id002 +- ansible.builtin.debug: msg="END cli_config/cli_basic.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/redirection/shortname.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/redirection/shortname.yaml new file mode 100644 index 00000000..d2eb4d5f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_config/tests/redirection/shortname.yaml @@ -0,0 +1,27 @@ +--- +- ansible.builtin.debug: msg="START redirection/shortname.yaml on connection={{ ansible_connection }}" + +- name: Use src with module alias + register: result + cisco.iosxr.config: + src: basic/configuration.j2 + +- ansible.builtin.assert: + that: + # make sure that the template content was read and not the path + - result.changed == true + - '"description test for ansible automation" in result.diff["prepared"]' + +- name: Use module alias to take configuration backup + register: result + cisco.iosxr.config: + backup: true + backup_options: + filename: backup_with_alias.cfg + dir_path: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}" + +- ansible.builtin.assert: + that: + - result.changed == true + +- ansible.builtin.debug: msg="END redirection/shortname.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/defaults/main.yaml new file mode 100644 index 00000000..9ef5ba51 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/meta/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/meta/main.yml new file mode 100644 index 00000000..be631e5d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_iosxr_tests diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tasks/cli.yaml new file mode 100644 index 00000000..59a889b4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/all_facts.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/all_facts.yaml new file mode 100644 index 00000000..7ba14f28 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/all_facts.yaml @@ -0,0 +1,33 @@ +--- +- ansible.builtin.debug: msg="START cli/all_facts.yaml on connection={{ ansible_connection }}" + +- name: Test getting all facts + register: result + cisco.iosxr.iosxr_facts: + gather_subset: + - all + +- ansible.builtin.assert: + that: + - result.changed == false + - "'config' in result.ansible_facts.ansible_net_gather_subset" + - "'hardware' in result.ansible_facts.ansible_net_gather_subset" + - "'default' in result.ansible_facts.ansible_net_gather_subset" + - "'interfaces' in result.ansible_facts.ansible_net_gather_subset" + - result.ansible_facts.ansible_net_model == 'IOS-XRv 9000' + - result.ansible_facts.ansible_net_filesystems is defined + +- name: Collect list of available network resources for iosxr + register: result + cisco.iosxr.iosxr_facts: + available_network_resources: true + gather_network_resources: all + +- name: Assert that correct available_network_resources returned + ansible.builtin.assert: + that: + - result.changed == false + - "{{ result['ansible_facts']['available_network_resources'] | symmetric_difference(result['ansible_facts']['ansible_net_gather_network_resources']) |length\ + \ == 0 }}" + +- ansible.builtin.debug: msg="END cli/all_facts.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/default_facts.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/default_facts.yaml new file mode 100644 index 00000000..065f07bf --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/default_facts.yaml @@ -0,0 +1,22 @@ +--- +- ansible.builtin.debug: msg="START cli/default_facts.yaml on connection={{ ansible_connection }}" + +- name: Test getting default facts + register: result + cisco.iosxr.iosxr_facts: + +- ansible.builtin.assert: + that: + - result.changed == false + - "'default' in result.ansible_facts.ansible_net_gather_subset" + - "'config' not in result.ansible_facts.ansible_net_gather_subset" + - result.ansible_facts.ansible_net_hostname is defined + - result.ansible_facts.ansible_net_image is defined + - result.ansible_facts.ansible_net_model is defined + - result.ansible_facts.ansible_net_python_version is defined + - result.ansible_facts.ansible_net_serialnum is defined + - result.ansible_facts.ansible_net_system is defined + - result.ansible_facts.ansible_net_version is defined + - result.ansible_facts.ansible_network_resources == {} + +- ansible.builtin.debug: msg="END cli/default.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/invalid_subset.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/invalid_subset.yaml new file mode 100644 index 00000000..26284ddb --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/invalid_subset.yaml @@ -0,0 +1,32 @@ +--- +- ansible.builtin.debug: msg="START cli/invalid_subset.yaml on connection={{ ansible_connection }}" + +- name: Test invalid subset (foobar) + register: result + ignore_errors: true + cisco.iosxr.iosxr_facts: + gather_subset: + - foobar + +- ansible.builtin.assert: + that: + - result.changed == false + - result.failed == true + - result.msg == 'Subset must be one of [config, default, hardware, interfaces], got foobar' + +- name: Test subset specified multiple times + register: result + ignore_errors: true + cisco.iosxr.iosxr_facts: + gather_subset: + - "!hardware" + - hardware + +- ansible.builtin.assert: + that: + - result.changed == false + - result.failed == true + - result.msg == 'Bad subset' + ignore_errors: true + +- ansible.builtin.debug: msg="END cli/invalid_subset.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/not_hardware.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/not_hardware.yaml new file mode 100644 index 00000000..6591a872 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_facts/tests/cli/not_hardware.yaml @@ -0,0 +1,20 @@ +--- +- ansible.builtin.debug: msg="START cli/not_hardware_facts.yaml on connection={{ ansible_connection }}" + +- name: Test not hardware + register: result + cisco.iosxr.iosxr_facts: + gather_subset: + - "!hardware" + +- ansible.builtin.assert: + that: + - result.changed == false + - "'config' in result.ansible_facts.ansible_net_gather_subset" + - "'default' in result.ansible_facts.ansible_net_gather_subset" + - "'interfaces' in result.ansible_facts.ansible_net_gather_subset" + - "'hardware' not in result.ansible_facts.ansible_net_gather_subset" + - result.ansible_facts.ansible_net_interfaces | length > 1 + - result.ansible_facts.ansible_net_filesystems is not defined + +- ansible.builtin.debug: msg="END cli/not_hardware_facts.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/defaults/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/defaults/main.yml new file mode 100644 index 00000000..871ea460 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/defaults/main.yml @@ -0,0 +1,2 @@ +--- +testcase: "[^_].*" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/meta/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/meta/main.yml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/meta/main.yml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tasks/cli.yaml new file mode 100644 index 00000000..a1b57ab4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tasks/cli.yaml @@ -0,0 +1,21 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tasks/main.yaml new file mode 100644 index 00000000..f75f2f03 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/_parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/_parsed.cfg new file mode 100644 index 00000000..309b8238 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/_parsed.cfg @@ -0,0 +1 @@ +hostname test diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/_populate_config.yaml new file mode 100644 index 00000000..c48c578e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/_populate_config.yaml @@ -0,0 +1,6 @@ +--- +- name: Populate hostname configuration + cisco.iosxr.iosxr_hostname: + config: + hostname: "iosxr1" + state: merged diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/_remove_config.yaml new file mode 100644 index 00000000..62851700 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/_remove_config.yaml @@ -0,0 +1,5 @@ +--- +- name: Remove hostname configuration + cisco.iosxr.iosxr_hostname: + config: + state: deleted diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/deleted.yaml new file mode 100644 index 00000000..e3b23dbd --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/deleted.yaml @@ -0,0 +1,27 @@ +--- +- ansible.builtin.debug: + msg: Start Deleted integration state for iosxr_hostname ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Iosxr_hostname deleted - play + register: result + cisco.iosxr.iosxr_hostname: + config: + state: deleted + + - name: Iosxr_hostname deleted - assert commands + ansible.builtin.assert: + that: + - deleted['commands'] == result['commands'] + + - name: Iosxr_hostname deleted - assert before + ansible.builtin.assert: + that: + - deleted['before'] == result['before'] + + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/empty_config.yaml new file mode 100644 index 00000000..e76ab5a0 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_hostname empty_config.yaml integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_hostname: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_hostname: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_hostname: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_hostname: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_hostname: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/gathered.yaml new file mode 100644 index 00000000..1cdd253a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/gathered.yaml @@ -0,0 +1,20 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_hostname gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Ios_hostname gather - play + register: result + cisco.iosxr.iosxr_hostname: + config: + state: gathered + + - name: Iosxr_hostname gather - assert + ansible.builtin.assert: + that: + - gathered['config'] == result['gathered'] + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/merged.yaml new file mode 100644 index 00000000..333eb069 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/merged.yaml @@ -0,0 +1,33 @@ +--- +- ansible.builtin.debug: + msg: START Merged iosxr_hostname state for integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Iosxr_hostname merged - play + register: result + cisco.iosxr.iosxr_hostname: &id001 + config: + hostname: "iosxr1" + state: merged + + - name: Iosxr_hostname merged - assert commands + ansible.builtin.assert: + that: + - merged['commands'] == result['commands'] + + - name: Iosxr_hostname merged - assert after + ansible.builtin.assert: + that: + - merged['after'] == result['after'] + + - name: Iosxr_hostname merged - play (idempotent) + register: result + cisco.iosxr.iosxr_hostname: *id001 + - name: Iosxr_hostname merged - assert above task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/parsed.yaml new file mode 100644 index 00000000..cfae6f30 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_hostname parsed integration tests on connection={{ ansible_connection }} + +- name: Iosxr_hostname parsed - play + register: result + cisco.iosxr.iosxr_hostname: + running_config: "{{ lookup('file', '_parsed.cfg') }}" + state: parsed + +- ansible.builtin.assert: + that: + - result.changed == false + - parsed['config'] == result['parsed'] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/rendered.yaml new file mode 100644 index 00000000..11976100 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/tests/common/rendered.yaml @@ -0,0 +1,16 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_hostname rendered integration tests ansible_connection={{ ansible_connection }} + +- block: + - name: Iosxr_hostname render - play + register: result + cisco.iosxr.iosxr_hostname: + config: + hostname: "test" + state: rendered + + - ansible.builtin.assert: + that: + - result.changed == false + - result.rendered == rendered['commands'] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/vars/main.yaml new file mode 100644 index 00000000..fce4dc5f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_hostname/vars/main.yaml @@ -0,0 +1,24 @@ +--- +merged: + commands: + - hostname iosxr1 + after: + hostname: "iosxr1" + +deleted: + before: + hostname: "iosxr1" + commands: + - no hostname iosxr1 + +parsed: + config: + hostname: "test" + +gathered: + config: + hostname: "iosxr1" + +rendered: + commands: + - hostname test diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/meta/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/meta/main.yaml new file mode 100644 index 00000000..23d65c7e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/meta/main.yaml @@ -0,0 +1,2 @@ +--- +dependencies: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_deleted.yaml new file mode 100644 index 00000000..2ccf6abf --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_deleted.yaml @@ -0,0 +1,38 @@ +--- +- ansible.builtin.debug: + msg: Start Deleted integration state for iosxr_interfaces ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete attributes of all configured interfaces + register: result + cisco.iosxr.iosxr_interfaces: &id001 + state: deleted + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Delete attributes of all configured interfaces (idempotent) + register: result + cisco.iosxr.iosxr_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_overridden.yaml new file mode 100644 index 00000000..7aa669f1 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_overridden.yaml @@ -0,0 +1,45 @@ +--- +- ansible.builtin.debug: + msg: START Overridden iosxr_interfaces state for integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Override device configuration of all interfaces with provided configuration + register: result + cisco.iosxr.iosxr_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/1 + description: Configured and Overridden by Ansible-Network + enabled: false + duplex: full + mtu: 2000 + speed: 100 + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Override device configuration of all interfaces with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_populate_config.yaml new file mode 100644 index 00000000..4c565b79 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_populate_config.yaml @@ -0,0 +1,18 @@ +--- +- name: "Populate configuration interface 0/0/0/0" + cisco.iosxr.iosxr_config: + lines: + - "description this is interface0" + - "mtu 65" + - "speed 10" + - "no shutdown" + parents: "interface GigabitEthernet 0/0/0/0" + +- name: "Populate configuration interface 0/0/0/1" + cisco.iosxr.iosxr_config: + lines: + - "description this is interface1" + - "mtu 65" + - "speed 10" + - "no shutdown" + parents: "interface GigabitEthernet 0/0/0/1" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..1512a4b3 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/_remove_config.yaml @@ -0,0 +1,17 @@ +--- +- name: Remove configuration + vars: + lines: "interface loopback888\nno description\nno shutdown\ninterface loopback999\nno description\nno shutdown\n" + ansible.netcommon.cli_config: + config: "{{ lines }}" + +- name: Remove interfaces from configuration before actual testing + loop: + - GigabitEthernet 0/0/0/0 + - GigabitEthernet 0/0/0/1 + - GigabitEthernet 0/0/0/2 + - GigabitEthernet 0/0/0/3 + ignore_errors: true + cisco.iosxr.iosxr_config: + lines: + - no interface {{ item }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/empty_config.yaml new file mode 100644 index 00000000..b8196c47 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_interfaces empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_interfaces: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_interfaces: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_interfaces: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_interfaces: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_interfaces: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/fixtures/parsed.cfg new file mode 100644 index 00000000..7fe3ef97 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/fixtures/parsed.cfg @@ -0,0 +1,19 @@ +interface Loopback888 + description test for ansible + shutdown +! +interface MgmtEth0/RP0/CPU0/0 + ipv4 address 10.8.38.70 255.255.255.0 +! +interface GigabitEthernet0/0/0/0 + description Configured and Merged by Ansible-Network + mtu 110 + ipv4 address 172.31.1.1 255.255.255.0 + duplex half +! +interface GigabitEthernet0/0/0/3 + shutdown +! +interface GigabitEthernet0/0/0/4 + shutdown +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/gathered.yaml new file mode 100644 index 00000000..a10b40a6 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/gathered.yaml @@ -0,0 +1,38 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_interfaces gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Merge provided configuration with device configuration + register: result + cisco.iosxr.iosxr_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + description: This interface is Configured and Merged by Ansible-Network + mtu: 110 + enabled: true + duplex: half + + - name: GigabitEthernet0/0/0/1 + description: Configured and Merged by Ansible-Network + mtu: 2800 + enabled: false + speed: 100 + duplex: full + state: merged + + - name: Gather interfaces facts using gathered state + register: result + cisco.iosxr.iosxr_interfaces: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: "{{ gathered['after'] | symmetric_difference(result['gathered']) |length == 0 }}" + + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/merged.yaml new file mode 100644 index 00000000..d8de4294 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/merged.yaml @@ -0,0 +1,99 @@ +--- +- ansible.builtin.debug: + msg: START Merged iosxr_interfaces state for integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Merge provided configuration with device configuration + register: result + cisco.iosxr.iosxr_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + description: Configured and Merged by Ansible-Network + mtu: 110 + enabled: true + duplex: half + + - name: GigabitEthernet0/0/0/1 + description: Configured and Merged by Ansible-Network + mtu: 2800 + enabled: false + speed: 100 + duplex: full + state: merged + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Merge provided configuration with device configuration (idempotent) + register: result + cisco.iosxr.iosxr_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.debug: + msg: START Merged interfaces configuration which are not in running config with iosxr_interfaces module on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml +- block: + - name: Merge provided configuration with device configuration + register: result + cisco.iosxr.iosxr_interfaces: &id002 + config: + - name: GigabitEthernet0/0/0/2 + description: Configured and Merged by Ansible-Network + mtu: 110 + enabled: true + duplex: half + + - name: GigabitEthernet0/0/0/3 + description: Configured and Merged by Ansible-Network + mtu: 2800 + enabled: false + speed: 100 + duplex: full + state: merged + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['preconfigure']['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['preconfigure']['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ merged['preconfigure']['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Merge provided configuration with device configuration (idempotent) + register: result + cisco.iosxr.iosxr_interfaces: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/parsed.yaml new file mode 100644 index 00000000..0d68c20f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_interfaces parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided interfaces configuration to agnostic model + register: result + cisco.iosxr.iosxr_interfaces: + running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ parsed['after'] | symmetric_difference(result['parsed']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/rendered.yaml new file mode 100644 index 00000000..0a5935d2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/rendered.yaml @@ -0,0 +1,26 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_interfaces rendered integration tests on connection={{ ansible_connection }} + +- name: Render platform specific commands from task input using rendered state + register: result + cisco.iosxr.iosxr_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + description: Configured and Merged by Ansible-Network + mtu: 110 + enabled: true + duplex: half + + - name: GigabitEthernet0/0/0/1 + description: Configured and Merged by Ansible-Network + mtu: 2800 + enabled: false + speed: 100 + duplex: full + state: rendered + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - "{{ rendered['commands'] | symmetric_difference(result['rendered']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/replaced.yaml new file mode 100644 index 00000000..c49fcd8b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/tests/cli/replaced.yaml @@ -0,0 +1,46 @@ +--- +- ansible.builtin.debug: + msg: START Replaced iosxr_interfaces state for integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replaces device configuration of listed interfaces with provided configuration + register: result + cisco.iosxr.iosxr_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + description: Configured and Replaced by Ansible-Network + mtu: 110 + + - name: GigabitEthernet0/0/0/1 + description: Configured and Replaced by Ansible-Network + speed: 100 + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Replaces device configuration of listed interfaces with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/vars/main.yaml new file mode 100644 index 00000000..c4bb4fda --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_interfaces/vars/main.yaml @@ -0,0 +1,231 @@ +--- +merged: + before: + - enabled: true + name: Loopback888 + - enabled: true + name: Loopback999 + - description: this is interface0 + enabled: true + mtu: 65 + name: GigabitEthernet0/0/0/0 + speed: 10 + - description: this is interface1 + enabled: true + mtu: 65 + name: GigabitEthernet0/0/0/1 + speed: 10 + commands: + - interface GigabitEthernet0/0/0/0 + - description Configured and Merged by Ansible-Network + - mtu 110 + - duplex half + - interface GigabitEthernet0/0/0/1 + - description Configured and Merged by Ansible-Network + - mtu 2800 + - speed 100 + - duplex full + - shutdown + after: + - enabled: true + name: Loopback888 + - enabled: true + name: Loopback999 + - description: Configured and Merged by Ansible-Network + duplex: half + enabled: true + mtu: 110 + name: GigabitEthernet0/0/0/0 + speed: 10 + - description: Configured and Merged by Ansible-Network + duplex: full + enabled: false + mtu: 2800 + name: GigabitEthernet0/0/0/1 + speed: 100 + preconfigure: + before: + - enabled: true + name: Loopback888 + - enabled: true + name: Loopback999 + commands: + - interface GigabitEthernet0/0/0/2 + - description Configured and Merged by Ansible-Network + - mtu 110 + - duplex half + - no shutdown + - interface GigabitEthernet0/0/0/3 + - description Configured and Merged by Ansible-Network + - mtu 2800 + - speed 100 + - duplex full + - shutdown + after: + - enabled: true + name: Loopback888 + - enabled: true + name: Loopback999 + - description: Configured and Merged by Ansible-Network + duplex: half + enabled: true + mtu: 110 + name: GigabitEthernet0/0/0/2 + - description: Configured and Merged by Ansible-Network + duplex: full + enabled: false + mtu: 2800 + speed: 100 + name: GigabitEthernet0/0/0/3 + +parsed: + after: + - description: test for ansible + enabled: false + name: Loopback888 + - description: Configured and Merged by Ansible-Network + duplex: half + enabled: true + mtu: 110 + name: GigabitEthernet0/0/0/0 + - enabled: false + name: GigabitEthernet0/0/0/3 + - enabled: false + name: GigabitEthernet0/0/0/4 +replaced: + before: + - enabled: true + name: Loopback888 + - enabled: true + name: Loopback999 + - description: this is interface0 + enabled: true + mtu: 65 + name: GigabitEthernet0/0/0/0 + speed: 10 + - description: this is interface1 + enabled: true + mtu: 65 + name: GigabitEthernet0/0/0/1 + speed: 10 + commands: + - interface GigabitEthernet0/0/0/0 + - no speed + - description Configured and Replaced by Ansible-Network + - mtu 110 + - interface GigabitEthernet0/0/0/1 + - no mtu + - description Configured and Replaced by Ansible-Network + - speed 100 + after: + - enabled: true + name: Loopback888 + - enabled: true + name: Loopback999 + - description: Configured and Replaced by Ansible-Network + enabled: true + mtu: 110 + name: GigabitEthernet0/0/0/0 + - description: Configured and Replaced by Ansible-Network + enabled: true + name: GigabitEthernet0/0/0/1 + speed: 100 +rendered: + commands: + - interface GigabitEthernet0/0/0/0 + - description Configured and Merged by Ansible-Network + - mtu 110 + - duplex half + - no shutdown + - interface GigabitEthernet0/0/0/1 + - description Configured and Merged by Ansible-Network + - mtu 2800 + - speed 100 + - duplex full + - shutdown +overridden: + before: + - enabled: true + name: Loopback888 + - enabled: true + name: Loopback999 + - description: this is interface0 + enabled: true + mtu: 65 + name: GigabitEthernet0/0/0/0 + speed: 10 + - description: this is interface1 + enabled: true + mtu: 65 + name: GigabitEthernet0/0/0/1 + speed: 10 + commands: + - interface GigabitEthernet0/0/0/0 + - no description + - no speed + - no mtu + - interface GigabitEthernet0/0/0/1 + - description Configured and Overridden by Ansible-Network + - mtu 2000 + - duplex full + - speed 100 + - shutdown + after: + - enabled: true + name: Loopback888 + - enabled: true + name: Loopback999 + - description: Configured and Overridden by Ansible-Network + duplex: full + enabled: false + mtu: 2000 + name: GigabitEthernet0/0/0/1 + speed: 100 +gathered: + after: + - enabled: true + name: Loopback888 + - enabled: true + name: Loopback999 + - description: This interface is Configured and Merged by Ansible-Network + duplex: half + enabled: true + mtu: 110 + name: GigabitEthernet0/0/0/0 + speed: 10 + - description: Configured and Merged by Ansible-Network + duplex: full + enabled: false + mtu: 2800 + name: GigabitEthernet0/0/0/1 + speed: 100 +deleted: + before: + - enabled: true + name: Loopback888 + - enabled: true + name: Loopback999 + - description: this is interface0 + enabled: true + mtu: 65 + name: GigabitEthernet0/0/0/0 + speed: 10 + - description: this is interface1 + enabled: true + mtu: 65 + name: GigabitEthernet0/0/0/1 + speed: 10 + commands: + - interface GigabitEthernet0/0/0/0 + - no description + - no speed + - no mtu + - interface GigabitEthernet0/0/0/1 + - no description + - no speed + - no mtu + after: + - enabled: true + name: Loopback888 + - enabled: true + name: Loopback999 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/meta/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/meta/main.yaml new file mode 100644 index 00000000..23d65c7e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/meta/main.yaml @@ -0,0 +1,2 @@ +--- +dependencies: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/_populate_config.yaml new file mode 100644 index 00000000..6eb91262 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/_populate_config.yaml @@ -0,0 +1,8 @@ +--- +- name: Populate configuration + vars: + lines: + "interface GigabitEthernet 0/0/0/1\nl2transport l2protocol cpsv tunnel\nl2transport propagate remote-status\ninterface GigabitEthernet 0/0/0/4\nl2transport\ + \ l2protocol cpsv tunnel\ninterface GigabitEthernet 0/0/0/3.900\nencapsulation dot1q 40 second-dot1q 60\n" + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..5b96e4a7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/_remove_config.yaml @@ -0,0 +1,8 @@ +--- +- name: Remove configuration + vars: + lines: + "interface GigabitEthernet 0/0/0/1\nno l2transport\nno interface GigabitEthernet 0/0/0/2\nno interface GigabitEthernet 0/0/0/3\nno interface GigabitEthernet\ + \ 0/0/0/3.900\nno interface GigabitEthernet 0/0/0/4\n" + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/deleted.yaml new file mode 100644 index 00000000..3d8b1c7f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/deleted.yaml @@ -0,0 +1,38 @@ +--- +- ansible.builtin.debug: + msg: Start Deleted integration state for ios_l2_interfaces ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete layer 2 interfaces attributes of all configured interfaces + register: result + cisco.iosxr.iosxr_l2_interfaces: &id001 + state: deleted + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Delete layer 2 interfaces attributes of all configured interfaces (idempotent) + register: result + cisco.iosxr.iosxr_l2_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/empty_config.yaml new file mode 100644 index 00000000..6acdd781 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_l2_interfaces empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_l2_interfaces: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_l2_interfaces: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_l2_interfaces: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_l2_interfaces: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_l2_interfaces: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/fixtures/parsed.cfg new file mode 100644 index 00000000..8fb1ec66 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/fixtures/parsed.cfg @@ -0,0 +1,16 @@ +interface Loopback888 + description test for ansible + shutdown +! +interface MgmtEth0/RP0/CPU0/0 + ipv4 address 10.8.38.70 255.255.255.0 +! +interface GigabitEthernet0/0/0/1 + l2transport + l2protocol cpsv tunnel + propagate remote-status + ! +! +interface GigabitEthernet0/0/0/3.900 + encapsulation dot1q 20 second-dot1q 40 +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/gathered.yaml new file mode 100644 index 00000000..4231d516 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/gathered.yaml @@ -0,0 +1,35 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_l2_interfaces gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_l2_interfaces: + config: + - name: GigabitEthernet0/0/0/1 + l2transport: true + l2protocol: + - cpsv: tunnel + propagate: true + + - name: GigabitEthernet0/0/0/3.900 + encapsulation: + dot1q: 20 + second_dot1q: 40 + + - name: GigabitEthernet0/0/0/4 + state: merged + + - name: Gather layer 2 interfaces facts using gathered state + register: result + cisco.iosxr.iosxr_l2_interfaces: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] | symmetric_difference(result['gathered']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/merged.yaml new file mode 100644 index 00000000..e4a051fd --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/merged.yaml @@ -0,0 +1,46 @@ +--- +- ansible.builtin.debug: + msg: START Merged ios_l2_interfaces state for integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge provided layer 2 configuration with device configuration + register: result + cisco.iosxr.iosxr_l2_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/1 + l2transport: true + l2protocol: + - cpsv: tunnel + propagate: true + - name: GigabitEthernet0/0/0/3.900 + encapsulation: + dot1q: 20 + second_dot1q: 40 + state: merged + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Merge provided layer 2 configuration with device configuration (idempotent) + register: result + cisco.iosxr.iosxr_l2_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/overridden.yaml new file mode 100644 index 00000000..8f347161 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/overridden.yaml @@ -0,0 +1,47 @@ +--- +- ansible.builtin.debug: + msg: START Overridden ios_l2_interfaces state for integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Override device layer 2 configuration of all interfaces with provided configuration + register: result + cisco.iosxr.iosxr_l2_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/4 + l2transport: true + l2protocol: + - cpsv: tunnel + - name: GigabitEthernet0/0/0/3.900 + encapsulation: + dot1q: 20 + second_dot1q: 40 + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Override device layer 2 configuration of all interfaces with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_l2_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/parsed.yaml new file mode 100644 index 00000000..82c06b18 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_l2_interfaces parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided layer 2 interfaces configuration to agnostic model + register: result + cisco.iosxr.iosxr_l2_interfaces: + running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['parsed']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/rendered.yaml new file mode 100644 index 00000000..5d5eafc9 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/rendered.yaml @@ -0,0 +1,24 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_l2_interfaces rendered integration tests on connection={{ ansible_connection }} + +- name: Render platform specific commands from task input using rendered state + register: result + cisco.iosxr.iosxr_l2_interfaces: + config: + - name: GigabitEthernet0/0/0/1 + l2transport: true + l2protocol: + - cpsv: tunnel + propagate: true + - name: GigabitEthernet0/0/0/3.900 + encapsulation: + dot1q: 20 + second_dot1q: 40 + - name: GigabitEthernet0/0/0/4 + state: rendered + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['rendered']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/replaced.yaml new file mode 100644 index 00000000..dfae20d5 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/tests/cli/replaced.yaml @@ -0,0 +1,43 @@ +--- +- ansible.builtin.debug: + msg: START Replaced ios_l2_interfaces state for integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replaces device layer 2 configuration of listed interfaces with provided configuration + register: result + cisco.iosxr.iosxr_l2_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/1 + l2transport: true + l2protocol: + - cpsv: drop + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Replaces device layer 2 configuration of listed interfaces with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_l2_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/vars/main.yaml new file mode 100644 index 00000000..54c7ef62 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l2_interfaces/vars/main.yaml @@ -0,0 +1,107 @@ +--- +merged: + before: [] + commands: + - interface GigabitEthernet0/0/0/1 + - l2transport l2protocol cpsv tunnel + - l2transport propagate remote-status + - interface GigabitEthernet0/0/0/3.900 + - encapsulation dot1q 20 second-dot1q 40 + after: + - l2protocol: + - cpsv: tunnel + l2transport: true + name: GigabitEthernet0/0/0/1 + propagate: true + - name: GigabitEthernet0/0/0/3.900 + encapsulation: + dot1q: 20 + second_dot1q: 40 + +replaced: + before: + - l2protocol: + - cpsv: tunnel + l2transport: true + name: GigabitEthernet0/0/0/1 + propagate: true + - name: GigabitEthernet0/0/0/3.900 + encapsulation: + dot1q: 40 + second_dot1q: 60 + - l2protocol: + - cpsv: tunnel + l2transport: true + name: GigabitEthernet0/0/0/4 + commands: + - interface GigabitEthernet0/0/0/1 + - no l2transport + - l2transport l2protocol cpsv drop + after: + - l2protocol: + - cpsv: drop + l2transport: true + name: GigabitEthernet0/0/0/1 + - name: GigabitEthernet0/0/0/3.900 + encapsulation: + dot1q: 40 + second_dot1q: 60 + - l2protocol: + - cpsv: tunnel + l2transport: true + name: GigabitEthernet0/0/0/4 + +overridden: + before: + - l2protocol: + - cpsv: tunnel + l2transport: true + name: GigabitEthernet0/0/0/1 + propagate: true + - name: GigabitEthernet0/0/0/3.900 + encapsulation: + dot1q: 40 + second_dot1q: 60 + - l2protocol: + - cpsv: tunnel + l2transport: true + name: GigabitEthernet0/0/0/4 + commands: + - interface GigabitEthernet0/0/0/1 + - no l2transport + - interface GigabitEthernet0/0/0/3.900 + - encapsulation dot1q 20 second-dot1q 40 + after: + - name: GigabitEthernet0/0/0/3.900 + encapsulation: + dot1q: 20 + second_dot1q: 40 + - l2protocol: + - cpsv: tunnel + l2transport: true + name: GigabitEthernet0/0/0/4 +deleted: + before: + - l2protocol: + - cpsv: tunnel + l2transport: true + name: GigabitEthernet0/0/0/1 + propagate: true + - name: GigabitEthernet0/0/0/3.900 + encapsulation: + dot1q: 40 + second_dot1q: 60 + - l2protocol: + - cpsv: tunnel + l2transport: true + name: GigabitEthernet0/0/0/4 + commands: + - interface GigabitEthernet0/0/0/1 + - no l2transport + - interface GigabitEthernet0/0/0/3.900 + - no encapsulation dot1q + - interface GigabitEthernet0/0/0/4 + - no l2transport + after: + - name: GigabitEthernet0/0/0/3.900 + - name: GigabitEthernet0/0/0/4 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/meta/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/meta/main.yaml new file mode 100644 index 00000000..23d65c7e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/meta/main.yaml @@ -0,0 +1,2 @@ +--- +dependencies: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/_populate_config.yaml new file mode 100644 index 00000000..a8dff61c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/_populate_config.yaml @@ -0,0 +1,8 @@ +--- +- name: Populate configuration + vars: + lines: + "interface GigabitEthernet 0/0/0/0\nipv4 address 198.51.100.1 255.255.255.0\nipv6 address 2001:db8::/32\ninterface GigabitEthernet 0/0/0/1\nipv4 address\ + \ 192.0.2.1 255.255.255.0\nipv4 address 192.0.2.2 255.255.255.0 secondary\n" + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..3813ccce --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/_remove_config.yaml @@ -0,0 +1,6 @@ +--- +- name: Remove configuration + vars: + lines: "interface GigabitEthernet 0/0/0/0\nno ipv4 address\nno ipv6 address\ninterface GigabitEthernet 0/0/0/1\nno ipv4 address\nno ipv6 address\n" + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/deleted.yaml new file mode 100644 index 00000000..b8562c85 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/deleted.yaml @@ -0,0 +1,42 @@ +--- +- ansible.builtin.debug: + msg: Start Deleted integration state for iosxr_l3_interfaces ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete attributes of all configured interfaces + register: result + cisco.iosxr.iosxr_l3_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + + - name: GigabitEthernet0/0/0/1 + state: deleted + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Delete attributes of all configured interfaces (idempotent) + register: result + cisco.iosxr.iosxr_l3_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/empty_config.yaml new file mode 100644 index 00000000..de3925d7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_l3_interfaces empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_l3_interfaces: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_l3_interfaces: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_l3_interfaces: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_l3_interfaces: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_l3_interfaces: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/fixtures/parsed.cfg new file mode 100644 index 00000000..38b5adde --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/fixtures/parsed.cfg @@ -0,0 +1,31 @@ +interface Loopback888 + description test for ansible + shutdown +! +interface MgmtEth0/RP0/CPU0/0 + ipv4 address 10.8.38.70 255.255.255.0 +! +interface GigabitEthernet0/0/0/0 + description Configured and Merged by Ansible-Network + mtu 66 + ipv4 address 192.0.2.1 255.255.255.0 + ipv4 address 192.0.2.2 255.255.255.0 secondary + ipv6 address 2001:db8:0:3::/64 + duplex half +! +interface GigabitEthernet0/0/0/1 + description Configured and Merged by Ansible-Network + mtu 66 + speed 100 + duplex full + dot1q native vlan 10 + l2transport + l2protocol cdp forward + l2protocol pvst tunnel + propagate remote-status + ! +! +interface GigabitEthernet0/0/0/3 + ipv4 address 192.0.22.1 255.255.255.0 + ipv4 address 192.0.23.1 255.255.255.0 +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/gathered.yaml new file mode 100644 index 00000000..abd09c02 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/gathered.yaml @@ -0,0 +1,35 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_l3_interfaces gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Gather the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_l3_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + ipv4: + - address: 198.51.100.1/24 + + - name: GigabitEthernet0/0/0/1 + ipv6: + - address: 2001:db8:0:3::/64 + ipv4: + - address: 192.0.2.1/24 + + - address: 192.0.2.2/24 + secondary: true + state: merged + + - name: Gather layer 3 interfaces facts using gathered state + register: result + cisco.iosxr.iosxr_l3_interfaces: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] | symmetric_difference(result['gathered']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/merged.yaml new file mode 100644 index 00000000..6660b9af --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/merged.yaml @@ -0,0 +1,49 @@ +--- +- ansible.builtin.debug: + msg: START Merged iosxr_l3_interfaces state for integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge provided configuration with device configuration + register: result + cisco.iosxr.iosxr_l3_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + ipv4: + - address: 198.51.100.1/24 + + - name: GigabitEthernet0/0/0/1 + ipv6: + - address: 2001:db8:0:3::/64 + ipv4: + - address: 192.0.2.1/24 + + - address: 192.0.2.2/24 + secondary: true + state: merged + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Merge provided configuration with device configuration (idempotent) + register: result + cisco.iosxr.iosxr_l3_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/overridden.yaml new file mode 100644 index 00000000..ded36a39 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/overridden.yaml @@ -0,0 +1,44 @@ +--- +- ansible.builtin.debug: + msg: START Overridden iosxr_l3_interfaces state for integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Override device configuration of all interfaces with provided configuration + register: result + cisco.iosxr.iosxr_l3_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/1 + ipv4: + - address: 198.51.102.1/24 + ipv6: + - address: 2001:db8:1::/64 + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Override device configuration of all interfaces with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_l3_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/parsed.yaml new file mode 100644 index 00000000..cb558916 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_l3_interfaces parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided layer 3 interfaces configuration to agnostic model + register: result + cisco.iosxr.iosxr_l3_interfaces: + running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ parsed['after'] | symmetric_difference(result['parsed']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/rendered.yaml new file mode 100644 index 00000000..76498b9b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/rendered.yaml @@ -0,0 +1,26 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_l3_interfaces rendered integration tests on connection={{ ansible_connection }} + +- name: Render platform specific commands from task input using rendered state + register: result + cisco.iosxr.iosxr_l3_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + ipv4: + - address: 198.51.100.1/24 + + - name: GigabitEthernet0/0/0/1 + ipv6: + - address: 2001:db8:0:3::/64 + ipv4: + - address: 192.0.2.1/24 + + - address: 192.0.2.2/24 + secondary: true + state: rendered + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - "{{ rendered['commands'] | symmetric_difference(result['rendered']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/replaced.yaml new file mode 100644 index 00000000..10a77a3c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/replaced.yaml @@ -0,0 +1,45 @@ +--- +- ansible.builtin.debug: + msg: START Replaced iosxr_l3_interfaces state for integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replaces device configuration of listed interfaces with provided configuration + register: result + cisco.iosxr.iosxr_l3_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + ipv4: + - address: 203.0.113.27/24 + + - address: 203.0.114.1/24 + secondary: true + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Replaces device configuration of listed interfaces with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_l3_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/rtt.yaml new file mode 100644 index 00000000..c90984a8 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/tests/cli/rtt.yaml @@ -0,0 +1,39 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_l3_interfaces round trip integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Round trip test by applying the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_l3_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + ipv4: + - address: 198.51.100.1/24 + + - name: GigabitEthernet0/0/0/1 + ipv6: + - address: 2001:db8:0:3::/64 + ipv4: + - address: 192.0.2.1/24 + + - secondary: true + address: 192.0.2.2/24 + state: merged + + - name: Gather interfaces facts + register: l3facts_config + cisco.iosxr.iosxr_facts: + gather_subset: + - default + gather_network_resources: + - l3_interfaces + + - name: Apply configuration from l3_interfaces facts generated (idempotent) + cisco.iosxr.iosxr_l3_interfaces: + config: "{{ l3facts_config['ansible_facts']['ansible_network_resources']['l3_interfaces'] }}" + state: merged + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/vars/main.yaml new file mode 100644 index 00000000..c144276d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_l3_interfaces/vars/main.yaml @@ -0,0 +1,133 @@ +--- +merged: + before: + - name: Loopback888 + - name: Loopback999 + commands: + - interface GigabitEthernet0/0/0/0 + - ipv4 address 198.51.100.1 255.255.255.0 + - interface GigabitEthernet0/0/0/1 + - ipv4 address 192.0.2.2 255.255.255.0 secondary + - ipv4 address 192.0.2.1 255.255.255.0 + - ipv6 address 2001:db8:0:3::/64 + after: + - name: Loopback888 + - name: Loopback999 + - ipv4: + - address: 198.51.100.1 255.255.255.0 + name: GigabitEthernet0/0/0/0 + - ipv4: + - address: 192.0.2.1 255.255.255.0 + - address: 192.0.2.2 255.255.255.0 + secondary: true + ipv6: + - address: 2001:db8:0:3::/64 + name: GigabitEthernet0/0/0/1 +replaced: + before: + - name: Loopback888 + - name: Loopback999 + - ipv4: + - address: 198.51.100.1 255.255.255.0 + ipv6: + - address: 2001:db8::/32 + name: GigabitEthernet0/0/0/0 + - ipv4: + - address: 192.0.2.1 255.255.255.0 + - address: 192.0.2.2 255.255.255.0 + secondary: true + name: GigabitEthernet0/0/0/1 + commands: + - interface GigabitEthernet0/0/0/0 + - no ipv6 address + - ipv4 address 203.0.113.27 255.255.255.0 + - ipv4 address 203.0.114.1 255.255.255.0 secondary + after: + - name: Loopback888 + - name: Loopback999 + - ipv4: + - address: 203.0.113.27 255.255.255.0 + - address: 203.0.114.1 255.255.255.0 + secondary: true + name: GigabitEthernet0/0/0/0 + - ipv4: + - address: 192.0.2.1 255.255.255.0 + - address: 192.0.2.2 255.255.255.0 + secondary: true + name: GigabitEthernet0/0/0/1 +overridden: + before: + - name: Loopback888 + - name: Loopback999 + - ipv4: + - address: 198.51.100.1 255.255.255.0 + ipv6: + - address: 2001:db8::/32 + name: GigabitEthernet0/0/0/0 + - ipv4: + - address: 192.0.2.1 255.255.255.0 + - address: 192.0.2.2 255.255.255.0 + secondary: true + name: GigabitEthernet0/0/0/1 + commands: + - interface GigabitEthernet0/0/0/0 + - no ipv4 address + - no ipv6 address + - interface GigabitEthernet0/0/0/1 + - no ipv4 address + - ipv4 address 198.51.102.1 255.255.255.0 + - ipv6 address 2001:db8:1::/64 + after: + - name: Loopback888 + - name: Loopback999 + - ipv4: + - address: 198.51.102.1 255.255.255.0 + ipv6: + - address: 2001:db8:1::/64 + name: GigabitEthernet0/0/0/1 +rendered: + commands: + - interface GigabitEthernet0/0/0/0 + - ipv4 address 198.51.100.1 255.255.255.0 + - interface GigabitEthernet0/0/0/1 + - ipv4 address 192.0.2.2 255.255.255.0 secondary + - ipv4 address 192.0.2.1 255.255.255.0 + - ipv6 address 2001:db8:0:3::/64 +parsed: + after: + - name: Loopback888 + - ipv6: + - address: 2001:db8:0:3::/64 + ipv4: + - address: 192.0.2.1 255.255.255.0 + - address: 192.0.2.2 255.255.255.0 + secondary: true + name: GigabitEthernet0/0/0/0 + - name: GigabitEthernet0/0/0/1 + - ipv4: + - address: 192.0.22.1 255.255.255.0 + - address: 192.0.23.1 255.255.255.0 + name: GigabitEthernet0/0/0/3 +deleted: + before: + - name: Loopback888 + - name: Loopback999 + - ipv4: + - address: 198.51.100.1 255.255.255.0 + ipv6: + - address: 2001:db8::/32 + name: GigabitEthernet0/0/0/0 + - ipv4: + - address: 192.0.2.1 255.255.255.0 + - address: 192.0.2.2 255.255.255.0 + secondary: true + name: GigabitEthernet0/0/0/1 + commands: + - interface GigabitEthernet0/0/0/0 + - no ipv4 address + - no ipv6 address + - interface GigabitEthernet0/0/0/1 + - no ipv4 address + after: + - name: Loopback888 + - name: Loopback999 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/_populate.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/_populate.yaml new file mode 100644 index 00000000..12f38f4c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/_populate.yaml @@ -0,0 +1,6 @@ +--- +- name: Setup + vars: + lines: "lacp system priority 12\nlacp system mac 00c1.4c00.bd16\n" + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..24c2846f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/_remove_config.yaml @@ -0,0 +1,6 @@ +--- +- name: Remove configuration + vars: + lines: "no lacp system priority\nno lacp system mac\n" + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/deleted.yaml new file mode 100644 index 00000000..c48f5018 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/deleted.yaml @@ -0,0 +1,43 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_lacp deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Delete lacp attributes + register: result + cisco.iosxr.iosxr_lacp: &id001 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ populate == result['before'] }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] == result['after'] }}" + + - name: Delete attributes of given interfaces (idempotent) + register: result + cisco.iosxr.iosxr_lacp: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] == result['before'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/empty_config.yaml new file mode 100644 index 00000000..ce135f73 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/empty_config.yaml @@ -0,0 +1,47 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lacp: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lacp: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lacp: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lacp: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/fixtures/parsed.cfg new file mode 100644 index 00000000..5b16c0e8 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/fixtures/parsed.cfg @@ -0,0 +1,2 @@ +lacp system mac 00c1.4c00.bd15 +lacp system priority 11 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/gathered.yaml new file mode 100644 index 00000000..2cfb94cf --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/gathered.yaml @@ -0,0 +1,27 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Gather the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_lacp: + config: + system: + priority: 11 + mac: + address: 00c1.4c00.bd15 + state: merged + + - name: Gather lacp facts using gathered state + register: result + cisco.iosxr.iosxr_lacp: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] == result['gathered'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/merged.yaml new file mode 100644 index 00000000..1632c6a6 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/merged.yaml @@ -0,0 +1,45 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_lacp: &id001 + config: + system: + priority: 11 + mac: + address: 00c1.4c00.bd15 + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['before'] == result['before'] }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['after'] }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_lacp: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['before']}}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/parsed.yaml new file mode 100644 index 00000000..b3b6fd59 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided lacp configuration to agnostic model + register: result + cisco.iosxr.iosxr_lacp: + running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ parsed['after'] == result['parsed'] }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/rendered.yaml new file mode 100644 index 00000000..01e90962 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/rendered.yaml @@ -0,0 +1,18 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp rendered integration tests on connection={{ ansible_connection }} + +- name: Render platform specific commands from task input using rendered state + register: result + cisco.iosxr.iosxr_lacp: + config: + system: + priority: 11 + mac: + address: 00c1.4c00.bd15 + state: rendered + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - "{{ rendered['commands'] | symmetric_difference(result['rendered']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/replaced.yaml new file mode 100644 index 00000000..b03d542f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/replaced.yaml @@ -0,0 +1,46 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Replace lacp configuration with provided configurations + register: result + cisco.iosxr.iosxr_lacp: &id001 + config: + system: + priority: 11 + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ populate == result['before'] }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] == result['after'] }}" + + - name: Replace device configurations of listed interfaces with provided configurarions (idempotent) + register: result + cisco.iosxr.iosxr_lacp: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] == result['before'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/rtt.yaml new file mode 100644 index 00000000..24e9ce68 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/tests/cli/rtt.yaml @@ -0,0 +1,50 @@ +--- +- ansible.builtin.debug: + msg: START isoxr_lacp round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Apply the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_lacp: + config: + system: + priority: 15 + mac: + address: 00c1.4c00.bd16 + state: merged + + - name: Gather interfaces facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - lacp + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_lacp: + config: + system: + priority: 10 + mac: + address: 00c1.4c00.bd10 + state: merged + + - name: Assert that changes were applied + ansible.builtin.assert: + that: "{{ round_trip['after'] == result['after'] }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_lacp: + config: "{{ ansible_facts['network_resources']['lacp'] }}" + state: replaced + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: "{{ base_config['after'] == revert['after'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/vars/main.yaml new file mode 100644 index 00000000..dc7a5246 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp/vars/main.yaml @@ -0,0 +1,44 @@ +--- +merged: + before: {} + commands: + - lacp system priority 11 + - lacp system mac 00c1.4c00.bd15 + after: + system: + priority: 11 + mac: + address: 00c1.4c00.bd15 +populate: + system: + priority: 12 + mac: + address: 00c1.4c00.bd16 +replaced: + commands: + - no lacp system mac + - lacp system priority 11 + after: + system: + priority: 11 +rendered: + commands: + - lacp system priority 11 + - lacp system mac 00c1.4c00.bd15 +parsed: + after: + system: + priority: 11 + mac: + address: 00c1.4c00.bd15 +deleted: + commands: + - no lacp system priority + - no lacp system mac + after: {} +round_trip: + after: + system: + priority: 10 + mac: + address: 00c1.4c00.bd10 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/_populate.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/_populate.yaml new file mode 100644 index 00000000..298d9ad1 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/_populate.yaml @@ -0,0 +1,26 @@ +--- +- name: Setup bundle-ether10 + cisco.iosxr.iosxr_config: + lines: + - lacp churn logging actor + - lacp switchover suppress-flaps 500 + - lacp collector-max-delay 100 + parents: interface Bundle-Ether10 + +- name: Setup bundle-ether11 + cisco.iosxr.iosxr_config: + lines: + - lacp system mac 00c2.4c00.bd15 + parents: interface Bundle-Ether11 + +- name: Setup gige0 + cisco.iosxr.iosxr_config: + lines: + - lacp period 100 + parents: interface GigabitEthernet0/0/0/0 + +- name: Setup gige1 + cisco.iosxr.iosxr_config: + lines: + - lacp period 200 + parents: interface GigabitEthernet0/0/0/1 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..72892ae2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/_remove_config.yaml @@ -0,0 +1,27 @@ +--- +- name: Remove bundles + vars: + lines: "no interface Bundle-Ether10\nno interface Bundle-Ether11\nno interface Bundle-Ether12\n" + ansible.netcommon.cli_config: + config: "{{ lines }}" + +- name: Remove lacp interface configuration + loop: + - 0/0/0/0 + - 0/0/0/1 + cisco.iosxr.iosxr_config: + lines: + - no lacp period + - shutdown + parents: interface GigabitEthernet{{ item }} + +- name: Remove unwanted interfaces from configuration + loop: + - 0/0/0/2 + - 0/0/0/3 + - 0/0/0/4 + - 0/0/0/5 + ignore_errors: true + cisco.iosxr.iosxr_config: + lines: + - no interface GigabitEthernet{{ item }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/deleted.yaml new file mode 100644 index 00000000..916884d4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/deleted.yaml @@ -0,0 +1,44 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_lacp_interfaces deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Delete lacp attributes of all interfaces + register: result + cisco.iosxr.iosxr_lacp_interfaces: &id001 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ populate | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Delete lacp attributes of all interfaces (idempotent) + register: result + cisco.iosxr.iosxr_lacp_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + - result.commands|length == 0 + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/empty_config.yaml new file mode 100644 index 00000000..5e5794d9 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp_interfaces empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lacp_interfaces: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lacp_interfaces: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lacp_interfaces: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lacp_interfaces: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lacp_interfaces: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/fixtures/parsed.cfg new file mode 100644 index 00000000..8e061b47 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/fixtures/parsed.cfg @@ -0,0 +1,14 @@ +interface Bundle-Ether10 + lacp churn logging actor + lacp switchover suppress-flaps 500 + lacp collector-max-delay 100 +! +interface Bundle-Ether11 + lacp system mac 00c2.4c00.bd15 +! +interface MgmtEth0/RP0/CPU0/0 + ipv4 address 192.0.2.11 255.255.255.0 +! +interface GigabitEthernet0/0/0/1 + lacp period 200 +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/gathered.yaml new file mode 100644 index 00000000..527c3c0d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/gathered.yaml @@ -0,0 +1,34 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp_interfaces gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_lacp_interfaces: + config: + - name: Bundle-Ether10 + churn_logging: actor + collector_max_delay: 100 + switchover_suppress_flaps: 500 + + - name: Bundle-Ether11 + system: + mac: 00c2.4c00.bd15 + + - name: GigabitEthernet0/0/0/1 + period: 100 + state: merged + + - name: Gather interfaces facts using gathered state + register: result + cisco.iosxr.iosxr_lacp_interfaces: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] | symmetric_difference(result['gathered']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/merged.yaml new file mode 100644 index 00000000..4ca41988 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/merged.yaml @@ -0,0 +1,53 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp_interfaces merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_lacp_interfaces: &id001 + config: + - name: Bundle-Ether10 + churn_logging: actor + collector_max_delay: 100 + switchover_suppress_flaps: 500 + + - name: Bundle-Ether11 + system: + mac: 00c2.4c00.bd15 + + - name: GigabitEthernet0/0/0/1 + period: 100 + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['before'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_lacp_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/overridden.yaml new file mode 100644 index 00000000..4dbe5b30 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/overridden.yaml @@ -0,0 +1,52 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp_interfaces overridden integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Overridde all interface lacp configuration with provided configuration + register: result + cisco.iosxr.iosxr_lacp_interfaces: &id001 + config: + - name: Bundle-Ether12 + churn_logging: both + collector_max_delay: 100 + switchover_suppress_flaps: 500 + + - name: GigabitEthernet0/0/0/1 + period: 300 + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ populate | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Overridde all interface lacp configuration with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_lacp_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/parsed.yaml new file mode 100644 index 00000000..2f040447 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp_interfaces parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided lacp configuration to agnostic model + register: result + cisco.iosxr.iosxr_lacp_interfaces: + running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ parsed['after'] == result['parsed'] }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/rendered.yaml new file mode 100644 index 00000000..11517fc9 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/rendered.yaml @@ -0,0 +1,25 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp_interfaces rendered integration tests on connection={{ ansible_connection }} + +- name: Render platform specific commands from task input using rendered state + register: result + cisco.iosxr.iosxr_lacp_interfaces: + config: + - name: Bundle-Ether10 + churn_logging: actor + collector_max_delay: 100 + switchover_suppress_flaps: 500 + + - name: Bundle-Ether11 + system: + mac: 00c2.4c00.bd15 + + - name: GigabitEthernet0/0/0/1 + period: 200 + state: rendered + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - "{{ rendered['commands'] | symmetric_difference(result['rendered']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/replaced.yaml new file mode 100644 index 00000000..e1c68093 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/replaced.yaml @@ -0,0 +1,50 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lacp_interfaces replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Replace device configurations of listed interfaces with provided configurations + register: result + cisco.iosxr.iosxr_lacp_interfaces: &id001 + config: + - name: Bundle-Ether10 + churn_logging: partner + + - name: GigabitEthernet0/0/0/1 + period: 300 + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ populate | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Replace device configurations of listed interfaces with provided configurarions (idempotent) + register: result + cisco.iosxr.iosxr_lacp_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/rtt.yaml new file mode 100644 index 00000000..fe7a1726 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/tests/cli/rtt.yaml @@ -0,0 +1,59 @@ +--- +- ansible.builtin.debug: + msg: START isoxr_lacp_interfaces round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Apply the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_lacp_interfaces: + config: + - name: Bundle-Ether10 + churn_logging: actor + collector_max_delay: 200 + + - name: Bundle-Ether11 + period: 100 + + - name: GigabitEthernet0/0/0/0 + period: 200 + state: merged + + - name: Gather interfaces facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - lacp_interfaces + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_lacp_interfaces: + config: + - name: Bundle-Ether10 + churn_logging: partner + + - name: Bundle-Ether11 + period: 200 + + - name: GigabitEthernet0/0/0/0 + period: 300 + state: overridden + + - name: Assert that changes were applied + ansible.builtin.assert: + that: "{{ round_trip['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_lacp_interfaces: + config: "{{ ansible_facts['network_resources']['lacp_interfaces'] }}" + state: overridden + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: "{{ base_config['after'] | symmetric_difference(revert['after']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/vars/main.yaml new file mode 100644 index 00000000..1f1f5cf9 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lacp_interfaces/vars/main.yaml @@ -0,0 +1,130 @@ +--- +merged: + before: + - name: GigabitEthernet0/0/0/0 + - name: GigabitEthernet0/0/0/1 + commands: + - interface Bundle-Ether10 + - lacp churn logging actor + - lacp switchover suppress-flaps 500 + - lacp collector-max-delay 100 + - interface Bundle-Ether11 + - lacp system mac 00c2.4c00.bd15 + - interface GigabitEthernet0/0/0/1 + - lacp period 100 + after: + - name: Bundle-Ether10 + churn_logging: actor + switchover_suppress_flaps: 500 + collector_max_delay: 100 + - name: Bundle-Ether11 + system: + mac: 00c2.4c00.bd15 + - name: GigabitEthernet0/0/0/0 + - name: GigabitEthernet0/0/0/1 + period: 100 +populate: + - name: Bundle-Ether10 + churn_logging: actor + switchover_suppress_flaps: 500 + collector_max_delay: 100 + - name: Bundle-Ether11 + system: + mac: 00c2.4c00.bd15 + - name: GigabitEthernet0/0/0/0 + period: 100 + - name: GigabitEthernet0/0/0/1 + period: 200 +replaced: + commands: + - interface Bundle-Ether10 + - no lacp switchover suppress-flaps 500 + - no lacp collector-max-delay 100 + - lacp churn logging partner + - interface GigabitEthernet0/0/0/1 + - lacp period 300 + after: + - name: Bundle-Ether10 + churn_logging: partner + - name: Bundle-Ether11 + system: + mac: 00c2.4c00.bd15 + - name: GigabitEthernet0/0/0/0 + period: 100 + - name: GigabitEthernet0/0/0/1 + period: 300 +overridden: + commands: + - interface Bundle-Ether10 + - no lacp switchover suppress-flaps 500 + - no lacp collector-max-delay 100 + - no lacp churn logging actor + - interface Bundle-Ether11 + - no lacp system mac 00c2.4c00.bd15 + - interface GigabitEthernet0/0/0/0 + - no lacp period 100 + - interface Bundle-Ether12 + - lacp churn logging both + - lacp collector-max-delay 100 + - lacp switchover suppress-flaps 500 + - interface GigabitEthernet0/0/0/1 + - lacp period 300 + after: + - name: Bundle-Ether10 + - name: Bundle-Ether11 + - name: Bundle-Ether12 + churn_logging: both + collector_max_delay: 100 + switchover_suppress_flaps: 500 + - name: GigabitEthernet0/0/0/0 + - name: GigabitEthernet0/0/0/1 + period: 300 +deleted: + commands: + - interface Bundle-Ether10 + - no lacp switchover suppress-flaps 500 + - no lacp collector-max-delay 100 + - no lacp churn logging actor + - interface Bundle-Ether11 + - no lacp system mac 00c2.4c00.bd15 + - interface GigabitEthernet0/0/0/0 + - no lacp period 100 + - interface GigabitEthernet0/0/0/1 + - no lacp period 200 + after: + - name: Bundle-Ether10 + - name: Bundle-Ether11 + - name: GigabitEthernet0/0/0/0 + - name: GigabitEthernet0/0/0/1 +round_trip: + after: + - name: Bundle-Ether10 + churn_logging: partner + - name: Bundle-Ether11 + period: 200 + - name: GigabitEthernet0/0/0/0 + period: 300 + - name: GigabitEthernet0/0/0/1 +parsed: + after: + - name: Bundle-Ether10 + churn_logging: actor + collector_max_delay: 100 + switchover_suppress_flaps: 500 + + - name: Bundle-Ether11 + system: + mac: 00c2.4c00.bd15 + + - name: GigabitEthernet0/0/0/1 + period: 200 +rendered: + commands: + - "interface Bundle-Ether10" + - "lacp churn logging actor" + - "lacp switchover suppress-flaps 500" + - "lacp collector-max-delay 100" + - "interface Bundle-Ether11" + - "lacp system mac 00c2.4c00.bd15" + - "interface GigabitEthernet0/0/0/1" + - "lacp period 200" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/_populate_config.yaml new file mode 100644 index 00000000..489bc2e5 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/_populate_config.yaml @@ -0,0 +1,25 @@ +--- +- name: Setup + cisco.iosxr.iosxr_lag_interfaces: + config: + - name: Bundle-Ether10 + mode: active + members: + - member: GigabitEthernet0/0/0/0 + mode: inherit + + - member: GigabitEthernet0/0/0/1 + mode: passive + links: + max_active: 10 + min_active: 2 + + - name: Bundle-Ether11 + mode: active + members: + - member: GigabitEthernet0/0/0/8 + mode: passive + + - member: GigabitEthernet0/0/0/9 + mode: passive + state: merged diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..f862a29c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/_remove_config.yaml @@ -0,0 +1,31 @@ +--- +- name: Remove bundles + vars: + lines: "no interface Bundle-Ether10\nno interface Bundle-Ether11\nno interface Bundle-Ether12\n" + ignore_errors: true + ansible.netcommon.cli_config: + config: "{{ lines }}" + +- name: Remove lag interface configuration + loop: + - 0/0/0/0 + - 0/0/0/1 + - 0/0/0/2 + - 0/0/0/8 + - 0/0/0/9 + ignore_errors: true + cisco.iosxr.iosxr_config: + lines: + - no bundle id + - shutdown + parents: interface GigabitEthernet{{ item }} + +- name: Remove unwanted interfaces from configuration + loop: + - 0/0/0/2 + - 0/0/0/8 + - 0/0/0/9 + ignore_errors: true + cisco.iosxr.iosxr_config: + lines: + - no interface GigabitEthernet{{ item }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/deleted.yaml new file mode 100644 index 00000000..549c6ccf --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/deleted.yaml @@ -0,0 +1,44 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_lag_interfaces deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete lag interfaces configuration + register: result + cisco.iosxr.iosxr_lag_interfaces: &id001 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Delete lacp attributes of all interfaces (idempotent) + register: result + cisco.iosxr.iosxr_lag_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + - result.commands|length == 0 + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/empty_config.yaml new file mode 100644 index 00000000..0d9505d7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lag_interfaces empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lag_interfaces: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lag_interfaces: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lag_interfaces: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lag_interfaces: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lag_interfaces: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/fixtures/parsed.cfg new file mode 100644 index 00000000..74fe481d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/fixtures/parsed.cfg @@ -0,0 +1,30 @@ +interface Bundle-Ether10 + lacp mode active + bundle maximum-active links 5 + bundle minimum-active links 2 +! +interface Bundle-Ether12 +! +interface Loopback888 + description test for ansible + shutdown +! +interface MgmtEth0/RP0/CPU0/0 + ipv4 address 192.0.2.11 255.255.255.0 +! +interface GigabitEthernet0/0/0/1 + description 'GigabitEthernet - 1" + bundle id 10 mode inherit +! +interface GigabitEthernet0/0/0/2 + description "GigabitEthernet - 2" + bundle id 12 mode passive +! +interface GigabitEthernet0/0/0/3 + description "GigabitEthernet - 3" + bundle id 10 mode inherit +! +interface GigabitEthernet0/0/0/4 + description "GigabitEthernet - 4" + bundle id 12 mode passive +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/gathered.yaml new file mode 100644 index 00000000..353162c0 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/gathered.yaml @@ -0,0 +1,43 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lag_interfaces gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Gather the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_lag_interfaces: + config: + - name: Bundle-Ether10 + mode: active + members: + - member: GigabitEthernet0/0/0/0 + mode: inherit + + - member: GigabitEthernet0/0/0/1 + mode: passive + links: + max_active: 10 + min_active: 2 + + - name: Bundle-Ether11 + mode: active + members: + - member: GigabitEthernet0/0/0/8 + mode: passive + + - member: GigabitEthernet0/0/0/9 + mode: passive + state: merged + + - name: Gather lacp facts using gathered state + register: result + cisco.iosxr.iosxr_lag_interfaces: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] == result['gathered'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/merged.yaml new file mode 100644 index 00000000..5191b38a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/merged.yaml @@ -0,0 +1,62 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lag_interfaces merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_lag_interfaces: &id001 + config: + - name: Bundle-Ether10 + mode: active + members: + - member: GigabitEthernet0/0/0/0 + mode: inherit + + - member: GigabitEthernet0/0/0/1 + mode: passive + links: + max_active: 10 + min_active: 2 + + - name: Bundle-Ether11 + mode: active + members: + - member: GigabitEthernet0/0/0/8 + mode: passive + + - member: GigabitEthernet0/0/0/9 + mode: passive + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['before'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_lag_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/overridden.yaml new file mode 100644 index 00000000..77c5ea02 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/overridden.yaml @@ -0,0 +1,56 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lag_interfaces overridden integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Overridde all lag interface configuration with provided configuration + register: result + cisco.iosxr.iosxr_lag_interfaces: &id001 + config: + - name: Bundle-Ether11 + mode: active + members: + - member: GigabitEthernet0/0/0/0 + mode: active + + - member: GigabitEthernet0/0/0/1 + mode: active + links: + max_active: 10 + min_active: 5 + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Overridde all interface lag interface configuration with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_lag_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/parsed.yaml new file mode 100644 index 00000000..f410f64a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lag_interfaces parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided lag interfaces configuration to agnostic model + register: result + cisco.iosxr.iosxr_lag_interfaces: + running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ parsed['after'] == result['parsed'] }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/rendered.yaml new file mode 100644 index 00000000..185014b4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/rendered.yaml @@ -0,0 +1,31 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lag_interfaces rendered integration tests on connection={{ ansible_connection }} + +- name: Render platform specific commands from task input using rendered state + register: result + cisco.iosxr.iosxr_lag_interfaces: + config: + - name: Bundle-Ether10 + members: + - member: GigabitEthernet0/0/0/1 + mode: inherit + - member: GigabitEthernet0/0/0/3 + mode: inherit + mode: active + links: + max_active: 5 + min_active: 2 + + - name: Bundle-Ether12 + members: + - member: GigabitEthernet0/0/0/2 + mode: passive + - member: GigabitEthernet0/0/0/4 + mode: passive + state: rendered + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - rendered['commands'].sort() == result['rendered'].sort() diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/replaced.yaml new file mode 100644 index 00000000..90d78cc5 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/replaced.yaml @@ -0,0 +1,53 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lag_interfaces replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replace device configurations of listed interfaces with provided configurations + register: result + cisco.iosxr.iosxr_lag_interfaces: &id001 + config: + - name: Bundle-Ether10 + mode: passive + members: + - member: GigabitEthernet0/0/0/0 + mode: passive + + - name: Bundle-Ether12 + mode: active + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Replace device configurations of listed interfaces with provided configurarions (idempotent) + register: result + cisco.iosxr.iosxr_lag_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/rtt.yaml new file mode 100644 index 00000000..e80c283d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/tests/cli/rtt.yaml @@ -0,0 +1,63 @@ +--- +- ansible.builtin.debug: + msg: START isoxr_lag_interfaces round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Apply the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_lag_interfaces: + config: + - name: Bundle-Ether10 + mode: active + members: + - member: GigabitEthernet0/0/0/1 + mode: passive + links: + max_active: 10 + min_active: 2 + + - name: Bundle-Ether11 + mode: passive + state: merged + + - name: Gather interfaces facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - lag_interfaces + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_lag_interfaces: + config: + - name: Bundle-Ether10 + members: + - member: GigabitEthernet0/0/0/9 + mode: active + + - member: GigabitEthernet0/0/0/8 + mode: passive + + - name: Bundle-Ether11 + mode: active + state: overridden + + - name: Assert that changes were applied + ansible.builtin.assert: + that: "{{ round_trip['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_lag_interfaces: + config: "{{ ansible_facts['network_resources']['lag_interfaces'] }}" + state: overridden + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: "{{ base_config['after'] | symmetric_difference(revert['after']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/vars/main.yaml new file mode 100644 index 00000000..b2b14a0c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lag_interfaces/vars/main.yaml @@ -0,0 +1,168 @@ +--- +merged: + before: [] + commands: + - interface Bundle-Ether10 + - bundle minimum-active links 2 + - bundle maximum-active links 10 + - lacp mode active + - interface GigabitEthernet0/0/0/1 + - bundle id 10 mode passive + - interface GigabitEthernet0/0/0/0 + - bundle id 10 mode inherit + - interface Bundle-Ether11 + - lacp mode active + - interface GigabitEthernet0/0/0/8 + - bundle id 11 mode passive + - interface GigabitEthernet0/0/0/9 + - bundle id 11 mode passive + after: + - name: Bundle-Ether10 + links: + max_active: 10 + min_active: 2 + members: + - member: GigabitEthernet0/0/0/0 + mode: inherit + - member: GigabitEthernet0/0/0/1 + mode: passive + mode: active + - name: Bundle-Ether11 + mode: active + members: + - member: GigabitEthernet0/0/0/8 + mode: passive + - member: GigabitEthernet0/0/0/9 + mode: passive +replaced: + commands: + - interface Bundle-Ether10 + - no bundle maximum-active links 10 + - no bundle minimum-active links 2 + - lacp mode passive + - interface GigabitEthernet0/0/0/1 + - no bundle id + - interface GigabitEthernet0/0/0/0 + - bundle id 10 mode passive + - interface Bundle-Ether12 + - lacp mode active + after: + - members: + - member: GigabitEthernet0/0/0/0 + mode: passive + mode: passive + name: Bundle-Ether10 + - members: + - member: GigabitEthernet0/0/0/8 + mode: passive + - member: GigabitEthernet0/0/0/9 + mode: passive + mode: active + name: Bundle-Ether11 + - mode: active + name: Bundle-Ether12 +overridden: + commands: + - interface Bundle-Ether10 + - no bundle maximum-active links 10 + - no bundle minimum-active links 2 + - no lacp mode active + - interface GigabitEthernet0/0/0/0 + - no bundle id + - interface GigabitEthernet0/0/0/1 + - no bundle id + - interface Bundle-Ether11 + - bundle minimum-active links 5 + - bundle maximum-active links 10 + - interface GigabitEthernet0/0/0/8 + - no bundle id + - interface GigabitEthernet0/0/0/9 + - no bundle id + - interface GigabitEthernet0/0/0/0 + - bundle id 11 mode active + - interface GigabitEthernet0/0/0/1 + - bundle id 11 mode active + after: + - name: Bundle-Ether10 + - links: + max_active: 10 + min_active: 5 + members: + - member: GigabitEthernet0/0/0/0 + mode: active + - member: GigabitEthernet0/0/0/1 + mode: active + mode: active + name: Bundle-Ether11 +deleted: + commands: + - interface Bundle-Ether10 + - no bundle maximum-active links 10 + - no bundle minimum-active links 2 + - no lacp mode active + - interface GigabitEthernet0/0/0/0 + - no bundle id + - interface GigabitEthernet0/0/0/1 + - no bundle id + - interface Bundle-Ether11 + - no lacp mode active + - interface GigabitEthernet0/0/0/8 + - no bundle id + - interface GigabitEthernet0/0/0/9 + - no bundle id + after: + - name: Bundle-Ether10 + - name: Bundle-Ether11 +round_trip: + after: + - members: + - member: GigabitEthernet0/0/0/8 + mode: passive + - member: GigabitEthernet0/0/0/9 + mode: active + name: Bundle-Ether10 + - mode: active + name: Bundle-Ether11 +rendered: + commands: + - "interface Bundle-Ether10" + - "lacp mode active" + - "bundle maximum-active links 5" + - "bundle minimum-active links 2" + - "interface Bundle-Ether12" + - "interface Loopback888" + - "description test for ansible" + - "shutdown" + - "interface MgmtEth0/RP0/CPU0/0" + - "ipv4 address 192.0.2.11 255.255.255.0" + - "interface GigabitEthernet0/0/0/1" + - "description 'GigabitEthernet - 1'" + - "bundle id 10 mode inherit" + - "interface GigabitEthernet0/0/0/2" + - "description 'GigabitEthernet - 2'" + - "bundle id 12 mode passive" + - "interface GigabitEthernet0/0/0/3" + - "description 'GigabitEthernet - 3'" + - "bundle id 10 mode inherit" + - "interface GigabitEthernet0/0/0/4" + - "description 'GigabitEthernet - 4'" + - "bundle id 12 mode passive" +parsed: + after: + - name: Bundle-Ether10 + members: + - member: GigabitEthernet0/0/0/1 + mode: inherit + - member: GigabitEthernet0/0/0/3 + mode: inherit + mode: active + links: + max_active: 5 + min_active: 2 + + - name: Bundle-Ether12 + members: + - member: GigabitEthernet0/0/0/2 + mode: passive + - member: GigabitEthernet0/0/0/4 + mode: passive diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/_populate.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/_populate.yaml new file mode 100644 index 00000000..e51c60d9 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/_populate.yaml @@ -0,0 +1,9 @@ +--- +- name: Setup + vars: + lines: + "lldp reinit 2\nlldp holdtime 100\nlldp timer 3000\nlldp subinterfaces\ + \ enable\nlldp tlv-select system-description disable\nlldp tlv-select management-address\ + \ disable\n" + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..bf35acd4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/_remove_config.yaml @@ -0,0 +1,6 @@ +--- +- name: Remove configuration + vars: + lines: "no lldp\n" + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/deleted.yaml new file mode 100644 index 00000000..291caf30 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/deleted.yaml @@ -0,0 +1,43 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_lldp_global deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Delete global lldp attributes + register: result + cisco.iosxr.iosxr_lldp_global: &id001 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['before'] }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] == result['after'] }}" + + - name: Delete attributes of given interfaces (idempotent) + register: result + cisco.iosxr.iosxr_lldp_global: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] == result['before'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/empty_config.yaml new file mode 100644 index 00000000..e1519c31 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/empty_config.yaml @@ -0,0 +1,47 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_global empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lldp_global: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lldp_global: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lldp_global: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lldp_global: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/fixtures/parsed.cfg new file mode 100644 index 00000000..4bd23847 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/fixtures/parsed.cfg @@ -0,0 +1,10 @@ +lldp + timer 3000 + reinit 2 + subinterfaces enable + holdtime 100 + tlv-select + management-address disable + system-description disable + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/gathered.yaml new file mode 100644 index 00000000..4a2bf6ac --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/gathered.yaml @@ -0,0 +1,31 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_global gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_lldp_global: + config: + holdtime: 100 + reinit: 2 + timer: 3000 + subinterfaces: true + tlv_select: + management_address: false + system_description: false + state: merged + + - name: Gather interfaces facts using gathered state + register: result + cisco.iosxr.iosxr_lldp_global: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: merged['after'] == result['gathered'] + + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/merged.yaml new file mode 100644 index 00000000..2dab5aea --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/merged.yaml @@ -0,0 +1,48 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_global merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_lldp_global: &id001 + config: + holdtime: 100 + reinit: 2 + timer: 3000 + subinterfaces: true + tlv_select: + management_address: false + system_description: false + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['before'] == result['before'] }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['after'] }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_lldp_global: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['before']}}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/parsed.yaml new file mode 100644 index 00000000..e163743e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_global parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided lacp configuration to agnostic model + register: result + cisco.iosxr.iosxr_lldp_global: + running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ parsed['after'] == result['parsed'] }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/rendered.yaml new file mode 100644 index 00000000..853637d7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/rendered.yaml @@ -0,0 +1,21 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_global rendered integration tests on connection={{ ansible_connection }} + +- name: Render platform specific commands from task input using rendered stateion + register: result + cisco.iosxr.iosxr_lldp_global: + config: + holdtime: 100 + reinit: 2 + timer: 3000 + subinterfaces: true + tlv_select: + management_address: false + system_description: false + state: rendered + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - "{{ rendered['commands'] | symmetric_difference(result['rendered']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/replaced.yaml new file mode 100644 index 00000000..13a8c5fc --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/replaced.yaml @@ -0,0 +1,49 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_global replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Replace global lldp configuration with provided configurations + register: result + cisco.iosxr.iosxr_lldp_global: &id001 + config: + holdtime: 100 + tlv_select: + port_description: false + system_description: false + management_address: false + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['before'] }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] == result['after'] }}" + + - name: Replace device global lldp configurations with provided configurarions (idempotent) + register: result + cisco.iosxr.iosxr_lldp_global: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] == result['before'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/rtt.yaml new file mode 100644 index 00000000..c35715bb --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/tests/cli/rtt.yaml @@ -0,0 +1,48 @@ +--- +- ansible.builtin.debug: + msg: START isoxr_lldp_global round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Apply the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_lldp_global: + config: + holdtime: 200 + timer: 500 + state: merged + + - name: Gather interfaces facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - lldp_global + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_lldp_global: + config: + holdtime: 200 + reinit: 4 + subinterfaces: true + timer: 3000 + state: merged + + - name: Assert that changes were applied + ansible.builtin.assert: + that: "{{ round_trip['after'] == result['after'] }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_lldp_global: + config: "{{ ansible_facts['network_resources']['lldp_global'] }}" + state: replaced + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: "{{ base_config['after'] == revert['after'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/vars/main.yaml new file mode 100644 index 00000000..8d6f0928 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_global/vars/main.yaml @@ -0,0 +1,63 @@ +--- +merged: + before: {} + commands: + - lldp reinit 2 + - lldp holdtime 100 + - lldp timer 3000 + - lldp subinterfaces enable + - lldp tlv-select system-description disable + - lldp tlv-select management-address disable + after: + holdtime: 100 + reinit: 2 + subinterfaces: true + timer: 3000 + tlv_select: + management_address: false + system_description: false +replaced: + commands: + - no lldp reinit 2 + - no lldp subinterfaces enable + - no lldp timer 3000 + - lldp tlv-select port-description disable + after: + holdtime: 100 + tlv_select: + management_address: false + port_description: false + system_description: false +deleted: + commands: + - no lldp holdtime 100 + - no lldp reinit 2 + - no lldp subinterfaces enable + - no lldp timer 3000 + - no lldp tlv-select management-address disable + - no lldp tlv-select system-description disable + after: {} +round_trip: + after: + holdtime: 200 + reinit: 4 + subinterfaces: true + timer: 3000 + +parsed: + after: + holdtime: 100 + reinit: 2 + timer: 3000 + subinterfaces: true + tlv_select: + management_address: false + system_description: false +rendered: + commands: + - "lldp subinterfaces enable" + - "lldp holdtime 100" + - "lldp reinit 2" + - "lldp tlv-select system-description disable" + - "lldp tlv-select management-address disable" + - "lldp timer 3000" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/_populate.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/_populate.yaml new file mode 100644 index 00000000..28531216 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/_populate.yaml @@ -0,0 +1,12 @@ +--- +- name: Setup gige1 + cisco.iosxr.iosxr_config: + lines: + - lldp receive disable + parents: interface GigabitEthernet0/0/0/1 + +- name: Setup gige0 + cisco.iosxr.iosxr_config: + lines: + - lldp transmit disable + parents: interface GigabitEthernet0/0/0/0 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..74ee5b41 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/_remove_config.yaml @@ -0,0 +1,22 @@ +--- +- name: Remove lldp interface configuration + loop: + - 0/0/0/0 + - 0/0/0/1 + ignore_errors: true + cisco.iosxr.iosxr_config: + lines: + - no lldp + - shutdown + parents: interface GigabitEthernet{{ item }} + +- name: Remove unwanted interfaces from configuration + loop: + - 0/0/0/2 + - 0/0/0/3 + - 0/0/0/4 + - 0/0/0/5 + ignore_errors: true + cisco.iosxr.iosxr_config: + lines: + - no interface GigabitEthernet{{ item }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/deleted.yaml new file mode 100644 index 00000000..572fb3f6 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/deleted.yaml @@ -0,0 +1,44 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_lldp_interfaces deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Delete lldp attributes of all interfaces + register: result + cisco.iosxr.iosxr_lldp_interfaces: &id001 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ populate | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Delete lacp attributes of all interfaces (idempotent) + register: result + cisco.iosxr.iosxr_lldp_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + - result.commands|length == 0 + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/empty_config.yaml new file mode 100644 index 00000000..94c53a86 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_interfaces empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lldp_interfaces: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lldp_interfaces: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lldp_interfaces: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lldp_interfaces: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_lldp_interfaces: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/fixtures/parsed.cfg new file mode 100644 index 00000000..8fbe03d5 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/fixtures/parsed.cfg @@ -0,0 +1,16 @@ +interface TenGigE0/0/0/0 + ipv4 address 192.0.2.11 255.255.255.192 +! +interface preconfigure GigabitEthernet0/0/0/1 + lldp + receive disable + destination mac-address + ieee-nearest-bridge + ! + ! +! +interface preconfigure GigabitEthernet0/0/0/2 + lldp + transmit disable + destination mac-address + ieee-nearest-non-tmpr-bridge diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/gathered.yaml new file mode 100644 index 00000000..ab9d0d0a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/gathered.yaml @@ -0,0 +1,28 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_interfaces gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_lldp_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + transmit: false + + - name: GigabitEthernet0/0/0/1 + receive: false + state: merged + + - name: Gather interfaces facts using gathered state + register: result + cisco.iosxr.iosxr_lldp_interfaces: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] | symmetric_difference(result['gathered']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/merged.yaml new file mode 100644 index 00000000..623bfe5c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/merged.yaml @@ -0,0 +1,47 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_interfaces merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_lldp_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + transmit: false + + - name: GigabitEthernet0/0/0/1 + receive: false + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['before'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_lldp_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/overridden.yaml new file mode 100644 index 00000000..0267ab16 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/overridden.yaml @@ -0,0 +1,47 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_interfaces overridden integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Overridde all interface lldp configuration with provided configuration + register: result + cisco.iosxr.iosxr_lldp_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + transmit: false + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ populate | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Overridde all interface lacp configuration with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_lldp_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/parsed.yaml new file mode 100644 index 00000000..7362cdbd --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_interfaces parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided lldp interfaces configuration to agnostic model + register: result + cisco.iosxr.iosxr_lldp_interfaces: + running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}" + state: parsed + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - "{{ parsed['config'] | symmetric_difference(result['parsed']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/rendered.yaml new file mode 100644 index 00000000..98a47434 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/rendered.yaml @@ -0,0 +1,24 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_interfaces rendered integration tests on connection={{ ansible_connection }} + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_lldp_interfaces: + config: + - name: GigabitEthernet0/0/0/1 + destination: + mac_address: ieee-nearest-non-tmpr-bridge + transmit: false + + - name: GigabitEthernet0/0/0/2 + destination: + mac_address: ieee-nearest-bridge + receive: false + state: rendered + + - name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - "{{ rendered['commands'] | symmetric_difference(result['rendered']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/replaced.yaml new file mode 100644 index 00000000..ab789717 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/replaced.yaml @@ -0,0 +1,47 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_interfaces replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate.yaml + +- block: + - name: Replace device configurations of listed interfaces with provided configurations + register: result + cisco.iosxr.iosxr_lldp_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/1 + transmit: false + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ populate | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Replace device configurations of listed interfaces with provided configurarions (idempotent) + register: result + cisco.iosxr.iosxr_lldp_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/rtt.yaml new file mode 100644 index 00000000..38d007d9 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/tests/cli/rtt.yaml @@ -0,0 +1,49 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_lldp_interfaces round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Apply the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_lldp_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + transmit: false + state: merged + + - name: Gather interfaces facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - lldp_interfaces + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_lldp_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + receive: false + + - name: GigabitEthernet0/0/0/1 + transmit: false + state: overridden + + - name: Assert that changes were applied + ansible.builtin.assert: + that: "{{ round_trip['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_lldp_interfaces: + config: "{{ ansible_facts['network_resources']['lldp_interfaces'] }}" + state: overridden + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: "{{ base_config['after'] | symmetric_difference(revert['after']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/vars/main.yaml new file mode 100644 index 00000000..403548b5 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_lldp_interfaces/vars/main.yaml @@ -0,0 +1,73 @@ +--- +merged: + before: + - name: GigabitEthernet0/0/0/0 + - name: GigabitEthernet0/0/0/1 + commands: + - interface GigabitEthernet0/0/0/0 + - lldp transmit disable + - interface GigabitEthernet0/0/0/1 + - lldp receive disable + after: + - name: GigabitEthernet0/0/0/0 + transmit: false + - name: GigabitEthernet0/0/0/1 + receive: false +populate: + - name: GigabitEthernet0/0/0/0 + transmit: false + - name: GigabitEthernet0/0/0/1 + receive: false +replaced: + commands: + - interface GigabitEthernet0/0/0/1 + - no lldp receive disable + - lldp transmit disable + after: + - name: GigabitEthernet0/0/0/0 + transmit: false + - name: GigabitEthernet0/0/0/1 + transmit: false +overridden: + commands: + - interface GigabitEthernet0/0/0/1 + - no lldp receive disable + after: + - name: GigabitEthernet0/0/0/0 + transmit: false + - name: GigabitEthernet0/0/0/1 +deleted: + commands: + - interface GigabitEthernet0/0/0/0 + - no lldp transmit disable + - interface GigabitEthernet0/0/0/1 + - no lldp receive disable + after: + - name: GigabitEthernet0/0/0/0 + - name: GigabitEthernet0/0/0/1 +round_trip: + after: + - name: GigabitEthernet0/0/0/0 + receive: false + - name: GigabitEthernet0/0/0/1 + transmit: false +parsed: + config: + - name: TenGigE0/0/0/0 + - name: GigabitEthernet0/0/0/2 + destination: + mac_address: ieee-nearest-non-tmpr-bridge + transmit: false + + - name: GigabitEthernet0/0/0/1 + destination: + mac_address: ieee-nearest-bridge + receive: false +rendered: + commands: + - "interface GigabitEthernet0/0/0/2" + - "lldp destination mac-address ieee-nearest-non-tmpr-bridge" + - "lldp transmit disable" + - "interface GigabitEthernet0/0/0/1" + - "lldp receive disable" + - "lldp destination mac-address ieee-nearest-bridge" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/defaults/main.yaml new file mode 100644 index 00000000..9ef5ba51 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/meta/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/meta/main.yaml new file mode 100644 index 00000000..be631e5d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_iosxr_tests diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tasks/cli.yaml new file mode 100644 index 00000000..8ae46e43 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tasks/cli.yaml @@ -0,0 +1,23 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli + +- name: Reset connection + ansible.builtin.meta: reset_connection diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tasks/main.yaml new file mode 100644 index 00000000..419a6cde --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tasks/main.yaml @@ -0,0 +1,6 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + +- name: Include the netconf tasks + ansible.builtin.include_tasks: netconf.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tasks/netconf.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tasks/netconf.yaml new file mode 100644 index 00000000..e5f214d1 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tasks/netconf.yaml @@ -0,0 +1,23 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/netconf" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.netconf) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.netconf + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - netconf + +- name: Reset connection + ansible.builtin.meta: reset_connection diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tests/cli/basic.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tests/cli/basic.yaml new file mode 100644 index 00000000..02280f4a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tests/cli/basic.yaml @@ -0,0 +1,140 @@ +--- +- name: Remove host logging + cisco.iosxr.iosxr_logging: + dest: host + name: 172.16.0.1 + state: absent + +- name: Remove console logging + register: result + cisco.iosxr.iosxr_logging: + dest: console + state: absent + +- name: Remove buffered logging + register: result + cisco.iosxr.iosxr_logging: + dest: buffered + size: 2097155 + state: absent + +- name: Set up syslog host logging + register: result + cisco.iosxr.iosxr_logging: &id001 + dest: host + name: 172.16.0.1 + level: errors + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"logging 172.16.0.1 vrf default severity error" in result.commands' + +- name: Set up syslog host logging (idempotent) + register: result + cisco.iosxr.iosxr_logging: *id001 +- ansible.builtin.assert: &id003 + that: + - result.changed == false + +- name: Delete/disable syslog host logging + register: result + cisco.iosxr.iosxr_logging: &id002 + dest: host + name: 172.16.0.1 + state: absent + +- ansible.builtin.assert: + that: + - result.changed == true + - '"no logging 172.16.0.1 vrf default" in result.commands' + +- name: Delete/disable syslog host logging (idempotent) + register: result + cisco.iosxr.iosxr_logging: *id002 +- ansible.builtin.assert: *id003 +- name: Add console logging with level warning + register: result + cisco.iosxr.iosxr_logging: &id004 + dest: console + level: warning + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"logging console warning" in result.commands' + +- name: Console logging with level warning (idempotent) + register: result + cisco.iosxr.iosxr_logging: *id004 +- ansible.builtin.assert: *id003 +- name: Remove console logging with level warning + register: result + cisco.iosxr.iosxr_logging: + dest: console + level: warning + state: absent + +- ansible.builtin.assert: &id006 + that: + - result.changed == true + +- name: Configure buffered logging size + register: result + cisco.iosxr.iosxr_logging: &id005 + dest: buffered + size: 4800000 + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"logging buffered 4800000" in result.commands' + +- name: Configure buffered logging size (idempotence) + register: result + cisco.iosxr.iosxr_logging: *id005 +- ansible.builtin.assert: *id003 +- name: Remove buffered logging size + register: result + cisco.iosxr.iosxr_logging: + dest: buffered + size: 4800000 + state: absent + +- ansible.builtin.assert: *id006 +- name: Change logging parameters using aggregate + register: result + cisco.iosxr.iosxr_logging: + aggregate: + - dest: console + level: notifications + + - dest: buffered + size: 4700000 + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"logging buffered 4700000" in result.commands' + - '"logging console notifications" in result.commands' + +- name: Remove logging parameters using aggregate + register: result + cisco.iosxr.iosxr_logging: + aggregate: + - dest: console + level: notifications + + - dest: buffered + size: 4700000 + state: absent + +- ansible.builtin.assert: + that: + - result.changed == true + - '"no logging console" in result.commands' + - '"no logging buffered" in result.commands' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tests/netconf/basic.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tests/netconf/basic.yaml new file mode 100644 index 00000000..2bd05e51 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging/tests/netconf/basic.yaml @@ -0,0 +1,208 @@ +--- +- name: Remove host logging + cisco.iosxr.iosxr_logging: + dest: host + name: 172.16.0.1 + state: absent + +- name: Remove console logging + register: result + cisco.iosxr.iosxr_logging: + dest: console + level: warning + state: absent + +- name: Remove buffered logging + register: result + cisco.iosxr.iosxr_logging: + dest: buffered + size: 2097155 + state: absent + +- name: Set up syslog host logging + register: result + cisco.iosxr.iosxr_logging: &id001 + dest: host + name: 172.16.0.1 + level: errors + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"172.16.0.1" in result.xml[0]' + +- name: Set up syslog host logging (idempotent) + register: result + cisco.iosxr.iosxr_logging: *id001 +- ansible.builtin.assert: &id003 + that: + - result.changed == false + +- name: Delete/disable syslog host logging + register: result + cisco.iosxr.iosxr_logging: &id002 + dest: host + name: 172.16.0.1 + state: absent + +- ansible.builtin.assert: + that: + - result.changed == true + - '"172.16.0.1" in result.xml[0]' + - '"delete" in result.xml[0]' + +- name: Delete/disable syslog host logging (idempotent) + register: result + cisco.iosxr.iosxr_logging: *id002 +- ansible.builtin.assert: *id003 +- name: Add console logging with level warning + register: result + cisco.iosxr.iosxr_logging: &id004 + dest: console + level: warning + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"console" in result.xml[0]' + - '"warning" in result.xml[0]' + +- name: Console logging with level warning (idempotent) + register: result + cisco.iosxr.iosxr_logging: *id004 +- ansible.builtin.assert: *id003 +- name: Remove console logging with level warning + register: result + cisco.iosxr.iosxr_logging: + dest: console + level: warning + state: absent + +- ansible.builtin.assert: &id006 + that: + - result.changed == true + +- name: Configure buffered logging size + register: result + cisco.iosxr.iosxr_logging: &id005 + dest: buffered + size: 4800000 + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"buffered" in result.xml[0]' + - '"4800000" in result.xml[0]' + +- name: Configure buffered logging size (idempotence) + register: result + cisco.iosxr.iosxr_logging: *id005 +- ansible.builtin.assert: *id003 +- name: Remove buffered logging size + register: result + cisco.iosxr.iosxr_logging: + dest: buffered + size: 4800000 + state: absent + +- ansible.builtin.assert: *id006 +- name: Change logging parameters using aggregate + register: result + cisco.iosxr.iosxr_logging: + aggregate: + - dest: console + level: notifications + + - dest: buffered + size: 4700000 + + - dest: monitor + level: alerts + + - dest: host + name: 10.10.10.1 + level: errors + + - dest: host + name: 10.10.10.2 + + - dest: file + name: file1 + size: 2048 + level: critical + path: /file1 + + - dest: file + name: file2 + size: 2048 + path: /file2 + + - facility: local3 + + - hostnameprefix: host3 + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"file1" in result.xml[0]' + - '"file2" in result.xml[0]' + - '"10.10.10.1" in result.xml[1]' + - '"10.10.10.2" in result.xml[1]' + - '"notice" in result.xml[2]' + - '"alert" in result.xml[3]' + - '"4700000" in result.xml[4]' + - '"debug" in result.xml[4]' + - '"local3" in result.xml[5]' + - '"host3" in result.xml[6]' + +- name: Remove logging parameters using aggregate + register: result + cisco.iosxr.iosxr_logging: + aggregate: + - dest: console + level: notifications + + - dest: buffered + size: 4700000 + + - dest: monitor + level: alerts + + - dest: host + name: 10.10.10.1 + level: errors + + - dest: host + name: 10.10.10.2 + + - dest: file + name: file1 + size: 2048 + level: critical + + - dest: file + name: file2 + size: 2048 + + - facility: local3 + + - hostnameprefix: host3 + state: absent + +- ansible.builtin.assert: + that: + - result.changed == true + - '"file1" in result.xml[0]' + - '"file2" in result.xml[0]' + - '"10.10.10.1" in result.xml[1]' + - '"10.10.10.2" in result.xml[1]' + - '"notice" in result.xml[2]' + - '"alert" in result.xml[3]' + - '"4700000" in result.xml[4]' + - '"debug" in result.xml[4]' + - '"local3" in result.xml[5]' + - '"host3" in result.xml[6]' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/defaults/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/defaults/main.yml new file mode 100644 index 00000000..871ea460 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/defaults/main.yml @@ -0,0 +1,2 @@ +--- +testcase: "[^_].*" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/meta/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/meta/main.yml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/meta/main.yml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tasks/cli.yaml new file mode 100644 index 00000000..1b019a5a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tasks/cli.yaml @@ -0,0 +1,21 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + vars: + ansible_connection: ansible.netcommon.network_cli + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tasks/main.yaml new file mode 100644 index 00000000..f75f2f03 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/_parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/_parsed.cfg new file mode 100644 index 00000000..196fdc6c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/_parsed.cfg @@ -0,0 +1,19 @@ +logging tls-server test + vrf test + trustpoint test2 + tls-hostname test2 +! +logging file test path test maxfilesize 1024 severity info +logging ipv4 dscp af11 +logging trap informational +logging events display-location +logging monitor errors +logging buffered 2097152 +logging buffered warnings +! +logging 1.1.1.1 vrf default severity critical port default +! +logging correlator buffer-size 1024 +logging localfilesize 1024 +logging source-interface GigabitEthernet0/0/0/0 vrf test +logging hostnameprefix test diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/_populate_config.yaml new file mode 100644 index 00000000..a124cb62 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/_populate_config.yaml @@ -0,0 +1,23 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "logging tls-server test" + - " vrf test" + - " trustpoint test2" + - " tls-hostname test2" + - "logging file test path test maxfilesize 1024 severity info" + - "logging ipv4 dscp af11" + - "logging trap informational" + - "logging events display-location" + - "logging monitor errors" + - "logging buffered 2097152" + - "logging buffered warnings" + - "logging 1.1.1.1 vrf default severity critical port default" + - "logging correlator buffer-size 1024" + - "logging localfilesize 1024" + - "logging source-interface GigabitEthernet0/0/0/0 vrf test" + - "logging hostnameprefix test" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/_remove_config.yaml new file mode 100644 index 00000000..a6ce93fb --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/_remove_config.yaml @@ -0,0 +1,6 @@ +--- +- name: "Remove logging configuration" + cisco.iosxr.iosxr_logging_global: + state: deleted + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/deleted.yaml new file mode 100644 index 00000000..1f477028 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/deleted.yaml @@ -0,0 +1,36 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_logging_global deleted integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete given logging_global configuration + become: true + register: result + cisco.iosxr.iosxr_logging_global: &deleted + state: deleted + + - become: true + cisco.iosxr.iosxr_facts: + gather_network_resources: logging_global + + - ansible.builtin.assert: + that: + - result.commands|length == 13 + - result.changed == true + - ansible_facts.network_resources.logging_global == result.after + - result.after == deleted.after + + - name: Idempotency check + become: true + register: result + cisco.iosxr.iosxr_logging_global: *deleted + - ansible.builtin.assert: + that: + - result.commands|length == 0 + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/empty_config.yaml new file mode 100644 index 00000000..529e437d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/empty_config.yaml @@ -0,0 +1,50 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_logging_global empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_logging_global: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_logging_global: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_logging_global: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_logging_global: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' + +- ansible.builtin.debug: + msg: END iosxr_logging_global empty_config integration tests on connection={{ ansible_connection }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/gathered.yaml new file mode 100644 index 00000000..90ceeead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/gathered.yaml @@ -0,0 +1,22 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_logging_global gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Gathered the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_logging_global: + config: + state: gathered + + - name: Assert + ansible.builtin.assert: + that: + - merged.after == result.gathered + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/merged.yaml new file mode 100644 index 00000000..c39b8564 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/merged.yaml @@ -0,0 +1,63 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_logging_global merged integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + cisco.iosxr.iosxr_logging_global: + config: + buffered: + size: 2097152 + severity: warnings + correlator: + buffer_size: 1024 + events: + display_location: true + files: + - maxfilesize: 1024 + name: test + path: test + severity: info + hostnameprefix: test + hosts: + - host: 1.1.1.1 + port: default + severity: critical + vrf: default + ipv4: + dscp: af11 + localfilesize: 1024 + monitor: + severity: errors + source_interfaces: + - interface: GigabitEthernet0/0/0/0 + vrf: test + tls_servers: + - name: test + tls_hostname: test2 + trustpoint: test2 + vrf: test + trap: + severity: informational + state: merged + + register: result + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ result['before'] == {} }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts were correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['after'] + + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/overridden.yaml new file mode 100644 index 00000000..7263cdad --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/overridden.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_logging_global overridden integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Override BGP configuration with provided configuration + cisco.iosxr.iosxr_logging_global: + config: + buffered: + severity: errors + correlator: + buffer_size: 1024 + files: + - maxfilesize: 1024 + name: test + path: test1 + severity: info + hostnameprefix: test1 + hosts: + - host: 1.1.1.3 + port: default + severity: critical + vrf: default + ipv6: + dscp: af11 + localfilesize: 1024 + monitor: + severity: errors + tls_servers: + - name: test + tls_hostname: test2 + trustpoint: test + vrf: test + trap: + severity: critical + state: overridden + register: result + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - replaced['after'] == result['after'] + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['before'] + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/parsed.yaml new file mode 100644 index 00000000..3bdf408c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_logging_global parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided BGP configuration + register: result + cisco.iosxr.iosxr_logging_global: + running_config: "{{ lookup('file', './_parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - merged['after'] == result['parsed'] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/rendered.yaml new file mode 100644 index 00000000..5c3f4567 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/rendered.yaml @@ -0,0 +1,59 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_logging_global rendered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- name: Render platform specific configuration lines with state rendered (without connecting to the device) + cisco.iosxr.iosxr_logging_global: + config: + buffered: + size: 2097152 + severity: warnings + correlator: + buffer_size: 1024 + events: + display_location: true + files: + - maxfilesize: 1024 + name: test + path: test + severity: info + hostnameprefix: test + hosts: + - host: 1.1.1.1 + port: default + severity: critical + vrf: default + ipv4: + dscp: af11 + localfilesize: 1024 + monitor: + severity: errors + source_interfaces: + - interface: GigabitEthernet0/0/0/0 + vrf: test + tls_servers: + - name: test + tls_hostname: test2 + trustpoint: test2 + vrf: test + trap: + severity: informational + state: rendered + register: result + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - merged['commands'] == result['rendered'] + +- name: Gather BGP facts + cisco.iosxr.iosxr_logging_global: + state: gathered + register: result + +- name: Ensure that no configuration changes were made + ansible.builtin.assert: + that: + - result.gathered == {} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/replaced.yaml new file mode 100644 index 00000000..4b882120 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/tests/common/replaced.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_logging_global replaced integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replace BGP configuration with provided configuration + cisco.iosxr.iosxr_logging_global: + config: + buffered: + severity: errors + correlator: + buffer_size: 1024 + files: + - maxfilesize: 1024 + name: test + path: test1 + severity: info + hostnameprefix: test1 + hosts: + - host: 1.1.1.3 + port: default + severity: critical + vrf: default + ipv6: + dscp: af11 + localfilesize: 1024 + monitor: + severity: errors + tls_servers: + - name: test + tls_hostname: test2 + trustpoint: test + vrf: test + trap: + severity: critical + state: replaced + register: result + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - replaced['after'] == result['after'] + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['before'] + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/vars/main.yaml new file mode 100644 index 00000000..0bc3459f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_logging_global/vars/main.yaml @@ -0,0 +1,98 @@ +--- +merged: + commands: + - logging buffered 2097152 + - logging buffered warnings + - logging correlator buffer-size 1024 + - logging events display-location + - logging hostnameprefix test + - logging ipv4 dscp af11 + - logging localfilesize 1024 + - logging monitor errors + - logging trap informational + - logging 1.1.1.1 vrf default severity critical port default + - logging file test path test maxfilesize 1024 severity info + - logging source-interface GigabitEthernet0/0/0/0 vrf test + - logging tls-server test tls-hostname test2 + - logging tls-server test trustpoint test2 + - logging tls-server test vrf test + after: + buffered: + size: 2097152 + severity: warnings + correlator: + buffer_size: 1024 + events: + display_location: true + files: + - maxfilesize: 1024 + name: test + path: test + severity: info + hostnameprefix: test + hosts: + - host: 1.1.1.1 + port: default + severity: critical + vrf: default + ipv4: + dscp: af11 + localfilesize: 1024 + monitor: + severity: errors + source_interfaces: + - interface: GigabitEthernet0/0/0/0 + vrf: test + tls_servers: + - name: test + tls_hostname: test2 + trustpoint: test2 + vrf: test + trap: + severity: informational + +deleted: + after: {} + +replaced: + commands: + - no logging buffered 2097152 + - no logging events display-location + - no logging ipv4 dscp af11 + - no logging 1.1.1.1 vrf default severity critical port default + - no logging source-interface GigabitEthernet0/0/0/0 vrf test + - logging buffered errors + - logging hostnameprefix test1 + - logging ipv6 dscp af11 + - logging trap critical + - logging 1.1.1.3 vrf default severity critical port default + - logging file test path test1 maxfilesize 1024 severity info + - logging tls-server test trustpoint test + after: + buffered: + severity: errors + correlator: + buffer_size: 1024 + files: + - maxfilesize: 1024 + name: test + path: test1 + severity: info + hostnameprefix: test1 + hosts: + - host: 1.1.1.3 + port: default + severity: critical + vrf: default + ipv6: + dscp: af11 + localfilesize: 1024 + monitor: + severity: errors + tls_servers: + - name: test + tls_hostname: test2 + trustpoint: test + vrf: test + trap: + severity: critical diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/defaults/main.yaml new file mode 100644 index 00000000..9ef5ba51 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/meta/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/meta/main.yaml new file mode 100644 index 00000000..be631e5d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_iosxr_tests diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/tasks/cli.yaml new file mode 100644 index 00000000..05e3269d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/tasks/cli.yaml @@ -0,0 +1,18 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/tests/cli/basic.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/tests/cli/basic.yaml new file mode 100644 index 00000000..182752f6 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_netconf/tests/cli/basic.yaml @@ -0,0 +1,65 @@ +--- +- ansible.builtin.debug: msg="START iosxr_netconf cli/basic.yaml on connection={{ ansible_connection }}" + +- name: Disable netconf service + cisco.iosxr.iosxr_netconf: &id003 + state: absent + +- block: + - name: Enable netconf service + register: result + cisco.iosxr.iosxr_netconf: + netconf_port: 830 + netconf_vrf: default + state: present + + - ansible.builtin.assert: &id001 + that: + - result.changed == true + + - name: Check idempotence of enable netconf service + register: result + cisco.iosxr.iosxr_netconf: + netconf_port: 830 + netconf_vrf: default + state: present + + - ansible.builtin.assert: &id002 + that: + - result.changed == false + + - name: Change netconf port + register: result + cisco.iosxr.iosxr_netconf: + netconf_port: 9000 + state: present + + - ansible.builtin.assert: *id001 + - name: Check idempotent of change netconf port + register: result + cisco.iosxr.iosxr_netconf: + netconf_port: 9000 + state: present + + - ansible.builtin.assert: *id002 + - name: Add netconf VRF + register: result + cisco.iosxr.iosxr_netconf: + netconf_port: 9000 + netconf_vrf: new_default + state: present + + - ansible.builtin.assert: *id001 + - name: Check idempotent of add netconf VRF + register: result + cisco.iosxr.iosxr_netconf: + netconf_port: 9000 + netconf_vrf: new_default + state: present + + - ansible.builtin.assert: *id002 + always: + - name: Disable netconf service + cisco.iosxr.iosxr_netconf: *id003 + +- ansible.builtin.debug: msg="END iosxr_netconf cli/basic.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/defaults/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/defaults/main.yml new file mode 100644 index 00000000..871ea460 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/defaults/main.yml @@ -0,0 +1,2 @@ +--- +testcase: "[^_].*" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/meta/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/meta/main.yml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/meta/main.yml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tasks/cli.yaml new file mode 100644 index 00000000..1b019a5a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tasks/cli.yaml @@ -0,0 +1,21 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + vars: + ansible_connection: ansible.netcommon.network_cli + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tasks/main.yaml new file mode 100644 index 00000000..f75f2f03 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/_parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/_parsed.cfg new file mode 100644 index 00000000..8caadb07 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/_parsed.cfg @@ -0,0 +1,29 @@ +ntp + max-associations 10 + interface GigabitEthernet0/0/0/0 + broadcast client + multicast client 224.0.0.8 + multicast destination 224.0.0.8 + ! + authenticate + trusted-key 1 + ipv4 dscp af11 + ipv6 precedence routine + peer vrf siteC 192.0.2.1 iburst + server vrf siteD 192.0.2.2 burst + drift file apphost + drift aging time 0 + master 1 + access-group vrf siteA ipv4 peer PeerAcl3 + access-group vrf siteA ipv4 serve ServeAcl2 + access-group ipv4 peer PeerAcl1 + access-group ipv4 serve ServeAcl1 + access-group ipv4 serve-only ServeOnlyAcl1 + access-group ipv4 query-only QueryOnlyAcl1 + source vrf siteE GigabitEthernet0/0/0/0 + source GigabitEthernet0/0/0/0 + passive + broadcastdelay 1 + update-calendar + log-internal-sync +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/_populate_config.yaml new file mode 100644 index 00000000..cbf196c4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/_populate_config.yaml @@ -0,0 +1,34 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "ntp" + - " max-associations 10" + - " interface GigabitEthernet0/0/0/0" + - " broadcast client" + - " multicast client 224.0.0.8" + - " multicast destination 224.0.0.8" + - " authenticate" + - " trusted-key 1" + - " ipv4 dscp af11" + - " ipv6 precedence routine" + - " peer vrf siteC 192.0.2.1 iburst" + - " server vrf siteD 192.0.2.2 burst" + - " drift file apphost" + - " drift aging time 0" + - " master 1" + - " access-group vrf siteA ipv4 peer PeerAcl3" + - " access-group vrf siteA ipv4 serve ServeAcl2" + - " access-group ipv4 peer PeerAcl1" + - " access-group ipv4 serve ServeAcl1" + - " access-group ipv4 serve-only ServeOnlyAcl1" + - " access-group ipv4 query-only QueryOnlyAcl1" + - " source vrf siteE GigabitEthernet0/0/0/0" + - " source GigabitEthernet0/0/0/0" + - " passive" + - " broadcastdelay 1" + - " update-calendar" + - " log-internal-sync" + + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/_remove_config.yaml new file mode 100644 index 00000000..84913e8c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/_remove_config.yaml @@ -0,0 +1,6 @@ +--- +- name: "Remove ntp global configuration" + cisco.iosxr.iosxr_ntp_global: + state: deleted + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/deleted.yaml new file mode 100644 index 00000000..0d5ded6a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/deleted.yaml @@ -0,0 +1,36 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_ntp_global deleted integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete given ntp_global configuration + become: true + register: result + cisco.iosxr.iosxr_ntp_global: &deleted + state: deleted + + - become: true + cisco.iosxr.iosxr_facts: + gather_network_resources: ntp_global + + - ansible.builtin.assert: + that: + - result.commands|length == 23 + - result.changed == true + - ansible_facts.network_resources.ntp_global == result.after + - result.after == deleted.after + + - name: Idempotency check + become: true + register: result + cisco.iosxr.iosxr_ntp_global: *deleted + - ansible.builtin.assert: + that: + - result.commands|length == 0 + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/empty_config.yaml new file mode 100644 index 00000000..4e380804 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/empty_config.yaml @@ -0,0 +1,50 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ntp_global empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ntp_global: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ntp_global: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ntp_global: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ntp_global: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' + +- ansible.builtin.debug: + msg: END iosxr_ntp_global empty_config integration tests on connection={{ ansible_connection }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/gathered.yaml new file mode 100644 index 00000000..8974e694 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/gathered.yaml @@ -0,0 +1,22 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ntp_global gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Gathered the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_ntp_global: + config: + state: gathered + + - name: Assert + ansible.builtin.assert: + that: + - merged.after == result.gathered + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/merged.yaml new file mode 100644 index 00000000..0f13ddbe --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/merged.yaml @@ -0,0 +1,74 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_ntp_global merged integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + cisco.iosxr.iosxr_ntp_global: + config: + access_group: + ipv4: + peer: PeerAcl1 + query_only: QueryOnlyAcl1 + serve: ServeAcl1 + serve_only: ServeOnlyAcl1 + vrfs: + - ipv4: + peer: PeerAcl3 + serve: ServeAcl2 + name: siteA + authenticate: true + broadcastdelay: 1 + drift: + aging_time: 0 + file: apphost + interfaces: + - name: GigabitEthernet0/0/0/0 + multicast_client: 224.0.0.8 + multicast_destination: 224.0.0.8 + broadcast_client: true + ipv4: + dscp: af11 + ipv6: + precedence: routine + log_internal_sync: true + master: + stratum: 1 + max_associations: 10 + passive: true + peers: + - iburst: true + peer: 192.0.2.1 + vrf: siteC + servers: + - burst: true + server: 192.0.2.2 + vrf: siteD + source_interface: GigabitEthernet0/0/0/0 + source_vrfs: + - name: GigabitEthernet0/0/0/0 + vrf: siteE + trusted_keys: + - key_id: 1 + update_calendar: true + + register: result + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ result['before'] == {} }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts were correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['after'] + + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/overridden.yaml new file mode 100644 index 00000000..e4fa06dc --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/overridden.yaml @@ -0,0 +1,76 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_ntp_global overridden integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Override BGP configuration with provided configuration + cisco.iosxr.iosxr_ntp_global: + state: overridden + config: + access_group: + ipv4: + peer: PeerAcl1 + query_only: QueryOnlyAcl1 + serve: ServeAcl4 + serve_only: ServeOnlyAcl1 + vrfs: + - ipv4: + peer: PeerAcl3 + serve: ServeAcl2 + name: siteA + authenticate: true + broadcastdelay: 1 + drift: + aging_time: 0 + file: apphost + interfaces: + - name: GigabitEthernet0/0/0/1 + multicast_client: 224.0.0.8 + multicast_destination: 224.0.0.8 + broadcast_client: true + ipv4: + dscp: af12 + ipv6: + precedence: routine + log_internal_sync: true + master: + stratum: 1 + max_associations: 10 + passive: true + peers: + - iburst: true + peer: 192.0.2.3 + vrf: siteC + servers: + - burst: true + server: 192.0.2.2 + vrf: siteD + source_interface: GigabitEthernet0/0/0/1 + source_vrfs: + - name: GigabitEthernet0/0/0/0 + vrf: siteE + trusted_keys: + - key_id: 1 + update_calendar: true + register: result + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - replaced['after'] == result['after'] + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['before'] + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/parsed.yaml new file mode 100644 index 00000000..4bae4e7d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ntp_global parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided ntp_global configuration + register: result + cisco.iosxr.iosxr_ntp_global: + running_config: "{{ lookup('file', './_parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - merged['after'] == result['parsed'] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/rendered.yaml new file mode 100644 index 00000000..b77ed565 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/rendered.yaml @@ -0,0 +1,71 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ntp_global rendered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- name: Render platform specific configuration lines with state rendered (without connecting to the device) + cisco.iosxr.iosxr_ntp_global: + state: rendered + config: + access_group: + ipv4: + peer: PeerAcl1 + query_only: QueryOnlyAcl1 + serve: ServeAcl1 + serve_only: ServeOnlyAcl1 + vrfs: + - ipv4: + peer: PeerAcl3 + serve: ServeAcl2 + name: siteA + authenticate: true + broadcastdelay: 1 + drift: + aging_time: 0 + file: apphost + interfaces: + - name: GigabitEthernet0/0/0/0 + multicast_client: 224.0.0.8 + multicast_destination: 224.0.0.8 + broadcast_client: true + ipv4: + dscp: af11 + ipv6: + precedence: routine + log_internal_sync: true + master: + stratum: 1 + max_associations: 10 + passive: true + peers: + - iburst: true + peer: 192.0.2.1 + vrf: siteC + servers: + - burst: true + server: 192.0.2.2 + vrf: siteD + source_interface: GigabitEthernet0/0/0/0 + source_vrfs: + - name: GigabitEthernet0/0/0/0 + vrf: siteE + trusted_keys: + - key_id: 1 + update_calendar: true + register: result + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - merged['commands'] == result['rendered'] + +- name: Gather BGP facts + cisco.iosxr.iosxr_ntp_global: + state: gathered + register: result + +- name: Ensure that no configuration changes were made + ansible.builtin.assert: + that: + - result.gathered == {} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/replaced.yaml new file mode 100644 index 00000000..9703e12d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/tests/common/replaced.yaml @@ -0,0 +1,79 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_ntp_global replaced integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replace BGP configuration with provided configuration + cisco.iosxr.iosxr_ntp_global: + state: replaced + config: + access_group: + ipv4: + peer: PeerAcl1 + query_only: QueryOnlyAcl1 + serve: ServeAcl4 + serve_only: ServeOnlyAcl1 + vrfs: + - ipv4: + peer: PeerAcl3 + serve: ServeAcl2 + name: siteA + authenticate: true + broadcastdelay: 1 + drift: + aging_time: 0 + file: apphost + interfaces: + - name: GigabitEthernet0/0/0/1 + multicast_client: 224.0.0.8 + multicast_destination: 224.0.0.8 + broadcast_client: true + ipv4: + dscp: af12 + ipv6: + precedence: routine + log_internal_sync: true + master: + stratum: 1 + max_associations: 10 + passive: true + peers: + - iburst: true + peer: 192.0.2.3 + vrf: siteC + servers: + - burst: true + server: 192.0.2.2 + vrf: siteD + source_interface: GigabitEthernet0/0/0/1 + source_vrfs: + - name: GigabitEthernet0/0/0/0 + vrf: siteE + trusted_keys: + - key_id: 1 + update_calendar: true + register: result + + - ansible.builtin.debug: + msg: "{{ replaced['commands'] | symmetric_difference(result['commands']) }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - replaced['after'] == result['after'] + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['before'] + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/vars/main.yaml new file mode 100644 index 00000000..0f2919b7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ntp_global/vars/main.yaml @@ -0,0 +1,136 @@ +--- +merged: + commands: + - ntp peer vrf siteC 192.0.2.1 iburst + - ntp server vrf siteD 192.0.2.2 burst + - ntp trusted-key 1 + - ntp interface GigabitEthernet0/0/0/0 broadcast client + - ntp interface GigabitEthernet0/0/0/0 multicast destination 224.0.0.8 + - ntp interface GigabitEthernet0/0/0/0 multicast client 224.0.0.8 + - ntp vrf siteE source GigabitEthernet0/0/0/0 + - ntp access-group vrf siteA ipv4 serve ServeAcl2 + - ntp access-group vrf siteA ipv4 peer PeerAcl3 + - ntp access-group ipv4 peer PeerAcl1 + - ntp access-group ipv4 serve ServeAcl1 + - ntp access-group ipv4 serve-only ServeOnlyAcl1 + - ntp access-group ipv4 query-only QueryOnlyAcl1 + - ntp authenticate + - ntp log-internal-sync + - ntp broadcastdelay 1 + - ntp drift aging time 0 + - ntp drift file apphost + - ntp ipv4 dscp af11 + - ntp ipv6 precedence routine + - ntp max-associations 10 + - ntp master 1 + - ntp passive + - ntp update-calendar + - ntp source GigabitEthernet0/0/0/0 + + after: + access_group: + ipv4: + peer: PeerAcl1 + query_only: QueryOnlyAcl1 + serve: ServeAcl1 + serve_only: ServeOnlyAcl1 + vrfs: + - ipv4: + peer: PeerAcl3 + serve: ServeAcl2 + name: siteA + authenticate: true + broadcastdelay: 1 + drift: + aging_time: 0 + file: apphost + interfaces: + - name: GigabitEthernet0/0/0/0 + multicast_client: 224.0.0.8 + multicast_destination: 224.0.0.8 + broadcast_client: true + ipv4: + dscp: af11 + ipv6: + precedence: routine + log_internal_sync: true + master: + stratum: 1 + max_associations: 10 + passive: true + peers: + - iburst: true + peer: 192.0.2.1 + vrf: siteC + servers: + - burst: true + server: 192.0.2.2 + vrf: siteD + source_interface: GigabitEthernet0/0/0/0 + source_vrfs: + - name: GigabitEthernet0/0/0/0 + vrf: siteE + trusted_keys: + - key_id: 1 + update_calendar: true + +deleted: + after: {} + +replaced: + commands: + - no ntp peer vrf siteC 192.0.2.1 iburst + - no ntp interface GigabitEthernet0/0/0/0 + - ntp peer vrf siteC 192.0.2.3 iburst + - ntp interface GigabitEthernet0/0/0/1 broadcast client + - ntp interface GigabitEthernet0/0/0/1 multicast destination 224.0.0.8 + - ntp interface GigabitEthernet0/0/0/1 multicast client 224.0.0.8 + - ntp access-group ipv4 serve ServeAcl4 + - ntp ipv4 dscp af12 + - ntp source GigabitEthernet0/0/0/1 + after: + access_group: + ipv4: + peer: PeerAcl1 + query_only: QueryOnlyAcl1 + serve: ServeAcl4 + serve_only: ServeOnlyAcl1 + vrfs: + - ipv4: + peer: PeerAcl3 + serve: ServeAcl2 + name: siteA + authenticate: true + broadcastdelay: 1 + drift: + aging_time: 0 + file: apphost + interfaces: + - name: GigabitEthernet0/0/0/1 + multicast_client: 224.0.0.8 + multicast_destination: 224.0.0.8 + broadcast_client: true + ipv4: + dscp: af12 + ipv6: + precedence: routine + log_internal_sync: true + master: + stratum: 1 + max_associations: 10 + passive: true + peers: + - iburst: true + peer: 192.0.2.3 + vrf: siteC + servers: + - burst: true + server: 192.0.2.2 + vrf: siteD + source_interface: GigabitEthernet0/0/0/1 + source_vrfs: + - name: GigabitEthernet0/0/0/0 + vrf: siteE + trusted_keys: + - key_id: 1 + update_calendar: true diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/fixtures/parsed.cfg new file mode 100644 index 00000000..b2677113 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/fixtures/parsed.cfg @@ -0,0 +1,51 @@ +router ospf LAB3 + area 0.0.0.3 + interface GigabitEthernet0/0/0/0 + cost 20 + authentication message-digest keychain cisco + ! + ! +! +router ospfv3 10 + area 11 + cost 11 + default-cost 5 + ! + area 22 + default-cost 6 + ! +! +router ospfv3 26 + authentication disable +! +router ospfv3 27 + area 10 + hello-interval 2 + ! +! +router ospfv3 30 + cost 2 + priority 1 + mtu-ignore + packet-size 577 + dead-interval 2 + retransmit-interval 2 + demand-circuit + hello-interval 1 + transmit-delay 2 + router-id 2.2.2.2 + default-metric 10 + area 11 + default-cost 5 + ! + area 22 + default-cost 6 + ! +! +router ospfv3 LAB3 + area 0.0.0.2 + interface GigabitEthernet0/0/0/0 + cost 30 + ! + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/_populate_config.yaml new file mode 100644 index 00000000..aeebcf9e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/_populate_config.yaml @@ -0,0 +1,23 @@ +--- +- name: Setup (populate OSPF interfaces config) + cisco.iosxr.iosxr_ospf_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + type: gigabitethernet + address_family: + - afi: ipv4 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.3 + cost: 20 + authentication: + message_digest: + keychain: cisco + - afi: ipv6 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.2 + cost: 30 + state: merged diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..738d377b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/_remove_config.yaml @@ -0,0 +1,7 @@ +--- +- name: Remove ospfv3 routes + vars: + lines: "no router ospf LAB3 \n no router ospfv3 LAB3 \n no router ospfv3 LAB \n no router ospf LAB \n no router ospf LAB1 \n no router ospfv3 LAB1 " + ignore_errors: true + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/deleted.yaml new file mode 100644 index 00000000..eeeb90de --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/deleted.yaml @@ -0,0 +1,74 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_ospf_interfaces deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete single OSPF interface + register: result + cisco.iosxr.iosxr_ospf_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + type: gigabitethernet + + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Delete a single OSPF process (idempotent) + register: result + cisco.iosxr.iosxr_ospf_interfaces: *id001 + - ansible.builtin.assert: &id003 + that: + - result.changed == false + - result.commands|length == 0 + + - ansible.builtin.include_tasks: _populate_config.yaml + + - name: Delete all OSPF processes + register: result + cisco.iosxr.iosxr_ospf_interfaces: &id002 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Delete all OSPF processes (idempotent) + register: result + cisco.iosxr.iosxr_ospf_interfaces: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: *id003 + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] == result['before'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/empty_config.yaml new file mode 100644 index 00000000..df23b9bc --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospf_interfaces empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospf_interfaces: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospf_interfaces: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Parsed with empty running_config should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospf_interfaces: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospf_interfaces: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospf_interfaces: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/gathered.yaml new file mode 100644 index 00000000..a6737e78 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/gathered.yaml @@ -0,0 +1,20 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospf_interfaces gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Gather OSPF interfaces facts from the device using iosxr_ospf_interfaces module + register: result + cisco.iosxr.iosxr_ospf_interfaces: + state: gathered + + - ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['gathered']) | length == 0 }}" + - "result.changed == false" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/merged.yaml new file mode 100644 index 00000000..70fc8c07 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/merged.yaml @@ -0,0 +1,108 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospf interfaces merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_ospf_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + type: gigabitethernet + address_family: + - afi: ipv4 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.3 + cost: 20 + authentication: + message_digest: + keychain: cisco + - afi: ipv6 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.2 + cost: 30 + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_ospf_interfaces: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Update existing configuration using merged + register: result + cisco.iosxr.iosxr_ospf_interfaces: &id002 + config: + - name: GigabitEthernet0/0/0/1 + type: gigabitethernet + address_family: + - afi: ipv4 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.1 + cost: 10 + authentication: + message_digest: + keychain: lab1 + - afi: ipv6 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.4 + cost: 40 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['update_commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['update_after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Update existing OSPF interfaces configuration using merged (idempotent) + register: result + cisco.iosxr.iosxr_ospf_interfaces: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/overridden.yaml new file mode 100644 index 00000000..8a9dcfe4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/overridden.yaml @@ -0,0 +1,57 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospf_interfaces overridden integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Overridde all ospf_interfaces configuration with provided configuration + register: result + cisco.iosxr.iosxr_ospf_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/1 + type: gigabitethernet + address_family: + - afi: ipv4 + processes: + - process_id: "LAB1" + area: + area_id: 0.0.0.3 + cost: 10 + authentication: + message_digest: + keychain: iosxr + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Overridde all ospf_interfaces configuration with given configuration (idempotent) + register: result + cisco.iosxr.iosxr_ospf_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/parsed.yaml new file mode 100644 index 00000000..598d2d69 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/parsed.yaml @@ -0,0 +1,15 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospf_interfaces parsed integration tests on connection={{ ansible_connection }} + +- block: + - name: Use parsed state to convert externally supplied device specific ospf_interfaces commands to structured format + register: result + cisco.iosxr.iosxr_ospf_interfaces: + running_config: "{{ lookup('file', '../../fixtures/parsed.cfg') }}" + state: parsed + + - ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['parsed']) | length == 0 }}" + - "result.changed == false" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/rendered.yaml new file mode 100644 index 00000000..c573a0e2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/rendered.yaml @@ -0,0 +1,46 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospf_interfaces rendered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Use rendered state to convert task input to device specific commands + register: result + cisco.iosxr.iosxr_ospf_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + type: gigabitethernet + address_family: + - afi: ipv4 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.3 + cost: 20 + authentication: + message_digest: + keychain: cisco + - afi: ipv6 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.2 + cost: 30 + state: rendered + + - ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['rendered']) |length==0 }}" + - "result.changed == false" + + - name: Gather OSPF interfaces facts from the device and assert that its empty + register: result + cisco.iosxr.iosxr_ospf_interfaces: + state: gathered + + - name: Make sure that rendered task actually did not make any changes to the device + ansible.builtin.assert: + that: "{{ result['gathered'] == [] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/replaced.yaml new file mode 100644 index 00000000..f8fb5ce4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/replaced.yaml @@ -0,0 +1,63 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospf_interfaces replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replace device configurations of ospf_interfaces with provided configurations + register: result + cisco.iosxr.iosxr_ospf_interfaces: &id001 + config: + - name: GigabitEthernet0/0/0/0 + type: gigabitethernet + address_family: + - afi: ipv4 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.3 + cost: 30 + authentication: + message_digest: + keychain: ciscoiosxr + - afi: ipv6 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.2 + cost: 30 + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Replace device configurations of listed vrfs/global entry with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_ospf_interfaces: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/rtt.yaml new file mode 100644 index 00000000..8eb6c2da --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/tests/cli/rtt.yaml @@ -0,0 +1,74 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospf_interfaces round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Apply the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_ospf_interfaces: + config: + - name: GigabitEthernet0/0/0/0 + type: gigabitethernet + address_family: + - afi: ipv4 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.3 + cost: 20 + authentication: + message_digest: + keychain: cisco + - afi: ipv6 + processes: + - process_id: "LAB3" + area: + area_id: 0.0.0.2 + cost: 30 + state: merged + + - name: Gather ospf_interfaces facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - ospf_interfaces + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_ospf_interfaces: + config: + - name: GigabitEthernet0/0/0/1 + type: gigabitethernet + address_family: + - afi: ipv4 + processes: + - process_id: "LAB1" + area: + area_id: 0.0.0.3 + cost: 10 + authentication: + message_digest: + keychain: iosxr + state: overridden + + - name: Assert that changes were applied + ansible.builtin.assert: + that: + - "{{ round_trip['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_ospf_interfaces: + config: "{{ ansible_facts['network_resources']['ospf_interfaces'] }}" + state: overridden + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: + - "{{ base_config['after'] | symmetric_difference(revert['after']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/vars/main.yaml new file mode 100644 index 00000000..95f5e7bf --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospf_interfaces/vars/main.yaml @@ -0,0 +1,138 @@ +--- +merged: + before: [] + commands: + - router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 cost 20 + - router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest + - router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest keychain cisco + - router ospfv3 LAB3 area 0.0.0.2 interface GigabitEthernet 0/0/0/0 cost 30 + + update_commands: + - router ospf LAB3 area 0.0.0.1 interface GigabitEthernet 0/0/0/1 cost 10 + - router ospf LAB3 area 0.0.0.1 interface GigabitEthernet 0/0/0/1 authentication message-digest + - router ospf LAB3 area 0.0.0.1 interface GigabitEthernet 0/0/0/1 authentication message-digest keychain lab1 + - router ospfv3 LAB3 area 0.0.0.4 interface GigabitEthernet 0/0/0/1 cost 40 + after: + - address_family: + - afi: ipv4 + authentication: + message_digest: + keychain: cisco + cost: 20 + processes: + - area: + area_id: 0.0.0.3 + process_id: "LAB3" + - afi: ipv6 + cost: 30 + processes: + - area: + area_id: 0.0.0.2 + process_id: "LAB3" + name: GigabitEthernet0/0/0/0 + type: gigabitethernet + + update_after: + - address_family: + - afi: ipv4 + authentication: + message_digest: + keychain: lab1 + cost: 10 + processes: + - area: + area_id: 0.0.0.1 + process_id: "LAB3" + - afi: ipv6 + cost: 40 + processes: + - area: + area_id: 0.0.0.4 + process_id: "LAB3" + name: GigabitEthernet0/0/0/1 + type: gigabitethernet + - address_family: + - afi: ipv4 + authentication: + message_digest: + keychain: cisco + cost: 20 + processes: + - area: + area_id: 0.0.0.3 + process_id: "LAB3" + - afi: ipv6 + cost: 30 + processes: + - area: + area_id: 0.0.0.2 + process_id: "LAB3" + name: GigabitEthernet0/0/0/0 + type: gigabitethernet +replaced: + commands: + - router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 cost 30 + - router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest + - router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest keychain ciscoiosxr + + after: + - address_family: + - afi: ipv4 + authentication: + message_digest: + keychain: ciscoiosxr + cost: 30 + processes: + - area: + area_id: 0.0.0.3 + process_id: "LAB3" + - afi: ipv6 + cost: 30 + processes: + - area: + area_id: 0.0.0.2 + process_id: "LAB3" + name: GigabitEthernet0/0/0/0 + type: gigabitethernet + +overridden: + commands: + - no router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 + - no router ospfv3 LAB3 area 0.0.0.2 interface GigabitEthernet 0/0/0/0 + - router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 cost 10 + - router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest + - router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest keychain iosxr + + after: + - address_family: + - afi: ipv4 + authentication: + message_digest: + keychain: iosxr + cost: 10 + processes: + - area: + area_id: 0.0.0.3 + process_id: "LAB1" + name: GigabitEthernet0/0/0/1 + type: gigabitethernet +deleted: + commands: + - no router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 + - no router ospfv3 LAB3 area 0.0.0.2 interface GigabitEthernet 0/0/0/0 + + after: [] +round_trip: + after: + - name: GigabitEthernet0/0/0/1 + type: gigabitethernet + address_family: + - afi: ipv4 + processes: + - process_id: "LAB1" + area: + area_id: 0.0.0.3 + cost: 10 + authentication: + message_digest: + keychain: iosxr diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/fixtures/parsed.cfg new file mode 100644 index 00000000..f3861f84 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/fixtures/parsed.cfg @@ -0,0 +1,42 @@ +Thu Jun 4 12:15:08.448 UTC +router ospf 10 + area 11 + cost 11 + default-cost 5 + ! + area 22 + default-cost 6 + ! +! +router ospf 26 + authentication message-digest keychain ansible1101pass + adjacency stagger 10 20 +! +router ospf 27 + area 10 + hello-interval 2 + ! +! +router ospf 30 + router-id 2.2.2.2 + summary-in enable + external-out disable + cost 2 + packet-size 577 + passive disable + priority 1 + mtu-ignore enable + flood-reduction disable + dead-interval 2 + retransmit-interval 2 + demand-circuit enable + hello-interval 1 + transmit-delay 2 + default-metric 10 + area 11 + default-cost 5 + ! + area 22 + default-cost 6 + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/_populate_config.yaml new file mode 100644 index 00000000..18322e6e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/_populate_config.yaml @@ -0,0 +1,46 @@ +--- +- name: Setup (populate ospfv2 routes) + cisco.iosxr.iosxr_ospfv2: + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - process_id: 26 + adjacency_stagger: + min_adjacency: 10 + max_adjacency: 20 + authentication: + message_digest: + keychain: "ansible1101pass" + - process_id: 10 + areas: + - area_id: 11 + default_cost: 5 + cost: 11 + - area_id: 22 + default_cost: 6 + - process_id: 30 + areas: + - area_id: 11 + default_cost: 5 + - area_id: 22 + default_cost: 6 + + cost: 2 + default_metric: 10 + transmit_delay: 2 + hello_interval: 1 + dead_interval: 2 + retransmit_interval: 2 + packet_size: 577 + priority: 1 + router_id: "2.2.2.2" + demand_circuit: enable + passive: disable + summary_in: enable + flood_reduction: disable + mtu_ignore: enable + external_out: disable + state: merged diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..db733bcc --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/_remove_config.yaml @@ -0,0 +1,7 @@ +--- +- name: Remove ospfv2 routes + vars: + lines: "no router ospf 26\n no router ospf 27\n no router ospf 30\n no router ospf 10\n " + ignore_errors: true + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/deleted.yaml new file mode 100644 index 00000000..9fb7bb8f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/deleted.yaml @@ -0,0 +1,76 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_ospfv2 deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete single OSPF process network + register: result + cisco.iosxr.iosxr_ospfv2: &id001 + config: + processes: + - process_id: 10 + - process_id: 26 + - process_id: 27 + - process_id: 30 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] == result['before'] }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] == result['after'] }}" + + - name: Delete a single OSPF process (idempotent) + register: result + cisco.iosxr.iosxr_ospfv2: *id001 + - ansible.builtin.assert: &id003 + that: + - result.changed == false + - result.commands|length == 0 + + - ansible.builtin.include_tasks: _populate_config.yaml + + - name: Delete all OSPF processes + register: result + cisco.iosxr.iosxr_ospfv2: &id002 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] == result['before'] }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] == result['after'] }}" + + - name: Delete all OSPF processes (idempotent) + register: result + cisco.iosxr.iosxr_ospfv2: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: *id003 + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] == result['before'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/empty_config.yaml new file mode 100644 index 00000000..4464f0cb --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv2 empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospfv2: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospfv2: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Parsed with empty running_config should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospfv2: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospfv2: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospfv2: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/gathered.yaml new file mode 100644 index 00000000..e2dcdbbf --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/gathered.yaml @@ -0,0 +1,18 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv2 gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Gather static routes facts from the device using iosxr_ospfv2 module + register: result + cisco.iosxr.iosxr_ospfv2: + state: gathered + + - ansible.builtin.assert: + that: "{{ replaced['before'] == result['gathered'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/merged.yaml new file mode 100644 index 00000000..2554f294 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/merged.yaml @@ -0,0 +1,124 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv2 merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_ospfv2: &id001 + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - process_id: 26 + adjacency_stagger: + min_adjacency: 10 + max_adjacency: 20 + authentication: + message_digest: + keychain: "ansible1101pass" + - process_id: 10 + areas: + - area_id: 11 + default_cost: 5 + cost: 11 + - area_id: 22 + default_cost: 6 + - process_id: 30 + areas: + - area_id: 11 + default_cost: 5 + - area_id: 22 + default_cost: 6 + + cost: 2 + default_metric: 10 + transmit_delay: 2 + hello_interval: 1 + dead_interval: 2 + retransmit_interval: 2 + packet_size: 577 + priority: 1 + router_id: "2.2.2.2" + demand_circuit: enable + passive: disable + summary_in: enable + flood_reduction: disable + mtu_ignore: enable + external_out: disable + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['before'] == result['before'] }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['after'] }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_ospfv2: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['before'] }}" + + - name: Update existing configuration using merged + register: result + cisco.iosxr.iosxr_ospfv2: &id002 + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - area_id: 30 + dead_interval: 4 + - process_id: 26 + adjacency_stagger: + min_adjacency: 11 + max_adjacency: 21 + authentication: + message_digest: + keychain: "ansible1101pass" + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] == result['before'] }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['update_commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['update_after'] == result['after'] }}" + + - name: Update existing ospfv2 configuration using merged (idempotent) + register: result + cisco.iosxr.iosxr_ospfv2: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/overridden.yaml new file mode 100644 index 00000000..61d12c06 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/overridden.yaml @@ -0,0 +1,60 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv2 overridden integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Overridde all ospfv2 configuration with provided configuration + register: result + cisco.iosxr.iosxr_ospfv2: &id001 + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - area_id: 20 + cost: 2 + default_cost: 2 + - process_id: 26 + adjacency_stagger: + min_adjacency: 10 + max_adjacency: 20 + authentication: + message_digest: + keychain: "ansible1101pass" + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] == result['before'] }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] == result['after'] }}" + + - name: Overridde all ospfv2 configuration with given configuration (idempotent) + register: result + cisco.iosxr.iosxr_ospfv2: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] == result['before'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/parsed.yaml new file mode 100644 index 00000000..cfa8ccc0 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/parsed.yaml @@ -0,0 +1,13 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv2 parsed integration tests on connection={{ ansible_connection }} + +- block: + - name: Use parsed state to convert externally supplied device specific ospfv2 routes commands to structured format + register: result + cisco.iosxr.iosxr_ospfv2: + running_config: "{{ lookup('file', '../../fixtures/parsed.cfg') }}" + state: parsed + + - ansible.builtin.assert: + that: "{{ merged['after'] == result['parsed'] }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/rendered.yaml new file mode 100644 index 00000000..b521881a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/rendered.yaml @@ -0,0 +1,67 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv2 rendered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Use rendered state to convert task input to device specific commands + register: result + cisco.iosxr.iosxr_ospfv2: + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - process_id: 26 + adjacency_stagger: + min_adjacency: 10 + max_adjacency: 20 + authentication: + message_digest: + keychain: "ansible1101pass" + - process_id: 10 + areas: + - area_id: 11 + default_cost: 5 + cost: 11 + - area_id: 22 + default_cost: 6 + - process_id: 30 + areas: + - area_id: 11 + default_cost: 5 + - area_id: 22 + default_cost: 6 + + cost: 2 + default_metric: 10 + transmit_delay: 2 + hello_interval: 1 + dead_interval: 2 + retransmit_interval: 2 + packet_size: 577 + priority: 1 + router_id: "2.2.2.2" + demand_circuit: enable + passive: disable + summary_in: enable + flood_reduction: disable + mtu_ignore: enable + external_out: disable + state: rendered + + - ansible.builtin.assert: + that: "{{ merged['commands'] | symmetric_difference(result['rendered']) |length==0 }}" + + - name: Gather static routes facts from the device and assert that its empty + register: result + cisco.iosxr.iosxr_ospfv2: + state: gathered + + - name: Make sure that rendered task actually did not make any changes to the device + ansible.builtin.assert: + that: "{{ result['gathered'] == {} }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/replaced.yaml new file mode 100644 index 00000000..d9aad879 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/replaced.yaml @@ -0,0 +1,60 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv2 replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replace device configurations of ospfv2 routes with provided configurations + register: result + cisco.iosxr.iosxr_ospfv2: &id001 + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - area_id: 20 + cost: 2 + default_cost: 2 + - process_id: 26 + adjacency_stagger: + min_adjacency: 10 + max_adjacency: 20 + authentication: + message_digest: + keychain: "ansible1101pass" + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] == result['before'] }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] == result['after'] }}" + + - name: Replace device configurations of listed vrfs/global entry with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_ospfv2: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] == result['before'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/rtt.yaml new file mode 100644 index 00000000..009fe56c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/tests/cli/rtt.yaml @@ -0,0 +1,98 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv2 round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Apply the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_ospfv2: + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - process_id: 26 + adjacency_stagger: + min_adjacency: 10 + max_adjacency: 20 + authentication: + message_digest: + keychain: "ansible1101pass" + - process_id: 10 + areas: + - area_id: 11 + default_cost: 5 + cost: 11 + - area_id: 22 + default_cost: 6 + - process_id: 30 + areas: + - area_id: 11 + default_cost: 5 + - area_id: 22 + default_cost: 6 + + cost: 2 + default_metric: 10 + transmit_delay: 2 + hello_interval: 1 + dead_interval: 2 + retransmit_interval: 2 + packet_size: 577 + priority: 1 + router_id: "2.2.2.2" + demand_circuit: enable + passive: disable + summary_in: enable + flood_reduction: disable + mtu_ignore: enable + external_out: disable + state: merged + + - name: Gather ospfv2 facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - ospfv2 + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_ospfv2: + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - area_id: 20 + cost: 2 + default_cost: 2 + - process_id: 26 + adjacency_stagger: + min_adjacency: 10 + max_adjacency: 20 + authentication: + message_digest: + keychain: "ansible1101pass" + state: overridden + + - name: Assert that changes were applied + ansible.builtin.assert: + that: "{{ round_trip['after'] == result['after'] }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_ospfv2: + config: "{{ ansible_facts['network_resources']['ospfv2'] }}" + state: overridden + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: "{{ base_config['after'] == revert['after'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/vars/main.yaml new file mode 100644 index 00000000..581b57ce --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv2/vars/main.yaml @@ -0,0 +1,316 @@ +--- +merged: + before: {} + commands: + - router ospf 10 + - area 11 default-cost 5 + - area 11 cost 11 + - area 22 default-cost 6 + - router ospf 27 + - area 10 hello-interval 2 + - router ospf 26 + - adjacency stagger 10 20 + - authentication message-digest keychain ansible1101pass + - router ospf 30 + - cost 2 + - passive disable + - priority 1 + - flood-reduction disable + - default-metric 10 + - router-id 2.2.2.2 + - demand-circuit enable + - packet-size 577 + - transmit-delay 2 + - summary-in enable + - external-out disable + - dead-interval 2 + - hello-interval 1 + - retransmit-interval 2 + - mtu-ignore enable + - area 11 default-cost 5 + - area 22 default-cost 6 + update_commands: + - router ospf 26 + - adjacency stagger 11 21 + - router ospf 27 + - area 30 dead-interval 4 + after: + processes: + - areas: + - area_id: "11" + cost: 11 + default_cost: 5 + - area_id: "22" + default_cost: 6 + process_id: "10" + + - adjacency_stagger: + max_adjacency: 20 + min_adjacency: 10 + authentication: + message_digest: + keychain: "ansible1101pass" + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + process_id: "27" + - areas: + - area_id: "11" + default_cost: 5 + - area_id: "22" + default_cost: 6 + cost: 2 + dead_interval: 2 + default_metric: 10 + demand_circuit: "enable" + external_out: "disable" + flood_reduction: "disable" + hello_interval: 1 + mtu_ignore: "enable" + packet_size: 577 + passive: "disable" + priority: 1 + process_id: "30" + retransmit_interval: 2 + router_id: "2.2.2.2" + summary_in: "enable" + transmit_delay: 2 + + update_after: + processes: + - areas: + - area_id: "11" + cost: 11 + default_cost: 5 + - area_id: "22" + default_cost: 6 + process_id: "10" + - adjacency_stagger: + max_adjacency: 21 + min_adjacency: 11 + authentication: + message_digest: + keychain: "ansible1101pass" + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + - area_id: "30" + dead_interval: 4 + process_id: "27" + - areas: + - area_id: "11" + default_cost: 5 + - area_id: "22" + default_cost: 6 + + cost: 2 + dead_interval: 2 + default_metric: 10 + demand_circuit: "enable" + external_out: "disable" + flood_reduction: "disable" + hello_interval: 1 + mtu_ignore: "enable" + packet_size: 577 + passive: "disable" + priority: 1 + process_id: "30" + retransmit_interval: 2 + router_id: "2.2.2.2" + summary_in: "enable" + transmit_delay: 2 +replaced: + before: + processes: + - areas: + - area_id: "11" + cost: 11 + default_cost: 5 + - area_id: "22" + default_cost: 6 + process_id: "10" + - adjacency_stagger: + max_adjacency: 20 + min_adjacency: 10 + authentication: + message_digest: + keychain: "ansible1101pass" + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + process_id: "27" + - areas: + - area_id: "11" + default_cost: 5 + - area_id: "22" + default_cost: 6 + cost: 2 + dead_interval: 2 + default_metric: 10 + demand_circuit: "enable" + external_out: "disable" + flood_reduction: "disable" + hello_interval: 1 + mtu_ignore: "enable" + packet_size: 577 + passive: "disable" + priority: 1 + process_id: "30" + retransmit_interval: 2 + router_id: "2.2.2.2" + summary_in: "enable" + transmit_delay: 2 + + commands: + - router ospf 27 + - area 20 default-cost 2 + - area 20 cost 2 + + after: + processes: + - areas: + - area_id: "11" + cost: 11 + default_cost: 5 + - area_id: "22" + default_cost: 6 + process_id: "10" + - adjacency_stagger: + max_adjacency: 20 + min_adjacency: 10 + authentication: + message_digest: + keychain: "ansible1101pass" + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + - area_id: "20" + cost: 2 + default_cost: 2 + process_id: "27" + - areas: + - area_id: "11" + default_cost: 5 + - area_id: "22" + default_cost: 6 + cost: 2 + dead_interval: 2 + default_metric: 10 + demand_circuit: "enable" + external_out: "disable" + flood_reduction: "disable" + hello_interval: 1 + mtu_ignore: "enable" + packet_size: 577 + passive: "disable" + priority: 1 + process_id: "30" + retransmit_interval: 2 + router_id: "2.2.2.2" + summary_in: "enable" + transmit_delay: 2 + +overridden: + commands: + - router ospf 10 + - no area 11 default-cost 5 + - no area 11 cost 11 + - no area 22 default-cost 6 + - router ospf 30 + - no cost 2 + - no passive disable + - no priority 1 + - no flood-reduction disable + - no default-metric 10 + - no router-id 2.2.2.2 + - no demand-circuit enable + - no packet-size 577 + - no transmit-delay 2 + - no summary-in enable + - no external-out disable + - no dead-interval 2 + - no hello-interval 1 + - no retransmit-interval 2 + - no mtu-ignore enable + - no area 11 default-cost 5 + - no area 22 default-cost 6 + - router ospf 27 + - area 20 default-cost 2 + - area 20 cost 2 + after: + processes: + - process_id: "10" + - adjacency_stagger: + max_adjacency: 20 + min_adjacency: 10 + authentication: + message_digest: + keychain: "ansible1101pass" + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + - area_id: "20" + cost: 2 + default_cost: 2 + process_id: "27" + - process_id: "30" +deleted: + commands: + - router ospf 10 + - no area 11 default-cost 5 + - no area 11 cost 11 + - no area 22 default-cost 6 + - router ospf 26 + - no adjacency stagger 10 20 + - no authentication message-digest keychain ansible1101pass + - router ospf 27 + - no area 10 hello-interval 2 + - router ospf 30 + - no cost 2 + - no passive disable + - no priority 1 + - no flood-reduction disable + - no default-metric 10 + - no router-id 2.2.2.2 + - no demand-circuit enable + - no packet-size 577 + - no transmit-delay 2 + - no summary-in enable + - no external-out disable + - no dead-interval 2 + - no hello-interval 1 + - no retransmit-interval 2 + - no mtu-ignore enable + - no area 11 default-cost 5 + - no area 22 default-cost 6 + + after: + processes: + - process_id: "10" + - process_id: "26" + - process_id: "27" + - process_id: "30" +round_trip: + after: + processes: + - process_id: "10" + - adjacency_stagger: + max_adjacency: 20 + min_adjacency: 10 + authentication: + message_digest: + keychain: "ansible1101pass" + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + - area_id: "20" + cost: 2 + default_cost: 2 + process_id: "27" + - process_id: "30" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/fixtures/parsed.cfg new file mode 100644 index 00000000..f0e69c9e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/fixtures/parsed.cfg @@ -0,0 +1,36 @@ +router ospfv3 10 + area 11 + cost 11 + default-cost 5 + ! + area 22 + default-cost 6 + ! +! +router ospfv3 26 + authentication disable +! +router ospfv3 27 + area 10 + hello-interval 2 + ! +! +router ospfv3 30 + router-id 2.2.2.2 + cost 2 + packet-size 577 + priority 1 + mtu-ignore + dead-interval 2 + retransmit-interval 2 + demand-circuit + hello-interval 1 + transmit-delay 2 + default-metric 10 + area 11 + default-cost 5 + ! + area 22 + default-cost 6 + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/_populate_config.yaml new file mode 100644 index 00000000..d90dafa4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/_populate_config.yaml @@ -0,0 +1,38 @@ +--- +- name: Setup (populate ospfv3 routes) + cisco.iosxr.iosxr_ospfv3: + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - process_id: 26 + authentication: + disable: true + - process_id: 10 + areas: + - area_id: 11 + default_cost: 5 + cost: 11 + - area_id: 22 + default_cost: 6 + - process_id: 30 + areas: + - area_id: 11 + default_cost: 5 + - area_id: 22 + default_cost: 6 + + cost: 2 + default_metric: 10 + transmit_delay: 2 + hello_interval: 1 + dead_interval: 2 + retransmit_interval: 2 + packet_size: 577 + priority: 1 + router_id: "2.2.2.2" + demand_circuit: true + mtu_ignore: true + state: merged diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..580027f6 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/_remove_config.yaml @@ -0,0 +1,7 @@ +--- +- name: Remove ospfv3 routes + vars: + lines: "no router ospfv3 26\n no router ospfv3 27\n no router ospfv3 30\n no router ospfv3 10\n " + ignore_errors: true + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/deleted.yaml new file mode 100644 index 00000000..f2652af6 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/deleted.yaml @@ -0,0 +1,76 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_ospfv3 deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete single OSPF process network + register: result + cisco.iosxr.iosxr_ospfv3: &id001 + config: + processes: + - process_id: 10 + - process_id: 26 + - process_id: 27 + - process_id: 30 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] == result['before'] }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] == result['after'] }}" + + - name: Delete a single OSPF process (idempotent) + register: result + cisco.iosxr.iosxr_ospfv3: *id001 + - ansible.builtin.assert: &id003 + that: + - result.changed == false + - result.commands|length == 0 + + - ansible.builtin.include_tasks: _populate_config.yaml + + - name: Delete all OSPF processes + register: result + cisco.iosxr.iosxr_ospfv3: &id002 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] == result['before'] }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] == result['after'] }}" + + - name: Delete all OSPF processes (idempotent) + register: result + cisco.iosxr.iosxr_ospfv3: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: *id003 + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] == result['before'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/empty_config.yaml new file mode 100644 index 00000000..3b56d814 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv3 empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospfv3: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospfv3: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Parsed with empty running_config should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospfv3: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospfv3: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_ospfv3: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/gathered.yaml new file mode 100644 index 00000000..1feedbb4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/gathered.yaml @@ -0,0 +1,20 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv3 gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Gather ospfv3 facts from the device using iosxr_ospfv3 module + register: result + cisco.iosxr.iosxr_ospfv3: + state: gathered + + - ansible.builtin.assert: + that: + - "{{ replaced['before'] == result['gathered'] }}" + - "result.changed == false" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/merged.yaml new file mode 100644 index 00000000..827d872f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/merged.yaml @@ -0,0 +1,112 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv3 merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_ospfv3: &id001 + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - process_id: 26 + authentication: + disable: true + - process_id: 10 + areas: + - area_id: 11 + default_cost: 5 + cost: 11 + - area_id: 22 + default_cost: 6 + - process_id: 30 + areas: + - area_id: 11 + default_cost: 5 + - area_id: 22 + default_cost: 6 + + cost: 2 + default_metric: 10 + transmit_delay: 2 + hello_interval: 1 + dead_interval: 2 + retransmit_interval: 2 + packet_size: 577 + priority: 1 + router_id: "2.2.2.2" + demand_circuit: true + mtu_ignore: true + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['before'] == result['before'] }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['after'] }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_ospfv3: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] == result['before'] }}" + + - name: Update existing configuration using merged + register: result + cisco.iosxr.iosxr_ospfv3: &id002 + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - area_id: 30 + dead_interval: 4 + - process_id: 26 + authentication: + disable: true + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] == result['before'] }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['update_commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['update_after'] == result['after'] }}" + + - name: Update existing ospfv3 configuration using merged (idempotent) + register: result + cisco.iosxr.iosxr_ospfv3: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/overridden.yaml new file mode 100644 index 00000000..7f485291 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/overridden.yaml @@ -0,0 +1,56 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv3 overridden integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Overridde all ospfv3 configuration with provided configuration + register: result + cisco.iosxr.iosxr_ospfv3: &id001 + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - area_id: 20 + cost: 2 + default_cost: 2 + - process_id: 26 + authentication: + disable: true + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] == result['before'] }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] == result['after'] }}" + + - name: Overridde all ospfv3 configuration with given configuration (idempotent) + register: result + cisco.iosxr.iosxr_ospfv3: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] == result['before'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/parsed.yaml new file mode 100644 index 00000000..c9b0e46b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/parsed.yaml @@ -0,0 +1,15 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv3 parsed integration tests on connection={{ ansible_connection }} + +- block: + - name: Use parsed state to convert externally supplied device specific ospfv3 routes commands to structured format + register: result + cisco.iosxr.iosxr_ospfv3: + running_config: "{{ lookup('file', '../../fixtures/parsed.cfg') }}" + state: parsed + + - ansible.builtin.assert: + that: + - "{{ merged['after'] == result['parsed'] }}" + - "result.changed == false" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/rendered.yaml new file mode 100644 index 00000000..c9960da0 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/rendered.yaml @@ -0,0 +1,63 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv3 rendered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Use rendered state to convert task input to device specific commands + register: result + cisco.iosxr.iosxr_ospfv3: + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - process_id: 26 + authentication: + disable: true + - process_id: 10 + areas: + - area_id: 11 + default_cost: 5 + cost: 11 + - area_id: 22 + default_cost: 6 + - process_id: 30 + areas: + - area_id: 11 + default_cost: 5 + - area_id: 22 + default_cost: 6 + + cost: 2 + default_metric: 10 + transmit_delay: 2 + hello_interval: 1 + dead_interval: 2 + retransmit_interval: 2 + packet_size: 577 + priority: 1 + router_id: "2.2.2.2" + demand_circuit: true + passive: false + flood_reduction: false + mtu_ignore: true + state: rendered + + - ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['rendered']) |length==0 }}" + - "result.changed == false" + + - name: Gather ospfv3 facts from the device and assert that its empty + register: result + cisco.iosxr.iosxr_ospfv3: + state: gathered + + - name: Make sure that rendered task actually did not make any changes to the device + ansible.builtin.assert: + that: "{{ result['gathered'] == {} }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/replaced.yaml new file mode 100644 index 00000000..4cf49d2b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/replaced.yaml @@ -0,0 +1,56 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv3 replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replace device configurations of ospfv3 routes with provided configurations + register: result + cisco.iosxr.iosxr_ospfv3: &id001 + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - area_id: 20 + cost: 2 + default_cost: 2 + - process_id: 26 + authentication: + disable: true + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] == result['before'] }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] == result['after'] }}" + + - name: Replace device configurations of listed vrfs/global entry with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_ospfv3: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] == result['before'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/rtt.yaml new file mode 100644 index 00000000..10b8d399 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/tests/cli/rtt.yaml @@ -0,0 +1,88 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_ospfv3 round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Apply the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_ospfv3: + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - process_id: 26 + authentication: + disable: true + - process_id: 10 + areas: + - area_id: 11 + default_cost: 5 + cost: 11 + - area_id: 22 + default_cost: 6 + - process_id: 30 + areas: + - area_id: 11 + default_cost: 5 + - area_id: 22 + default_cost: 6 + + cost: 2 + default_metric: 10 + transmit_delay: 2 + hello_interval: 1 + dead_interval: 2 + retransmit_interval: 2 + packet_size: 577 + priority: 1 + router_id: "2.2.2.2" + demand_circuit: true + passive: false + flood_reduction: false + mtu_ignore: true + state: merged + + - name: Gather ospfv3 facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - ospfv3 + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_ospfv3: + config: + processes: + - process_id: 27 + areas: + - area_id: 10 + hello_interval: 2 + - area_id: 20 + cost: 2 + default_cost: 2 + - process_id: 26 + authentication: + disable: true + state: overridden + + - name: Assert that changes were applied + ansible.builtin.assert: + that: "{{ round_trip['after'] == result['after'] }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_ospfv3: + config: "{{ ansible_facts['network_resources']['ospfv3'] }}" + state: overridden + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: "{{ base_config['after'] == revert['after'] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/vars/main.yaml new file mode 100644 index 00000000..a1038098 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ospfv3/vars/main.yaml @@ -0,0 +1,260 @@ +--- +merged: + before: {} + commands: + - router ospfv3 10 + - area 11 default-cost 5 + - area 11 cost 11 + - area 22 default-cost 6 + - router ospfv3 27 + - area 10 hello-interval 2 + - router ospfv3 26 + - authentication disable + - router ospfv3 30 + - cost 2 + - priority 1 + - default-metric 10 + - router-id 2.2.2.2 + - demand-circuit + - packet-size 577 + - transmit-delay 2 + - dead-interval 2 + - hello-interval 1 + - retransmit-interval 2 + - mtu-ignore + - area 11 default-cost 5 + - area 22 default-cost 6 + update_commands: + - router ospfv3 27 + - area 30 dead-interval 4 + after: + processes: + - areas: + - area_id: "11" + cost: 11 + default_cost: 5 + - area_id: "22" + default_cost: 6 + process_id: "10" + + - authentication: + disable: true + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + process_id: "27" + - areas: + - area_id: "11" + default_cost: 5 + - area_id: "22" + default_cost: 6 + cost: 2 + dead_interval: 2 + default_metric: 10 + demand_circuit: true + hello_interval: 1 + mtu_ignore: true + packet_size: 577 + priority: 1 + process_id: "30" + retransmit_interval: 2 + router_id: "2.2.2.2" + transmit_delay: 2 + + update_after: + processes: + - areas: + - area_id: "11" + cost: 11 + default_cost: 5 + - area_id: "22" + default_cost: 6 + process_id: "10" + - authentication: + disable: true + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + - area_id: "30" + dead_interval: 4 + process_id: "27" + - areas: + - area_id: "11" + default_cost: 5 + - area_id: "22" + default_cost: 6 + + cost: 2 + dead_interval: 2 + default_metric: 10 + demand_circuit: true + hello_interval: 1 + mtu_ignore: true + packet_size: 577 + priority: 1 + process_id: "30" + retransmit_interval: 2 + router_id: "2.2.2.2" + transmit_delay: 2 +replaced: + before: + processes: + - areas: + - area_id: "11" + cost: 11 + default_cost: 5 + - area_id: "22" + default_cost: 6 + process_id: "10" + - authentication: + disable: true + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + process_id: "27" + - areas: + - area_id: "11" + default_cost: 5 + - area_id: "22" + default_cost: 6 + cost: 2 + dead_interval: 2 + default_metric: 10 + demand_circuit: true + hello_interval: 1 + mtu_ignore: true + packet_size: 577 + priority: 1 + process_id: "30" + retransmit_interval: 2 + router_id: "2.2.2.2" + transmit_delay: 2 + + commands: + - router ospfv3 27 + - area 20 default-cost 2 + - area 20 cost 2 + + after: + processes: + - areas: + - area_id: "11" + cost: 11 + default_cost: 5 + - area_id: "22" + default_cost: 6 + process_id: "10" + - authentication: + disable: true + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + - area_id: "20" + cost: 2 + default_cost: 2 + process_id: "27" + - areas: + - area_id: "11" + default_cost: 5 + - area_id: "22" + default_cost: 6 + cost: 2 + dead_interval: 2 + default_metric: 10 + demand_circuit: true + hello_interval: 1 + mtu_ignore: true + packet_size: 577 + priority: 1 + process_id: "30" + retransmit_interval: 2 + router_id: "2.2.2.2" + transmit_delay: 2 + +overridden: + commands: + - router ospfv3 10 + - no area 11 default-cost 5 + - no area 11 cost 11 + - no area 22 default-cost 6 + - router ospfv3 30 + - no cost 2 + - no priority 1 + - no default-metric 10 + - no router-id 2.2.2.2 + - no demand-circuit + - no packet-size 577 + - no transmit-delay 2 + - no dead-interval 2 + - no hello-interval 1 + - no retransmit-interval 2 + - no mtu-ignore + - no area 11 default-cost 5 + - no area 22 default-cost 6 + - router ospfv3 27 + - area 20 default-cost 2 + - area 20 cost 2 + after: + processes: + - process_id: "10" + - authentication: + disable: true + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + - area_id: "20" + cost: 2 + default_cost: 2 + process_id: "27" + - process_id: "30" +deleted: + commands: + - router ospfv3 10 + - no area 11 default-cost 5 + - no area 11 cost 11 + - no area 22 default-cost 6 + - router ospfv3 26 + - no authentication disable + - router ospfv3 27 + - no area 10 hello-interval 2 + - router ospfv3 30 + - no cost 2 + - no priority 1 + - no default-metric 10 + - no router-id 2.2.2.2 + - no demand-circuit + - no packet-size 577 + - no transmit-delay 2 + - no dead-interval 2 + - no hello-interval 1 + - no retransmit-interval 2 + - no mtu-ignore + - no area 11 default-cost 5 + - no area 22 default-cost 6 + + after: + processes: + - process_id: "10" + - process_id: "26" + - process_id: "27" + - process_id: "30" +round_trip: + after: + processes: + - process_id: "10" + - authentication: + disable: true + process_id: "26" + - areas: + - area_id: "10" + hello_interval: 2 + - area_id: "20" + cost: 2 + default_cost: 2 + process_id: "27" + - process_id: "30" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/defaults/main.yaml new file mode 100644 index 00000000..9ef5ba51 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/tests/cli/ping.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/tests/cli/ping.yaml new file mode 100644 index 00000000..6c47cb95 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_ping/tests/cli/ping.yaml @@ -0,0 +1,51 @@ +--- +- ansible.builtin.debug: msg="START cli/ping.yaml on connection={{ ansible_connection }}" + +- register: show_version_result + cisco.iosxr.iosxr_command: + commands: show version + +- ansible.builtin.set_fact: management_interface=GigabitEthernet0/0 + when: "'Cisco IOSXR' in show_version_result.stdout[0]" + +- ansible.builtin.set_fact: management_interface=GigabitEthernet1 + when: "'Cisco IOS-XR' in show_version_result.stdout[0]" + +- name: Get show IP management interface output + register: show_ip_interface_result + cisco.iosxr.iosxr_command: + commands: + - show ip interface {{ management_interface }} | include Internet address + +- name: Extract the IP address from registered output + ansible.builtin.set_fact: management_ip="{{ show_ip_interface_result.stdout[0].split()[-1].split('/')[0]}}" + +- name: Expected successful ping + register: esp + cisco.iosxr.iosxr_ping: + dest: "{{ management_ip }}" + +- name: Unexpected unsuccessful ping + register: uup + ignore_errors: true + cisco.iosxr.iosxr_ping: + dest: 10.255.255.250 + +- name: Unexpected successful ping + register: usp + ignore_errors: true + cisco.iosxr.iosxr_ping: + dest: "{{ management_ip }}" + state: absent + +- name: Expected unsuccessful ping + register: eup + cisco.iosxr.iosxr_ping: + dest: 10.255.255.250 + state: absent + +- name: Assert + ansible.builtin.assert: + that: + - esp.failed == eup.failed == false + - usp.failed == uup.failed == true diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/_populate_config.yaml new file mode 100644 index 00000000..1782148a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/_populate_config.yaml @@ -0,0 +1,22 @@ +--- +- name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_prefix_lists: + config: + - afi: ipv6 + prefix_lists: + - name: pl_1 + entries: + - prefix: 2001:db8:1234::/48 + action: deny + sequence: 1 + - afi: ipv4 + prefix_lists: + - name: pl1 + entries: + - sequence: 3 + action: remark + description: TEST_PL1_2_REMARK + - sequence: 4 + action: permit + prefix: 10.0.0.0/24 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..4470966a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/_remove_config.yaml @@ -0,0 +1,5 @@ +--- +- name: Delete all prefix-lists from the device + register: result + cisco.iosxr.iosxr_prefix_lists: + state: deleted diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/deleted.yaml new file mode 100644 index 00000000..1f7b9d90 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/deleted.yaml @@ -0,0 +1,60 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_prefix_list deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete prefix-list by afi. + register: result + cisco.iosxr.iosxr_prefix_lists: &id001 + config: + - afi: ipv6 + state: deleted + + - ansible.builtin.assert: + that: + - '"no ipv6 prefix-list pl_1" in result.commands' + - result.commands|length == 1 + + - name: Delete a single prefix-list by name (idempotent) + register: result + cisco.iosxr.iosxr_prefix_lists: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + - result.commands|length == 0 + + - ansible.builtin.include_tasks: _populate_config.yaml + + - name: Delete all prefix-lists from the device + register: result + cisco.iosxr.iosxr_prefix_lists: &id002 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Delete all prefix_lists from the device (idempotent) + register: result + cisco.iosxr.iosxr_prefix_lists: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result.changed == false + - result.commands|length == 0 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/empty_config.yaml new file mode 100644 index 00000000..d2f3c00b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/empty_config.yaml @@ -0,0 +1,58 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_prefix_lists empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_prefix_lists: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_prefix_lists: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_prefix_lists: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_prefix_lists: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_prefix_lists: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/fixtures/parsed.cfg new file mode 100644 index 00000000..a8d69e9b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/fixtures/parsed.cfg @@ -0,0 +1,7 @@ +ipv6 prefix-list pl1 + 1 remark test +! +ipv4 prefix-list pl2 + 1 deny 35.0.0.0/8 + 2 deny 10.0.0.0/24 +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/gathered.yaml new file mode 100644 index 00000000..76c386b6 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/gathered.yaml @@ -0,0 +1,19 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_prefix_lists gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Gather ACL interfaces facts using gathered state + register: result + cisco.iosxr.iosxr_prefix_lists: + state: gathered + + - name: Assert that facts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] | symmetric_difference(result['gathered']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/merged.yaml new file mode 100644 index 00000000..2850388b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/merged.yaml @@ -0,0 +1,61 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_prefix_lists merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_prefix_lists: &id001 + config: + - afi: ipv6 + prefix_lists: + - name: pl_1 + entries: + - prefix: 2001:db8:1234::/48 + action: deny + sequence: 1 + - afi: ipv4 + prefix_lists: + - name: pl1 + entries: + - sequence: 3 + action: remark + description: TEST_PL1_2_REMARK + - sequence: 4 + action: permit + prefix: 10.0.0.0/24 + + state: merged + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['before'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_prefix_lists: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/overridden.yaml new file mode 100644 index 00000000..5bb6db4d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/overridden.yaml @@ -0,0 +1,55 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_prefix_lists overridden integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Overridde all prefix_lists configuration with provided configuration + register: result + cisco.iosxr.iosxr_prefix_lists: &id001 + config: + - afi: ipv4 + prefix_lists: + - name: pl3 + entries: + - sequence: 3 + action: remark + description: TEST_PL1_3_REMARK + - sequence: 4 + action: permit + prefix: 10.0.0.0/24 + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Overridde all interface lag interface configuration with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_prefix_lists: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/parsed.yaml new file mode 100644 index 00000000..5e639264 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_prefix_lists parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided prefix_lists configuration to agnostic model + register: result + cisco.iosxr.iosxr_prefix_lists: + running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - "{{ parsed | symmetric_difference(result['parsed']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/rendered.yaml new file mode 100644 index 00000000..3568ac8b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/rendered.yaml @@ -0,0 +1,32 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_prefix_lists rendered integration tests on connection={{ ansible_connection }} + +- name: Render platform specific commands from task input using rendered state + register: result + cisco.iosxr.iosxr_prefix_lists: + config: + - afi: ipv6 + prefix_lists: + - name: pl_1 + entries: + - prefix: 2001:db8:1234::/48 + action: deny + sequence: 1 + - afi: ipv4 + prefix_lists: + - name: pl1 + entries: + - sequence: 3 + action: remark + description: TEST_PL1_2_REMARK + - sequence: 4 + action: permit + prefix: 10.0.0.0/24 + + state: rendered + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['rendered']) |length == 0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/replaced.yaml new file mode 100644 index 00000000..eb35e084 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/replaced.yaml @@ -0,0 +1,54 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_prefix_lists replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replace device configurations of listed ACL with provided configurations + register: result + cisco.iosxr.iosxr_prefix_lists: &id001 + config: + - afi: ipv4 + prefix_lists: + - name: pl1 + entries: + - sequence: 3 + action: permit + prefix: 10.0.0.0/24 + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + - ansible.builtin.debug: + msg: "{{ replaced['after'] | symmetric_difference(result['after']) }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Replace device configurations of listed interfaces with provided configurarions (idempotent) + register: result + cisco.iosxr.iosxr_prefix_lists: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/rtt.yaml new file mode 100644 index 00000000..bf00d14d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/tests/cli/rtt.yaml @@ -0,0 +1,81 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_prefix_lists round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Apply the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_prefix_lists: + config: + - afi: ipv6 + prefix_lists: + - name: pl1_1 + entries: + - prefix: 2001:db8:1234::/48 + action: deny + sequence: 1 + - name: pl1_2 + entries: + - sequence: 2 + action: remark + description: TEST_PL1_2_REMARK + - afi: ipv4 + prefix_lists: + - name: pl1 + entries: + - sequence: 3 + action: remark + description: TEST_PL1_REMARK + - sequence: 4 + action: permit + prefix: 10.0.0.0/24 + - name: pl2 + entries: + - sequence: 5 + action: remark + description: TEST_PL2_REMARK + + state: merged + + - name: Gather interfaces facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - prefix_lists + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_prefix_lists: + config: + - afi: ipv4 + prefix_lists: + - name: pl3 + entries: + - sequence: 3 + action: remark + description: TEST_PL1_3_REMARK + - sequence: 4 + action: permit + prefix: 10.0.0.0/24 + + state: overridden + + - name: Assert that changes were applied + ansible.builtin.assert: + that: "{{ overridden['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_prefix_lists: + config: "{{ ansible_facts['network_resources']['prefix_lists'] }}" + state: overridden + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: "{{ base_config['after'] | symmetric_difference(revert['after']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/vars/main.yaml new file mode 100644 index 00000000..8db2ca54 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_prefix_lists/vars/main.yaml @@ -0,0 +1,87 @@ +--- +merged: + before: [] + commands: + - ipv6 prefix-list pl_1 1 deny 2001:db8:1234::/48 + - ipv4 prefix-list pl1 3 remark TEST_PL1_2_REMARK + - ipv4 prefix-list pl1 4 permit 10.0.0.0/24 + after: + - prefix_lists: + - entries: + - sequence: 3 + action: remark + description: TEST_PL1_2_REMARK + - sequence: 4 + action: permit + prefix: 10.0.0.0/24 + name: pl1 + afi: ipv4 + - prefix_lists: + - entries: + - prefix: 2001:db8:1234::/48 + action: deny + sequence: 1 + name: pl_1 + afi: ipv6 + +replaced: + commands: + - no ipv4 prefix-list pl1 3 remark TEST_PL1_2_REMARK + - no ipv4 prefix-list pl1 4 permit 10.0.0.0/24 + - ipv4 prefix-list pl1 3 permit 10.0.0.0/24 + + after: + - prefix_lists: + - entries: + - prefix: "2001:db8:1234::/48" + action: "deny" + sequence: 1 + name: "pl_1" + afi: "ipv6" + - prefix_lists: + - entries: + - sequence: 3 + action: "permit" + prefix: "10.0.0.0/24" + name: "pl1" + afi: "ipv4" +overridden: + commands: + - no ipv6 prefix-list pl_1 + - no ipv4 prefix-list pl1 + - ipv4 prefix-list pl3 3 remark TEST_PL1_3_REMARK + - ipv4 prefix-list pl3 4 permit 10.0.0.0/24 + after: + - afi: ipv4 + prefix_lists: + - name: pl3 + entries: + - sequence: 3 + action: remark + description: TEST_PL1_3_REMARK + - sequence: 4 + action: permit + prefix: 10.0.0.0/24 +deleted: + commands: + - no ipv6 prefix-list pl_1 + - no ipv4 prefix-list pl1 + after: [] +parsed: + - afi: ipv6 + prefix_lists: + - name: pl1 + entries: + - action: remark + description: test + sequence: 1 + - afi: ipv4 + prefix_lists: + - name: pl2 + entries: + - action: deny + prefix: 35.0.0.0/8 + sequence: 1 + - action: deny + prefix: 10.0.0.0/24 + sequence: 2 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/defaults/main.yaml new file mode 100644 index 00000000..9ef5ba51 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/meta/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/meta/main.yaml new file mode 100644 index 00000000..be631e5d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_iosxr_tests diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tasks/cli.yaml new file mode 100644 index 00000000..f0489b91 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tasks/cli.yaml @@ -0,0 +1,28 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + with_items: "{{ test_items }}" + vars: + ansible_connection: ansible.netcommon.network_cli + loop_control: + loop_var: test_case_to_run + tags: + - network_cli + +- name: Run test cases with single_user_mode (connection=network_cli) + ansible.builtin.include_tasks: "{{ role_path }}/tests/cli/caching.yaml" + vars: + ansible_connection: ansible.netcommon.network_cli + ansible_network_single_user_mode: true + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tasks/main.yaml new file mode 100644 index 00000000..419a6cde --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tasks/main.yaml @@ -0,0 +1,6 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + +- name: Include the netconf tasks + ansible.builtin.include_tasks: netconf.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tasks/netconf.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tasks/netconf.yaml new file mode 100644 index 00000000..7488554f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tasks/netconf.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all netconf test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/netconf" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test cases (connection=netconf) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.netconf + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - netconf diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tests/cli/caching.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tests/cli/caching.yaml new file mode 100644 index 00000000..3ff359ca --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tests/cli/caching.yaml @@ -0,0 +1,127 @@ +--- +- block: + - ansible.builtin.debug: msg="START connection={{ ansible_connection }} cli/caching.yaml" + + - name: Remove interfaces from configuration before actual testing + ignore_errors: true + cisco.iosxr.iosxr_config: &rem + lines: + - no interface GigabitEthernet 0/0/0/1 + - no interface GigabitEthernet 0/0/0/2 + - no interface GigabitEthernet 0/0/0/4 + match: none + + # We need to do this because of a bug in iosxr_interfaces module + # https://github.com/ansible-collections/cisco.iosxr/issues/106 + - name: Add back interfaces to configuration before actual testing + ignore_errors: true + cisco.iosxr.iosxr_config: + lines: shutdown + parents: "interface GigabitEthernet {{ intf }}" + match: none + with_items: + - "0/0/0/1" + - "0/0/0/2" + - "0/0/0/4" + loop_control: + loop_var: intf + + - name: Merge base interfaces configuration + register: result + cisco.iosxr.iosxr_interfaces: &merged + config: + - name: GigabitEthernet0/0/0/1 + description: Configured by Ansible + mtu: 110 + enabled: true + duplex: half + + - name: GigabitEthernet0/0/0/2 + description: Configured by Ansible + mtu: 2800 + speed: 100 + enabled: true + duplex: full + state: merged + + - ansible.builtin.assert: + that: + - '"interface GigabitEthernet0/0/0/1" in result.commands' + - '"description Configured by Ansible" in result.commands' + - '"mtu 110" in result.commands' + - '"duplex half" in result.commands' + - '"no shutdown" in result.commands' + - '"interface GigabitEthernet0/0/0/2" in result.commands' + - '"description Configured by Ansible" in result.commands' + - '"mtu 2800" in result.commands' + - '"speed 100" in result.commands' + - '"duplex full" in result.commands' + - '"no shutdown" in result.commands' + - result.commands|length == 11 + + - name: Merge base interfaces configuration (idempotent) + register: result + cisco.iosxr.iosxr_interfaces: *merged + - ansible.builtin.assert: + that: + - result.changed == False + + - name: Merge layer 2 interfaces configuration + register: result + cisco.iosxr.iosxr_l2_interfaces: &mergedl2 + config: + - name: GigabitEthernet0/0/0/1 + l2transport: true + l2protocol: + - cpsv: drop + propagate: true + + - name: GigabitEthernet0/0/0/4.1 + encapsulation: + dot1q: 20 + second_dot1q: 40 + + state: merged + + - ansible.builtin.assert: + that: + - '"interface GigabitEthernet0/0/0/1" in result.commands' + - '"l2transport l2protocol cpsv drop" in result.commands' + - '"l2transport propagate remote-status" in result.commands' + - '"interface GigabitEthernet0/0/0/4.1" in result.commands' + - '"encapsulation dot1q 20 second-dot1q 40" in result.commands' + - result.commands|length == 5 + + - name: Merge layer 2 interfaces configuration (idempotent) + register: result + cisco.iosxr.iosxr_l2_interfaces: *mergedl2 + - ansible.builtin.assert: + that: + - result.changed == False + + - name: Merge layer 3 interfaces configuration + register: result + cisco.iosxr.iosxr_l3_interfaces: &mergedl3 + config: + - name: GigabitEthernet0/0/0/2 + ipv4: + - address: 198.51.100.1/24 + state: merged + + - ansible.builtin.assert: + that: + - '"interface GigabitEthernet0/0/0/2" in result.commands' + - '"ipv4 address 198.51.100.1 255.255.255.0" in result.commands' + - result.commands|length == 2 + + - name: Merge layer 3 interfaces configuration (idempotent) + register: result + cisco.iosxr.iosxr_l3_interfaces: *mergedl3 + - ansible.builtin.assert: + that: + - result.changed == False + + always: + - name: Cleanup + cisco.iosxr.iosxr_config: *rem + when: ansible_connection == "ansible.netcommon.network_cli" and ansible_network_single_user_mode|d(False) diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tests/cli/common_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tests/cli/common_config.yaml new file mode 100644 index 00000000..6b2376cd --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tests/cli/common_config.yaml @@ -0,0 +1,105 @@ +--- +- ansible.builtin.debug: msg="START cli/common_config.yaml on connection={{ ansible_connection }}" + +# Sublevel / Block +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.2 any log + - 30 permit ipv4 host 192.0.2.3 any log + parents: + - "ipv4 access-list test" + before: + - "no ipv4 access-list test" + match: none + +- name: Configure sub level command using block resplace + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.2 any log + - 30 permit ipv4 host 192.0.2.3 any log + - 40 permit ipv4 host 192.0.2.4 any log + parents: + - "ipv4 access-list test" + replace: block + register: result + +- ansible.builtin.assert: + that: + - "result.changed == true" + - "'ipv4 access-list test' in result.commands" + - "'10 permit ipv4 host 192.0.2.1 any log' in result.commands" + - "'20 permit ipv4 host 192.0.2.2 any log' in result.commands" + - "'30 permit ipv4 host 192.0.2.3 any log' in result.commands" + - "'40 permit ipv4 host 192.0.2.4 any log' in result.commands" + +- name: Check sub level command using block replace + cisco.iosxr.iosxr_config: + commands: + - 10 permit ipv4 host 192.0.2.1 any log + - 20 permit ipv4 host 192.0.2.2 any log + - 30 permit ipv4 host 192.0.2.3 any log + - 40 permit ipv4 host 192.0.2.4 any log + parents: + - "ipv4 access-list test" + replace: block + register: result + +- ansible.builtin.assert: + that: + - "result.changed == false" + +- name: Teardown + cisco.iosxr.iosxr_config: + commands: + - "no ipv4 access-list test" + match: none + +# diff exact, strict, line +- name: Setup + cisco.iosxr.iosxr_config: + commands: + - "hostname {{ inventory_hostname_short }}" + register: result + +- name: Set hostname + cisco.iosxr.iosxr_config: + commands: + - hostname testhost + match: strict + register: result + +- cisco.iosxr.iosxr_command: + commands: + - show configuration running-config hostname + register: configured_hostname + +- ansible.builtin.assert: + that: + - "'testhost' in configured_hostname.stdout[0]" + +- name: Set hostname + cisco.iosxr.iosxr_config: + commands: + - hostname testhost2 + match: exact + register: result + +- cisco.iosxr.iosxr_command: + commands: + - show configuration running-config hostname + register: configured_hostname + +- ansible.builtin.assert: + that: + - "'testhost2' in configured_hostname.stdout[0]" + +- name: Teardown + cisco.iosxr.iosxr_config: + commands: + - "hostname {{ inventory_hostname_short }}" + register: result + +- ansible.builtin.debug: msg="END cli/common_config.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tests/netconf/common_netconf.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tests/netconf/common_netconf.yaml new file mode 100644 index 00000000..2ab0957a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_smoke/tests/netconf/common_netconf.yaml @@ -0,0 +1,46 @@ +--- +- ansible.builtin.debug: msg="START iosxr netconf/common_netconf.yaml on connection={{ ansible_connection }}" + +# hit general code +- name: Setup - remove login + cisco.iosxr.iosxr_banner: + banner: login + state: absent + +- name: Set login + cisco.iosxr.iosxr_banner: + banner: login + text: "@this is my login banner\nthat has a multiline\nstring\n@" + state: present + register: result + +- ansible.builtin.debug: + msg: "{{ result }}" + +- ansible.builtin.assert: + that: + - "result.changed == true" + - "'this is my login banner' in result.xml" + - "'that has a multiline' in result.xml" + +# hit etree_findall() +- name: Remove host logging + cisco.iosxr.iosxr_logging: + dest: host + name: 172.16.0.1 + state: absent + +- name: Set up syslog host logging + cisco.iosxr.iosxr_logging: + dest: host + name: 172.16.0.1 + level: errors + state: present + register: result + +- ansible.builtin.assert: + that: + - "result.changed == true" + - '"172.16.0.1" in result.xml[0]' + +- ansible.builtin.debug: msg="END iosxr netconf/common_netconf.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/defaults/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/defaults/main.yml new file mode 100644 index 00000000..871ea460 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/defaults/main.yml @@ -0,0 +1,2 @@ +--- +testcase: "[^_].*" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/meta/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/meta/main.yml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/meta/main.yml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tasks/cli.yaml new file mode 100644 index 00000000..a1b57ab4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tasks/cli.yaml @@ -0,0 +1,21 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tasks/main.yaml new file mode 100644 index 00000000..f75f2f03 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/_parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/_parsed.cfg new file mode 100644 index 00000000..fd40661b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/_parsed.cfg @@ -0,0 +1,54 @@ +snmp-server vrf vrf1 + host 1.1.1.1 traps test1 +! +snmp-server drop report acl IPv4 test1 +snmp-server drop unknown-user +snmp-server ipv4 dscp af11 +snmp-server ipv6 precedence routine +snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 +snmp-server community test2 RO SDROwner IPv4 test IPv6 test1 +snmp-server queue-length 2 +snmp-server trap-timeout 3 +snmp-server trap throttle-time 12 +snmp-server traps bfd +snmp-server traps bgp cbgp2 +snmp-server traps copy-complete +snmp-server traps hsrp +snmp-server traps ipsla +snmp-server traps msdp peer-state-change +snmp-server traps ipsec tunnel stop +snmp-server traps ipsec tunnel start +snmp-server traps config +snmp-server traps l2tun sessions +snmp-server traps l2tun tunnel-up +snmp-server traps l2tun tunnel-down +snmp-server traps bulkstat collection +snmp-server traps l2vpn all +snmp-server traps l2vpn vc-up +snmp-server traps l2vpn vc-down +snmp-server traps bridgemib +snmp-server traps addrpool low +snmp-server traps addrpool high +snmp-server traps cisco-entity-ext +snmp-server chassis-id test2 +snmp-server contact t1 +snmp-server location test1 +snmp-server target list test host 1.1.1.2 +snmp-server context c1 +snmp-server context c2 +snmp-server logging threshold oid-processing 1 +snmp-server logging threshold pdu-processing 1 +snmp-server mib bulkstat max-procmem-size 101 +snmp-server timeouts duplicate 0 +snmp-server timeouts inQdrop 0 +snmp-server packetsize 490 +snmp-server correlator buffer-size 1024 +snmp-server trap-source GigabitEthernet0/0/0/2 +snmp-server throttle-time 60 +snmp-server community-map cm1 context c1 security-name s1 target-list t1 +snmp-server inform retries 7 +snmp-server overload-control 4 6 +snmp-server ifmib internal cache max-duration 4 +snmp-server mroutemib send-all-vrf +snmp-server notification-log-mib size 5 +snmp-server notification-log-mib GlobalSize 5 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/_populate_config.yaml new file mode 100644 index 00000000..550c7bcf --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/_populate_config.yaml @@ -0,0 +1,59 @@ +--- +- name: "Setup" + cisco.iosxr.iosxr_config: + lines: + - "snmp-server vrf vrf1" + - " host 1.1.1.1 traps test1" + - "snmp-server drop report acl IPv4 test1" + - "snmp-server drop unknown-user" + - "snmp-server ipv4 dscp af11" + - "snmp-server ipv6 precedence routine" + - "snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2" + - "snmp-server community test2 RO SDROwner IPv4 test IPv6 test1" + - "snmp-server queue-length 2" + - "snmp-server trap-timeout 3" + - "snmp-server trap throttle-time 12" + - "snmp-server traps bfd" + - "snmp-server traps bgp cbgp2" + - "snmp-server traps copy-complete" + - "snmp-server traps hsrp" + - "snmp-server traps ipsla" + - "snmp-server traps msdp peer-state-change" + - "snmp-server traps ipsec tunnel stop" + - "snmp-server traps ipsec tunnel start" + - "snmp-server traps config" + - "snmp-server traps l2tun sessions" + - "snmp-server traps l2tun tunnel-up" + - "snmp-server traps l2tun tunnel-down" + - "snmp-server traps bulkstat collection" + - "snmp-server traps l2vpn all" + - "snmp-server traps l2vpn vc-up" + - "snmp-server traps l2vpn vc-down" + - "snmp-server traps bridgemib" + - "snmp-server traps addrpool low" + - "snmp-server traps addrpool high" + - "snmp-server traps cisco-entity-ext" + - "snmp-server chassis-id test2" + - "snmp-server contact t1" + - "snmp-server location test1" + - "snmp-server target list test host 1.1.1.2" + - "snmp-server context c1" + - "snmp-server context c2" + - "snmp-server logging threshold oid-processing 1" + - "snmp-server logging threshold pdu-processing 1" + - "snmp-server mib bulkstat max-procmem-size 101" + - "snmp-server timeouts duplicate 0" + - "snmp-server timeouts inQdrop 0" + - "snmp-server packetsize 490" + - "snmp-server correlator buffer-size 1024" + - "snmp-server trap-source GigabitEthernet0/0/0/2" + - "snmp-server throttle-time 60" + - "snmp-server community-map cm1 context c1 security-name s1 target-list t1" + - "snmp-server inform retries 7" + - "snmp-server overload-control 4 6" + - "snmp-server ifmib internal cache max-duration 4" + - "snmp-server mroutemib send-all-vrf" + - "snmp-server notification-log-mib size 5" + - "snmp-server notification-log-mib GlobalSize 5" + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/_remove_config.yaml new file mode 100644 index 00000000..cc6fd8fd --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/_remove_config.yaml @@ -0,0 +1,6 @@ +--- +- name: "Remove SNMP server configuration" + cisco.iosxr.iosxr_snmp_server: + state: deleted + vars: + ansible_connection: ansible.netcommon.network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/deleted.yaml new file mode 100644 index 00000000..cb1115d2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/deleted.yaml @@ -0,0 +1,36 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_snmp_server deleted integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete given snmp-server configuration + become: true + register: result + cisco.iosxr.iosxr_snmp_server: &deleted + state: deleted + + - become: true + cisco.iosxr.iosxr_facts: + gather_network_resources: snmp_server + + - ansible.builtin.assert: + that: + - result.commands|length == 52 + - result.changed == true + - ansible_facts.network_resources.snmp_server == result.after + - result.after == deleted.after + + - name: Idempotency check + become: true + register: result + cisco.iosxr.iosxr_snmp_server: *deleted + - ansible.builtin.assert: + that: + - result.commands|length == 0 + - result.changed == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/empty_config.yaml new file mode 100644 index 00000000..07010879 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/empty_config.yaml @@ -0,0 +1,61 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_snmp_server empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_snmp_server: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_snmp_server: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Override with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_snmp_server: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Rendered with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_snmp_server: + config: + state: rendered + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state rendered' + +- name: Parsed with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_snmp_server: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' + +- ansible.builtin.debug: + msg: END iosxr_snmp_server empty_config integration tests on connection={{ ansible_connection }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/gathered.yaml new file mode 100644 index 00000000..3ce0b0d2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/gathered.yaml @@ -0,0 +1,22 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_snmp_server gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Gathered the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_snmp_server: + config: + state: gathered + + - name: Assert + ansible.builtin.assert: + that: + - merged.after == result.gathered + - result['changed'] == false + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/merged.yaml new file mode 100644 index 00000000..c591a543 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/merged.yaml @@ -0,0 +1,130 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_snmp_server merged integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + cisco.iosxr.iosxr_snmp_server: &merged + config: + vrfs: + - hosts: + - community: test1 + host: 1.1.1.1 + traps: true + vrf: vrf1 + users: + - Ipv4_acl: test1 + Ipv6_acl: test2 + group: test2 + user: u1 + version: v1 + timeouts: + duplicate: 0 + inQdrop: 0 + trap: + throttle_time: 12 + targets: + - host: 1.1.1.2 + name: test + + ifmib: + internal_cache_max_duration: 4 + inform: + retries: 7 + chassis_id: test2 + packetsize: 490 + queue_length: 2 + throttle_time: 60 + trap_source: GigabitEthernet0/0/0/2 + trap_timeout: 3 + context: + - c1 + - c2 + contact: t1 + correlator: + buffer_size: 1024 + communities: + - name: test2 + ro: true + sdrowner: true + acl_v4: test + acl_v6: test1 + community_maps: + - name: cm1 + context: c1 + target_list: t1 + security_name: s1 + drop: + report_IPv4: test1 + unknown_user: true + ipv6: + precedence: routine + ipv4: + dscp: af11 + location: test1 + logging_threshold_oid_processing: 1 + logging_threshold_pdu_processing: 1 + mib_bulkstat_max_procmem_size: 101 + mroutemib_send_all_vrf: true + overload_control: + overload_drop_time: 4 + overload_throttle_rate: 6 + notification_log_mib: + GlobalSize: 5 + size: 5 + traps: + hsrp: true + ipsla: true + ipsec: + start: true + stop: true + bridgemib: true + bulkstat_collection: true + cisco_entity_ext: true + config: true + copy_complete: true + addrpool: + high: true + low: true + bfd: true + bgp: + cbgp2: true + l2tun: + sessions: true + tunnel_down: true + tunnel_up: true + l2vpn: + all: true + vc_down: true + vc_up: true + msdp_peer_state_change: true + + register: result + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ result['before'] == {} }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts were correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['after'] + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_snmp_server: *merged + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/overridden.yaml new file mode 100644 index 00000000..e0dabf5c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/overridden.yaml @@ -0,0 +1,112 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_snmp_server overridden integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Override snmp-server configuration with provided configuration + cisco.iosxr.iosxr_snmp_server: &override + config: + timeouts: + duplicate: 0 + inQdrop: 0 + trap: + throttle_time: 13 + targets: + - host: 1.1.1.2 + name: test + + ifmib: + internal_cache_max_duration: 5 + inform: + retries: 7 + chassis_id: test + packetsize: 491 + queue_length: 2 + throttle_time: 60 + trap_source: GigabitEthernet0/0/0/2 + trap_timeout: 3 + context: + - c1 + - c2 + contact: t1 + correlator: + buffer_size: 1025 + communities: + - name: test1 + ro: true + sdrowner: true + acl_v4: test + acl_v6: test1 + community_maps: + - name: cm2 + context: c1 + target_list: t1 + security_name: s1 + drop: + report_IPv4: test2 + unknown_user: true + ipv6: + precedence: routine + ipv4: + dscp: af11 + location: test1 + logging_threshold_oid_processing: 2 + logging_threshold_pdu_processing: 2 + mib_bulkstat_max_procmem_size: 101 + mroutemib_send_all_vrf: true + overload_control: + overload_drop_time: 4 + overload_throttle_rate: 6 + notification_log_mib: + GlobalSize: 5 + size: 5 + traps: + hsrp: true + ipsla: true + ipsec: + start: true + stop: true + bridgemib: true + bulkstat_collection: true + cisco_entity_ext: true + config: true + copy_complete: true + l2vpn: + all: true + vc_down: true + vc_up: true + msdp_peer_state_change: true + state: overridden + + register: result + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - replaced['after'] == result['after'] + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['before'] + + - name: Override the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_snmp_server: *override + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/parsed.yaml new file mode 100644 index 00000000..4d7dce10 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/parsed.yaml @@ -0,0 +1,14 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_snmp_server parsed integration tests on connection={{ ansible_connection }} + +- name: Parse externally provided snmp_server configuration + register: result + cisco.iosxr.iosxr_snmp_server: + running_config: "{{ lookup('file', './_parsed.cfg') }}" + state: parsed + +- name: Assert that configuration was correctly parsed + ansible.builtin.assert: + that: + - merged['after'] == result['parsed'] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/rendered.yaml new file mode 100644 index 00000000..052dd7fc --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/rendered.yaml @@ -0,0 +1,108 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_snmp_server rendered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- name: Render platform specific configuration lines with state rendered (without connecting to the device) + cisco.iosxr.iosxr_snmp_server: + state: rendered + config: + vrfs: + - hosts: + - community: test1 + host: 1.1.1.1 + traps: true + vrf: vrf1 + users: + - Ipv4_acl: test1 + Ipv6_acl: test2 + group: test2 + user: u1 + version: v1 + timeouts: + duplicate: 0 + inQdrop: 0 + trap: + throttle_time: 12 + targets: + - host: 1.1.1.2 + name: test + + ifmib: + internal_cache_max_duration: 4 + inform: + retries: 7 + chassis_id: test2 + packetsize: 490 + queue_length: 2 + throttle_time: 60 + trap_source: GigabitEthernet0/0/0/2 + trap_timeout: 3 + context: + - c1 + - c2 + contact: t1 + correlator: + buffer_size: 1024 + communities: + - name: test2 + ro: true + sdrowner: true + acl_v4: test + acl_v6: test1 + community_maps: + - name: cm1 + context: c1 + target_list: t1 + security_name: s1 + drop: + report_IPv4: test1 + unknown_user: true + ipv6: + precedence: routine + ipv4: + dscp: af11 + location: test1 + logging_threshold_oid_processing: 1 + logging_threshold_pdu_processing: 1 + mib_bulkstat_max_procmem_size: 101 + mroutemib_send_all_vrf: true + overload_control: + overload_drop_time: 4 + overload_throttle_rate: 6 + notification_log_mib: + GlobalSize: 5 + size: 5 + traps: + hsrp: true + ipsla: true + ipsec: + start: true + stop: true + bridgemib: true + bulkstat_collection: true + cisco_entity_ext: true + config: true + copy_complete: true + addrpool: + high: true + low: true + bfd: true + bgp: + cbgp2: true + l2tun: + sessions: true + tunnel_down: true + tunnel_up: true + l2vpn: + all: true + vc_down: true + vc_up: true + msdp_peer_state_change: true + register: result + +- name: Assert that correct set of commands were rendered + ansible.builtin.assert: + that: + - merged['commands'] == result['rendered'] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/replaced.yaml new file mode 100644 index 00000000..c295777b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/tests/common/replaced.yaml @@ -0,0 +1,114 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_snmp_server replaced integration tests connection={{ ansible_connection}} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replace snmp-server configuration with provided configuration + cisco.iosxr.iosxr_snmp_server: &replace + state: replaced + config: + timeouts: + duplicate: 0 + inQdrop: 0 + trap: + throttle_time: 13 + targets: + - host: 1.1.1.2 + name: test + + ifmib: + internal_cache_max_duration: 5 + inform: + retries: 7 + chassis_id: test + packetsize: 491 + queue_length: 2 + throttle_time: 60 + trap_source: GigabitEthernet0/0/0/2 + trap_timeout: 3 + context: + - c1 + - c2 + contact: t1 + correlator: + buffer_size: 1025 + communities: + - name: test1 + ro: true + sdrowner: true + acl_v4: test + acl_v6: test1 + community_maps: + - name: cm2 + context: c1 + target_list: t1 + security_name: s1 + drop: + report_IPv4: test2 + unknown_user: true + ipv6: + precedence: routine + ipv4: + dscp: af11 + location: test1 + logging_threshold_oid_processing: 2 + logging_threshold_pdu_processing: 2 + mib_bulkstat_max_procmem_size: 101 + mroutemib_send_all_vrf: true + overload_control: + overload_drop_time: 4 + overload_throttle_rate: 6 + notification_log_mib: + GlobalSize: 5 + size: 5 + traps: + hsrp: true + ipsla: true + ipsec: + start: true + stop: true + bridgemib: true + bulkstat_collection: true + cisco_entity_ext: true + config: true + copy_complete: true + l2vpn: + all: true + vc_down: true + vc_up: true + msdp_peer_state_change: true + register: result + + - ansible.builtin.debug: + msg: "{{ replaced['commands'] | symmetric_difference(result['commands']) }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - replaced['after'] == result['after'] + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - merged['after'] == result['before'] + + - name: Replace the provided configuration with the existing running configuration (idempotent) + cisco.iosxr.iosxr_snmp_server: *replace + register: result + + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/vars/main.yaml new file mode 100644 index 00000000..39031229 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_snmp_server/vars/main.yaml @@ -0,0 +1,249 @@ +--- +merged: + commands: + - snmp-server chassis-id test2 + - snmp-server correlator buffer-size 1024 + - snmp-server contact t1 + - snmp-server ipv4 dscp af11 + - snmp-server ipv6 precedence routine + - snmp-server location test1 + - snmp-server logging threshold oid-processing 1 + - snmp-server logging threshold pdu-processing 1 + - snmp-server mib bulkstat max-procmem-size 101 + - snmp-server mroutemib send-all-vrf + - snmp-server overload-control 4 6 + - snmp-server packetsize 490 + - snmp-server queue-length 2 + - snmp-server throttle-time 60 + - snmp-server trap-source GigabitEthernet0/0/0/2 + - snmp-server trap-timeout 3 + - snmp-server drop report acl IPv4 test1 + - snmp-server drop unknown-user + - snmp-server ifmib internal cache max-duration 4 + - snmp-server inform retries 7 + - snmp-server notification-log-mib size 5 + - snmp-server notification-log-mib GlobalSize 5 + - snmp-server trap throttle-time 12 + - snmp-server timeouts inQdrop 0 + - snmp-server timeouts duplicate 0 + - snmp-server traps addrpool low + - snmp-server traps addrpool high + - snmp-server traps bfd + - snmp-server traps bgp cbgp2 + - snmp-server traps bulkstat collection + - snmp-server traps bridgemib + - snmp-server traps copy-complete + - snmp-server traps cisco-entity-ext + - snmp-server traps config + - snmp-server traps hsrp + - snmp-server traps ipsla + - snmp-server traps ipsec tunnel start + - snmp-server traps ipsec tunnel stop + - snmp-server traps l2tun sessions + - snmp-server traps l2tun tunnel-up + - snmp-server traps l2tun tunnel-down + - snmp-server traps l2vpn all + - snmp-server traps l2vpn vc-up + - snmp-server traps l2vpn vc-down + - snmp-server traps msdp peer-state-change + - snmp-server community test2 RO SDROwner IPv4 test IPv6 test1 + - snmp-server community-map cm1 context c1 security-name s1 target-list t1 + - snmp-server context c1 + - snmp-server context c2 + - snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 + - snmp-server target list test host 1.1.1.2 + - snmp-server vrf vrf1 + - host 1.1.1.1 traps test1 + + after: + vrfs: + - hosts: + - community: test1 + host: 1.1.1.1 + traps: true + vrf: vrf1 + users: + - acl_v4: test1 + acl_v6: test2 + group: test2 + user: u1 + version: v1 + timeouts: + duplicate: 0 + inQdrop: 0 + trap: + throttle_time: 12 + targets: + - host: 1.1.1.2 + name: test + + ifmib: + internal_cache_max_duration: 4 + inform: + retries: 7 + chassis_id: test2 + packetsize: 490 + queue_length: 2 + throttle_time: 60 + trap_source: GigabitEthernet0/0/0/2 + trap_timeout: 3 + context: + - c1 + - c2 + contact: t1 + correlator: + buffer_size: 1024 + communities: + - name: test2 + ro: true + sdrowner: true + acl_v4: test + acl_v6: test1 + community_maps: + - name: cm1 + context: c1 + target_list: t1 + security_name: s1 + drop: + report_IPv4: test1 + unknown_user: true + ipv6: + precedence: routine + ipv4: + dscp: af11 + location: test1 + logging_threshold_oid_processing: 1 + logging_threshold_pdu_processing: 1 + mib_bulkstat_max_procmem_size: 101 + mroutemib_send_all_vrf: true + overload_control: + overload_drop_time: 4 + overload_throttle_rate: 6 + notification_log_mib: + GlobalSize: 5 + size: 5 + traps: + hsrp: true + ipsla: true + ipsec: + start: true + stop: true + bridgemib: true + bulkstat_collection: true + cisco_entity_ext: true + config: true + copy_complete: true + addrpool: + high: true + low: true + bfd: true + bgp: + cbgp2: true + l2tun: + sessions: true + tunnel_down: true + tunnel_up: true + l2vpn: + all: true + vc_down: true + vc_up: true + msdp_peer_state_change: true + +deleted: + after: {} + +replaced: + commands: + - no snmp-server traps addrpool low + - no snmp-server traps addrpool high + - no snmp-server traps bfd + - no snmp-server traps bgp cbgp2 + - no snmp-server traps l2tun sessions + - no snmp-server traps l2tun tunnel-up + - no snmp-server traps l2tun tunnel-down + - no snmp-server community test2 RO SDROwner IPv4 test IPv6 test1 + - no snmp-server community-map cm1 context c1 security-name s1 target-list t1 + - no snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 + - no snmp-server vrf vrf1 + - snmp-server chassis-id test + - snmp-server correlator buffer-size 1025 + - snmp-server logging threshold oid-processing 2 + - snmp-server logging threshold pdu-processing 2 + - snmp-server packetsize 491 + - snmp-server drop report acl IPv4 test2 + - snmp-server ifmib internal cache max-duration 5 + - snmp-server trap throttle-time 13 + - snmp-server community test1 RO SDROwner IPv4 test IPv6 test1 + - snmp-server community-map cm2 context c1 security-name s1 target-list t1 + + after: + timeouts: + duplicate: 0 + inQdrop: 0 + trap: + throttle_time: 13 + targets: + - host: 1.1.1.2 + name: test + + ifmib: + internal_cache_max_duration: 5 + inform: + retries: 7 + chassis_id: test + packetsize: 491 + queue_length: 2 + throttle_time: 60 + trap_source: GigabitEthernet0/0/0/2 + trap_timeout: 3 + context: + - c1 + - c2 + contact: t1 + correlator: + buffer_size: 1025 + communities: + - name: test1 + ro: true + sdrowner: true + acl_v4: test + acl_v6: test1 + community_maps: + - name: cm2 + context: c1 + target_list: t1 + security_name: s1 + drop: + report_IPv4: test2 + unknown_user: true + ipv6: + precedence: routine + ipv4: + dscp: af11 + location: test1 + logging_threshold_oid_processing: 2 + logging_threshold_pdu_processing: 2 + mib_bulkstat_max_procmem_size: 101 + mroutemib_send_all_vrf: true + overload_control: + overload_drop_time: 4 + overload_throttle_rate: 6 + notification_log_mib: + GlobalSize: 5 + size: 5 + traps: + hsrp: true + ipsla: true + ipsec: + start: true + stop: true + bridgemib: true + bulkstat_collection: true + cisco_entity_ext: true + config: true + copy_complete: true + l2vpn: + all: true + vc_down: true + vc_up: true + msdp_peer_state_change: true diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/fixtures/parsed.cfg b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/fixtures/parsed.cfg new file mode 100644 index 00000000..35948336 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/fixtures/parsed.cfg @@ -0,0 +1,18 @@ +Fri Nov 29 21:10:41.896 UTC +router static + address-family ipv4 unicast + 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120 + 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1 + 192.0.2.32/28 192.0.2.11 100 + ! + address-family ipv6 unicast + 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC + 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1 + ! + vrf DEV_SITE + address-family ipv4 unicast + 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV + 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2 + ! + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tasks/cli.yaml new file mode 100644 index 00000000..01bf509b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tasks/cli.yaml @@ -0,0 +1,20 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + delegate_to: localhost + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tasks/main.yaml new file mode 100644 index 00000000..4b7d599c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tasks/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/_populate_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/_populate_config.yaml new file mode 100644 index 00000000..e38008ec --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/_populate_config.yaml @@ -0,0 +1,58 @@ +--- +- name: Setup + cisco.iosxr.iosxr_static_routes: + config: + - address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.16/28 + next_hops: + - forward_router_address: 192.0.2.10 + interface: FastEthernet0/0/0/1 + description: LAB + metric: 120 + tag: 10 + + - interface: FastEthernet0/0/0/5 + track: ip_sla_1 + + - dest: 192.0.2.32/28 + next_hops: + - forward_router_address: 192.0.2.11 + admin_distance: 100 + + - afi: ipv6 + safi: unicast + routes: + - dest: 2001:db8:1000::/36 + next_hops: + - interface: FastEthernet0/0/0/7 + description: DC + + - interface: FastEthernet0/0/0/8 + forward_router_address: 2001:db8:2000:2::1 + + - vrf: DEV_SITE + address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.48/28 + next_hops: + - forward_router_address: 192.0.2.12 + description: DEV + dest_vrf: test_1 + + - forward_router_address: 192.0.3.24 + interface: GigabitEthernet0/0/0/1 + vrflabel: 2302 + + - dest: 192.0.2.80/28 + next_hops: + - interface: FastEthernet0/0/0/2 + forward_router_address: 192.0.2.14 + dest_vrf: test_1 + track: ip_sla_2 + vrflabel: 124 + state: merged diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/_remove_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/_remove_config.yaml new file mode 100644 index 00000000..7acca740 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/_remove_config.yaml @@ -0,0 +1,7 @@ +--- +- name: Remove static routes + vars: + lines: "no router static\n" + ignore_errors: true + ansible.netcommon.cli_config: + config: "{{ lines }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/deleted.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/deleted.yaml new file mode 100644 index 00000000..dc53d003 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/deleted.yaml @@ -0,0 +1,68 @@ +--- +- ansible.builtin.debug: + msg: Start iosxr_static_routes deleted integration tests ansible_connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Delete all destination network entries under a single AFI + register: result + cisco.iosxr.iosxr_static_routes: &id001 + config: + - vrf: DEV_SITE + address_families: + - afi: ipv4 + safi: unicast + state: deleted + + - ansible.builtin.assert: + that: + - '"router static" in result.commands' + - '"vrf DEV_SITE" in result.commands' + - '"no address-family ipv4 unicast" in result.commands' + - result.commands|length == 3 + + - name: Delete all destination network entries under a single AFI (idempotent) + register: result + cisco.iosxr.iosxr_static_routes: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: &id003 + that: + - result['changed'] == false + - result.commands|length == 0 + + - ansible.builtin.include_tasks: _populate_config.yaml + + - name: Delete static routes configuration + register: result + cisco.iosxr.iosxr_static_routes: &id002 + state: deleted + + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that the correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that the after dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Delete all static routes (idempotent) + register: result + cisco.iosxr.iosxr_static_routes: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: *id003 + - name: Assert that the before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/empty_config.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/empty_config.yaml new file mode 100644 index 00000000..4dd456a1 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/empty_config.yaml @@ -0,0 +1,47 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_static_routes empty_config integration tests on connection={{ ansible_connection }} + +- name: Merged with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_static_routes: + config: + state: merged + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state merged' + +- name: Replaced with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_static_routes: + config: + state: replaced + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state replaced' + +- name: Overridden with empty configuration should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_static_routes: + config: + state: overridden + +- ansible.builtin.assert: + that: + - result.msg == 'value of config parameter must not be empty for state overridden' + +- name: Parsed with empty running_config should give appropriate error message + register: result + ignore_errors: true + cisco.iosxr.iosxr_static_routes: + running_config: + state: parsed + +- ansible.builtin.assert: + that: + - result.msg == 'value of running_config parameter must not be empty for state parsed' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/gathered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/gathered.yaml new file mode 100644 index 00000000..23b9b3d0 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/gathered.yaml @@ -0,0 +1,18 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_static_routes gathered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Gather static routes facts from the device using iosxr_static_routes module + register: result + cisco.iosxr.iosxr_static_routes: + state: gathered + + - ansible.builtin.assert: + that: "{{ replaced['before'] | symmetric_difference(result['gathered']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/merged.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/merged.yaml new file mode 100644 index 00000000..c848e7c2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/merged.yaml @@ -0,0 +1,138 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_static_routes merged integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Merge the provided configuration with the existing running configuration + register: result + cisco.iosxr.iosxr_static_routes: &id001 + config: + - address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.16/28 + next_hops: + - forward_router_address: 192.0.2.10 + interface: FastEthernet0/0/0/1 + description: LAB + metric: 120 + tag: 10 + + - interface: FastEthernet0/0/0/5 + track: ip_sla_1 + + - dest: 192.0.2.32/28 + next_hops: + - forward_router_address: 192.0.2.11 + admin_distance: 100 + + - afi: ipv6 + safi: unicast + routes: + - dest: 2001:db8:1000::/36 + next_hops: + - interface: FastEthernet0/0/0/7 + description: DC + + - interface: FastEthernet0/0/0/8 + forward_router_address: 2001:db8:2000:2::1 + + - vrf: DEV_SITE + address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.48/28 + next_hops: + - forward_router_address: 192.0.2.12 + description: DEV + dest_vrf: test_1 + + - dest: 192.0.2.80/28 + next_hops: + - interface: FastEthernet0/0/0/2 + forward_router_address: 192.0.2.14 + dest_vrf: test_1 + track: ip_sla_2 + vrflabel: 124 + state: merged + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['before'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - ansible.builtin.set_fact: + diff: "{{ merged['after'] | symmetric_difference(result['after']) }}" + + - name: Assert that after dicts was correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Merge the provided configuration with the existing running configuration (idempotent) + register: result + cisco.iosxr.iosxr_static_routes: *id001 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: + - "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Update existing configuration using merged + register: result + cisco.iosxr.iosxr_static_routes: &id002 + config: + - vrf: DEV_SITE + address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.48/28 + next_hops: + - forward_router_address: 192.0.2.12 + vrflabel: 2301 + dest_vrf: test_1 + + - dest: 192.0.2.80/28 + next_hops: + - interface: FastEthernet0/0/0/2 + forward_router_address: 192.0.2.14 + dest_vrf: test_1 + description: rt_test_1 + + - name: Assert that before dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['after'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ merged['update_commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that after dicts were correctly generated + ansible.builtin.assert: + that: "{{ merged['update_after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Update existing static_routes configuration using merged (idempotent) + register: result + cisco.iosxr.iosxr_static_routes: *id002 + - name: Assert that the previous task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/overridden.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/overridden.yaml new file mode 100644 index 00000000..0c75b6ca --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/overridden.yaml @@ -0,0 +1,65 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_static_routes overridden integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Overridde all static routes configuration with provided configuration + register: result + cisco.iosxr.iosxr_static_routes: &id001 + config: + - vrf: DEV_NEW + address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.48/28 + next_hops: + - forward_router_address: 192.0.2.15 + interface: FastEthernet0/0/0/3 + description: DEV1 + + - afi: ipv6 + safi: unicast + routes: + - dest: 2001:db8:3000::/36 + next_hops: + - interface: FastEthernet0/0/0/4 + forward_router_address: 2001:db8:2000:2::2 + description: PROD1 + track: ip_sla_1 + state: overridden + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Overridde all static routes configuration with given configuration (idempotent) + register: result + cisco.iosxr.iosxr_static_routes: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/parsed.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/parsed.yaml new file mode 100644 index 00000000..d06987a5 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/parsed.yaml @@ -0,0 +1,13 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_static_routes parsed integration tests on connection={{ ansible_connection }} + +- block: + - name: Use parsed state to convert externally supplied device specific static routes commands to structured format + register: result + cisco.iosxr.iosxr_static_routes: + running_config: "{{ lookup('file', '../../fixtures/parsed.cfg') }}" + state: parsed + + - ansible.builtin.assert: + that: "{{ merged['after'] | symmetric_difference(result['parsed']) |length==0 }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/rendered.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/rendered.yaml new file mode 100644 index 00000000..8170afb7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/rendered.yaml @@ -0,0 +1,75 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_static_routes rendered integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- block: + - name: Use rendered state to convert task input to device specific commands + register: result + cisco.iosxr.iosxr_static_routes: + config: + - vrf: DEV_SITE + address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.48/28 + next_hops: + - forward_router_address: 192.0.2.12 + description: DEV + dest_vrf: test_1 + + - dest: 192.0.2.80/28 + next_hops: + - interface: FastEthernet0/0/0/2 + forward_router_address: 192.0.2.14 + dest_vrf: test_1 + track: ip_sla_2 + vrflabel: 124 + + - address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.16/28 + next_hops: + - forward_router_address: 192.0.2.10 + interface: FastEthernet0/0/0/1 + description: LAB + metric: 120 + tag: 10 + + - interface: FastEthernet0/0/0/5 + track: ip_sla_1 + + - dest: 192.0.2.32/28 + next_hops: + - forward_router_address: 192.0.2.11 + admin_distance: 100 + + - afi: ipv6 + safi: unicast + routes: + - dest: 2001:db8:1000::/36 + next_hops: + - interface: FastEthernet0/0/0/7 + description: DC + + - interface: FastEthernet0/0/0/8 + forward_router_address: 2001:db8:2000:2::1 + state: rendered + + - ansible.builtin.assert: + that: "{{ merged['commands'] | symmetric_difference(result['rendered']) |length==0 }}" + + - name: Gather static routes facts from the device and assert that its empty + register: result + cisco.iosxr.iosxr_static_routes: + state: gathered + + - name: Make sure that rendered task actually did not make any changes to the device + ansible.builtin.assert: + that: "{{ result['gathered'] == [] }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/replaced.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/replaced.yaml new file mode 100644 index 00000000..4386731d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/replaced.yaml @@ -0,0 +1,56 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_static_routes replaced integration tests on connection={{ ansible_connection }} + +- ansible.builtin.include_tasks: _remove_config.yaml + +- ansible.builtin.include_tasks: _populate_config.yaml + +- block: + - name: Replace device configurations of static routes with provided configurations + register: result + cisco.iosxr.iosxr_static_routes: &id001 + config: + - vrf: DEV_SITE + address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.48/28 + next_hops: + - forward_router_address: 192.0.2.15 + interface: FastEthernet0/0/0/3 + description: DEV_NEW + dest_vrf: dev_test_2 + state: replaced + + - name: Assert that correct set of commands were generated + ansible.builtin.assert: + that: + - "{{ replaced['commands'] | symmetric_difference(result['commands']) |length == 0 }}" + + - name: Assert that before dicts are correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['before'] | symmetric_difference(result['before']) |length == 0 }}" + + - name: Assert that after dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Replace device configurations of listed vrfs/global entry with provided configuration (idempotent) + register: result + cisco.iosxr.iosxr_static_routes: *id001 + - name: Assert that task was idempotent + ansible.builtin.assert: + that: + - result['changed'] == false + - result.commands|length == 0 + + - name: Assert that before dict is correctly generated + ansible.builtin.assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['before']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/rtt.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/rtt.yaml new file mode 100644 index 00000000..40e47d2a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/tests/cli/rtt.yaml @@ -0,0 +1,73 @@ +--- +- ansible.builtin.debug: + msg: START iosxr_static_routes round trip integration tests on connection={{ ansible_connection }} + +- block: + - ansible.builtin.include_tasks: _remove_config.yaml + + - name: Apply the provided configuration (base config) + register: base_config + cisco.iosxr.iosxr_static_routes: + config: + - address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.48/28 + next_hops: + - forward_router_address: 192.0.2.15 + admin_distance: 105 + track: ip_sla_2 + + - vrf: DEV_SITE + address_families: + - afi: ipv6 + safi: unicast + routes: + - dest: 2001:db8:3000::/36 + next_hops: + - forward_router_address: 2001:db8:2000:2::2 + interface: FastEthernet0/0/0/11 + description: PROD1 + state: merged + + - name: Gather interfaces facts + cisco.iosxr.iosxr_facts: + gather_subset: + - "!all" + - "!min" + gather_network_resources: + - static_routes + + - name: Apply the provided configuration (config to be reverted) + register: result + cisco.iosxr.iosxr_static_routes: + config: + - vrf: TEST_SITE + address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.80/28 + next_hops: + - forward_router_address: 192.0.2.12 + interface: FastEthernet0/0/0/3 + description: DEV_MOVED + dest_vrf: dev_moved + state: overridden + + - name: Assert that changes were applied + ansible.builtin.assert: + that: "{{ round_trip['after'] | symmetric_difference(result['after']) |length == 0 }}" + + - name: Revert back to base configuration using facts round trip + register: revert + cisco.iosxr.iosxr_static_routes: + config: "{{ ansible_facts['network_resources']['static_routes'] }}" + state: overridden + + - name: Assert that configuration was reverted + ansible.builtin.assert: + that: "{{ base_config['after'] | symmetric_difference(revert['after']) |length == 0 }}" + always: + - ansible.builtin.include_tasks: _remove_config.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/vars/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/vars/main.yaml new file mode 100644 index 00000000..b12c6698 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_static_routes/vars/main.yaml @@ -0,0 +1,264 @@ +--- +merged: + before: [] + commands: + - router static + - address-family ipv4 unicast + - 192.0.2.16/28 192.0.2.10 FastEthernet0/0/0/1 description LAB metric 120 tag + 10 + - 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1 + - 192.0.2.32/28 192.0.2.11 100 + - address-family ipv6 unicast + - 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC + - 2001:db8:1000::/36 2001:db8:2000:2::1 FastEthernet0/0/0/8 + - vrf DEV_SITE + - address-family ipv4 unicast + - 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV + - 192.0.2.80/28 vrf test_1 192.0.2.14 FastEthernet0/0/0/2 track ip_sla_2 vrflabel + 124 + update_commands: + - router static + - vrf DEV_SITE + - address-family ipv4 unicast + - 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV vrflabel 2301 + - 192.0.2.80/28 vrf test_1 192.0.2.14 FastEthernet0/0/0/2 description rt_test_1 + track ip_sla_2 vrflabel 124 + after: + - address_families: + - afi: ipv4 + routes: + - dest: 192.0.2.16/28 + next_hops: + - description: LAB + forward_router_address: 192.0.2.10 + interface: FastEthernet0/0/0/1 + metric: 120 + tag: 10 + - interface: FastEthernet0/0/0/5 + track: ip_sla_1 + - dest: 192.0.2.32/28 + next_hops: + - admin_distance: 100 + forward_router_address: 192.0.2.11 + safi: unicast + - afi: ipv6 + routes: + - dest: 2001:db8:1000::/36 + next_hops: + - description: DC + interface: FastEthernet0/0/0/7 + - forward_router_address: 2001:db8:2000:2::1 + interface: FastEthernet0/0/0/8 + safi: unicast + - address_families: + - afi: ipv4 + routes: + - dest: 192.0.2.48/28 + next_hops: + - description: DEV + dest_vrf: test_1 + forward_router_address: 192.0.2.12 + - dest: 192.0.2.80/28 + next_hops: + - dest_vrf: test_1 + forward_router_address: 192.0.2.14 + interface: FastEthernet0/0/0/2 + track: ip_sla_2 + vrflabel: 124 + safi: unicast + vrf: DEV_SITE + update_after: + - address_families: + - afi: ipv4 + routes: + - dest: 192.0.2.16/28 + next_hops: + - description: LAB + forward_router_address: 192.0.2.10 + interface: FastEthernet0/0/0/1 + metric: 120 + tag: 10 + - interface: FastEthernet0/0/0/5 + track: ip_sla_1 + - dest: 192.0.2.32/28 + next_hops: + - admin_distance: 100 + forward_router_address: 192.0.2.11 + safi: unicast + - afi: ipv6 + routes: + - dest: 2001:db8:1000::/36 + next_hops: + - description: DC + interface: FastEthernet0/0/0/7 + - forward_router_address: 2001:db8:2000:2::1 + interface: FastEthernet0/0/0/8 + safi: unicast + - address_families: + - afi: ipv4 + routes: + - dest: 192.0.2.48/28 + next_hops: + - description: DEV + dest_vrf: test_1 + forward_router_address: 192.0.2.12 + vrflabel: 2301 + - dest: 192.0.2.80/28 + next_hops: + - dest_vrf: test_1 + forward_router_address: 192.0.2.14 + interface: FastEthernet0/0/0/2 + track: ip_sla_2 + vrflabel: 124 + description: rt_test_1 + safi: unicast + vrf: DEV_SITE +replaced: + before: + - address_families: + - afi: ipv4 + routes: + - dest: 192.0.2.16/28 + next_hops: + - description: LAB + forward_router_address: 192.0.2.10 + interface: FastEthernet0/0/0/1 + metric: 120 + tag: 10 + - interface: FastEthernet0/0/0/5 + track: ip_sla_1 + - dest: 192.0.2.32/28 + next_hops: + - admin_distance: 100 + forward_router_address: 192.0.2.11 + safi: unicast + - afi: ipv6 + routes: + - dest: 2001:db8:1000::/36 + next_hops: + - description: DC + interface: FastEthernet0/0/0/7 + - forward_router_address: 2001:db8:2000:2::1 + interface: FastEthernet0/0/0/8 + safi: unicast + - address_families: + - afi: ipv4 + routes: + - dest: 192.0.2.48/28 + next_hops: + - description: DEV + dest_vrf: test_1 + forward_router_address: 192.0.2.12 + - forward_router_address: 192.0.3.24 + interface: GigabitEthernet0/0/0/1 + vrflabel: 2302 + - dest: 192.0.2.80/28 + next_hops: + - dest_vrf: test_1 + forward_router_address: 192.0.2.14 + interface: FastEthernet0/0/0/2 + track: ip_sla_2 + vrflabel: 124 + safi: unicast + vrf: DEV_SITE + commands: + - router static + - vrf DEV_SITE + - address-family ipv4 unicast + - no 192.0.2.48/28 192.0.3.24 GigabitEthernet0/0/0/1 + - no 192.0.2.48/28 vrf test_1 192.0.2.12 + - 192.0.2.48/28 vrf dev_test_2 192.0.2.15 FastEthernet0/0/0/3 description DEV_NEW + after: + - address_families: + - afi: ipv4 + routes: + - dest: 192.0.2.16/28 + next_hops: + - description: LAB + forward_router_address: 192.0.2.10 + interface: FastEthernet0/0/0/1 + metric: 120 + tag: 10 + - interface: FastEthernet0/0/0/5 + track: ip_sla_1 + - dest: 192.0.2.32/28 + next_hops: + - admin_distance: 100 + forward_router_address: 192.0.2.11 + safi: unicast + - afi: ipv6 + routes: + - dest: 2001:db8:1000::/36 + next_hops: + - description: DC + interface: FastEthernet0/0/0/7 + - forward_router_address: 2001:db8:2000:2::1 + interface: FastEthernet0/0/0/8 + safi: unicast + - address_families: + - afi: ipv4 + routes: + - dest: 192.0.2.48/28 + next_hops: + - forward_router_address: 192.0.2.15 + interface: FastEthernet0/0/0/3 + description: DEV_NEW + dest_vrf: dev_test_2 + - dest: 192.0.2.80/28 + next_hops: + - dest_vrf: test_1 + forward_router_address: 192.0.2.14 + interface: FastEthernet0/0/0/2 + track: ip_sla_2 + vrflabel: 124 + safi: unicast + vrf: DEV_SITE +overridden: + commands: + - router static + - no vrf DEV_SITE + - no address-family ipv4 unicast + - no address-family ipv6 unicast + - vrf DEV_NEW + - address-family ipv4 unicast + - 192.0.2.48/28 192.0.2.15 FastEthernet0/0/0/3 description DEV1 + - address-family ipv6 unicast + - 2001:db8:3000::/36 2001:db8:2000:2::2 FastEthernet0/0/0/4 description PROD1 + track ip_sla_1 + after: + - vrf: DEV_NEW + address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.48/28 + next_hops: + - forward_router_address: 192.0.2.15 + interface: FastEthernet0/0/0/3 + description: DEV1 + - afi: ipv6 + safi: unicast + routes: + - dest: 2001:db8:3000::/36 + next_hops: + - interface: FastEthernet0/0/0/4 + forward_router_address: 2001:db8:2000:2::2 + description: PROD1 + track: ip_sla_1 +deleted: + commands: + - no router static + after: [] +round_trip: + after: + - vrf: TEST_SITE + address_families: + - afi: ipv4 + safi: unicast + routes: + - dest: 192.0.2.80/28 + next_hops: + - forward_router_address: 192.0.2.12 + interface: FastEthernet0/0/0/3 + description: DEV_MOVED + dest_vrf: dev_moved diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/defaults/main.yaml new file mode 100644 index 00000000..5f709c5a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "*" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/meta/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/meta/main.yml new file mode 100644 index 00000000..be631e5d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_iosxr_tests diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tasks/cli.yaml new file mode 100644 index 00000000..8ae46e43 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tasks/cli.yaml @@ -0,0 +1,23 @@ +--- +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli + +- name: Reset connection + ansible.builtin.meta: reset_connection diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tasks/main.yaml new file mode 100644 index 00000000..419a6cde --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tasks/main.yaml @@ -0,0 +1,6 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + +- name: Include the netconf tasks + ansible.builtin.include_tasks: netconf.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tasks/netconf.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tasks/netconf.yaml new file mode 100644 index 00000000..d04b0210 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tasks/netconf.yaml @@ -0,0 +1,21 @@ +--- +- name: Collect all netconf test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/netconf" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.netconf) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - netconf + +- name: Reset connection + ansible.builtin.meta: reset_connection diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_domain_list.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_domain_list.yaml new file mode 100644 index 00000000..0cde8790 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_domain_list.yaml @@ -0,0 +1,111 @@ +--- +- ansible.builtin.debug: msg="START cli/set_domain_search.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + lines: + - no domain list ansible.com + - no domain list redhat.com + match: none + +- name: Configure domain_search + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + - redhat.com + +- ansible.builtin.assert: + that: + - result.changed == true + - "'domain list ansible.com' in result.commands" + - "'domain list redhat.com' in result.commands" + +- name: Verify domain_search + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + - redhat.com + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Remove one entry + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + +- ansible.builtin.assert: + that: + - result.changed == true + - "'no domain list redhat.com' in result.commands" + +- name: Verify remove one entry + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Add one entry + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + - redhat.com + +- ansible.builtin.assert: + that: + - result.changed == true + - "'domain list redhat.com' in result.commands" + +- name: Verify add one entry + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + - redhat.com + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Add and remove one entry + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + - eng.ansible.com + +- ansible.builtin.assert: + that: + - result.changed == true + - "'no domain list redhat.com' in result.commands" + - "'domain list eng.ansible.com' in result.commands" + - result.commands|length == 2 + +- name: Verify add and remove one entry + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + - eng.ansible.com + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + lines: + - no domain list ansible.com + - no domain list eng.ansible.com + match: none + +- ansible.builtin.debug: msg="END cli/set_domain_search.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_domain_name.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_domain_name.yaml new file mode 100644 index 00000000..08e18c2b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_domain_name.yaml @@ -0,0 +1,32 @@ +--- +- ansible.builtin.debug: msg="START cli/set_domain_name.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + lines: no domain name + match: none + +- name: Configure domain_name + register: result + cisco.iosxr.iosxr_system: + domain_name: eng.ansible.com + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Verify domain_name + register: result + cisco.iosxr.iosxr_system: + domain_name: eng.ansible.com + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + lines: no domain name + match: none + +- ansible.builtin.debug: msg="END cli/set_domain_name.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_hostname.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_hostname.yaml new file mode 100644 index 00000000..f9a9e13f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_hostname.yaml @@ -0,0 +1,32 @@ +--- +- ansible.builtin.debug: msg="START cli/set_hostname.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + lines: hostname switch + match: none + +- name: Configure hostname + register: result + cisco.iosxr.iosxr_system: + hostname: foo + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Verify hostname + register: result + cisco.iosxr.iosxr_system: + hostname: foo + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + lines: hostname {{ inventory_hostname }} + match: none + +- ansible.builtin.debug: msg="END cli/set_hostname.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_lookup_source.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_lookup_source.yaml new file mode 100644 index 00000000..098741fa --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_lookup_source.yaml @@ -0,0 +1,34 @@ +--- +- ansible.builtin.debug: msg="START cli/set_lookup_source.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + lines: no domain lookup source-interface Loopback10 + match: none + +- name: Configure lookup_source + register: result + cisco.iosxr.iosxr_system: + lookup_source: Loopback10 + +- ansible.builtin.assert: + that: + - result.changed == true + - "'domain lookup source-interface Loopback10' in result.commands" + +- name: Verify lookup_source + register: result + cisco.iosxr.iosxr_system: + lookup_source: Loopback10 + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + cisco.iosxr.iosxr_config: + lines: + - no domain lookup source-interface Loopback10 + match: none + +- ansible.builtin.debug: msg="END cli/set_lookup_source.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_name_servers.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_name_servers.yaml new file mode 100644 index 00000000..cc2df411 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/cli/set_name_servers.yaml @@ -0,0 +1,59 @@ +--- +- ansible.builtin.debug: msg="START cli/set_name_servers.yaml on connection={{ ansible_connection }}" + +- name: Setup + cisco.iosxr.iosxr_config: + lines: + - no ip name-server 192.0.2.1 + - no ip name-server 192.0.2.2 + - no ip name-server 192.0.2.3 + match: none + +- name: Configure name_servers + register: result + cisco.iosxr.iosxr_system: + name_servers: + - 192.0.2.1 + - 192.0.2.2 + - 192.0.2.3 + +- ansible.builtin.assert: + that: + - result.changed == true + - "'domain name-server 192.0.2.1' in result.commands" + - "'domain name-server 192.0.2.2' in result.commands" + - "'domain name-server 192.0.2.3' in result.commands" + +- name: Verify name_servers + register: result + cisco.iosxr.iosxr_system: + name_servers: + - 192.0.2.1 + - 192.0.2.2 + - 192.0.2.3 + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Remove one + register: result + cisco.iosxr.iosxr_system: + name_servers: + - 192.0.2.1 + - 192.0.2.2 + +- ansible.builtin.assert: + that: + - result.changed == true + - result.commands|length == 1 + - "'no domain name-server 192.0.2.3' in result.commands" + +- name: Setup + cisco.iosxr.iosxr_config: + lines: + - no ip name-server 192.0.2.1 + - no ip name-server 192.0.2.2 + match: none + +- ansible.builtin.debug: msg="END cli/set_name_servers.yaml on connection={{ ansible_connection }}" diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_domain_list.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_domain_list.yaml new file mode 100644 index 00000000..e83cda97 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_domain_list.yaml @@ -0,0 +1,164 @@ +--- +- ansible.builtin.debug: + msg: START netconf/set_domain_search.yaml on connection={{ ansible_connection }} + +- name: Setup + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_config: + lines: + - no domain list ansible.com + - no domain list redhat.com + - no domain list eng.ansible.com + - no domain vrf ansiblevrf list redhat.com + - no domain vrf ansiblevrf list ansible.com + match: none + +- name: Configure domain_search + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + - redhat.com + +- ansible.builtin.assert: + that: + - result.changed == true + - "'ansible.com' in result.xml[0]" + - "'redhat.com' in result.xml[0]" + +- name: Configure domain_search with VRF + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id001 + vrf: ansiblevrf + domain_search: + - redhat.com + - ansible.com + +- ansible.builtin.assert: + that: + - result.changed == true + - "'ansiblevrf' in result.xml[0]" + - "'ansible.com' in result.xml[0]" + - "'redhat.com' in result.xml[0]" + +- name: Verify domain_search with VRF + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id001 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Delete domain_search with VRF + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id002 + vrf: ansiblevrf + domain_search: + - redhat.com + +- ansible.builtin.assert: + that: + - result.changed == true + - "'ansiblevrf' in result.xml[0]" + - "'ansible.com' in result.xml[0]" + +- name: Verify delete domain_search with VRF + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id002 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Remove one entry + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + +- ansible.builtin.assert: + that: + - result.changed == true + - "'redhat.com' in result.xml[0]" + +- name: Verify remove one entry + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Add one entry + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + - redhat.com + +- ansible.builtin.assert: + that: + - result.changed == true + - "'redhat.com' in result.xml[0]" + +- name: Verify add one entry + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + - redhat.com + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Add and remove one entry + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + - eng.ansible.com + +- ansible.builtin.assert: + that: + - result.changed == true + - "'redhat.com' in result.xml[1]" + - "'eng.ansible.com' in result.xml[0]" + - result.xml|length == 2 + +- name: Verify add and remove one entry + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: + domain_search: + - ansible.com + - eng.ansible.com + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_config: + lines: + - no domain list ansible.com + - no domain list redhat.com + - no domain list eng.ansible.com + - no domain vrf ansiblevrf list redhat.com + - no domain vrf ansiblevrf list ansible.com + - no domain vrf ansiblevrf list eng.ansible.com + match: none + +- ansible.builtin.debug: + msg: END netconf/set_domain_search.yaml on connection={{ ansible_connection }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_domain_name.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_domain_name.yaml new file mode 100644 index 00000000..b2b9d7b4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_domain_name.yaml @@ -0,0 +1,70 @@ +--- +- ansible.builtin.debug: + msg: START netconf/set_domain_name.yaml on connection={{ ansible_connection }} + +- name: Setup + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_config: + lines: + - no domain name + - no domain vrf ansiblevrf name + match: none + +- name: Configure domain_name + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id001 + domain_name: eng.ansible.com + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Verify domain_name + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id001 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Configure domain_name + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id002 + domain_name: eng.ansible.com + state: absent + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Verify domain_name + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id002 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Configure domain_name with VRF + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id003 + domain_name: eng.ansible.com + vrf: ansiblevrf + +- ansible.builtin.assert: + that: + - result.changed == true + +- name: Verify domain_name with VRF + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id003 +- ansible.builtin.assert: + that: + - result.changed == false + +- ansible.builtin.debug: + msg: END netconf/set_domain_name.yaml on connection={{ ansible_connection }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_hostname.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_hostname.yaml new file mode 100644 index 00000000..fb803845 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_hostname.yaml @@ -0,0 +1,39 @@ +--- +- ansible.builtin.debug: + msg: START netconf/set_hostname.yaml on connection={{ ansible_connection }} + +- block: + - name: Setup + vars: + ansible_connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_config: + lines: hostname switch + match: none + + - name: Configure hostname + register: result + cisco.iosxr.iosxr_system: + hostname: foo + + - ansible.builtin.assert: + that: + - result.changed == true + + - name: Verify hostname + register: result + cisco.iosxr.iosxr_system: + hostname: foo + + - ansible.builtin.assert: + that: + - result.changed == false + always: + - name: Teardown + vars: + ansible_connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_config: + lines: hostname {{ inventory_hostname }} + match: none + +- ansible.builtin.debug: + msg: END netconf/set_hostname.yaml on connection={{ ansible_connection }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_lookup_source.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_lookup_source.yaml new file mode 100644 index 00000000..61277e0d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_lookup_source.yaml @@ -0,0 +1,149 @@ +--- +- ansible.builtin.debug: + msg: START netconf/set_lookup_source.yaml on connection={{ ansible_connection }} + +- name: Setup + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_config: + lines: + - no domain lookup source-interface Loopback10 + - no domain vrf ansiblevrf lookup source-interface Loopback10 + - no domain lookup disable + - no domain vrf ansiblevrf lookup disable + match: none + +- name: Reset connection + ansible.builtin.meta: reset_connection + +- name: Configure lookup_source + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id001 + lookup_source: Loopback10 + +- ansible.builtin.assert: + that: + - result.changed == true + - "'Loopback10' in result.xml[0]" + +- name: Verify lookup_source + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id001 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Disable lookup + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id002 + lookup_enabled: false + +- ansible.builtin.assert: + that: + - result.changed == true + - "'lookup' in result.xml[0]" + +- name: Verify disable lookup + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id002 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Delete lookup_source + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id003 + lookup_source: Loopback10 + state: absent + +- ansible.builtin.assert: + that: + - result.changed == true + - "'Loopback10' in result.xml[0]" + +- name: Verify lookup_source + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id003 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Configure lookup_source with VRF + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id004 + lookup_source: Loopback10 + vrf: ansiblevrf + +- ansible.builtin.assert: + that: + - result.changed == true + - "'Loopback10' in result.xml[0]" + - "'ansiblevrf' in result.xml[0]" + +- name: Verify lookup_source + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id004 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Disable lookup + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id005 + lookup_enabled: false + vrf: ansiblevrf + +- ansible.builtin.assert: + that: + - result.changed == true + - "'lookup' in result.xml[0]" + - "'ansiblevrf' in result.xml[0]" + +- name: Verify disable lookup + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id005 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Delete lookup_source + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id006 + lookup_source: Loopback10 + vrf: ansiblevrf + state: absent + +- ansible.builtin.assert: + that: + - result.changed == true + - "'Loopback10' in result.xml[0]" + - "'ansiblevrf' in result.xml[0]" + +- name: Verify lookup_source + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id006 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Teardown + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_config: + lines: + - no domain lookup disable + - no domain vrf ansiblevrf lookup disable + match: none + +- ansible.builtin.debug: + msg: END netconf/set_lookup_source.yaml on connection={{ ansible_connection }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_name_servers.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_name_servers.yaml new file mode 100644 index 00000000..dc888158 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_system/tests/netconf/set_name_servers.yaml @@ -0,0 +1,127 @@ +--- +- ansible.builtin.debug: + msg: START netconf/set_name_servers.yaml on connection={{ ansible_connection }} + +- name: Setup + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_config: + lines: + - no domain name-server 192.0.2.1 + - no domain name-server 192.0.2.2 + - no domain name-server 192.0.2.3 + match: none + +- name: Setup + connection: ansible.netcommon.netconf + ignore_errors: true + register: result + cisco.iosxr.iosxr_system: + vrf: ansible + name_servers: + - 192.0.2.1 + - 192.0.2.2 + - 192.0.2.3 + state: absent + +- name: Configure name_servers + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: + name_servers: + - 192.0.2.1 + - 192.0.2.2 + - 192.0.2.3 + +- ansible.builtin.assert: + that: + - result.changed == true + - result.xml|length == 1 + - "'192.0.2.1' in result.xml[0]" + - "'192.0.2.2' in result.xml[0]" + - "'192.0.2.3' in result.xml[0]" + +- name: Verify name_servers + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: + name_servers: + - 192.0.2.1 + - 192.0.2.2 + - 192.0.2.3 + +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Add name servers with VRF + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: &id001 + vrf: ansible + name_servers: + - 192.0.2.1 + - 192.0.2.2 + - 192.0.2.3 + +- ansible.builtin.assert: + that: + - result.changed == true + - result.xml|length == 1 + - "'ansible' in result.xml[0]" + - "'192.0.2.1' in result.xml[0]" + - "'192.0.2.2' in result.xml[0]" + - "'192.0.2.3' in result.xml[0]" + +- name: Verify change to VRF + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: *id001 +- ansible.builtin.assert: + that: + - result.changed == false + +- name: Remove one + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_system: + name_servers: + - 192.0.2.1 + - 192.0.2.2 + +- ansible.builtin.assert: + that: + - result.changed == true + - result.xml|length == 1 + - "'192.0.2.3' in result.xml[0]" + +- name: Remove one with VRF + connection: ansible.netcommon.netconf + ignore_errors: true + register: result + cisco.iosxr.iosxr_system: + vrf: ansible + name_servers: + - 192.0.2.1 + - 192.0.2.2 + +- name: Teardown + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_config: + lines: + - no domain name-server 192.0.2.1 + - no domain name-server 192.0.2.2 + match: none + +- name: Teardown + connection: ansible.netcommon.netconf + ignore_errors: true + register: result + cisco.iosxr.iosxr_system: + vrf: ansible + name_servers: + - 192.0.2.1 + - 192.0.2.2 + state: absent + +- ansible.builtin.debug: + msg: END netconf/set_name_servers.yaml on connection={{ ansible_connection }} diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/defaults/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/defaults/main.yaml new file mode 100644 index 00000000..164afead --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/files/private b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/files/private new file mode 100644 index 00000000..bf2425bb --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/files/private @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,A823A6B5ED873917 + +mLZ1xM1+xwutkRy+K/c9QsstDPQ9F6UWtDpoYyIgs7n9VgMjhIMbWQC9CkTvnFJM +ey+iwGdQZZOThwxalm+k3pMibwRjhnF+PNFhiVkzWH8/K8QvXRQiW/vYmE/QB9pY +T0IWbMcC7/ktEfQn+6GLXoe/L7yH+aNv/2Flsa2jN2cfSXpzbneUA06/LVVOw6E+ +C74NKRWUmMPA39Zd4WOeBoWUdS5Kgwl57SOtrKs1LIGh33+TPu+Go8gJ7h/t/kaN +kverVSz+0eeX+exKumejfo1UfosplRhcjRG8YgiQ8l7SN3NBF/gXiiSrH3fLwmRJ +hbokJ8TmCozrYBs1MNe3LoU2iuIqVnJ5Sd6DJELs6vCuFz+v6J/s80NaaYMlBCbB +1lahelYqoyLb4uiDd4zQSpaxzO+Cx/d50Wpee8mFxbAL/YxacOzD3b/VCBgB+AZN +TTHr1ayd+ITd8gewXAyERKWyrDcC2beJI0fOil23PYowWvEncS6I1f4hKQY28sRf +vHSbwQdltky/xiib2/feQTaMSQFvsY67uTHipMwl5wJNOKcbeqDVMWPYST3XUsBg +LRlbT+VTUEehbOJAJ6Hh7Yv4nqu7fEh95HUQK7Ed56rMLKpmdorYO49JtewkEUsj +LJn7tcxMUuOcWKHMPu6vB/63f6Ulthqp1SEG8aNBaZMuPyLWAPAJc2okOmkiSbvO +0Hxe6BtAGn2fUo2jK6E3tD/dsIR2qqMlL09FkACGT8D5Lfh5d3z+lo9DxpXl281R +ablehPyHgHcIC6cD2/7FwwjzUuyj/kYcETnMs51agcWFAXTom/ehqD+IQ8jZ73zT +5O4FFgslnNmB/vddh9PeYpjDYdR4y5xMrlMxJ+qcZuQOq7dfaiodq8oj+XPmwgxA +audX/sHMutOpmOagrsQfaQXaPqRXdQTnuwHacQfwq+tBBhrft5gwt1HE7Ir2ulwD +Q19kefchkJu/0c1cAGg1VHtQic0a6tX6PrwqZOMDfpSywcImMCF4KHgD2EC5/8h6 +tq0PqPLNcwiM2NhpypCuYmkYZ0gnJ/xAwtM85Ck9nmPFptLSd0b7YB7dtGsFYY5A +rhIcq5lZhy06/RRAPluIkniscA50iEO/EXKwzYzovBJh6jQz7oYsbEUW5kwg0gm/ +YPSa6lqv2kTpXS+UiGyeNWdUkr5DpdwKe4lrAsN94HE9/SoLgFvz0X5/WyTssSzo +IO3WfLfBc7SOkZK1ibcleIqilzd+LSoIqqGrft2yonXgJD3p9xO+Hlldczx2kHmu +z4lZBq53AkVAQ4os5L7ZRnmxoqKn2XAQRwVH3M9ZFYFEqEyDmZhlFdJSGEnKws81 +Ej48t6KWwqml02cx675bSYI22tL3+RL7AGmlC0/Xh8wIVesgulsYmnhW4BtpBYf2 +fwv5esJJMjkh2LvLNG3edYChugudeZXtcBJdNr0GYRbBAhvO25bRcr6z8nYDusKX +e/+30vATOcBO/zaOYIwDGT5ZwMQAV1aQl8HyeyYESNjb0fBXQ3OYObOrTTs8MLyC +I4b6wr1vlbN+lMOm+RIXCDgmC3COdlgCHyo3qiIu2YNYQVoNF4NN4A== +-----END RSA PRIVATE KEY----- diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/files/public.pub b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/files/public.pub new file mode 100644 index 00000000..db1847f4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/files/public.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAkvLTTJdwZ0lg1cUCn13Hi3+ho2+G6/96XuAP7jA7Ghz9NPbC/eqXnjvb27BA8CxtFXYuXR5eZWSq2UN5zFcfrFb57XFxdAg2q21hGEX+FGiTUuRZh8+ByVEh0LUetFTwsEZ1iGv6GZiLBt7IJvClXbyNTJEt3DZncHfGwudyGFviV4dGrzusDAGAcoHqvD/5uXYl4PjMH9oSfraO3sG4Q7soQwxNeiM8qOLf3c1SabHBAtSewwnA0E/jhzpOLD2QUncU5s+Oa9PvEXXhGv5eZo9lp71brsgyWj32m2UuXx/n+EZg78GVJT5mFO7LG239n3gTnwkMVdr6zVBFNX5Mvw== rsa-key-20171025 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/files/public2.pub b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/files/public2.pub new file mode 100644 index 00000000..26af0db9 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/files/public2.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAhTxbibM8hKZn7xDURs15L3gkcsnpDoZ+tNm5zpP9dcboASnIyJzfC7J/RdRCQsO/pDmUY4y/tsTx18uenyfazxtNkyCHdANlp8XVF1fGNv5GM+QbsDqxe54sdG9csASX0/Ljvl538IbcLFVH0zxyKspbDOgkAkUSuKIAH5x+/GhkAoGQO2tOhYjqofNtUxLSvfRsf4Gm1M0WgdWmz3MW4NOdZhsL4S+STgRPU1jy1dKGj7BKY9cpnCWBFHa2wSaOXJEBZEKNaFVxlBBrFs5brjRQA0mVPmE+pz+/+IJeSNEEma9cXur0ONeb6OoXvkManxKfkaswT2ybOChAzJR8dQ== T-MOBILE diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/meta/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/meta/main.yaml new file mode 100644 index 00000000..be631e5d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_iosxr_tests diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tasks/cli.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tasks/cli.yaml new file mode 100644 index 00000000..ab72bff1 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tasks/cli.yaml @@ -0,0 +1,34 @@ +--- +- name: Collect all common test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: common_test_cases + delegate_to: localhost + +- name: Collect all CLI test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + use_regex: true + register: test_cases + delegate_to: localhost + +- name: Set facts + ansible.builtin.set_fact: + test_cases: + files: "{{ common_test_cases.files + test_cases.files }}" + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.network_cli) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - network_cli diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tasks/main.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tasks/main.yaml new file mode 100644 index 00000000..419a6cde --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tasks/main.yaml @@ -0,0 +1,6 @@ +--- +- name: Include the CLI tasks + ansible.builtin.include_tasks: cli.yaml + +- name: Include the netconf tasks + ansible.builtin.include_tasks: netconf.yaml diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tasks/netconf.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tasks/netconf.yaml new file mode 100644 index 00000000..855bba5c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tasks/netconf.yaml @@ -0,0 +1,32 @@ +--- +- name: Collect all common test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + register: common_test_cases + delegate_to: localhost + +- name: Collect all netconf test cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/netconf" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: Set facts + ansible.builtin.set_fact: + test_cases: + files: "{{ common_test_cases.files + test_cases.files }}" + +- name: Set test_items + ansible.builtin.set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: Run test case (connection=ansible.netcommon.netconf) + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + vars: + ansible_connection: ansible.netcommon.netconf + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + tags: + - netconf diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tests/cli/basic.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tests/cli/basic.yaml new file mode 100644 index 00000000..d8c12a8a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tests/cli/basic.yaml @@ -0,0 +1,165 @@ +--- +- name: Remove users prior to tests + cisco.iosxr.iosxr_config: + lines: + - no username ansibletest1 + - no username ansibletest2 + - no username ansibletest3 + +- name: Create user (setup) + register: result + cisco.iosxr.iosxr_user: + name: ansibletest1 + configured_password: test + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"username" in result.commands[0]' + - '"secret" in result.commands[1]' + +- name: Create user with update_password always (not idempotent) + register: result + cisco.iosxr.iosxr_user: + name: ansibletest1 + configured_password: test + update_password: always + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"username" in result.commands[0]' + - '"secret" in result.commands[0]' + +- name: Create user again with update_password on_create (idempotent) + register: result + cisco.iosxr.iosxr_user: + name: ansibletest1 + configured_password: test + update_password: on_create + state: present + +- ansible.builtin.assert: + that: + - result.changed == false + - result.commands | length == 0 + +- name: Modify user group + register: result + cisco.iosxr.iosxr_user: + name: ansibletest1 + configured_password: test + update_password: on_create + group: sysadmin + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"username" in result.commands[0]' + - '"group" in result.commands[0]' + +- name: Modify user group again (idempotent) + register: result + cisco.iosxr.iosxr_user: + name: ansibletest1 + configured_password: test + update_password: on_create + group: sysadmin + state: present + +- ansible.builtin.assert: + that: + - result.changed == false + - result.commands | length == 0 + +- name: Collection of users (setup) + register: result + cisco.iosxr.iosxr_user: + aggregate: + - name: ansibletest2 + + - name: ansibletest3 + configured_password: test + state: present + group: sysadmin + +- ansible.builtin.assert: + that: + - result.changed == true + - '"username" in result.commands[0]' + - '"secret" in result.commands[1]' + - '"group sysadmin" in result.commands[2]' + - '"username" in result.commands[3]' + - '"secret" in result.commands[4]' + - '"group sysadmin" in result.commands[5]' + +- name: Add collection of users again with update_password always (not idempotent) + register: result + cisco.iosxr.iosxr_user: + aggregate: + - name: ansibletest2 + + - name: ansibletest3 + configured_password: test + state: present + group: sysadmin + +- ansible.builtin.assert: + that: + - result.changed == true + - '"username" in result.commands[0]' + - '"secret" in result.commands[0]' + - '"username" in result.commands[1]' + - '"secret" in result.commands[1]' + +- name: Add collection of users again with update_password on_create (idempotent) + register: result + cisco.iosxr.iosxr_user: + aggregate: + - name: ansibletest2 + + - name: ansibletest3 + configured_password: test + update_password: on_create + state: present + group: sysadmin + +- ansible.builtin.assert: + that: + - result.changed == false + - result.commands | length == 0 + +- name: Delete collection of users + register: result + cisco.iosxr.iosxr_user: + aggregate: + - name: ansibletest1 + + - name: ansibletest2 + + - name: ansibletest3 + state: absent + +- ansible.builtin.assert: + that: + - result.changed == true + - result.commands == ["no username ansibletest1", "no username ansibletest2", "no username ansibletest3"] + +- name: Delete collection of users again (idempotent) + register: result + cisco.iosxr.iosxr_user: + aggregate: + - name: ansibletest1 + + - name: ansibletest2 + + - name: ansibletest3 + state: absent + +- ansible.builtin.assert: + that: + - result.changed == false + - result.commands | length == 0 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tests/common/auth.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tests/common/auth.yaml new file mode 100644 index 00000000..3c2e6e46 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tests/common/auth.yaml @@ -0,0 +1,109 @@ +--- +- block: + - name: Create user with password + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_user: + name: auth_user + state: present + configured_password: pass123 + + - name: Test login + ansible.builtin.expect: + command: ssh auth_user@{{ ansible_ssh_host }} -p {{ ansible_ssh_port|default(22) }} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no show version + responses: + (?i)password: pass123 + connection: ansible.netcommon.network_cli + + - name: Test login with invalid password (should fail) + ansible.builtin.expect: + command: ssh auth_user@{{ ansible_ssh_host }} -p {{ ansible_ssh_port|default(22) }} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no show version + responses: + (?i)password: badpass + ignore_errors: true + connection: ansible.netcommon.network_cli + register: results + + - name: Check that attempt failed + ansible.builtin.assert: + that: + - results.failed + + - name: Create user with private key (contents input) + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_user: + name: auth_user + state: present + public_key_contents: '{{ lookup(''file'', "{{ role_path }}/files/public.pub") }}' + + - name: Test login with private key + ansible.builtin.expect: + command: + ssh auth_user@{{ ansible_ssh_host }} -p {{ ansible_ssh_port|default(22) }} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i {{ role_path + }}/files/private show version + responses: + (?i)password: pass123 + connection: ansible.netcommon.network_cli + + - name: Remove user and key + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_user: + name: auth_user + state: absent + + - name: Test login with private key (should fail, no user) + ansible.builtin.expect: + command: + ssh auth_user@{{ ansible_ssh_host }} -p {{ ansible_ssh_port|default(22) }} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i {{ role_path + }}/files/private show version + responses: + (?i)password: pass123 + ignore_errors: true + connection: ansible.netcommon.network_cli + register: results + + - name: Create user with private key (path input) + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_user: + name: auth_user + state: present + public_key: "{{ role_path }}/files/public.pub" + + - name: Test login with private key + ansible.builtin.expect: + command: + ssh auth_user@{{ ansible_ssh_host }} -p {{ ansible_ssh_port|default(22) }} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i {{ role_path + }}/files/private show version + responses: + (?i)password: pass123 + ignore_errors: true + connection: ansible.netcommon.network_cli + + - name: Change private key for user + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_user: + name: auth_user + state: present + public_key_contents: '{{ lookup(''file'', "{{ role_path }}/files/public2.pub") }}' + + - name: Test login with invalid private key (should fail) + ansible.builtin.expect: + command: + ssh auth_user@{{ ansible_ssh_host }} -p {{ ansible_ssh_port|default(22) }} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i {{ role_path + }}/files/private show version + responses: + (?i)password: pass123 + ignore_errors: true + connection: ansible.netcommon.network_cli + register: results + + - name: Check that attempt failed + ansible.builtin.assert: + that: + - results.failed + always: + - name: Delete user + connection: ansible.netcommon.network_cli + register: result + cisco.iosxr.iosxr_user: + name: auth_user + state: absent diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tests/netconf/_basic.yaml b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tests/netconf/_basic.yaml new file mode 100644 index 00000000..6107ff02 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/iosxr_user/tests/netconf/_basic.yaml @@ -0,0 +1,177 @@ +--- +- name: Remove users prior to tests + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_config: + lines: + - no username ansible1 + - no username ansible2 + - no username ansible3 + +- name: Create user (setup) + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_user: + name: ansible1 + configured_password: password + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"ansible1" in result.xml[0]' + - '"secret" in result.xml[0]' + +- name: Create user with update_password always (not idempotent) + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_user: + name: ansible1 + configured_password: password + update_password: always + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"ansible1" in result.xml[0]' + - '"secret" in result.xml[0]' + +- name: Create user again with update_password on_create (idempotent) + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_user: + name: ansible1 + configured_password: password + update_password: on_create + state: present + +- ansible.builtin.assert: + that: + - result.changed == false + - result.xml | length == 0 + +- name: Modify user group + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_user: + name: ansible1 + configured_password: password + update_password: on_create + group: sysadmin + state: present + +- ansible.builtin.assert: + that: + - result.changed == true + - '"ansible1" in result.xml[0]' + - '"sysadmin" in result.xml[0]' + +- name: Modify user group again (idempotent) + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_user: + name: ansible1 + configured_password: password + update_password: on_create + group: sysadmin + state: present + +- ansible.builtin.assert: + that: + - result.changed == false + - result.xml | length == 0 + +- name: Collection of users (setup) + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_user: + aggregate: + - name: ansible2 + + - name: ansible3 + configured_password: password + state: present + group: sysadmin + +- ansible.builtin.assert: + that: + - result.changed == true + - '"ansible2" in result.xml[0]' + - '"secret" in result.xml[0]' + - '"sysadmin" in result.xml[1]' + - '"ansible2" in result.xml[0]' + - '"secret" in result.xml[0]' + - '"sysadmin" in result.xml[1]' + +- name: Add collection of users again with update_password always (not idempotent) + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_user: + aggregate: + - name: ansible2 + + - name: ansible3 + configured_password: password + state: present + group: sysadmin + +- ansible.builtin.assert: + that: + - result.changed == true + - '"ansible2" in result.xml[0]' + - '"ansible3" in result.xml[0]' + - '"secret" in result.xml[0]' + +- name: Add collection of users again with update_password on_create (idempotent) + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_user: + aggregate: + - name: ansible2 + + - name: ansible3 + configured_password: password + update_password: on_create + state: present + group: sysadmin + +- ansible.builtin.assert: + that: + - result.changed == false + - result.xml | length == 0 + +- name: Delete collection of users + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_user: + aggregate: + - name: ansible1 + + - name: ansible2 + + - name: ansible3 + state: absent + +- ansible.builtin.assert: + that: + - result.changed == true + - '"ansible1" in result.xml[0]' + - '"ansible2" in result.xml[0]' + - '"ansible3" in result.xml[0]' + +- name: Delete collection of users again (idempotent) + connection: ansible.netcommon.netconf + register: result + cisco.iosxr.iosxr_user: + aggregate: + - name: ansible1 + + - name: ansible2 + + - name: ansible3 + state: absent + +- ansible.builtin.assert: + that: + - result.changed == false + - result.xml | length == 0 diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/prepare_iosxr_tests/tasks/main.yml b/ansible_collections/cisco/iosxr/tests/integration/targets/prepare_iosxr_tests/tasks/main.yml new file mode 100644 index 00000000..d93230f9 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/prepare_iosxr_tests/tasks/main.yml @@ -0,0 +1,17 @@ +--- +- name: Ensure we have loopback 888 for testing + connection: ansible.netcommon.network_cli + cisco.iosxr.iosxr_config: + src: config.j2 + +- name: Enable netconf service + connection: ansible.netcommon.network_cli + tags: netconf + cisco.iosxr.iosxr_netconf: + netconf_port: 830 + netconf_vrf: default + state: present + +- name: Set facts + ansible.builtin.set_fact: + shorter_hostname: '{{ inventory_hostname_short | truncate(10, True, "") }}' diff --git a/ansible_collections/cisco/iosxr/tests/integration/targets/prepare_iosxr_tests/templates/config.j2 b/ansible_collections/cisco/iosxr/tests/integration/targets/prepare_iosxr_tests/templates/config.j2 new file mode 100644 index 00000000..cc89171c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/integration/targets/prepare_iosxr_tests/templates/config.j2 @@ -0,0 +1,3 @@ +interface Loopback888 + description test for ansible + shutdown diff --git a/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.10.txt b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.10.txt new file mode 100644 index 00000000..b61dcef1 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.10.txt @@ -0,0 +1,30 @@ +plugins/action/iosxr.py action-plugin-docs # base class for deprecated network platform modules using `connection: local +plugins/modules/iosxr_bgp.py validate-modules:deprecation-mismatch +plugins/modules/iosxr_bgp.py validate-modules:invalid-documentation +plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/logging_global/logging_global.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py import-2.6!skip +plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py import-2.6!skip +plugins/module_utils/network/iosxr/config/logging_global/logging_global.py import-2.6!skip +plugins/modules/iosxr_acl_interfaces.py import-2.6!skip +plugins/modules/iosxr_ospf_interfaces.py import-2.6!skip +plugins/modules/iosxr_ospfv2.py import-2.6!skip +plugins/modules/iosxr_ospfv3.py import-2.6!skip +plugins/modules/iosxr_bgp_neighbor_address_family.py import-2.6!skip +plugins/modules/iosxr_bgp_address_family.py import-2.6!skip +plugins/modules/iosxr_bgp_global.py import-2.6!skip +plugins/modules/iosxr_prefix_lists.py import-2.6!skip +plugins/modules/iosxr_logging_global.py import-2.6!skip diff --git a/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.11.txt b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.11.txt new file mode 100644 index 00000000..b83ac9dc --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.11.txt @@ -0,0 +1,36 @@ +plugins/action/iosxr.py action-plugin-docs # base class for deprecated network platform modules using `connection: local +plugins/modules/iosxr_bgp.py validate-modules:deprecation-mismatch +plugins/modules/iosxr_bgp.py validate-modules:invalid-documentation +plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/logging_global/logging_global.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py import-2.6!skip +plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py import-2.6!skip +plugins/module_utils/network/iosxr/config/logging_global/logging_global.py import-2.6!skip +plugins/modules/iosxr_acl_interfaces.py import-2.6!skip +plugins/modules/iosxr_ospf_interfaces.py import-2.6!skip +plugins/modules/iosxr_ospfv2.py import-2.6!skip +plugins/modules/iosxr_ospfv3.py import-2.6!skip +plugins/modules/iosxr_bgp_neighbor_address_family.py import-2.6!skip +plugins/modules/iosxr_bgp_address_family.py import-2.6!skip +plugins/modules/iosxr_bgp_global.py import-2.6!skip +plugins/modules/iosxr_prefix_lists.py import-2.6!skip +plugins/modules/iosxr_logging_global.py import-2.6!skip +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.7!skip +plugins/sub_plugins/grpc/iosxr.py import-3.7!skip +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.8!skip +plugins/sub_plugins/grpc/iosxr.py import-3.8!skip +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.9!skip +plugins/sub_plugins/grpc/iosxr.py import-3.9!skip diff --git a/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.12.txt b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.12.txt new file mode 100644 index 00000000..393d598b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.12.txt @@ -0,0 +1,39 @@ +plugins/action/iosxr.py action-plugin-docs # base class for deprecated network platform modules using `connection: local +plugins/modules/iosxr_bgp.py validate-modules:deprecation-mismatch +plugins/modules/iosxr_bgp.py validate-modules:invalid-documentation +plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/logging_global/logging_global.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py import-2.6!skip +plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py import-2.6!skip +plugins/module_utils/network/iosxr/config/logging_global/logging_global.py import-2.6!skip +plugins/modules/iosxr_acl_interfaces.py import-2.6!skip +plugins/modules/iosxr_ospf_interfaces.py import-2.6!skip +plugins/modules/iosxr_ospfv2.py import-2.6!skip +plugins/modules/iosxr_ospfv3.py import-2.6!skip +plugins/modules/iosxr_bgp_neighbor_address_family.py import-2.6!skip +plugins/modules/iosxr_bgp_address_family.py import-2.6!skip +plugins/modules/iosxr_bgp_global.py import-2.6!skip +plugins/modules/iosxr_prefix_lists.py import-2.6!skip +plugins/modules/iosxr_logging_global.py import-2.6!skip +plugins/cliconf/iosxr.py pylint:arguments-renamed +plugins/netconf/iosxr.py pylint:arguments-renamed +tests/unit/mock/loader.py pylint:arguments-renamed +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.8!skip +plugins/sub_plugins/grpc/iosxr.py import-3.8!skip +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.9!skip +plugins/sub_plugins/grpc/iosxr.py import-3.9!skip +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.10!skip +plugins/sub_plugins/grpc/iosxr.py import-3.10!skip diff --git a/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.13.txt b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.13.txt new file mode 100644 index 00000000..b00006c2 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.13.txt @@ -0,0 +1,12 @@ +plugins/action/iosxr.py action-plugin-docs # base class for deprecated network platform modules using `connection: local +plugins/modules/iosxr_bgp.py validate-modules:deprecation-mismatch +plugins/modules/iosxr_bgp.py validate-modules:invalid-documentation +plugins/cliconf/iosxr.py pylint:arguments-renamed +plugins/netconf/iosxr.py pylint:arguments-renamed +tests/unit/mock/loader.py pylint:arguments-renamed +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.8!skip +plugins/sub_plugins/grpc/iosxr.py import-3.8!skip +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.9!skip +plugins/sub_plugins/grpc/iosxr.py import-3.9!skip +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.10!skip +plugins/sub_plugins/grpc/iosxr.py import-3.10!skip diff --git a/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.14.txt b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.14.txt new file mode 100644 index 00000000..ad1f84d8 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.14.txt @@ -0,0 +1,12 @@ +plugins/action/iosxr.py action-plugin-docs # base class for deprecated network platform modules using `connection: local +plugins/modules/iosxr_bgp.py validate-modules:deprecation-mismatch +plugins/modules/iosxr_bgp.py validate-modules:invalid-documentation +plugins/cliconf/iosxr.py pylint:arguments-renamed +plugins/netconf/iosxr.py pylint:arguments-renamed +tests/unit/mock/loader.py pylint:arguments-renamed +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.9!skip +plugins/sub_plugins/grpc/iosxr.py import-3.9!skip +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.10!skip +plugins/sub_plugins/grpc/iosxr.py import-3.10!skip +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.11!skip +plugins/sub_plugins/grpc/iosxr.py import-3.11!skip diff --git a/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.15.txt b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.15.txt new file mode 100644 index 00000000..ad1f84d8 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.15.txt @@ -0,0 +1,12 @@ +plugins/action/iosxr.py action-plugin-docs # base class for deprecated network platform modules using `connection: local +plugins/modules/iosxr_bgp.py validate-modules:deprecation-mismatch +plugins/modules/iosxr_bgp.py validate-modules:invalid-documentation +plugins/cliconf/iosxr.py pylint:arguments-renamed +plugins/netconf/iosxr.py pylint:arguments-renamed +tests/unit/mock/loader.py pylint:arguments-renamed +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.9!skip +plugins/sub_plugins/grpc/iosxr.py import-3.9!skip +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.10!skip +plugins/sub_plugins/grpc/iosxr.py import-3.10!skip +plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py import-3.11!skip +plugins/sub_plugins/grpc/iosxr.py import-3.11!skip diff --git a/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.9.txt b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.9.txt new file mode 100644 index 00000000..eedc28b7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/sanity/ignore-2.9.txt @@ -0,0 +1,32 @@ +plugins/action/iosxr.py action-plugin-docs # base class for deprecated network platform modules using `connection: local +plugins/modules/iosxr_logging.py validate-modules:deprecation-mismatch # 2.9 expects METADATA +plugins/modules/iosxr_logging.py validate-modules:invalid-documentation # removed_at_date not supported in `deprecated` dict +plugins/modules/iosxr_bgp.py validate-modules:deprecation-mismatch +plugins/modules/iosxr_bgp.py validate-modules:invalid-documentation +plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/logging_global/logging_global.py compile-2.6!skip +plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py import-2.6!skip +plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py import-2.6!skip +plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py import-2.6!skip +plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py import-2.6!skip +plugins/module_utils/network/iosxr/config/logging_global/logging_global.py import-2.6!skip +plugins/modules/iosxr_acl_interfaces.py import-2.6!skip +plugins/modules/iosxr_ospf_interfaces.py import-2.6!skip +plugins/modules/iosxr_ospfv2.py import-2.6!skip +plugins/modules/iosxr_ospfv3.py import-2.6!skip +plugins/modules/iosxr_bgp_neighbor_address_family.py import-2.6!skip +plugins/modules/iosxr_bgp_address_family.py import-2.6!skip +plugins/modules/iosxr_bgp_global.py import-2.6!skip +plugins/modules/iosxr_prefix_lists.py import-2.6!skip +plugins/modules/iosxr_logging_global.py import-2.6!skip diff --git a/ansible_collections/cisco/iosxr/tests/unit/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/__init__.py diff --git a/ansible_collections/cisco/iosxr/tests/unit/compat/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/compat/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/compat/__init__.py diff --git a/ansible_collections/cisco/iosxr/tests/unit/compat/builtins.py b/ansible_collections/cisco/iosxr/tests/unit/compat/builtins.py new file mode 100644 index 00000000..e898a081 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/compat/builtins.py @@ -0,0 +1,35 @@ +# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +# +# Compat for python2.7 +# + +# One unittest needs to import builtins via __import__() so we need to have +# the string that represents it +try: + import __builtin__ +except ImportError: + BUILTINS = "builtins" +else: + BUILTINS = "__builtin__" diff --git a/ansible_collections/cisco/iosxr/tests/unit/compat/mock.py b/ansible_collections/cisco/iosxr/tests/unit/compat/mock.py new file mode 100644 index 00000000..e4ce72b3 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/compat/mock.py @@ -0,0 +1,129 @@ +# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +""" +Compat module for Python3.x's unittest.mock module +""" +import sys + +import _io + + +# Python 2.7 + +# Note: Could use the pypi mock library on python3.x as well as python2.x. It +# is the same as the python3 stdlib mock library + +try: + # Allow wildcard import because we really do want to import all of mock's + # symbols into this compat shim + # pylint: disable=wildcard-import,unused-wildcard-import + from unittest.mock import * +except ImportError: + # Python 2 + # pylint: disable=wildcard-import,unused-wildcard-import + try: + from mock import * + except ImportError: + print("You need the mock library installed on python2.x to run tests") + + +# Prior to 3.4.4, mock_open cannot handle binary read_data +if sys.version_info >= (3,) and sys.version_info < (3, 4, 4): + file_spec = None + + def _iterate_read_data(read_data): + # Helper for mock_open: + # Retrieve lines from read_data via a generator so that separate calls to + # readline, read, and readlines are properly interleaved + sep = b"\n" if isinstance(read_data, bytes) else "\n" + data_as_list = [l + sep for l in read_data.split(sep)] + + if data_as_list[-1] == sep: + # If the last line ended in a newline, the list comprehension will have an + # extra entry that's just a newline. Remove this. + data_as_list = data_as_list[:-1] + else: + # If there wasn't an extra newline by itself, then the file being + # emulated doesn't have a newline to end the last line remove the + # newline that our naive format() added + data_as_list[-1] = data_as_list[-1][:-1] + + for line in data_as_list: + yield line + + def mock_open(mock=None, read_data=""): + """ + A helper function to create a mock to replace the use of `open`. It works + for `open` called directly or used as a context manager. + + The `mock` argument is the mock object to configure. If `None` (the + default) then a `MagicMock` will be created for you, with the API limited + to methods or attributes available on standard file handles. + + `read_data` is a string for the `read` methoddline`, and `readlines` of the + file handle to return. This is an empty string by default. + """ + + def _readlines_side_effect(*args, **kwargs): + if handle.readlines.return_value is not None: + return handle.readlines.return_value + return list(_data) + + def _read_side_effect(*args, **kwargs): + if handle.read.return_value is not None: + return handle.read.return_value + return type(read_data)().join(_data) + + def _readline_side_effect(): + if handle.readline.return_value is not None: + while True: + yield handle.readline.return_value + for line in _data: + yield line + + global file_spec + if file_spec is None: + file_spec = list( + set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))), + ) + + if mock is None: + mock = MagicMock(name="open", spec=open) + + handle = MagicMock(spec=file_spec) + handle.__enter__.return_value = handle + + _data = _iterate_read_data(read_data) + + handle.write.return_value = None + handle.read.return_value = None + handle.readline.return_value = None + handle.readlines.return_value = None + + handle.read.side_effect = _read_side_effect + handle.readline.side_effect = _readline_side_effect() + handle.readlines.side_effect = _readlines_side_effect + + mock.return_value = handle + return mock diff --git a/ansible_collections/cisco/iosxr/tests/unit/compat/unittest.py b/ansible_collections/cisco/iosxr/tests/unit/compat/unittest.py new file mode 100644 index 00000000..df4266ec --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/compat/unittest.py @@ -0,0 +1,41 @@ +# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +""" +Compat module for Python2.7's unittest module +""" + +import sys + + +# Allow wildcard import because we really do want to import all of +# unittests's symbols into this compat shim +# pylint: disable=wildcard-import,unused-wildcard-import +if sys.version_info < (2, 7): + try: + # Need unittest2 on python2.6 + from unittest2 import * + except ImportError: + print("You need unittest2 installed on python2.6.x to run tests") +else: + from unittest import * diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/mock/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/mock/__init__.py diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/loader.py b/ansible_collections/cisco/iosxr/tests/unit/mock/loader.py new file mode 100644 index 00000000..2b5eb36a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/mock/loader.py @@ -0,0 +1,117 @@ +# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +import os + +from ansible.errors import AnsibleParserError +from ansible.module_utils._text import to_bytes, to_text +from ansible.parsing.dataloader import DataLoader + + +class DictDataLoader(DataLoader): + def __init__(self, file_mapping=None): + file_mapping = {} if file_mapping is None else file_mapping + assert type(file_mapping) == dict + + super(DictDataLoader, self).__init__() + + self._file_mapping = file_mapping + self._build_known_directories() + self._vault_secrets = None + + def load_from_file(self, path, cache=True, unsafe=False): + path = to_text(path) + if path in self._file_mapping: + return self.load(self._file_mapping[path], path) + return None + + # TODO: the real _get_file_contents returns a bytestring, so we actually convert the + # unicode/text it's created with to utf-8 + def _get_file_contents(self, path): + path = to_text(path) + if path in self._file_mapping: + return (to_bytes(self._file_mapping[path]), False) + else: + raise AnsibleParserError("file not found: %s" % path) + + def path_exists(self, path): + path = to_text(path) + return path in self._file_mapping or path in self._known_directories + + def is_file(self, path): + path = to_text(path) + return path in self._file_mapping + + def is_directory(self, path): + path = to_text(path) + return path in self._known_directories + + def list_directory(self, path): + ret = [] + path = to_text(path) + for x in list(self._file_mapping.keys()) + self._known_directories: + if x.startswith(path): + if os.path.dirname(x) == path: + ret.append(os.path.basename(x)) + return ret + + def is_executable(self, path): + # FIXME: figure out a way to make paths return true for this + return False + + def _add_known_directory(self, directory): + if directory not in self._known_directories: + self._known_directories.append(directory) + + def _build_known_directories(self): + self._known_directories = [] + for path in self._file_mapping: + dirname = os.path.dirname(path) + while dirname not in ("/", ""): + self._add_known_directory(dirname) + dirname = os.path.dirname(dirname) + + def push(self, path, content): + rebuild_dirs = False + if path not in self._file_mapping: + rebuild_dirs = True + + self._file_mapping[path] = content + + if rebuild_dirs: + self._build_known_directories() + + def pop(self, path): + if path in self._file_mapping: + del self._file_mapping[path] + self._build_known_directories() + + def clear(self): + self._file_mapping = dict() + self._known_directories = [] + + def get_basedir(self): + return os.getcwd() + + def set_vault_secrets(self, vault_secrets): + self._vault_secrets = vault_secrets diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/path.py b/ansible_collections/cisco/iosxr/tests/unit/mock/path.py new file mode 100644 index 00000000..0c87896d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/mock/path.py @@ -0,0 +1,13 @@ +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type +from ansible.utils.path import unfrackpath + +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import MagicMock + + +mock_unfrackpath_noop = MagicMock( + spec_set=unfrackpath, + side_effect=lambda x, *args, **kwargs: x, +) diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/procenv.py b/ansible_collections/cisco/iosxr/tests/unit/mock/procenv.py new file mode 100644 index 00000000..3a4231bd --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/mock/procenv.py @@ -0,0 +1,97 @@ +# (c) 2016, Matt Davis <mdavis@ansible.com> +# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +import json +import sys + +from contextlib import contextmanager +from io import BytesIO, StringIO + +from ansible.module_utils._text import to_bytes +from ansible.module_utils.six import PY3 + +from ansible_collections.cisco.iosxr.tests.unit.compat import unittest + + +@contextmanager +def swap_stdin_and_argv(stdin_data="", argv_data=tuple()): + """ + context manager that temporarily masks the test runner's values for stdin and argv + """ + real_stdin = sys.stdin + real_argv = sys.argv + + if PY3: + fake_stream = StringIO(stdin_data) + fake_stream.buffer = BytesIO(to_bytes(stdin_data)) + else: + fake_stream = BytesIO(to_bytes(stdin_data)) + + try: + sys.stdin = fake_stream + sys.argv = argv_data + + yield + finally: + sys.stdin = real_stdin + sys.argv = real_argv + + +@contextmanager +def swap_stdout(): + """ + context manager that temporarily replaces stdout for tests that need to verify output + """ + old_stdout = sys.stdout + + if PY3: + fake_stream = StringIO() + else: + fake_stream = BytesIO() + + try: + sys.stdout = fake_stream + + yield fake_stream + finally: + sys.stdout = old_stdout + + +class ModuleTestCase(unittest.TestCase): + def setUp(self, module_args=None): + if module_args is None: + module_args = { + "_ansible_remote_tmp": "/tmp", + "_ansible_keep_remote_files": False, + } + + args = json.dumps(dict(ANSIBLE_MODULE_ARGS=module_args)) + + # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually + self.stdin_swap = swap_stdin_and_argv(stdin_data=args) + self.stdin_swap.__enter__() + + def tearDown(self): + # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually + self.stdin_swap.__exit__(None, None, None) diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/vault_helper.py b/ansible_collections/cisco/iosxr/tests/unit/mock/vault_helper.py new file mode 100644 index 00000000..82d01f5c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/mock/vault_helper.py @@ -0,0 +1,44 @@ +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible.module_utils._text import to_bytes +from ansible.parsing.vault import VaultSecret + + +class TextVaultSecret(VaultSecret): + """A secret piece of text. ie, a password. Tracks text encoding. + + The text encoding of the text may not be the default text encoding so + we keep track of the encoding so we encode it to the same bytes.""" + + def __init__(self, text, encoding=None, errors=None, _bytes=None): + super(TextVaultSecret, self).__init__() + self.text = text + self.encoding = encoding or "utf-8" + self._bytes = _bytes + self.errors = errors or "strict" + + @property + def bytes(self): + """The text encoded with encoding, unless we specifically set _bytes.""" + return self._bytes or to_bytes( + self.text, + encoding=self.encoding, + errors=self.errors, + ) diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/yaml_helper.py b/ansible_collections/cisco/iosxr/tests/unit/mock/yaml_helper.py new file mode 100644 index 00000000..e46d3180 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/mock/yaml_helper.py @@ -0,0 +1,177 @@ +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type +import io + +import yaml + +from ansible.module_utils.six import PY3 +from ansible.parsing.yaml.dumper import AnsibleDumper +from ansible.parsing.yaml.loader import AnsibleLoader + + +class YamlTestUtils(object): + """Mixin class to combine with a unittest.TestCase subclass.""" + + def _loader(self, stream): + """Vault related tests will want to override this. + + Vault cases should setup a AnsibleLoader that has the vault password.""" + return AnsibleLoader(stream) + + def _dump_stream(self, obj, stream, dumper=None): + """Dump to a py2-unicode or py3-string stream.""" + if PY3: + return yaml.dump(obj, stream, Dumper=dumper) + else: + return yaml.dump(obj, stream, Dumper=dumper, encoding=None) + + def _dump_string(self, obj, dumper=None): + """Dump to a py2-unicode or py3-string""" + if PY3: + return yaml.dump(obj, Dumper=dumper) + else: + return yaml.dump(obj, Dumper=dumper, encoding=None) + + def _dump_load_cycle(self, obj): + # Each pass though a dump or load revs the 'generation' + # obj to yaml string + string_from_object_dump = self._dump_string(obj, dumper=AnsibleDumper) + + # wrap a stream/file like StringIO around that yaml + stream_from_object_dump = io.StringIO(string_from_object_dump) + loader = self._loader(stream_from_object_dump) + # load the yaml stream to create a new instance of the object (gen 2) + obj_2 = loader.get_data() + + # dump the gen 2 objects directory to strings + string_from_object_dump_2 = self._dump_string( + obj_2, + dumper=AnsibleDumper, + ) + + # The gen 1 and gen 2 yaml strings + self.assertEqual(string_from_object_dump, string_from_object_dump_2) + # the gen 1 (orig) and gen 2 py object + self.assertEqual(obj, obj_2) + + # again! gen 3... load strings into py objects + stream_3 = io.StringIO(string_from_object_dump_2) + loader_3 = self._loader(stream_3) + obj_3 = loader_3.get_data() + + string_from_object_dump_3 = self._dump_string( + obj_3, + dumper=AnsibleDumper, + ) + + self.assertEqual(obj, obj_3) + # should be transitive, but... + self.assertEqual(obj_2, obj_3) + self.assertEqual(string_from_object_dump, string_from_object_dump_3) + + def _old_dump_load_cycle(self, obj): + """Dump the passed in object to yaml, load it back up, dump again, compare.""" + stream = io.StringIO() + + yaml_string = self._dump_string(obj, dumper=AnsibleDumper) + self._dump_stream(obj, stream, dumper=AnsibleDumper) + + yaml_string_from_stream = stream.getvalue() + + # reset stream + stream.seek(0) + + loader = self._loader(stream) + # loader = AnsibleLoader(stream, vault_password=self.vault_password) + obj_from_stream = loader.get_data() + + stream_from_string = io.StringIO(yaml_string) + loader2 = self._loader(stream_from_string) + # loader2 = AnsibleLoader(stream_from_string, vault_password=self.vault_password) + obj_from_string = loader2.get_data() + + stream_obj_from_stream = io.StringIO() + stream_obj_from_string = io.StringIO() + + if PY3: + yaml.dump( + obj_from_stream, + stream_obj_from_stream, + Dumper=AnsibleDumper, + ) + yaml.dump( + obj_from_stream, + stream_obj_from_string, + Dumper=AnsibleDumper, + ) + else: + yaml.dump( + obj_from_stream, + stream_obj_from_stream, + Dumper=AnsibleDumper, + encoding=None, + ) + yaml.dump( + obj_from_stream, + stream_obj_from_string, + Dumper=AnsibleDumper, + encoding=None, + ) + + yaml_string_stream_obj_from_stream = stream_obj_from_stream.getvalue() + yaml_string_stream_obj_from_string = stream_obj_from_string.getvalue() + + stream_obj_from_stream.seek(0) + stream_obj_from_string.seek(0) + + if PY3: + yaml_string_obj_from_stream = yaml.dump( + obj_from_stream, + Dumper=AnsibleDumper, + ) + yaml_string_obj_from_string = yaml.dump( + obj_from_string, + Dumper=AnsibleDumper, + ) + else: + yaml_string_obj_from_stream = yaml.dump( + obj_from_stream, + Dumper=AnsibleDumper, + encoding=None, + ) + yaml_string_obj_from_string = yaml.dump( + obj_from_string, + Dumper=AnsibleDumper, + encoding=None, + ) + + assert yaml_string == yaml_string_obj_from_stream + assert yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string + assert ( + yaml_string + == yaml_string_obj_from_stream + == yaml_string_obj_from_string + == yaml_string_stream_obj_from_stream + == yaml_string_stream_obj_from_string + ) + assert obj == obj_from_stream + assert obj == obj_from_string + assert obj == yaml_string_obj_from_stream + assert obj == yaml_string_obj_from_string + assert ( + obj + == obj_from_stream + == obj_from_string + == yaml_string_obj_from_stream + == yaml_string_obj_from_string + ) + return { + "obj": obj, + "yaml_string": yaml_string, + "yaml_string_from_stream": yaml_string_from_stream, + "obj_from_stream": obj_from_stream, + "obj_from_string": obj_from_string, + "yaml_string_obj_from_string": yaml_string_obj_from_string, + } diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/modules/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/__init__.py diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/conftest.py b/ansible_collections/cisco/iosxr/tests/unit/modules/conftest.py new file mode 100644 index 00000000..349e71ad --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/conftest.py @@ -0,0 +1,34 @@ +# Copyright (c) 2017 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +import json + +import pytest + +from ansible.module_utils._text import to_bytes +from ansible.module_utils.common._collections_compat import MutableMapping +from ansible.module_utils.six import string_types + + +@pytest.fixture +def patch_ansible_module(request, mocker): + if isinstance(request.param, string_types): + args = request.param + elif isinstance(request.param, MutableMapping): + if "ANSIBLE_MODULE_ARGS" not in request.param: + request.param = {"ANSIBLE_MODULE_ARGS": request.param} + if "_ansible_remote_tmp" not in request.param["ANSIBLE_MODULE_ARGS"]: + request.param["ANSIBLE_MODULE_ARGS"]["_ansible_remote_tmp"] = "/tmp" + if "_ansible_keep_remote_files" not in request.param["ANSIBLE_MODULE_ARGS"]: + request.param["ANSIBLE_MODULE_ARGS"]["_ansible_keep_remote_files"] = False + args = json.dumps(request.param) + else: + raise Exception( + "Malformed data to the patch_ansible_module pytest fixture", + ) + + mocker.patch("ansible.module_utils.basic._ANSIBLE_ARGS", to_bytes(args)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/__init__.py diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/__init__.py diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/__init__.py diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_running-config_hostname b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_running-config_hostname new file mode 100644 index 00000000..ebc5bf85 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_running-config_hostname @@ -0,0 +1 @@ +hostname iosxr01 diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_version__utility_head_-n_20 b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_version__utility_head_-n_20 new file mode 100644 index 00000000..6922cbbf --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_version__utility_head_-n_20 @@ -0,0 +1,17 @@ +Cisco IOS XR Software, Version 6.0.0[Default] +Copyright (c) 2015 by Cisco Systems, Inc. + +ROM: GRUB, Version 1.99(0), DEV RELEASE + +iosxr01 uptime is 11 weeks, 2 days, 5 hours, 48 minutes +System image file is "bootflash:disk0/xrvr-os-mbi-6.0.0/mbixrvr-rp.vm" + +cisco IOS XRv Series (Pentium Celeron Stepping 3) processor with 3169911K bytes of memory. +Pentium Celeron Stepping 3 processor at 3836MHz, Revision 2.174 +IOS XRv Chassis + +1 Management Ethernet +6 GigabitEthernet +97070k bytes of non-volatile configuration memory. +866M bytes of hard disk. +2321392k bytes of disk0: (Sector size 512 bytes). diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_running-config_hostname b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_running-config_hostname new file mode 100644 index 00000000..ebc5bf85 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_running-config_hostname @@ -0,0 +1 @@ +hostname iosxr01 diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_version__utility_head_-n_20 b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_version__utility_head_-n_20 new file mode 100644 index 00000000..5aa174c4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_version__utility_head_-n_20 @@ -0,0 +1,15 @@ +Cisco IOS XR Software, Version 7.5.2 LNT +Copyright (c) 2013-2022 by Cisco Systems, Inc. + +Build Information: + Built By : ingunawa + Built On : Tue Apr 26 23:47:22 UTC 2022 + Build Host : iox-lnx-023 + Workspace : /auto/srcarchive14/prod/7.5.2/ncs540l-aarch64/ws + Version : 7.5.2 + Label : 7.5.2 + +cisco NCS540L +cisco N540X-6Z18G-SYS-A processor with 8GB of memory +iosxr01 uptime is 5 days, 1 hour, 45 minutes +Cisco NCS 540 Series Fixed Router 18x1G, 6x1/10G, AC diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/dir_7all b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/dir_7all new file mode 100644 index 00000000..b992498c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/dir_7all @@ -0,0 +1,6 @@ +Directory of disk0: +file1 +file2 + +Directory of flash0: +file3 diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acl_interfaces_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acl_interfaces_config.cfg new file mode 100644 index 00000000..6a05274a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acl_interfaces_config.cfg @@ -0,0 +1,11 @@ +interface GigabitEthernet0/0/0/0 + shutdown + ipv4 access-group acl_1 ingress + ipv4 access-group acl_2 egress + ipv6 access-group acl6_1 ingress + ipv6 access-group acl6_2 egress +! +interface GigabitEthernet0/0/0/1 + shutdown + ipv4 access-group acl_1 egress +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acls_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acls_config.cfg new file mode 100644 index 00000000..f5d1708c --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acls_config.cfg @@ -0,0 +1,8 @@ +ipv4 access-list acl_2 + 10 deny ipv4 any any + 20 permit tcp host 192.168.1.100 any +ipv4 access-list acl_1 + 10 deny ipv4 10.233.0.0 0.0.255.255 net-group netgroup1 + 20 deny ipv4 10.233.0.0 0.0.255.255 port-group portgroup1 +ipv6 access-list acl6_1 + 10 deny icmpv6 any any diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_banner_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_banner_config.cfg new file mode 100644 index 00000000..ed8e6d6d --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_banner_config.cfg @@ -0,0 +1,2 @@ +banner motd this is my motd banner +banner login this is my login banner diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_config.cfg new file mode 100644 index 00000000..afad9d08 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_config.cfg @@ -0,0 +1,12 @@ +! +hostname router +! +interface GigabitEthernet0/0 + ip address 1.2.3.4 255.255.255.0 + description test string +! +interface GigabitEthernet0/1 + ip address 6.7.8.9 255.255.255.0 + description test string + shutdown +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_src.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_src.cfg new file mode 100644 index 00000000..b3d8961a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_src.cfg @@ -0,0 +1,11 @@ +! +hostname foo +! +interface GigabitEthernet0/0 + no ip address +! +interface GigabitEthernet0/1 + ip address 6.7.8.9 255.255.255.0 + description test string + shutdown +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_interface_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_interface_config.cfg new file mode 100644 index 00000000..700dde0a --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_interface_config.cfg @@ -0,0 +1,9 @@ +interface GigabitEthernet0/0/0/0 + description Configured and Merged by Ansible-Network + mtu 110 + duplex half +interface GigabitEthernet0/0/0/1 + description Configured and Merged by Ansible-Network + no shutdown + mtu 2800 + speed 100 diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l2_interface_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l2_interface_config.cfg new file mode 100644 index 00000000..4192ee39 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l2_interface_config.cfg @@ -0,0 +1,9 @@ +interface GigabitEthernet0/0/0/1 + l2transport + l2protocol cpsv tunnel + propagate remote-status + ! +! +interface GigabitEthernet0/0/0/3.900 + encapsulation dot1q 20 second-dot1q 40 +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l3_interface_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l3_interface_config.cfg new file mode 100644 index 00000000..d870f4e8 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l3_interface_config.cfg @@ -0,0 +1,6 @@ +interface GigabitEthernet0/0/0/0 +ipv4 address 198.51.100.1 255.255.255.0 +ipv6 address 2001:db8::/32 +interface GigabitEthernet0/0/0/1 +ipv4 address 192.0.2.1 255.255.255.0 +ipv4 address 192.0.2.2 255.255.255.0 secondary diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_config.cfg new file mode 100644 index 00000000..01776dbe --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_config.cfg @@ -0,0 +1,2 @@ +lacp system mac 00c1.4c00.bd15 +lacp system priority 12 diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_interfaces_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_interfaces_config.cfg new file mode 100644 index 00000000..b38bb39f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_interfaces_config.cfg @@ -0,0 +1,11 @@ +interface Bundle-Ether10 + lacp churn logging actor + lacp switchover suppress-flaps 500 + lacp collector-max-delay 100 +! +interface Bundle-Ether11 + lacp system mac 00c2.4c00.bd15 +! +interface GigabitEthernet0/0/0/1 + lacp period 200 +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lag_interface_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lag_interface_config.cfg new file mode 100644 index 00000000..256d3f23 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lag_interface_config.cfg @@ -0,0 +1,24 @@ +interface Bundle-Ether10 + lacp mode active + bundle maximum-active links 10 + bundle minimum-active links 2 +! +interface Bundle-Ether11 +lacp mode active +! +interface GigabitEthernet0/0/0/0 + description "GigabitEthernet - 0" + bundle id 10 mode inherit +! +interface GigabitEthernet0/0/0/1 + description "GigabitEthernet - 2" + bundle id 10 mode passive +! +interface GigabitEthernet0/0/0/8 + description "GigabitEthernet - 8" + bundle id 11 mode passive +! +interface GigabitEthernet0/0/0/9 + description "GigabitEthernet - 9" + bundle id 11 mode passive +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_global_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_global_config.cfg new file mode 100644 index 00000000..4bd23847 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_global_config.cfg @@ -0,0 +1,10 @@ +lldp + timer 3000 + reinit 2 + subinterfaces enable + holdtime 100 + tlv-select + management-address disable + system-description disable + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_interfaces_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_interfaces_config.cfg new file mode 100644 index 00000000..b50b42e5 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_interfaces_config.cfg @@ -0,0 +1,16 @@ +interface TenGigE0/0/0/0 + ipv4 address 192.0.2.11 255.255.255.192 +! +interface preconfigure GigabitEthernet0/0/0/0 + lldp + transmit disable + destination mac-address + ieee-nearest-bridge + ! + ! +! +interface preconfigure GigabitEthernet0/0/0/1 + lldp + receive disable + destination mac-address + ieee-nearest-non-tmpr-bridge diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospf_interfaces.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospf_interfaces.cfg new file mode 100644 index 00000000..9ddb8d66 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospf_interfaces.cfg @@ -0,0 +1,8 @@ +router ospf LAB3 + area 0.0.0.3 + interface GigabitEthernet0/0/0/0 + cost 20 + authentication message-digest keychain cisco + ! + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv2.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv2.cfg new file mode 100644 index 00000000..8645482e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv2.cfg @@ -0,0 +1,8 @@ +Sun Jun 14 12:10:47.455 UTC +router ospf 30 + cost 2 + default-metric 10 + area 11 + default-cost 5 + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv3.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv3.cfg new file mode 100644 index 00000000..b52c0ee0 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv3.cfg @@ -0,0 +1,8 @@ +Sun Jun 14 12:10:47.455 UTC +router ospfv3 30 + cost 2 + default-metric 10 + area 11 + default-cost 5 + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_static_routes_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_static_routes_config.cfg new file mode 100644 index 00000000..35948336 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_static_routes_config.cfg @@ -0,0 +1,18 @@ +Fri Nov 29 21:10:41.896 UTC +router static + address-family ipv4 unicast + 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120 + 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1 + 192.0.2.32/28 192.0.2.11 100 + ! + address-family ipv6 unicast + 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC + 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1 + ! + vrf DEV_SITE + address-family ipv4 unicast + 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV + 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2 + ! + ! +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_system_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_system_config.cfg new file mode 100644 index 00000000..fc6fd2b7 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_system_config.cfg @@ -0,0 +1,8 @@ +hostname iosxr01 +domain name eng.ansible.com +domain lookup disable +domain lookup source-interface MgmtEth0/0/CPU0/0 +domain list redhat.com +domain list cisco.com +domain name-server 8.8.8.8 +domain name-server 8.8.4.4 diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_user_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_user_config.cfg new file mode 100644 index 00000000..0f0ab168 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_user_config.cfg @@ -0,0 +1,8 @@ +username admin + secret 5 $1$mdQIUxjg$3t3lzBpfKfITKvFm1uEIY. + group sysadmin +! +username ansible + secret 5 $1$3yWSXiIi$VdzV59ChiurrNdGxlDeAW/ + group sysadmin +! diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_interfaces b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_interfaces new file mode 100644 index 00000000..edb3c6a0 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_interfaces @@ -0,0 +1,41 @@ +Loopback0 is up, line protocol is up + Interface state transitions: 1 + Hardware is Loopback interface(s) + Description: Loopback + Internet address is 192.168.0.3/32 + MTU 1500 bytes, BW 0 Kbit + reliability Unknown, txload Unknown, rxload Unknown + Encapsulation Loopback, loopback not set, + Last link flapped 12w1d + Last input Unknown, output Unknown + Last clearing of "show interface" counters Unknown + Input/output data rate is disabled. + +GigabitEthernet0/0/0/0 is up, line protocol is up + Interface state transitions: 1 + Hardware is GigabitEthernet, address is fa16.3e6c.20bd (bia fa16.3e6c.20bd) + Description: to nxos01 + Internet address is 10.0.0.5/30 + MTU 1514 bytes, BW 1000000 Kbit (Max: 1000000 Kbit) + reliability 255/255, txload 0/255, rxload 0/255 + Encapsulation ARPA, + Full-duplex, 1000Mb/s, unknown, link type is force-up + output flow control is off, input flow control is off + Carrier delay (up) is 10 msec + loopback not set, + Last link flapped 12w1d + ARP type ARPA, ARP timeout 04:00:00 + Last input 00:00:44, output 00:12:45 + Last clearing of "show interface" counters never + 5 minute input rate 0 bits/sec, 0 packets/sec + 5 minute output rate 0 bits/sec, 0 packets/sec + 150700 packets input, 36897055 bytes, 0 total input drops + 0 drops for unrecognized upper-level protocol + Received 1 broadcast packets, 150445 multicast packets + 0 runts, 0 giants, 0 throttles, 0 parity + 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort + 11691 packets output, 2904632 bytes, 0 total output drops + Output 1 broadcast packets, 11436 multicast packets + 0 output errors, 0 underruns, 0 applique, 0 resets + 0 output buffer failures, 0 output buffers swapped out + 1 carrier transitions diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_ipv6_interface b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_ipv6_interface new file mode 100644 index 00000000..971d1f65 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_ipv6_interface @@ -0,0 +1,5 @@ +Loopback0 is Up, ipv6 protocol is Up, Vrfid is default (0x60000000) + IPv6 is disabled, link-local address unassigned + No global unicast address is configured +GigabitEthernet0/0/0/0 is Up, ipv6 protocol is Up, Vrfid is default (0x60000000) + IPv6 is disabled, link-local address unassigned diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp new file mode 100644 index 00000000..60ab287f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp @@ -0,0 +1 @@ +% LLDP is not enabled diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp_neighbors_detail b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp_neighbors_detail new file mode 100644 index 00000000..60ab287f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp_neighbors_detail @@ -0,0 +1 @@ +% LLDP is not enabled diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_memory_summary b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_memory_summary new file mode 100644 index 00000000..b26abeae --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_memory_summary @@ -0,0 +1,5 @@ +Physical Memory: 3095M total (1499M available) + Application Memory : 2893M (1499M available) + Image: 73M (bootram: 73M) + Reserved: 128M, IOMem: 0, flashfsys: 0 + Total shared window: 23M diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_running-config b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_running-config new file mode 100644 index 00000000..085baef4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_running-config @@ -0,0 +1,43 @@ +hostname iosxr01 +service timestamps log datetime msec +service timestamps debug datetime msec +telnet vrf default ipv4 server max-servers 10 +telnet vrf Mgmt-intf ipv4 server max-servers 10 +domain name eng.ansible.com +domain lookup disable +vrf Mgmt-intf + address-family ipv4 unicast + ! + address-family ipv6 unicast + ! +! +line template vty + timestamp + exec-timeout 720 0 +! +line console + exec-timeout 0 0 +! +line default + exec-timeout 720 0 +! +vty-pool default 0 50 +control-plane + management-plane + inband + interface all + allow all + ! + ! + ! +! +interface Loopback0 + description Loopback + ipv4 address 192.168.0.1 255.255.255.255 +! +interface GigabitEthernet0/0/0/0 + description to nxos01 + cdp + ipv4 address 10.0.0.1 255.255.255.252 +! +end diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version new file mode 100644 index 00000000..faecfffd --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version @@ -0,0 +1,84 @@ +Cisco IOS XR Software, Version 6.0.0[Default] +Copyright (c) 2015 by Cisco Systems, Inc. + +ROM: GRUB, Version 1.99(0), DEV RELEASE + +iosxr01 uptime is 11 weeks, 2 days, 5 hours, 48 minutes +System image file is "bootflash:disk0/xrvr-os-mbi-6.0.0/mbixrvr-rp.vm" + +cisco IOS XRv Series (Pentium Celeron Stepping 3) processor with 3169911K bytes of memory. +Pentium Celeron Stepping 3 processor at 3836MHz, Revision 2.174 +IOS XRv Chassis + +1 Management Ethernet +6 GigabitEthernet +97070k bytes of non-volatile configuration memory. +866M bytes of hard disk. +2321392k bytes of disk0: (Sector size 512 bytes). + +Configuration register on node 0/0/CPU0 is 0x2102 +Boot device on node 0/0/CPU0 is disk0: +Package active on node 0/0/CPU0: +iosxr-infra, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-infra-6.0.0 + Built on Thu Dec 24 08:53:49 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +iosxr-fwding, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-fwding-6.0.0 + Built on Thu Dec 24 08:53:49 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +iosxr-routing, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-routing-6.0.0 + Built on Thu Dec 24 08:53:49 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +iosxr-ce, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-ce-6.0.0 + Built on Thu Dec 24 08:53:49 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +xrvr-os-mbi, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-os-mbi-6.0.0 + Built on Thu Dec 24 08:54:41 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +xrvr-base, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-base-6.0.0 + Built on Thu Dec 24 08:53:49 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +xrvr-fwding, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-fwding-6.0.0 + Built on Thu Dec 24 08:53:49 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +xrvr-mgbl-x, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-mgbl-x-6.0.0 + Built on Thu Dec 24 08:53:57 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +iosxr-mpls, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-mpls-6.0.0 + Built on Thu Dec 24 08:53:49 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +iosxr-mgbl, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-mgbl-6.0.0 + Built on Thu Dec 24 08:53:49 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +iosxr-mcast, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-mcast-6.0.0 + Built on Thu Dec 24 08:53:49 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +xrvr-mcast-supp, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-mcast-supp-6.0.0 + Built on Thu Dec 24 08:53:49 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +iosxr-bng, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-bng-6.0.0 + Built on Thu Dec 24 08:53:47 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +xrvr-bng-supp, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-bng-supp-6.0.0 + Built on Thu Dec 24 08:53:47 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +iosxr-security, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-security-6.0.0 + Built on Thu Dec 24 08:53:41 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie + +xrvr-fullk9-x, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-fullk9-x-6.0.0 + Built on Thu Dec 24 08:55:12 UTC 2015 + By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version___utility_head_-n_20 b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version___utility_head_-n_20 new file mode 100644 index 00000000..7f82039f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version___utility_head_-n_20 @@ -0,0 +1,18 @@ +Cisco IOS XR Software, Version 6.0.0[Default] +Copyright (c) 2015 by Cisco Systems, Inc. + +ROM: GRUB, Version 1.99(0), DEV RELEASE + +iosxr01 uptime is 11 weeks, 6 days, 2 hours, 2 minutes +System image file is "bootflash:disk0/xrvr-os-mbi-6.0.0/mbixrvr-rp.vm" + +cisco IOS XRv Series (Pentium Celeron Stepping 3) processor with 3169911K bytes +of memory. +Pentium Celeron Stepping 3 processor at 3836MHz, Revision 2.174 +IOS XRv Chassis + +1 Management Ethernet +6 GigabitEthernet +97070k bytes of non-volatile configuration memory. +866M bytes of hard disk. +2321392k bytes of disk0: (Sector size 512 bytes). diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version_brief b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version_brief new file mode 100644 index 00000000..7f82039f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version_brief @@ -0,0 +1,18 @@ +Cisco IOS XR Software, Version 6.0.0[Default] +Copyright (c) 2015 by Cisco Systems, Inc. + +ROM: GRUB, Version 1.99(0), DEV RELEASE + +iosxr01 uptime is 11 weeks, 6 days, 2 hours, 2 minutes +System image file is "bootflash:disk0/xrvr-os-mbi-6.0.0/mbixrvr-rp.vm" + +cisco IOS XRv Series (Pentium Celeron Stepping 3) processor with 3169911K bytes +of memory. +Pentium Celeron Stepping 3 processor at 3836MHz, Revision 2.174 +IOS XRv Chassis + +1 Management Ethernet +6 GigabitEthernet +97070k bytes of non-volatile configuration memory. +866M bytes of hard disk. +2321392k bytes of disk0: (Sector size 512 bytes). diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/iosxr_module.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/iosxr_module.py new file mode 100644 index 00000000..1915b07e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/iosxr_module.py @@ -0,0 +1,108 @@ +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +import json +import os + +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import ( + AnsibleExitJson, + AnsibleFailJson, + ModuleTestCase, +) + + +fixture_path = os.path.join(os.path.dirname(__file__), "fixtures") +fixture_data = {} + + +def load_fixture(name): + path = os.path.join(fixture_path, name) + + if path in fixture_data: + return fixture_data[path] + + with open(path) as f: + data = f.read() + + try: + data = json.loads(data) + except Exception: + pass + + fixture_data[path] = data + return data + + +class TestIosxrModule(ModuleTestCase): + def execute_module( + self, + failed=False, + changed=False, + commands=None, + sort=True, + defaults=False, + ): + + self.load_fixtures(commands) + + if failed: + result = self.failed() + self.assertTrue(result["failed"], result) + else: + result = self.changed(changed) + self.assertEqual(result["changed"], changed, result) + + if commands is not None: + if sort: + self.assertEqual( + sorted(commands), + sorted(result["commands"]), + result["commands"], + ) + else: + self.assertEqual( + commands, + result["commands"], + result["commands"], + ) + + return result + + def failed(self): + with self.assertRaises(AnsibleFailJson) as exc: + self.module.main() + + result = exc.exception.args[0] + self.assertTrue(result["failed"], result) + return result + + def changed(self, changed=False): + with self.assertRaises(AnsibleExitJson) as exc: + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result["changed"], changed, result) + return result + + def load_fixtures(self, commands=None): + pass diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_hostname.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_hostname.py new file mode 100644 index 00000000..7c676530 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_hostname.py @@ -0,0 +1,114 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from textwrap import dedent + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_hostname +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule + + +class TestIosxrHostnameModule(TestIosxrModule): + module = iosxr_hostname + + def setUp(self): + super(TestIosxrHostnameModule, self).setUp() + + self.mock_get_resource_connection = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base." + "get_resource_connection", + ) + self.get_resource_connection = self.mock_get_resource_connection.start() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.hostname.hostname." + "HostnameFacts.get_config", + ) + self.get_config = self.mock_get_config.start() + + def tearDown(self): + super(TestIosxrHostnameModule, self).tearDown() + self.get_resource_connection.stop() + self.get_config.stop() + + def test_iosxr_hostname_merged_idempotent(self): + self.maxDiff = None + run_cfg = dedent( + """\ + hostname iosxr1 + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(config=dict(hostname="iosxr1"), state="merged")) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_hostname_merged(self): + self.maxDiff = None + set_module_args(dict(config=dict(hostname="iosxr1"), state="merged")) + commands = ["hostname iosxr1"] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_hostname_deleted(self): + self.maxDiff = None + run_cfg = dedent( + """\ + hostname iosxr1 + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(state="deleted")) + commands = ["no hostname iosxr1"] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_hostname_rendered(self): + self.maxDiff = None + set_module_args(dict(config=dict(hostname="iosxr1"), state="rendered")) + commands = ["hostname iosxr1"] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_hostname_gathered(self): + self.maxDiff = None + run_cfg = dedent( + """\ + hostname iosxr1 + """, + ) + self.get_config.return_value = run_cfg + print(self.get_config.return_value) + set_module_args(dict(state="gathered")) + gathered = {"hostname": "iosxr1"} + result = self.execute_module(changed=False) + self.assertEqual(gathered, result["gathered"]) + + def test_iosxr_hostname_parsed(self): + self.maxDiff = None + set_module_args(dict(running_config="hostname iosxr1", state="parsed")) + result = self.execute_module(changed=False) + parsed_list = {"hostname": "iosxr1"} + self.assertEqual(parsed_list, result["parsed"]) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr.py new file mode 100644 index 00000000..af2fd3a5 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr.py @@ -0,0 +1,97 @@ +# +# (c) 2020 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. +# +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from os import path + +from ansible.module_utils._text import to_bytes, to_text +from mock import MagicMock + +from ansible_collections.cisco.iosxr.plugins.cliconf import iosxr +from ansible_collections.cisco.iosxr.tests.unit.compat import unittest + + +class TestPluginCLIConfIOSXR(unittest.TestCase): + """Test class for IOSXR CLI Conf Methods""" + + def setUp(self): + self._mock_connection = MagicMock() + self._prepare() + self._cliconf = iosxr.Cliconf(self._mock_connection) + self.maxDiff = None + + def _prepare(self, platform="iosxr"): + b_FIXTURE_DIR = b"%s/fixtures/cliconf/%s" % ( + to_bytes( + path.dirname(path.abspath(__file__)), + errors="surrogate_or_strict", + ), + to_bytes(platform), + ) + + def _connection_side_effect(*args, **kwargs): + try: + if args: + value = args[0] + else: + value = kwargs.get("command") + if b"|" in value: + value = value.replace(b"|", b"") + fixture_path = path.abspath( + b"%s/%s" % (b_FIXTURE_DIR, b"_".join(value.split(b" "))), + ) + with open(fixture_path, "rb") as file_desc: + return to_text(file_desc.read()) + except (OSError, IOError): + if args: + value = args[0] + return value + elif kwargs.get("command"): + value = kwargs.get("command") + return value + return "NO-OP" + + self._mock_connection.send.side_effect = _connection_side_effect + + def tearDown(self): + pass + + def test_get_device_info_iosxr(self): + """Test get_device_info for nxos""" + device_info = self._cliconf.get_device_info() + + mock_device_info = { + "network_os_image": "bootflash:disk0/xrvr-os-mbi-6.0.0/mbixrvr-rp.vm", + "network_os_version": "6.0.0[Default]", + "network_os": "iosxr", + "network_os_hostname": "iosxr01", + "network_os_model": "IOS XRv", + } + + self.assertEqual(device_info, mock_device_info) + + def test_get_command_output_iosxr(self): + """Test _get_command_with_output for iosxr""" + self._prepare() + cmd = self._cliconf.get_command_output("show running-config hostname") + + self.assertEqual(cmd, "hostname iosxr01") diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acl_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acl_interfaces.py new file mode 100644 index 00000000..8500c073 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acl_interfaces.py @@ -0,0 +1,329 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_acl_interfaces +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrAclInterfacesModule(TestIosxrModule): + module = iosxr_acl_interfaces + + def setUp(self): + super(TestIosxrAclInterfacesModule, self).setUp() + + self.mock_get_resource_connection = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base.get_resource_connection", + ) + self.get_resource_connection = self.mock_get_resource_connection.start() + + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.acl_interfaces.acl_interfaces.Acl_interfacesFacts.get_config", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrAclInterfacesModule, self).tearDown() + self.get_resource_connection.stop() + self.mock_execute_show_command.stop() + + def _prepare(self): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_acl_interfaces_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_acl_interfaces_merged_idempotent(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + access_groups=[ + dict( + afi="ipv4", + acls=[ + dict(name="acl_1", direction="in"), + dict(name="acl_2", direction="out"), + ], + ), + dict( + afi="ipv6", + acls=[ + dict(name="acl6_1", direction="in"), + dict(name="acl6_2", direction="out"), + ], + ), + ], + ), + dict( + name="GigabitEthernet0/0/0/1", + access_groups=[ + dict( + afi="ipv4", + acls=[dict(name="acl_1", direction="out")], + ), + ], + ), + ], + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_acl_interfaces_merged(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + access_groups=[ + dict( + afi="ipv4", + acls=[ + dict(name="acl_1", direction="in"), + dict(name="acl_2", direction="out"), + ], + ), + dict( + afi="ipv6", + acls=[ + dict(name="acl6_1", direction="in"), + dict(name="acl6_2", direction="out"), + ], + ), + ], + ), + dict( + name="GigabitEthernet0/0/0/1", + access_groups=[ + dict( + afi="ipv4", + acls=[dict(name="acl_1", direction="in")], + ), + ], + ), + ], + state="merged", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/0", + "ipv4 access-group acl_1 ingress", + "ipv4 access-group acl_2 egress", + "ipv6 access-group acl6_1 ingress", + "ipv6 access-group acl6_2 egress", + "interface GigabitEthernet0/0/0/1", + "ipv4 access-group acl_1 ingress", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_acl_interfaces_replaced(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + access_groups=[ + dict( + afi="ipv6", + acls=[dict(name="acl6_3", direction="in")], + ), + ], + ), + ], + state="replaced", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/0", + "no ipv4 access-group acl_1 ingress", + "no ipv4 access-group acl_2 egress", + "no ipv6 access-group acl6_2 egress", + "ipv6 access-group acl6_3 ingress", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_acl_interfaces_deleted(self): + self._prepare() + set_module_args(dict(state="deleted")) + + commands = [ + "interface GigabitEthernet0/0/0/0", + "no ipv4 access-group acl_1 ingress", + "no ipv4 access-group acl_2 egress", + "no ipv6 access-group acl6_1 ingress", + "no ipv6 access-group acl6_2 egress", + "interface GigabitEthernet0/0/0/1", + "no ipv4 access-group acl_1 egress", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_acl_interfaces_rendered(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + access_groups=[ + dict( + afi="ipv4", + acls=[ + dict(name="acl_1", direction="in"), + dict(name="acl_2", direction="out"), + ], + ), + dict( + afi="ipv6", + acls=[ + dict(name="acl6_1", direction="in"), + dict(name="acl6_2", direction="out"), + ], + ), + ], + ), + dict( + name="GigabitEthernet0/0/0/1", + access_groups=[ + dict( + afi="ipv4", + acls=[dict(name="acl_1", direction="in")], + ), + ], + ), + ], + state="rendered", + ), + ) + + commands = [ + "interface GigabitEthernet0/0/0/0", + "ipv4 access-group acl_1 ingress", + "ipv4 access-group acl_2 egress", + "ipv6 access-group acl6_1 ingress", + "ipv6 access-group acl6_2 egress", + "interface GigabitEthernet0/0/0/1", + "ipv4 access-group acl_1 ingress", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_acl_interfaces_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="interface GigabitEthernet0/0/0/0\r\n shutdown\r\n ipv4 access-group acl_1 ingress\r\n" + " ipv4 access-group acl_2 egress\r\n ipv6 access-group acl6_1 ingress\r\n ipv6 " + "access-group acl6_2 egress\r\n!\r\ninterface GigabitEthernet0/0/0/1\r\n " + "shutdown\r\n ipv4 access-group acl_1 egress\r\n!", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + print(result["parsed"]) + parsed_list = [ + { + "name": "GigabitEthernet0/0/0/0", + "access_groups": [ + { + "afi": "ipv4", + "acls": [ + {"name": "acl_1", "direction": "in"}, + {"name": "acl_2", "direction": "out"}, + ], + }, + { + "afi": "ipv6", + "acls": [ + {"name": "acl6_1", "direction": "in"}, + {"name": "acl6_2", "direction": "out"}, + ], + }, + ], + }, + { + "name": "GigabitEthernet0/0/0/1", + "access_groups": [ + { + "afi": "ipv4", + "acls": [{"name": "acl_1", "direction": "out"}], + }, + ], + }, + ] + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_acl_interfaces_overridden(self): + self.maxDiff = None + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + access_groups=[ + dict( + afi="ipv6", + acls=[dict(name="acl6_3", direction="in")], + ), + ], + ), + dict( + name="GigabitEthernet0/0/0/1", + access_groups=[ + dict( + afi="ipv4", + acls=[dict(name="acl_2", direction="in")], + ), + dict( + afi="ipv6", + acls=[dict(name="acl6_3", direction="out")], + ), + ], + ), + ], + state="overridden", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/0", + "no ipv4 access-group acl_1 ingress", + "no ipv4 access-group acl_2 egress", + "no ipv6 access-group acl6_2 egress", + "ipv6 access-group acl6_3 ingress", + "interface GigabitEthernet0/0/0/1", + "no ipv4 access-group acl_1 egress", + "ipv4 access-group acl_2 ingress", + "ipv6 access-group acl6_3 egress", + ] + + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acls.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acls.py new file mode 100644 index 00000000..ed826b93 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acls.py @@ -0,0 +1,496 @@ +# +# (c) 2019, Ansible by Red Hat, inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_acls +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrAclsModule(TestIosxrModule): + module = iosxr_acls + + def setUp(self): + super(TestIosxrAclsModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.acls.acls.AclsFacts.get_device_data", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrAclsModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def _prepare(self): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_acls_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_acls_merged(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + acls=[ + dict( + name="acl_1", + aces=[ + dict( + sequence="30", + grant="permit", + protocol="ospf", + source=dict(prefix="192.168.1.0/24"), + destination=dict(any="true"), + log="true", + ), + dict( + sequence="40", + grant="deny", + protocol="ipv4", + source=dict( + address="10.233.0.0", + wildcard_bits="0.0.255.255", + ), + destination=dict( + net_group="netgroup1", + ), + ), + dict( + sequence="50", + grant="deny", + protocol="ipv4", + source=dict( + address="10.233.0.0", + wildcard_bits="0.0.255.255", + ), + destination=dict( + port_group="portgroup1", + ), + ), + ], + ), + ], + ), + ], + state="merged", + ), + ) + commands = [ + "ipv4 access-list acl_1", + "30 permit ospf 192.168.1.0 0.0.0.255 any log", + "40 deny ipv4 10.233.0.0 0.0.255.255 net-group netgroup1", + "50 deny ipv4 10.233.0.0 0.0.255.255 port-group portgroup1", + ] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_acls_merged_idempotent(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + acls=[ + dict( + name="acl_2", + aces=[ + dict( + sequence="10", + grant="deny", + protocol="ipv4", + destination=dict(any="true"), + source=dict(any="true"), + ), + ], + ), + ], + ), + ], + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_acls_replaced(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + acls=[ + dict( + name="acl_2", + aces=[ + dict( + sequence="30", + grant="permit", + protocol="ospf", + source=dict(prefix="10.0.0.0/8"), + destination=dict(any="true"), + log="true", + ), + dict( + sequence="40", + grant="deny", + protocol="ipv4", + source=dict( + address="10.233.0.0", + wildcard_bits="0.0.255.255", + ), + destination=dict( + net_group="netgroup1", + ), + ), + dict( + sequence="50", + grant="deny", + protocol="ipv4", + source=dict( + address="10.233.0.0", + wildcard_bits="0.0.255.255", + ), + destination=dict( + port_group="portgroup1", + ), + ), + ], + ), + ], + ), + ], + state="replaced", + ), + ) + commands = [ + "ipv4 access-list acl_2", + "no 10", + "no 20", + "30 permit ospf 10.0.0.0 0.255.255.255 any log", + "40 deny ipv4 10.233.0.0 0.0.255.255 net-group netgroup1", + "50 deny ipv4 10.233.0.0 0.0.255.255 port-group portgroup1", + ] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_acls_replaced_idempotent(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + acls=[ + dict( + name="acl_2", + aces=[ + dict( + sequence="10", + grant="deny", + protocol="ipv4", + destination=dict(any="true"), + source=dict(any="true"), + ), + dict( + sequence="20", + grant="permit", + protocol="tcp", + destination=dict(any="true"), + source=dict(host="192.168.1.100"), + ), + ], + ), + ], + ), + ], + state="replaced", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_acls_overridden(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + acls=[ + dict( + name="acl_2", + aces=[ + dict( + sequence="40", + grant="permit", + protocol="ospf", + source=dict(any="true"), + destination=dict(any="true"), + log="true", + ), + dict( + sequence="50", + grant="deny", + protocol="ipv4", + source=dict( + address="10.233.0.0", + wildcard_bits="0.0.255.255", + ), + destination=dict( + net_group="netgroup1", + ), + ), + dict( + sequence="60", + grant="deny", + protocol="ipv4", + source=dict( + address="10.233.0.0", + wildcard_bits="0.0.255.255", + ), + destination=dict( + port_group="portgroup1", + ), + ), + ], + ), + ], + ), + ], + state="overridden", + ), + ) + commands = [ + "no ipv6 access-list acl6_1", + "no ipv4 access-list acl_1", + "ipv4 access-list acl_2", + "no 10", + "no 20", + "40 permit ospf any any log", + "50 deny ipv4 10.233.0.0 0.0.255.255 net-group netgroup1", + "60 deny ipv4 10.233.0.0 0.0.255.255 port-group portgroup1", + ] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_acls_overridden_idempotent(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + acls=[ + dict( + name="acl_1", + aces=[ + dict( + sequence="10", + grant="deny", + protocol="ipv4", + source=dict( + address="10.233.0.0", + wildcard_bits="0.0.255.255", + ), + destination=dict( + net_group="netgroup1", + ), + ), + dict( + sequence="20", + grant="deny", + protocol="ipv4", + source=dict( + address="10.233.0.0", + wildcard_bits="0.0.255.255", + ), + destination=dict( + port_group="portgroup1", + ), + ), + ], + ), + dict( + name="acl_2", + aces=[ + dict( + sequence="10", + grant="deny", + protocol="ipv4", + destination=dict(any="true"), + source=dict(any="true"), + ), + dict( + sequence="20", + grant="permit", + protocol="tcp", + destination=dict(any="true"), + source=dict(host="192.168.1.100"), + ), + ], + ), + ], + ), + dict( + afi="ipv6", + acls=[ + dict( + name="acl6_1", + aces=[ + dict( + sequence="10", + grant="deny", + protocol="icmpv6", + destination=dict(any="true"), + source=dict(any="true"), + ), + ], + ), + ], + ), + ], + state="overridden", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_acls_deletedacls(self): + self._prepare() + set_module_args( + dict( + config=[dict(afi="ipv6", acls=[dict(name="acl6_1")])], + state="deleted", + ), + ) + commands = ["no ipv6 access-list acl6_1"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_acls_deletedafis(self): + self._prepare() + set_module_args(dict(config=[dict(afi="ipv4")], state="deleted")) + commands = ["no ipv4 access-list acl_2", "no ipv4 access-list acl_1"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_acls_rendered(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + acls=[ + dict( + name="acl_2", + aces=[ + dict( + grant="permit", + source=dict(any="true"), + destination=dict(any="true"), + protocol="igmp", + ), + ], + ), + ], + ), + ], + state="rendered", + ), + ) + commands = ["ipv4 access-list acl_2", "permit igmp any any"] + result = self.execute_module(changed=False) + self.assertEqual( + sorted(result["rendered"]), + sorted(commands), + result["rendered"], + ) + + def test_iosxr_acls_overridden_on_empty_config(self): + self.execute_show_command.return_value = "" + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + acls=[ + dict( + name="acl_1", + aces=[ + dict( + sequence="10", + grant="deny", + source=dict(any=True), + destination=dict(any=True), + protocol="ip", + ), + ], + ), + ], + ), + ], + state="overridden", + ), + ) + cmds = ["ipv4 access-list acl_1", "10 deny ip any any"] + self.execute_module(changed=True, commands=cmds) + + def test_iosxr_acls_parsed_matches(self): + set_module_args( + dict( + running_config="""ipv4 access-list ACL_NAME\n5 permit ipv4 host x.x.x.x any (409 matches)""", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = [ + { + "acls": [ + { + "name": "ACL_NAME", + "aces": [ + { + "sequence": 5, + "grant": "permit", + "protocol": "ipv4", + "source": {"host": "x.x.x.x"}, + "destination": {"any": True}, + }, + ], + }, + ], + "afi": "ipv4", + }, + ] + self.assertEqual(parsed_list, result["parsed"]) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_banner.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_banner.py new file mode 100644 index 00000000..8c426f83 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_banner.py @@ -0,0 +1,117 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_banner +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrBannerModule(TestIosxrModule): + + module = iosxr_banner + + def setUp(self): + super(TestIosxrBannerModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_banner.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_banner.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_is_cliconf = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_banner.is_cliconf", + ) + self.is_cliconf = self.mock_is_cliconf.start() + + def tearDown(self): + super(TestIosxrBannerModule, self).tearDown() + + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_is_cliconf.stop() + + def load_fixtures(self, commands=None): + self.get_config.return_value = load_fixture("iosxr_banner_config.cfg") + self.load_config.return_value = dict(diff=None, session="session") + self.is_cliconf.return_value = True + + def test_iosxr_banner_login_create(self): + set_module_args(dict(banner="login", text="test\nbanner\nstring")) + commands = ["banner login test\nbanner\nstring"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_banner_login_remove(self): + set_module_args(dict(banner="login", state="absent")) + commands = ["no banner login"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_banner_fail_create(self): + set_module_args(dict(banner="exec1", text="test\nbanner\nstring")) + result = self.execute_module(failed=True, changed=True) + self.assertEqual( + result["msg"], + "value of banner must be one of: login, motd, got: exec1", + ) + + def test_iosxr_banner_exec1_fail_remove(self): + set_module_args(dict(banner="exec1", state="absent")) + result = self.execute_module(failed=True, changed=True) + self.assertIn( + result["msg"], + "value of banner must be one of: login, motd, got: exec1", + ) + + def test_iosxr_banner_motd_create(self): + set_module_args(dict(banner="motd", text="test\nbanner\nstring")) + commands = ["banner motd test\nbanner\nstring"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_banner_motd_remove(self): + set_module_args(dict(banner="motd", state="absent")) + commands = ["no banner motd"] + self.execute_module(changed=True, commands=commands) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_address_family.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_address_family.py new file mode 100644 index 00000000..57770b59 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_address_family.py @@ -0,0 +1,384 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from textwrap import dedent + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_bgp_address_family +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule + + +class TestIosxrBgpGlobalModule(TestIosxrModule): + module = iosxr_bgp_address_family + + def setUp(self): + super(TestIosxrBgpGlobalModule, self).setUp() + + self.mock_get_resource_connection = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base.get_resource_connection", + ) + self.get_resource_connection = self.mock_get_resource_connection.start() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.bgp_address_family.bgp_address_family.Bgp_address_familyFacts.get_config", + ) + self.get_config = self.mock_get_config.start() + + def tearDown(self): + super(TestIosxrBgpGlobalModule, self).tearDown() + self.get_resource_connection.stop() + self.get_config.stop() + + def test_iosxr_bgp_address_family_merged_idempotent(self): + run_cfg = dedent( + """\ + router bgp 65536 + address-family ipv4 unicast + bgp attribute-download + advertise best-external + dynamic-med interval 10 + bgp scan-time 20 + redistribute connected metric 10 + redistribute isis test3 metric 4 + redistribute application test1 metric 10 + allocate-label all + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + as_number="65536", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + dynamic_med=10, + redistribute=[ + dict( + protocol="application", + id="test1", + metric=10, + ), + dict(protocol="connected", metric=10), + dict(protocol="isis", id="test3", metric=4), + ], + bgp=dict(scan_time=20, attribute_download=True), + advertise_best_external=True, + allocate_label=dict(all=True), + ), + ], + ), + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_bgp_address_family_merged(self): + set_module_args( + dict( + config=dict( + as_number="65536", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + dynamic_med=10, + redistribute=[ + dict( + protocol="application", + id="test1", + metric=10, + ), + dict(protocol="connected", metric=10), + dict(protocol="isis", id="test3", metric=4), + ], + bgp=dict(scan_time=20, attribute_download=True), + advertise_best_external=True, + allocate_label=dict(all=True), + ), + ], + ), + state="merged", + ), + ) + commands = [ + "router bgp 65536", + "address-family ipv4 unicast", + "advertise best-external", + "allocate-label all", + "bgp attribute-download", + "bgp scan-time 20", + "dynamic-med interval 10", + "redistribute application test1 metric 10", + "redistribute connected metric 10", + "redistribute isis test3 metric 4", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_bgp_address_family_replaced(self): + run_cfg = dedent( + """\ + router bgp 65536 + address-family ipv4 unicast + bgp attribute-download + advertise best-external + dynamic-med interval 10 + bgp scan-time 20 + redistribute connected metric 10 + redistribute isis test3 metric 4 + redistribute application test1 metric 10 + allocate-label all + address-family ipv4 mvpn + """, + ) + self.get_config.return_value = run_cfg + + set_module_args( + dict( + config=dict( + as_number="65536", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + dynamic_med=4, + redistribute=[ + dict( + protocol="application", + id="test1", + metric=10, + ), + dict(protocol="connected", metric=10), + dict(protocol="isis", id="test3", metric=4), + ], + ), + ], + ), + state="replaced", + ), + ) + commands = [ + "router bgp 65536", + "address-family ipv4 unicast", + "no advertise best-external", + "no allocate-label all", + "no bgp attribute-download", + "no bgp scan-time 20", + "dynamic-med interval 4", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_bgp_address_family_replaced_idempotent(self): + run_cfg = dedent( + """\ + router bgp 65536 + address-family ipv4 unicast + dynamic-med interval 4 + redistribute connected metric 10 + redistribute isis test3 metric 4 + redistribute application test1 metric 10 + address-family ipv4 mvpn + """, + ) + self.get_config.return_value = run_cfg + + set_module_args( + dict( + config=dict( + as_number="65536", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + dynamic_med=4, + redistribute=[ + dict( + protocol="application", + id="test1", + metric=10, + ), + dict(protocol="connected", metric=10), + dict(protocol="isis", id="test3", metric=4), + ], + ), + ], + ), + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_bgp_address_family_deleted(self): + run_cfg = dedent( + """\ + router bgp 65536 + address-family ipv4 unicast + bgp attribute-download + advertise best-external + dynamic-med interval 10 + bgp scan-time 20 + redistribute connected metric 10 + redistribute isis test3 metric 4 + redistribute application test1 metric 10 + allocate-label all + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(config=dict(), state="deleted")) + + commands = ["router bgp 65536", "no address-family ipv4 unicast"] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_bgp_address_family_deleted1(self): + run_cfg = dedent( + """\ + router bgp 65536 + address-family ipv6 unicast + dynamic-med interval 4 + address-family ipv4 unicast + bgp attribute-download + advertise best-external + dynamic-med interval 10 + bgp scan-time 20 + redistribute connected metric 10 + redistribute isis test3 metric 4 + redistribute application test1 metric 10 + allocate-label all + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + as_number=65536, + address_family=[ + dict(afi="ipv6", safi="unicast", dynamic_med=4), + ], + ), + state="deleted", + ), + ) + commands = ["router bgp 65536", "no address-family ipv6 unicast"] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_bgp_address_family_deleted_idempotent(self): + run_cfg = dedent( + """\ + "router bgp 65536" + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(config=dict(as_number="65536"), state="deleted")) + + result = self.execute_module(changed=False) + self.assertEqual(result["commands"], []) + + def test_iosxr_bgp_address_family_rendered(self): + set_module_args( + dict( + config=dict( + as_number="65536", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + dynamic_med=10, + redistribute=[ + dict( + protocol="application", + id="test1", + metric=10, + ), + dict(protocol="connected", metric=10), + dict(protocol="isis", id="test3", metric=4), + ], + bgp=dict(scan_time=20, attribute_download=True), + advertise_best_external=True, + allocate_label=dict(all=True), + ), + ], + ), + state="rendered", + ), + ) + commands = [ + "router bgp 65536", + "address-family ipv4 unicast", + "advertise best-external", + "allocate-label all", + "bgp attribute-download", + "bgp scan-time 20", + "dynamic-med interval 10", + "redistribute application test1 metric 10", + "redistribute connected metric 10", + "redistribute isis test3 metric 4", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_bgp_address_family_parsed(self): + self.maxDiff = None + run_cfg = dedent( + """\ + router bgp 65536 + address-family ipv4 unicast + bgp attribute-download + advertise best-external + dynamic-med interval 10 + bgp scan-time 20 + redistribute application test1 metric 10 + allocate-label all + """, + ) + set_module_args(dict(running_config=run_cfg, state="parsed")) + result = self.execute_module(changed=False) + parsed_list = { + "address_family": [ + { + "advertise_best_external": True, + "safi": "unicast", + "afi": "ipv4", + "allocate_label": {"all": True}, + "bgp": {"attribute_download": True, "scan_time": 20}, + "dynamic_med": 10, + "redistribute": [ + { + "protocol": "application", + "metric": 10, + "id": "test1", + }, + ], + }, + ], + "as_number": "65536", + } + + self.assertEqual(parsed_list, result["parsed"]) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_global.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_global.py new file mode 100644 index 00000000..05480d09 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_global.py @@ -0,0 +1,493 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from textwrap import dedent + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_bgp_global +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule + + +class TestIosxrBgpGlobalModule(TestIosxrModule): + module = iosxr_bgp_global + + def setUp(self): + super(TestIosxrBgpGlobalModule, self).setUp() + + self.mock_get_resource_connection = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base." + "get_resource_connection", + ) + self.get_resource_connection = self.mock_get_resource_connection.start() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.bgp_global.bgp_global." + "Bgp_globalFacts.get_config", + ) + self.get_config = self.mock_get_config.start() + + def tearDown(self): + super(TestIosxrBgpGlobalModule, self).tearDown() + self.get_resource_connection.stop() + self.get_config.stop() + + def test_iosxr_bgp_global_merged_idempotent(self): + run_cfg = dedent( + """\ + router bgp 65536 + bgp confederation identifier 4 + bgp router-id 192.0.2.10 + bgp cluster-id 5 + default-metric 4 + socket send-buffer-size 4098 + bgp bestpath med confed + socket receive-buffer-size 514 + neighbor 192.0.2.11 + remote-as 65537 + cluster-id 3 + neighbor 192.0.2.14 + remote-as 65538 + bfd fast-detect strict-mode + bfd multiplier 6 + bfd minimum-interval 20 + vrf vrf1 + default-metric 5 + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + as_number="65536", + default_metric=4, + socket=dict( + receive_buffer_size=514, + send_buffer_size=4098, + ), + bgp=dict( + confederation=dict(identifier=4), + bestpath=dict(med=dict(confed=True)), + cluster_id=5, + router_id="192.0.2.10", + ), + neighbors=[ + dict( + neighbor="192.0.2.11", + cluster_id=3, + remote_as="65537", + ), + dict( + neighbor="192.0.2.14", + remote_as="65538", + bfd=dict( + multiplier=6, + minimum_interval=20, + fast_detect=dict(strict_mode=True), + ), + ), + ], + vrfs=[dict(vrf="vrf1", default_metric=5)], + ), + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_bgp_global_merged(self): + set_module_args( + dict( + config=dict( + as_number="65536", + default_metric=4, + socket=dict( + receive_buffer_size=514, + send_buffer_size=4098, + ), + bgp=dict( + confederation=dict(identifier=4), + bestpath=dict(med=dict(confed=True)), + cluster_id=5, + router_id="192.0.2.10", + ), + neighbors=[ + dict( + neighbor="192.0.2.11", + cluster_id=3, + remote_as="65537", + ), + dict( + neighbor="192.0.2.14", + remote_as="65538", + bfd=dict( + multiplier=6, + minimum_interval=20, + fast_detect=dict(strict_mode=True), + ), + ), + ], + vrfs=[dict(vrf="vrf1", default_metric=5)], + ), + state="merged", + ), + ) + commands = [ + "router bgp 65536", + "bgp cluster-id 5", + "bgp router-id 192.0.2.10", + "bgp bestpath med confed", + "bgp confederation identifier 4", + "default-metric 4", + "socket receive-buffer-size 514", + "socket send-buffer-size 4098", + "neighbor 192.0.2.11", + "cluster-id 3", + "remote-as 65537", + "neighbor 192.0.2.14", + "bfd fast-detect strict-mode", + "bfd minimum-interval 20", + "bfd multiplier 6", + "remote-as 65538", + "vrf vrf1", + "default-metric 5", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_bgp_global_replaced(self): + run_cfg = dedent( + """\ + router bgp 65536 + bgp confederation identifier 4 + bgp router-id 192.0.2.10 + bgp cluster-id 5 + default-metric 4 + socket send-buffer-size 4098 + bgp bestpath med confed + socket receive-buffer-size 514 + neighbor 192.0.2.11 + remote-as 65537 + cluster-id 3 + neighbor 192.0.2.14 + remote-as 65538 + bfd fast-detect strict-mode + bfd multiplier 6 + bfd minimum-interval 20 + vrf vrf1 + default-metric 5 + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + as_number="65536", + default_metric=5, + socket=dict( + receive_buffer_size=514, + send_buffer_size=4098, + ), + bgp=dict( + confederation=dict(identifier=4), + bestpath=dict(med=dict(confed=True)), + cluster_id=5, + router_id="192.0.2.10", + ), + neighbors=[ + dict( + neighbor="192.0.2.13", + remote_as="65538", + bfd=dict( + multiplier=6, + minimum_interval=20, + fast_detect=dict(strict_mode=True), + ), + ), + ], + vrfs=[dict(vrf="vrf1", default_metric=5)], + ), + state="replaced", + ), + ) + commands = [ + "router bgp 65536", + "no neighbor 192.0.2.11", + "no neighbor 192.0.2.14", + "default-metric 5", + "neighbor 192.0.2.13", + "bfd fast-detect strict-mode", + "bfd minimum-interval 20", + "bfd multiplier 6", + "remote-as 65538", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_bgp_global_replaced_idempotent(self): + run_cfg = dedent( + """\ + router bgp 65536 + bgp confederation identifier 4 + bgp router-id 192.0.2.10 + bgp cluster-id 5 + default-metric 4 + socket send-buffer-size 4098 + bgp bestpath med confed + socket receive-buffer-size 514 + neighbor 192.0.2.11 + remote-as 65537 + cluster-id 3 + neighbor 192.0.2.14 + remote-as 65538 + bfd fast-detect strict-mode + bfd multiplier 6 + bfd minimum-interval 20 + vrf vrf1 + default-metric 5 + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + as_number="65536", + default_metric=4, + socket=dict( + receive_buffer_size=514, + send_buffer_size=4098, + ), + bgp=dict( + confederation=dict(identifier=4), + bestpath=dict(med=dict(confed=True)), + cluster_id=5, + router_id="192.0.2.10", + ), + neighbors=[ + dict( + neighbor="192.0.2.11", + cluster_id=3, + remote_as="65537", + ), + dict( + neighbor="192.0.2.14", + remote_as="65538", + bfd=dict( + multiplier=6, + minimum_interval=20, + fast_detect=dict(strict_mode=True), + ), + ), + ], + vrfs=[dict(vrf="vrf1", default_metric=5)], + ), + state="replaced", + ), + ) + + self.execute_module(changed=False, commands=[]) + + def test_iosxr_bgp_global_deleted(self): + run_cfg = dedent( + """\ + router bgp 65536 + bgp confederation identifier 4 + bgp router-id 192.0.2.10 + bgp cluster-id 5 + default-metric 4 + socket send-buffer-size 4098 + bgp bestpath med confed + socket receive-buffer-size 514 + neighbor 192.0.2.11 + remote-as 65537 + cluster-id 3 + neighbor 192.0.2.14 + remote-as 65538 + bfd fast-detect strict-mode + bfd multiplier 6 + bfd minimum-interval 20 + vrf vrf1 + default-metric 5 + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(config=dict(as_number="65536"), state="deleted")) + + commands = [ + "router bgp 65536", + "no bgp cluster-id 5", + "no bgp router-id 192.0.2.10", + "no bgp bestpath med confed", + "no bgp confederation identifier 4", + "no default-metric 4", + "no socket receive-buffer-size 514", + "no socket send-buffer-size 4098", + "no neighbor 192.0.2.11", + "no neighbor 192.0.2.14", + "no vrf vrf1", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_bgp_global_deleted_idempotent(self): + run_cfg = dedent( + """\ + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(config=dict(as_number="65536"), state="deleted")) + + result = self.execute_module(changed=False) + self.assertEqual(result["commands"], []) + + def test_iosxr_bgp_global_rendered(self): + set_module_args( + dict( + config=dict( + as_number="65536", + default_metric=4, + socket=dict( + receive_buffer_size=514, + send_buffer_size=4098, + ), + bgp=dict( + confederation=dict(identifier=4), + bestpath=dict(med=dict(confed=True)), + cluster_id=5, + router_id="192.0.2.10", + ), + neighbors=[ + dict( + neighbor="192.0.2.11", + cluster_id=3, + remote_as="65537", + ), + dict( + neighbor="192.0.2.14", + remote_as="65538", + bfd=dict( + multiplier=6, + minimum_interval=20, + fast_detect=dict(set=True), + ), + ), + ], + vrfs=[dict(vrf="vrf1", default_metric=5)], + ), + state="rendered", + ), + ) + + commands = [ + "router bgp 65536", + "bgp cluster-id 5", + "bgp router-id 192.0.2.10", + "bgp bestpath med confed", + "bgp confederation identifier 4", + "default-metric 4", + "socket receive-buffer-size 514", + "socket send-buffer-size 4098", + "neighbor 192.0.2.11", + "cluster-id 3", + "remote-as 65537", + "neighbor 192.0.2.14", + "bfd fast-detect", + "bfd minimum-interval 20", + "bfd multiplier 6", + "remote-as 65538", + "vrf vrf1", + "default-metric 5", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_bgp_global_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="router bgp 65536\n bgp confederation identifier 4\n " + "bgp router-id 192.0.2.10\n bgp cluster-id 5\n default-metric 4\n " + "socket send-buffer-size 4098\n bgp bestpath med confed\n " + "socket receive-buffer-size 514\n neighbor 192.0.2.11\n remote-as 65537\n " + "cluster-id 3\n !\n neighbor 192.0.2.14\n remote-as 65538\n description test nbr description\n" + " bfd fast-detect strict-mode\n " + " bfd multiplier 6\n bfd minimum-interval 20\n !\n!", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = { + "as_number": "65536", + "bgp": { + "confederation": {"identifier": 4}, + "cluster_id": "5", + "router_id": "192.0.2.10", + "bestpath": {"med": {"confed": True}}, + }, + "default_metric": 4, + "socket": {"send_buffer_size": 4098, "receive_buffer_size": 514}, + "neighbors": [ + {"neighbor_address": "192.0.2.11", "remote_as": 65537, "cluster_id": "3"}, + { + "neighbor_address": "192.0.2.14", + "remote_as": 65538, + "description": "test nbr description", + }, + ], + "bfd": {"multiplier": 6, "minimum_interval": 20}, + } + + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_bgp_global_purged(self): + run_cfg = dedent( + """\ + router bgp 65536 + bgp confederation identifier 4 + bgp router-id 192.0.2.10 + bgp cluster-id 5 + default-metric 4 + socket send-buffer-size 4098 + bgp bestpath med confed + socket receive-buffer-size 514 + neighbor 192.0.2.11 + remote-as 65537 + cluster-id 3 + neighbor 192.0.2.14 + remote-as 65538 + bfd fast-detect strict-mode + bfd multiplier 6 + bfd minimum-interval 20 + vrf vrf1 + default-metric 5 + """, + ) + + self.get_config.return_value = run_cfg + + set_module_args(dict(state="purged")) + commands = ["no router bgp 65536"] + + result = self.execute_module(changed=True) + self.assertEqual(set(result["commands"]), set(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_neighbor_address_family.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_neighbor_address_family.py new file mode 100644 index 00000000..d6fd0610 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_neighbor_address_family.py @@ -0,0 +1,826 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from textwrap import dedent + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_bgp_neighbor_address_family +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule + + +class TestIosxrBgpNeighborAddressFamilyModule(TestIosxrModule): + module = iosxr_bgp_neighbor_address_family + + def setUp(self): + super(TestIosxrBgpNeighborAddressFamilyModule, self).setUp() + + self.mock_get_resource_connection = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base." + "get_resource_connection", + ) + self.get_resource_connection = self.mock_get_resource_connection.start() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.bgp_neighbor_address_family.bgp_neighbor_address_family." + "Bgp_neighbor_address_familyFacts.get_config", + ) + self.get_config = self.mock_get_config.start() + + def tearDown(self): + super(TestIosxrBgpNeighborAddressFamilyModule, self).tearDown() + self.get_resource_connection.stop() + self.get_config.stop() + + def test_iosxr_bgp_nbr_af_merged_idempotent(self): + run_cfg = dedent( + """\ + router bgp 1 + bgp router-id 1.2.3.4 + neighbor 1.1.1.1 + remote-as 5 + address-family ipv4 unicast + origin-as validation disable + bestpath origin-as allow invalid + aigp + aigp send med + send-community-ebgp + multipath + allowas-in 4 + maximum-prefix 10 20 restart 10 + as-override + capability orf prefix both + send-extended-community-ebgp + default-originate + next-hop-self + send-community-gshut-ebgp + soft-reconfiguration inbound + send-multicast-attributes + remove-private-AS inbound entire-aspath + route-policy test1 in + route-policy test1 out + next-hop-unchanged multipath + vrf vrf1 + rd auto + address-family ipv4 unicast + neighbor 1.2.1.2 + remote-as 5 + address-family ipv4 unicast + multipath + capability orf prefix both + default-originate + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + as_number="1", + vrfs=[ + dict( + vrf="vrf1", + neighbors=[ + dict( + neighbor_address="1.2.1.2", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + multipath=True, + default_originate=dict(set=True), + capability_orf_prefix="both", + ), + ], + ), + ], + ), + ], + neighbors=[ + dict( + neighbor_address="1.1.1.1", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + multipath=True, + default_originate=dict(set=True), + capability_orf_prefix="both", + send_multicast_attributes=dict(set=True), + soft_reconfiguration=dict(inbound=dict(set=True)), + send_community_gshut_ebgp=dict(set=True), + send_extended_community_ebgp=dict(set=True), + send_community_ebgp=dict(set=True), + origin_as=dict(validation=dict(disable=True)), + remove_private_AS=dict( + set=True, + inbound=True, + entire_aspath=True, + ), + route_policy=dict(inbound="test1", outbound="test1"), + maximum_prefix=dict( + max_limit=10, + threshold_value=20, + restart=10, + ), + next_hop_self=dict(set=True), + next_hop_unchanged=dict(multipath=True), + aigp=dict(set=True, send_med=dict(set=True)), + as_override=dict(set=True), + allowas_in=dict(value=4), + bestpath_origin_as_allow_invalid=True, + long_lived_graceful_restart=dict( + stale_time=dict(send=20, accept=30), + ), + ), + ], + ), + ], + ), + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_bgp_nbr_af_merged(self): + self.maxDiff = None + set_module_args( + dict( + config=dict( + as_number="1", + vrfs=[ + dict( + vrf="vrf1", + neighbors=[ + dict( + neighbor_address="1.2.1.2", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + multipath=True, + default_originate=dict(set=True), + capability_orf_prefix="both", + ), + ], + ), + ], + ), + ], + neighbors=[ + dict( + neighbor_address="1.1.1.1", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + multipath=True, + default_originate=dict(set=True), + capability_orf_prefix="both", + send_multicast_attributes=dict(set=True), + soft_reconfiguration=dict(inbound=dict(set=True)), + send_community_gshut_ebgp=dict(set=True), + send_extended_community_ebgp=dict(set=True), + send_community_ebgp=dict(set=True), + origin_as=dict(validation=dict(disable=True)), + remove_private_AS=dict( + set=True, + inbound=True, + entire_aspath=True, + ), + route_policy=dict(inbound="test1", outbound="test1"), + maximum_prefix=dict( + max_limit=10, + threshold_value=20, + restart=10, + ), + next_hop_self=dict(set=True), + next_hop_unchanged=dict(multipath=True), + aigp=dict(set=True, send_med=dict(set=True)), + as_override=dict(set=True), + bestpath_origin_as_allow_invalid=True, + long_lived_graceful_restart=dict( + stale_time=dict(send=20, accept=30), + ), + ), + ], + ), + ], + ), + state="merged", + ), + ) + commands = [ + "router bgp 1", + "neighbor 1.1.1.1", + "address-family ipv4 unicast", + "aigp", + "aigp send med", + "as-override", + "bestpath origin-as allow invalid", + "capability orf prefix both", + "default-originate", + "maximum-prefix 10 20 restart 10", + "multipath", + "next-hop-self", + "next-hop-unchanged multipath", + "origin-as validation disable", + "remove-private-AS inbound entire-aspath", + "route-policy test1 in", + "route-policy test1 out", + "send-community-ebgp", + "send-community-gshut-ebgp", + "send-extended-community-ebgp", + "send-multicast-attributes", + "soft-reconfiguration inbound", + "vrf vrf1", + "neighbor 1.2.1.2", + "address-family ipv4 unicast", + "capability orf prefix both", + "default-originate", + "multipath", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_bgp_nbr_af_replaced(self): + run_cfg = dedent( + """\ + router bgp 1 + bgp router-id 1.2.3.4 + neighbor 1.1.1.1 + remote-as 5 + address-family ipv4 unicast + origin-as validation disable + bestpath origin-as allow invalid + aigp + aigp send med + send-community-ebgp + multipath + allowas-in 4 + maximum-prefix 10 20 restart 10 + as-override + capability orf prefix both + send-extended-community-ebgp + default-originate + next-hop-self + send-community-gshut-ebgp + soft-reconfiguration inbound + send-multicast-attributes + remove-private-AS inbound entire-aspath + next-hop-unchanged multipath + vrf vrf1 + rd auto + address-family ipv4 unicast + neighbor 1.2.1.2 + remote-as 5 + address-family ipv4 unicast + multipath + capability orf prefix both + default-originate + route-policy test2 in + route-policy test2 out + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + as_number="1", + vrfs=[ + dict( + vrf="vrf1", + neighbors=[ + dict( + neighbor_address="1.2.1.2", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + multipath=True, + default_originate=dict(set=True), + route_policy=dict(inbound="test1", outbound="test1"), + ), + ], + ), + ], + ), + ], + ), + state="replaced", + ), + ) + commands = [ + "router bgp 1", + "vrf vrf1", + "neighbor 1.2.1.2", + "address-family ipv4 unicast", + "no capability orf prefix both", + "route-policy test1 in", + "route-policy test1 out", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_bgp_nbr_af_replaced_idempotent(self): + run_cfg = dedent( + """\ + router bgp 1 + bgp router-id 1.2.3.4 + neighbor 1.1.1.1 + remote-as 5 + address-family ipv4 unicast + origin-as validation disable + bestpath origin-as allow invalid + aigp + aigp send med + send-community-ebgp + multipath + allowas-in 4 + maximum-prefix 10 20 restart 10 + as-override + capability orf prefix both + send-extended-community-ebgp + default-originate + next-hop-self + send-community-gshut-ebgp + soft-reconfiguration inbound + send-multicast-attributes + remove-private-AS inbound entire-aspath + next-hop-unchanged multipath + vrf vrf1 + rd auto + address-family ipv4 unicast + neighbor 1.2.1.2 + remote-as 5 + address-family ipv4 unicast + multipath + capability orf prefix both + default-originate + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + as_number="1", + vrfs=[ + dict( + vrf="vrf1", + neighbors=[ + dict( + neighbor_address="1.2.1.2", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + multipath=True, + default_originate=dict(set=True), + capability_orf_prefix="both", + ), + ], + ), + ], + ), + ], + ), + state="replaced", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_bgp_nbr_af_deleted(self): + self.maxDiff = None + run_cfg = dedent( + """\ + router bgp 1 + bgp router-id 1.2.3.4 + neighbor 1.1.1.1 + remote-as 5 + address-family ipv4 unicast + origin-as validation disable + bestpath origin-as allow invalid + aigp + aigp send med + send-community-ebgp + multipath + allowas-in 4 + maximum-prefix 10 20 restart 10 + as-override + capability orf prefix both + send-extended-community-ebgp + default-originate + next-hop-self + send-community-gshut-ebgp + soft-reconfiguration inbound + send-multicast-attributes + remove-private-AS inbound entire-aspath + next-hop-unchanged multipath + vrf vrf1 + rd auto + address-family ipv4 unicast + neighbor 1.2.1.2 + remote-as 5 + address-family ipv4 unicast + multipath + capability orf prefix both + default-originate + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(config=dict(), state="deleted")) + commands = [ + "router bgp 1", + "neighbor 1.1.1.1", + "no address-family ipv4 unicast", + "vrf vrf1", + "neighbor 1.2.1.2", + "no address-family ipv4 unicast", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_bgp_nbr_af_deleted_idempotent(self): + run_cfg = dedent( + """\ + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(config=dict(as_number="1"), state="deleted")) + + result = self.execute_module(changed=False) + self.assertEqual(result["commands"], []) + + def test_iosxr_bgp_nbr_af_rendered(self): + set_module_args( + dict( + config=dict( + as_number="1", + vrfs=[ + dict( + vrf="vrf1", + neighbors=[ + dict( + neighbor_address="1.2.1.2", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + multipath=True, + default_originate=dict(set=True), + capability_orf_prefix="both", + as_override=dict(set=True), + ), + ], + ), + ], + ), + ], + neighbors=[ + dict( + neighbor_address="1.1.1.1", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + multipath=True, + default_originate=dict(set=True), + capability_orf_prefix="both", + send_multicast_attributes=dict(set=True), + soft_reconfiguration=dict(inbound=dict(set=True)), + send_community_gshut_ebgp=dict(set=True), + send_extended_community_ebgp=dict(set=True), + send_community_ebgp=dict(set=True), + origin_as=dict(validation=dict(disable=True)), + remove_private_AS=dict( + set=True, + inbound=True, + entire_aspath=True, + ), + maximum_prefix=dict( + max_limit=10, + threshold_value=20, + restart=10, + ), + next_hop_self=dict(set=True), + next_hop_unchanged=dict(multipath=True), + aigp=dict(set=True, send_med=dict(set=True)), + as_override=dict(set=True), + allowas_in=dict(value=4), + bestpath_origin_as_allow_invalid=True, + long_lived_graceful_restart=dict( + stale_time=dict(send=20, accept=30), + ), + ), + ], + ), + ], + ), + state="rendered", + ), + ) + commands = [ + "router bgp 1", + "neighbor 1.1.1.1", + "address-family ipv4 unicast", + "aigp", + "aigp send med", + "allowas-in 4", + "as-override", + "bestpath origin-as allow invalid", + "capability orf prefix both", + "default-originate", + "maximum-prefix 10 20 restart 10", + "multipath", + "next-hop-self", + "next-hop-unchanged multipath", + "origin-as validation disable", + "remove-private-AS inbound entire-aspath", + "send-community-ebgp", + "send-community-gshut-ebgp", + "send-extended-community-ebgp", + "send-multicast-attributes", + "soft-reconfiguration inbound", + "vrf vrf1", + "neighbor 1.2.1.2", + "address-family ipv4 unicast", + "as-override", + "capability orf prefix both", + "default-originate", + "multipath", + ] + + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_bgp_global_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="router bgp 1\n bgp router-id 1.2.1.3\n neighbor 1.1.1.1\n " + "remote-as 6\n address-family ipv4 unicast\n origin-as validation disable\n " + "bestpath origin-as allow invalid\n weight 0\n send-community-ebgp\n " + " multipath\n allowas-in 3\n maximum-prefix 1 1 discard-extra-paths\n" + " capability orf prefix both\n " + "send-extended-community-ebgp\n long-lived-graceful-restart capable\n" + " next-hop-self\n " + "remove-private-AS\n send-community-gshut-ebgp inheritance-disable\n " + " send-multicast-attributes\n " + "remove-private-AS inbound entire-aspath\n " + "next-hop-unchanged multipath\n !\n " + "!\n !", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = { + "as_number": "1", + "neighbors": [ + { + "address_family": [ + { + "afi": "ipv4", + "allowas_in": {"value": 3}, + "bestpath_origin_as_allow_invalid": True, + "capability_orf_prefix": "both", + "long_lived_graceful_restart": {"capable": True}, + "multipath": True, + "next_hop_self": {"set": True}, + "next_hop_unchanged": {"multipath": True}, + "origin_as": {"validation": {"disable": True}}, + "remove_private_AS": { + "entire_aspath": True, + "inbound": True, + "set": True, + }, + "safi": "unicast", + "send_community_ebgp": {"set": True}, + "send_community_gshut_ebgp": {"inheritance_disable": True}, + "send_extended_community_ebgp": {"set": True}, + "send_multicast_attributes": {"set": True}, + "weight": 0, + }, + ], + "neighbor_address": "1.1.1.1", + }, + ], + } + + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_bgp_add_fam_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="router bgp 1\n bgp router-id 1.2.1.3\n neighbor 1.1.1.1\n " + "remote-as 6\n address-family vpnv4 unicast\n origin-as validation disable\n " + "bestpath origin-as allow invalid\n weight 0\n send-community-ebgp\n " + " multipath\n allowas-in 3\n maximum-prefix 1 1 discard-extra-paths\n" + " capability orf prefix both\n " + "next-hop-unchanged multipath\n !\n " + "!\n !", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = { + "as_number": "1", + "neighbors": [ + { + "neighbor_address": "1.1.1.1", + "address_family": [ + { + "afi": "vpnv4", + "safi": "unicast", + "origin_as": {"validation": {"disable": True}}, + "bestpath_origin_as_allow_invalid": True, + "weight": 0, + "send_community_ebgp": {"set": True}, + "multipath": True, + "allowas_in": {"value": 3}, + "capability_orf_prefix": "both", + "next_hop_unchanged": {"multipath": True}, + }, + ], + }, + ], + } + + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_bgp_nbr_af_afi_replaced(self): + self.maxDiff = None + set_module_args( + dict( + config=dict( + as_number="1", + neighbors=[ + dict( + neighbor_address="1.1.1.1", + address_family=[ + dict( + afi="vpnv4", + safi="flowspec", + multipath=True, + default_originate=dict(set=True), + capability_orf_prefix="both", + send_multicast_attributes=dict(set=True), + soft_reconfiguration=dict(inbound=dict(set=True)), + send_community_gshut_ebgp=dict(set=True), + send_extended_community_ebgp=dict(set=True), + send_community_ebgp=dict(set=True), + origin_as=dict(validation=dict(disable=True)), + remove_private_AS=dict( + set=True, + inbound=True, + entire_aspath=True, + ), + route_policy=dict(inbound="test1", outbound="test1"), + maximum_prefix=dict( + max_limit=10, + threshold_value=20, + restart=10, + ), + next_hop_self=dict(set=True), + next_hop_unchanged=dict(multipath=True), + aigp=dict(set=True, send_med=dict(set=True)), + as_override=dict(set=True), + bestpath_origin_as_allow_invalid=True, + long_lived_graceful_restart=dict( + stale_time=dict(send=20, accept=30), + ), + ), + ], + ), + ], + ), + state="replaced", + ), + ) + commands = [ + "address-family vpnv4 flowspec", + "aigp", + "aigp send med", + "as-override", + "bestpath origin-as allow invalid", + "capability orf prefix both", + "default-originate", + "maximum-prefix 10 20 restart 10", + "multipath", + "neighbor 1.1.1.1", + "next-hop-self", + "next-hop-unchanged multipath", + "origin-as validation disable", + "remove-private-AS inbound entire-aspath", + "route-policy test1 in", + "route-policy test1 out", + "router bgp 1", + "send-community-ebgp", + "send-community-gshut-ebgp", + "send-extended-community-ebgp", + "send-multicast-attributes", + "soft-reconfiguration inbound", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_bgp_nbr_af_overridden(self): + run_cfg = dedent( + """\ + router bgp 1 + bgp router-id 1.2.3.4 + neighbor 1.1.1.1 + remote-as 5 + address-family ipv4 unicast + origin-as validation disable + bestpath origin-as allow invalid + aigp + aigp send med + send-community-ebgp + multipath + allowas-in 4 + maximum-prefix 10 20 restart 10 + as-override + capability orf prefix both + send-extended-community-ebgp + default-originate + next-hop-self + send-community-gshut-ebgp + soft-reconfiguration inbound + send-multicast-attributes + remove-private-AS inbound entire-aspath + next-hop-unchanged multipath + vrf vrf1 + rd auto + address-family ipv4 unicast + neighbor 1.2.1.2 + remote-as 5 + address-family ipv4 unicast + multipath + capability orf prefix both + default-originate + route-policy test2 in + route-policy test2 out + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + as_number="1", + vrfs=[ + dict( + vrf="vrf1", + neighbors=[ + dict( + neighbor_address="1.2.1.2", + address_family=[ + dict( + afi="ipv4", + safi="unicast", + multipath=True, + default_originate=dict(set=True), + ), + ], + ), + ], + ), + ], + ), + state="overridden", + ), + ) + commands = [ + "router bgp 1", + "vrf vrf1", + "neighbor 1.2.1.2", + "address-family ipv4 unicast", + "no capability orf prefix both", + "no route-policy test2 in", + "no route-policy test2 out", + "neighbor 1.1.1.1", + "no address-family ipv4 unicast", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_command.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_command.py new file mode 100644 index 00000000..feb70876 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_command.py @@ -0,0 +1,128 @@ +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_command +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrCommandModule(TestIosxrModule): + + module = iosxr_command + + def setUp(self): + super(TestIosxrCommandModule, self).setUp() + + self.mock_run_commands = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_command.run_commands", + ) + self.run_commands = self.mock_run_commands.start() + + def tearDown(self): + super(TestIosxrCommandModule, self).tearDown() + + self.mock_run_commands.stop() + + def load_fixtures(self, commands=None): + def load_from_file(*args, **kwargs): + module, commands = args + output = list() + + for item in commands: + try: + command = item["command"] + except Exception: + command = item + filename = str(command).replace(" ", "_") + output.append(load_fixture(filename)) + return output + + self.run_commands.side_effect = load_from_file + + def test_iosxr_command_simple(self): + set_module_args(dict(commands=["show version"])) + result = self.execute_module() + self.assertEqual(len(result["stdout"]), 1) + self.assertTrue( + result["stdout"][0].startswith("Cisco IOS XR Software"), + ) + + def test_iosxr_command_multiple(self): + set_module_args(dict(commands=["show version", "show version"])) + result = self.execute_module() + self.assertEqual(len(result["stdout"]), 2) + self.assertTrue( + result["stdout"][0].startswith("Cisco IOS XR Software"), + ) + + def test_iosxr_command_wait_for(self): + wait_for = 'result[0] contains "Cisco IOS"' + set_module_args(dict(commands=["show version"], wait_for=wait_for)) + self.execute_module() + + def test_iosxr_command_wait_for_fails(self): + wait_for = 'result[0] contains "test string"' + set_module_args(dict(commands=["show version"], wait_for=wait_for)) + self.execute_module(failed=True) + self.assertEqual(self.run_commands.call_count, 10) + + def test_iosxr_command_retries(self): + wait_for = 'result[0] contains "test string"' + set_module_args( + dict(commands=["show version"], wait_for=wait_for, retries=2), + ) + self.execute_module(failed=True) + self.assertEqual(self.run_commands.call_count, 2) + + def test_iosxr_command_match_any(self): + wait_for = [ + 'result[0] contains "Cisco IOS"', + 'result[0] contains "test string"', + ] + set_module_args( + dict(commands=["show version"], wait_for=wait_for, match="any"), + ) + self.execute_module() + + def test_iosxr_command_match_all(self): + wait_for = [ + 'result[0] contains "Cisco IOS"', + 'result[0] contains "XR Software"', + ] + set_module_args( + dict(commands=["show version"], wait_for=wait_for, match="all"), + ) + self.execute_module() + + def test_iosxr_command_match_all_failure(self): + wait_for = [ + 'result[0] contains "Cisco IOS"', + 'result[0] contains "test string"', + ] + commands = ["show version", "show version"] + set_module_args( + dict(commands=commands, wait_for=wait_for, match="all"), + ) + self.execute_module(failed=True) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_config.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_config.py new file mode 100644 index 00000000..bbfdcb3e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_config.py @@ -0,0 +1,313 @@ +# +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.cliconf.iosxr import Cliconf +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_config +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import MagicMock, patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrConfigModule(TestIosxrModule): + + module = iosxr_config + + def setUp(self): + super(TestIosxrConfigModule, self).setUp() + + self.patcher_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_config.get_config", + ) + self.mock_get_config = self.patcher_get_config.start() + + self.patcher_exec_command = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_config.load_config", + ) + self.mock_exec_command = self.patcher_exec_command.start() + + self.mock_get_connection = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_config.get_connection", + ) + self.get_connection = self.mock_get_connection.start() + + self.conn = self.get_connection() + self.conn.edit_config = MagicMock() + + self.cliconf_obj = Cliconf(MagicMock()) + self.running_config = load_fixture("iosxr_config_config.cfg") + + def tearDown(self): + super(TestIosxrConfigModule, self).tearDown() + + self.patcher_get_config.stop() + self.patcher_exec_command.stop() + self.mock_get_connection.stop() + + def load_fixtures(self, commands=None): + config_file = "iosxr_config_config.cfg" + self.mock_get_config.return_value = load_fixture(config_file) + self.mock_exec_command.return_value = "dummy diff" + + def test_iosxr_config_unchanged(self): + src = load_fixture("iosxr_config_config.cfg") + set_module_args(dict(src=src)) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff(src, src), + ) + self.execute_module() + + def test_iosxr_config_src(self): + src = load_fixture("iosxr_config_src.cfg") + set_module_args(dict(src=src)) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff(src, self.running_config), + ) + commands = [ + "hostname foo", + "interface GigabitEthernet0/0", + "no ip address", + ] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_config_backup(self): + set_module_args(dict(backup=True)) + result = self.execute_module() + self.assertIn("__backup__", result) + + def test_iosxr_config_lines_wo_parents(self): + lines = ["hostname foo"] + set_module_args(dict(lines=lines)) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff( + "\n".join(lines), + self.running_config, + ), + ) + commands = ["hostname foo"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_config_lines_w_parents(self): + lines = ["shutdown"] + parents = ["interface GigabitEthernet0/0"] + set_module_args(dict(lines=lines, parents=parents)) + module = MagicMock() + module.params = {"lines": lines, "parents": parents, "src": None} + candidate_config = iosxr_config.get_candidate(module) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff( + candidate_config, + self.running_config, + ), + ) + commands = ["interface GigabitEthernet0/0", "shutdown"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_config_before(self): + lines = ["hostname foo"] + set_module_args(dict(lines=lines, before=["test1", "test2"])) + commands = ["test1", "test2", "hostname foo"] + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff( + "\n".join(lines), + self.running_config, + ), + ) + self.execute_module(changed=True, commands=commands, sort=False) + + def test_iosxr_config_after(self): + lines = ["hostname foo"] + set_module_args(dict(lines=lines, after=["test1", "test2"])) + commands = ["hostname foo", "test1", "test2"] + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff( + "\n".join(lines), + self.running_config, + ), + ) + self.execute_module(changed=True, commands=commands, sort=False) + + def test_iosxr_config_before_after_no_change(self): + lines = ["hostname router"] + set_module_args( + dict( + lines=lines, + before=["test1", "test2"], + after=["test3", "test4"], + ), + ) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff( + "\n".join(lines), + self.running_config, + ), + ) + self.execute_module() + + def test_iosxr_config_config(self): + config = "hostname localhost" + lines = ["hostname router"] + set_module_args(dict(lines=["hostname router"], config=config)) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff("\n".join(lines), config), + ) + commands = ["hostname router"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_config_replace_block(self): + lines = ["description test string", "test string"] + parents = ["interface GigabitEthernet0/0"] + set_module_args(dict(lines=lines, replace="block", parents=parents)) + commands = parents + lines + + module = MagicMock() + module.params = {"lines": lines, "parents": parents, "src": None} + candidate_config = iosxr_config.get_candidate(module) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff( + candidate_config, + self.running_config, + diff_replace="block", + path=parents, + ), + ) + self.execute_module(changed=True, commands=commands) + + def test_iosxr_config_force(self): + lines = ["hostname router"] + set_module_args(dict(lines=lines, force=True)) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff( + "\n".join(lines), + self.running_config, + diff_match="none", + ), + ) + self.execute_module(changed=True, commands=lines) + + def test_iosxr_config_admin(self): + lines = ["username admin", "group root-system", "secret P@ssw0rd"] + set_module_args(dict(lines=lines, admin=True)) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff( + "\n".join(lines), + self.running_config, + ), + ) + self.execute_module(changed=True, commands=lines) + + def test_iosxr_config_match_none(self): + lines = ["ip address 1.2.3.4 255.255.255.0", "description test string"] + parents = ["interface GigabitEthernet0/0"] + set_module_args(dict(lines=lines, parents=parents, match="none")) + commands = parents + lines + module = MagicMock() + module.params = {"lines": lines, "parents": parents, "src": None} + candidate_config = iosxr_config.get_candidate(module) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff( + candidate_config, + self.running_config, + diff_match="none", + path=parents, + ), + ) + + self.execute_module(changed=True, commands=commands, sort=False) + + def test_iosxr_config_match_strict(self): + lines = [ + "ip address 1.2.3.4 255.255.255.0", + "description test string", + "shutdown", + ] + parents = ["interface GigabitEthernet0/0"] + set_module_args(dict(lines=lines, parents=parents, match="strict")) + commands = parents + ["shutdown"] + module = MagicMock() + module.params = {"lines": lines, "parents": parents, "src": None} + candidate_config = iosxr_config.get_candidate(module) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff( + candidate_config, + self.running_config, + diff_match="strict", + path=parents, + ), + ) + + self.execute_module(changed=True, commands=commands, sort=False) + + def test_iosxr_config_match_exact(self): + lines = [ + "ip address 1.2.3.4 255.255.255.0", + "description test string", + "shutdown", + ] + parents = ["interface GigabitEthernet0/0"] + set_module_args(dict(lines=lines, parents=parents, match="exact")) + commands = parents + lines + module = MagicMock() + module.params = {"lines": lines, "parents": parents, "src": None} + candidate_config = iosxr_config.get_candidate(module) + self.conn.get_diff = MagicMock( + return_value=self.cliconf_obj.get_diff( + candidate_config, + self.running_config, + diff_match="exact", + path=parents, + ), + ) + + self.execute_module(changed=True, commands=commands, sort=False) + + def test_iosxr_config_src_and_lines_fails(self): + args = dict(src="foo", lines="foo") + set_module_args(args) + self.execute_module(failed=True) + + def test_iosxr_config_src_and_parents_fails(self): + args = dict(src="foo", parents="foo") + set_module_args(args) + self.execute_module(failed=True) + + def test_iosxr_config_match_exact_requires_lines(self): + args = dict(match="exact") + set_module_args(args) + self.execute_module(failed=True) + + def test_iosxr_config_match_strict_requires_lines(self): + args = dict(match="strict") + set_module_args(args) + self.execute_module(failed=True) + + def test_iosxr_config_replace_block_requires_lines(self): + args = dict(replace="block") + set_module_args(args) + self.execute_module(failed=True) + + def test_iosxr_config_replace_config_requires_src(self): + args = dict(replace="config") + set_module_args(args) + self.execute_module(failed=True) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_facts.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_facts.py new file mode 100644 index 00000000..7848f798 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_facts.py @@ -0,0 +1,120 @@ +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +import json + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_facts +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrFacts(TestIosxrModule): + + module = iosxr_facts + + def setUp(self): + super(TestIosxrFacts, self).setUp() + + self.mock_run_commands = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.legacy.base.run_commands", + ) + self.run_commands = self.mock_run_commands.start() + + self.mock_get_resource_connection = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection = self.mock_get_resource_connection.start() + + self.mock_get_capabilities = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.legacy.base.get_capabilities", + ) + self.get_capabilities = self.mock_get_capabilities.start() + self.get_capabilities.return_value = { + "device_info": { + "network_os": "iosxr", + "network_os_hostname": "iosxr01", + "network_os_image": "bootflash:disk0/xrvr-os-mbi-6.1.3/mbixrvr-rp.vm", + "network_os_version": "6.1.3[Default]", + }, + "network_api": "cliconf", + } + + def tearDown(self): + super(TestIosxrFacts, self).tearDown() + + self.mock_run_commands.stop() + self.mock_get_capabilities.stop() + self.mock_get_resource_connection.stop() + + def load_fixtures(self, commands=None): + def load_from_file(*args, **kwargs): + module, commands = args + output = list() + + for item in commands: + try: + obj = json.loads(item) + command = obj["command"] + except ValueError: + command = item + filename = str(command).replace(" ", "_") + filename = filename.replace("/", "7") + filename = filename.replace("|", "_") + output.append(load_fixture(filename)) + return output + + self.run_commands.side_effect = load_from_file + + def test_iosxr_facts_gather_subset_default(self): + set_module_args(dict()) + result = self.execute_module() + ansible_facts = result["ansible_facts"] + self.assertIn("default", ansible_facts["ansible_net_gather_subset"][0]) + self.assertEqual( + [], + ansible_facts["ansible_net_gather_network_resources"], + ) + self.assertEqual("iosxr", ansible_facts["ansible_net_system"]) + self.assertEqual( + True, + True if ansible_facts.get("ansible_net_version") else False, + ) + self.assertEqual( + True, + True if ansible_facts.get("ansible_net_python_version") else False, + ) + self.assertEqual( + True, + True if ansible_facts.get("ansible_net_api") else False, + ) + + def test_iosxr_facts_gather_subset_config(self): + set_module_args({"gather_subset": "config"}) + result = self.execute_module() + ansible_facts = result["ansible_facts"] + self.assertIn("default", ansible_facts["ansible_net_gather_subset"]) + self.assertIn("config", ansible_facts["ansible_net_gather_subset"]) + self.assertEqual("iosxr01", ansible_facts["ansible_net_hostname"]) + self.assertIn("ansible_net_config", ansible_facts) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_interfaces.py new file mode 100644 index 00000000..4b7a0bcd --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_interfaces.py @@ -0,0 +1,288 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_interfaces +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrInterfacesModule(TestIosxrModule): + module = iosxr_interfaces + + def setUp(self): + super(TestIosxrInterfacesModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.interfaces.interfaces.InterfacesFacts.get_config", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrInterfacesModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def _prepare(self): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_interface_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_interfaces_merged_idempotent(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + description="Configured and Merged by Ansible-Network", + mtu=110, + enabled=True, + duplex="half", + ), + dict( + name="GigabitEthernet0/0/0/1", + description="Configured and Merged by Ansible-Network", + mtu=2800, + speed=100, + ), + ], + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_interfaces_merged(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + description="Configured and Merged by Ansible-Network", + mtu=110, + enabled=True, + duplex="half", + ), + dict( + name="GigabitEthernet0/0/0/1", + description="Configured and Merged by Ansible-Network", + mtu=2800, + enabled=False, + duplex="full", + speed=100, + ), + ], + state="merged", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/0", + "description Configured and Merged by Ansible-Network", + "mtu 110", + "duplex half", + "no shutdown", + "interface GigabitEthernet0/0/0/1", + "description Configured and Merged by Ansible-Network", + "mtu 2800", + "speed 100", + "duplex full", + "shutdown", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_interfaces_replaced(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + description="Configured and Replaced by Ansible-Network", + mtu=110, + ), + dict( + name="GigabitEthernet0/0/0/1", + description="Configured and Replaced by Ansible-Network", + speed=100, + ), + ], + state="replaced", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/0", + "description Configured and Replaced by Ansible-Network", + "no duplex", + "interface GigabitEthernet0/0/0/1", + "description Configured and Replaced by Ansible-Network", + "no mtu", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_interfaces_deleted(self): + self._prepare() + set_module_args(dict(state="deleted")) + + commands = [ + "interface GigabitEthernet0/0/0/0", + "no description", + "no mtu", + "no duplex", + "interface GigabitEthernet0/0/0/1", + "no description", + "no speed", + "no mtu", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_interfaces_rendered(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + description="Configured and Merged by Ansible-Network", + mtu=110, + enabled=True, + duplex="half", + ), + dict( + name="GigabitEthernet0/0/0/1", + description="Configured and Merged by Ansible-Network", + mtu=2800, + enabled=False, + duplex="full", + speed=100, + ), + ], + state="rendered", + ), + ) + + commands = [ + "interface GigabitEthernet0/0/0/0", + "description Configured and Merged by Ansible-Network", + "mtu 110", + "duplex half", + "no shutdown", + "interface GigabitEthernet0/0/0/1", + "description Configured and Merged by Ansible-Network", + "mtu 2800", + "speed 100", + "duplex full", + "shutdown", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_interfaces_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="interface GigabitEthernet0/0/0/0\n description Configured and Merged by Ansible-Network\n " + "mtu 110\n duplex half\ninterface GigabitEthernet0/0/0/1\n " + "description Configured and Merged by Ansible-Network\n no shutdown\n mtu 2800\n speed 100", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = [ + { + "description": "Configured and Merged by Ansible-Network", + "duplex": "half", + "enabled": True, + "mtu": 110, + "name": "GigabitEthernet0/0/0/0", + }, + { + "description": "Configured and Merged by Ansible-Network", + "enabled": True, + "mtu": 2800, + "name": "GigabitEthernet0/0/0/1", + "speed": 100, + }, + ] + + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_interfaces_overridden(self): + self.maxDiff = None + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/1", + description="Configured and Overridden by Ansible-Network", + mtu=2000, + enabled=False, + duplex="full", + speed=100, + ), + ], + state="overridden", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/0", + "no description", + "no mtu", + "no duplex", + "interface GigabitEthernet0/0/0/1", + "description Configured and Overridden by Ansible-Network", + "mtu 2000", + "duplex full", + "shutdown", + ] + + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l2_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l2_interfaces.py new file mode 100644 index 00000000..10053878 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l2_interfaces.py @@ -0,0 +1,246 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_l2_interfaces +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrL2InterfacesModule(TestIosxrModule): + module = iosxr_l2_interfaces + + def setUp(self): + super(TestIosxrL2InterfacesModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + self.mock_get_os_version = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.l2_interfaces.l2_interfaces.get_os_version", + ) + self.get_os_version = self.mock_get_os_version.start() + self.get_os_version.return_value = "7.0.2" + self.mock_get_os_version1 = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.l2_interfaces.l2_interfaces.get_os_version", + ) + self.get_os_version1 = self.mock_get_os_version1.start() + self.get_os_version1.return_value = "7.0.2" + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.l2_interfaces.l2_interfaces.L2_InterfacesFacts.get_config", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrL2InterfacesModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_get_os_version.stop() + self.get_os_version1.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def _prepare(self): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_l2_interface_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_l2_interfaces_merged_idempotent(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/1", + l2transport=True, + l2protocol=[dict(cpsv="tunnel")], + ), + dict( + name="GigabitEthernet0/0/0/3.900", + encapsulation=dict(dot1q=20, second_dot1q=40), + ), + ], + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_l2_interfaces_merged(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/1", + l2transport=True, + l2protocol=[dict(cpsv="tunnel")], + ), + dict( + name="GigabitEthernet0/0/0/3.900", + encapsulation=dict(dot1q=20, second_dot1q=40), + ), + ], + state="merged", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/1", + "l2transport l2protocol cpsv tunnel", + "interface GigabitEthernet0/0/0/3.900", + "encapsulation dot1q 20 second-dot1q 40", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_l2_interfaces_replaced(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/1", + l2transport=True, + l2protocol=[dict(cpsv="drop")], + ), + ], + state="replaced", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/1", + "l2transport l2protocol cpsv drop", + "no l2transport", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_l2_interfaces_deleted(self): + self._prepare() + set_module_args(dict(state="deleted")) + + commands = [ + "interface GigabitEthernet0/0/0/1", + "no l2transport", + "interface GigabitEthernet0/0/0/3.900", + "no encapsulation dot1q", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_l2_interfaces_rendered(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/1", + l2transport=True, + l2protocol=[dict(cpsv="tunnel")], + ), + dict( + name="GigabitEthernet0/0/0/3.900", + encapsulation=dict(dot1q=20, second_dot1q=40), + ), + ], + state="rendered", + ), + ) + + commands = [ + "interface GigabitEthernet0/0/0/1", + "l2transport l2protocol cpsv tunnel", + "interface GigabitEthernet0/0/0/3.900", + "encapsulation dot1q 20 second-dot1q 40", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_l2_interfaces_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="interface GigabitEthernet0/0/0/1\n l2transport\n l2protocol cpsv tunnel\n " + "propagate remote-status\n !", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + print(result["parsed"]) + parsed_list = [ + { + "name": "GigabitEthernet0/0/0/1", + "l2transport": True, + "l2protocol": [{"cpsv": "tunnel"}], + "propagate": True, + }, + ] + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_l2_interfaces_overridden(self): + self.maxDiff = None + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/4", + l2transport=True, + l2protocol=[dict(cpsv="tunnel")], + ), + dict( + name="GigabitEthernet0/0/0/3.900", + encapsulation=dict(dot1q=40, second_dot1q=60), + ), + ], + state="overridden", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/4", + "l2transport l2protocol cpsv tunnel", + "interface GigabitEthernet0/0/0/3.900", + "encapsulation dot1q 40 second-dot1q 60", + "interface GigabitEthernet0/0/0/1", + "no l2transport", + ] + + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l3_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l3_interfaces.py new file mode 100644 index 00000000..5fab9f7e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l3_interfaces.py @@ -0,0 +1,255 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_l3_interfaces +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrL3InterfacesModule(TestIosxrModule): + module = iosxr_l3_interfaces + + def setUp(self): + super(TestIosxrL3InterfacesModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.l3_interfaces.l3_interfaces.L3_InterfacesFacts.get_config", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrL3InterfacesModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def _prepare(self): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_l3_interface_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_l3_interfaces_merged_idempotent(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + ipv4=[dict(address="198.51.100.1/24")], + ipv6=[dict(address="2001:db8::/32")], + ), + dict( + name="GigabitEthernet0/0/0/1", + ipv4=[ + dict(address="192.0.2.1/24"), + dict(address="192.0.2.2/24", secondary=True), + ], + ), + ], + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_l3_interfaces_merged(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + ipv4=[dict(address="198.51.100.1/24")], + ), + dict( + name="GigabitEthernet0/0/0/1", + ipv4=[ + dict(address="192.0.2.1/24"), + dict(address="192.0.2.2/24", secondary=True), + ], + ipv6=[dict(address="2001:db8:0:3::/64")], + ), + ], + state="merged", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/0", + "ipv4 address 198.51.100.1 255.255.255.0", + "interface GigabitEthernet0/0/0/1", + "ipv4 address 192.0.2.2 255.255.255.0 secondary", + "ipv4 address 192.0.2.1 255.255.255.0", + "ipv6 address 2001:db8:0:3::/64", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_l3_interfaces_replaced(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + ipv4=[ + dict(address="203.0.113.27/24"), + dict(address="203.0.114.1/24", secondary=True), + ], + ), + ], + state="replaced", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/0", + "no ipv6 address", + "ipv4 address 203.0.113.27 255.255.255.0", + "ipv4 address 203.0.114.1 255.255.255.0 secondary", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_l3_interfaces_deleted(self): + self._prepare() + set_module_args(dict(state="deleted")) + + commands = [ + "interface GigabitEthernet0/0/0/0", + "no ipv4 address", + "no ipv6 address", + "interface GigabitEthernet0/0/0/1", + "no ipv4 address", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_l3_interfaces_rendered(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + ipv4=[dict(address="198.51.100.1/24")], + ), + dict( + name="GigabitEthernet0/0/0/1", + ipv4=[ + dict(address="192.0.2.1/24"), + dict(address="192.0.2.2/24", secondary=True), + ], + ipv6=[dict(address="2001:db8:0:3::/64")], + ), + ], + state="rendered", + ), + ) + + commands = [ + "interface GigabitEthernet0/0/0/0", + "ipv4 address 198.51.100.1 255.255.255.0", + "interface GigabitEthernet0/0/0/1", + "ipv4 address 192.0.2.2 255.255.255.0 secondary", + "ipv4 address 192.0.2.1 255.255.255.0", + "ipv6 address 2001:db8:0:3::/64", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_l3_interfaces_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="interface GigabitEthernet0/0/0/0\nipv4 address 198.51.100.1 255.255.255.0\n" + "ipv6 address 2001:db8::/32\ninterface GigabitEthernet0/0/0/1\nipv4 address" + " 192.0.2.1 255.255.255.0\nipv4 address 192.0.2.2 255.255.255.0 secondary\n", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + print(result["parsed"]) + parsed_list = [ + { + "name": "GigabitEthernet0/0/0/0", + "ipv4": [{"address": "198.51.100.1 255.255.255.0"}], + "ipv6": [{"address": "2001:db8::/32"}], + }, + { + "name": "GigabitEthernet0/0/0/1", + "ipv4": [ + {"address": "192.0.2.1 255.255.255.0"}, + {"address": "192.0.2.2 255.255.255.0", "secondary": True}, + ], + }, + ] + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_l3_interfaces_overridden(self): + self.maxDiff = None + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/1", + ipv4=[dict(address="198.51.102.1/24")], + ipv6=[dict(address="2001:db8:1::/64")], + ), + ], + state="overridden", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/0", + "no ipv4 address", + "no ipv6 address", + "interface GigabitEthernet0/0/0/1", + "no ipv4 address", + "ipv4 address 198.51.102.1 255.255.255.0", + "ipv6 address 2001:db8:1::/64", + ] + + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp.py new file mode 100644 index 00000000..e4c9c467 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp.py @@ -0,0 +1,93 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_lacp +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrLacpModule(TestIosxrModule): + module = iosxr_lacp + + def setUp(self): + super(TestIosxrLacpModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lacp.lacp.LacpFacts.get_config", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrLacpModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def _prepare(self): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_lacp_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_lacp_merged(self): + set_module_args( + dict( + config=dict( + system=dict( + priority=12, + mac=dict(address="00c1.4c00.bd15"), + ), + ), + state="merged", + ), + ) + commands = [ + "lacp system mac 00c1.4c00.bd15", + "lacp system priority 12", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp_interfaces.py new file mode 100644 index 00000000..55358a06 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp_interfaces.py @@ -0,0 +1,263 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_lacp_interfaces +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrLacpInterfacesModule(TestIosxrModule): + module = iosxr_lacp_interfaces + + def setUp(self): + super(TestIosxrLacpInterfacesModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lacp_interfaces.lacp_interfaces.Lacp_interfacesFacts.get_config", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrLacpInterfacesModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def _prepare(self): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_lacp_interfaces_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_lacp_interfaces_merged_idempotent(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="Bundle-Ether10", + churn_logging="actor", + collector_max_delay=100, + switchover_suppress_flaps=500, + ), + dict( + name="Bundle-Ether11", + system=dict(mac="00c2.4c00.bd15"), + ), + dict(name="GigabitEthernet0/0/0/1", period=200), + ], + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_lacp_interfaces_merged(self): + set_module_args( + dict( + config=[ + dict( + name="Bundle-Ether10", + churn_logging="actor", + collector_max_delay=100, + switchover_suppress_flaps=500, + ), + dict( + name="Bundle-Ether11", + system=dict(mac="00c2.4c00.bd15"), + ), + dict(name="GigabitEthernet0/0/0/1", period=100), + ], + state="merged", + ), + ) + commands = [ + "interface Bundle-Ether10", + "lacp churn logging actor", + "lacp switchover suppress-flaps 500", + "lacp collector-max-delay 100", + "interface Bundle-Ether11", + "lacp system mac 00c2.4c00.bd15", + "interface GigabitEthernet0/0/0/1", + "lacp period 100", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lacp_interfaces_replaced(self): + self._prepare() + set_module_args( + dict( + config=[ + dict(name="Bundle-Ether10", churn_logging="partner"), + dict(name="GigabitEthernet0/0/0/1", period=300), + ], + state="replaced", + ), + ) + commands = [ + "interface Bundle-Ether10", + "no lacp switchover suppress-flaps 500", + "no lacp collector-max-delay 100", + "lacp churn logging partner", + "interface GigabitEthernet0/0/0/1", + "lacp period 300", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lacp_interfaces_deleted(self): + self._prepare() + set_module_args(dict(state="deleted")) + + commands = [ + "interface Bundle-Ether10", + "no lacp switchover suppress-flaps 500", + "no lacp collector-max-delay 100", + "no lacp churn logging actor", + "interface Bundle-Ether11", + "no lacp system mac 00c2.4c00.bd15", + "interface GigabitEthernet0/0/0/1", + "no lacp period 200", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lag_interfaces_rendered(self): + set_module_args( + dict( + config=[ + dict( + name="Bundle-Ether10", + churn_logging="actor", + collector_max_delay=100, + switchover_suppress_flaps=500, + ), + dict( + name="Bundle-Ether11", + system=dict(mac="00c2.4c00.bd15"), + ), + dict(name="GigabitEthernet0/0/0/1", period=100), + ], + state="rendered", + ), + ) + + commands = [ + "interface Bundle-Ether10", + "lacp churn logging actor", + "lacp switchover suppress-flaps 500", + "lacp collector-max-delay 100", + "interface Bundle-Ether11", + "lacp system mac 00c2.4c00.bd15", + "interface GigabitEthernet0/0/0/1", + "lacp period 100", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_lacp_interfaces_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="interface Bundle-Ether10\r\n lacp churn logging actor\r\n lacp" + " switchover suppress-flaps 500\r\n " + "lacp collector-max-delay 100\r\n!\r\ninterface " + "Bundle-Ether11\r\n lacp system mac 00c2.4c00.bd15\r" + "\n!\r\ninterface MgmtEth0/RP0/CPU0/0\r\n ipv4 address" + " 192.0.2.11 255.255.255.0\r\n!\r\ninterface " + "GigabitEthernet0/0/0/1\r\n lacp period 200\r\n!", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + print(result["parsed"]) + parsed_list = [ + { + "churn_logging": "actor", + "collector_max_delay": 100, + "name": "Bundle-Ether10", + "switchover_suppress_flaps": 500, + }, + {"name": "Bundle-Ether11", "system": {"mac": "00c2.4c00.bd15"}}, + {"name": "GigabitEthernet0/0/0/1", "period": 200}, + ] + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_lag_interfaces_overridden(self): + self.maxDiff = None + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="Bundle-Ether12", + churn_logging="both", + collector_max_delay=100, + switchover_suppress_flaps=500, + ), + dict(name="GigabitEthernet0/0/0/1", period=300), + ], + state="overridden", + ), + ) + commands = [ + "interface Bundle-Ether10", + "no lacp switchover suppress-flaps 500", + "no lacp collector-max-delay 100", + "no lacp churn logging actor", + "interface Bundle-Ether11", + "no lacp system mac 00c2.4c00.bd15", + "interface Bundle-Ether12", + "lacp churn logging both", + "lacp collector-max-delay 100", + "lacp switchover suppress-flaps 500", + "interface GigabitEthernet0/0/0/1", + "lacp period 300", + ] + + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lag_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lag_interfaces.py new file mode 100644 index 00000000..b0d68fc6 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lag_interfaces.py @@ -0,0 +1,375 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_lag_interfaces +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrLagInterfacesModule(TestIosxrModule): + module = iosxr_lag_interfaces + + def setUp(self): + super(TestIosxrLagInterfacesModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lag_interfaces.lag_interfaces.Lag_interfacesFacts.get_config", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrLagInterfacesModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def _prepare(self): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_lag_interface_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_lag_interfaces_merged_idempotent(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="Bundle-Ether10", + mode="active", + members=[ + dict( + member="GigabitEthernet0/0/0/0", + mode="inherit", + ), + dict( + member="GigabitEthernet0/0/0/1", + mode="passive", + ), + ], + links=dict(max_active=10, min_active=2), + ), + dict( + name="Bundle-Ether11", + mode="active", + members=[ + dict( + member="GigabitEthernet0/0/0/8", + mode="passive", + ), + dict( + member="GigabitEthernet0/0/0/9", + mode="passive", + ), + ], + ), + ], + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_lag_interfaces_merged(self): + set_module_args( + dict( + config=[ + dict( + name="Bundle-Ether10", + mode="active", + members=[ + dict( + member="GigabitEthernet0/0/0/0", + mode="inherit", + ), + dict( + member="GigabitEthernet0/0/0/1", + mode="passive", + ), + ], + links=dict(max_active=10, min_active=2), + ), + dict( + name="Bundle-Ether11", + mode="active", + members=[ + dict( + member="GigabitEthernet0/0/0/8", + mode="passive", + ), + dict( + member="GigabitEthernet0/0/0/9", + mode="passive", + ), + ], + ), + ], + state="merged", + ), + ) + commands = [ + "interface Bundle-Ether10", + "bundle minimum-active links 2", + "bundle maximum-active links 10", + "lacp mode active", + "interface GigabitEthernet0/0/0/1", + "bundle id 10 mode passive", + "interface GigabitEthernet0/0/0/0", + "bundle id 10 mode inherit", + "interface Bundle-Ether11", + "lacp mode active", + "interface GigabitEthernet0/0/0/8", + "bundle id 11 mode passive", + "interface GigabitEthernet0/0/0/9", + "bundle id 11 mode passive", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lag_interfaces_replaced(self): + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="Bundle-Ether10", + mode="passive", + members=[ + dict( + member="GigabitEthernet0/0/0/0", + mode="passive", + ), + ], + ), + dict(name="Bundle-Ether12", mode="active"), + ], + state="replaced", + ), + ) + commands = [ + "interface Bundle-Ether10", + "no bundle maximum-active links 10", + "no bundle minimum-active links 2", + "lacp mode passive", + "interface GigabitEthernet0/0/0/1", + "no bundle id", + "interface GigabitEthernet0/0/0/0", + "bundle id 10 mode passive", + "interface Bundle-Ether12", + "lacp mode active", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lag_interfaces_deleted(self): + self._prepare() + set_module_args(dict(state="deleted")) + + commands = [ + "interface Bundle-Ether10", + "no bundle maximum-active links 10", + "no bundle minimum-active links 2", + "no lacp mode active", + "interface GigabitEthernet0/0/0/0", + "no bundle id", + "interface GigabitEthernet0/0/0/1", + "no bundle id", + "interface Bundle-Ether11", + "no lacp mode active", + "interface GigabitEthernet0/0/0/8", + "no bundle id", + "interface GigabitEthernet0/0/0/9", + "no bundle id", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lag_interfaces_rendered(self): + set_module_args( + dict( + config=[ + dict( + name="Bundle-Ether10", + mode="active", + members=[ + dict( + member="GigabitEthernet0/0/0/0", + mode="passive", + ), + dict( + member="GigabitEthernet0/0/0/1", + mode="passive", + ), + ], + links=dict(max_active=10, min_active=2), + ), + dict( + name="Bundle-Ether11", + mode="active", + members=[ + dict( + member="GigabitEthernet0/0/0/8", + mode="passive", + ), + dict( + member="GigabitEthernet0/0/0/9", + mode="passive", + ), + ], + ), + ], + state="rendered", + ), + ) + + commands = [ + "interface Bundle-Ether10", + "bundle minimum-active links 2", + "bundle maximum-active links 10", + "lacp mode active", + "interface GigabitEthernet0/0/0/1", + "bundle id 10 mode passive", + "interface GigabitEthernet0/0/0/0", + "bundle id 10 mode passive", + "interface Bundle-Ether11", + "lacp mode active", + "interface GigabitEthernet0/0/0/8", + "bundle id 11 mode passive", + "interface GigabitEthernet0/0/0/9", + "bundle id 11 mode passive", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_lag_interfaces_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="interface Bundle-Ether10\r\n lacp mode active\r\n bundle maximum-active " + "links 10\r\n bundle minimum-active links 2\r\n!\r\ninterface Bundle-Ether11" + "\r\nlacp mode active\r\n!\r\ninterface GigabitEthernet0/0/0/0\r\n description " + '"GigabitEthernet - 0"\r\n bundle id 10 mode inherit\r\n!\r\ninterface ' + "GigabitEthernet0/0/0/1" + '\r\n description "GigabitEthernet - 2"\r\n bundle id 10 mode passive\r\n!\r\n' + 'interface GigabitEthernet0/0/0/8\r\n description "GigabitEthernet - 8"' + "\r\n bundle id 11 mode passive" + "\r\n!\r\ninterface GigabitEthernet0/0/0/9\r\n description " + '"GigabitEthernet - 9"\r\n bundle id 11 mode passive\r\n!', + state="parsed", + ), + ) + result = self.execute_module(changed=False) + print(result["parsed"]) + parsed_list = [ + { + "links": {"max_active": 10, "min_active": 2}, + "members": [ + {"member": "GigabitEthernet0/0/0/0", "mode": "inherit"}, + {"member": "GigabitEthernet0/0/0/1", "mode": "passive"}, + ], + "mode": "active", + "name": "Bundle-Ether10", + }, + { + "members": [ + {"member": "GigabitEthernet0/0/0/8", "mode": "passive"}, + {"member": "GigabitEthernet0/0/0/9", "mode": "passive"}, + ], + "mode": "active", + "name": "Bundle-Ether11", + }, + ] + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_lag_interfaces_overridden(self): + self.maxDiff = None + self._prepare() + set_module_args( + dict( + config=[ + dict( + name="Bundle-Ether11", + mode="active", + members=[ + dict( + member="GigabitEthernet0/0/0/0", + mode="active", + ), + dict( + member="GigabitEthernet0/0/0/1", + mode="active", + ), + ], + links=dict(max_active=10, min_active=5), + ), + ], + state="overridden", + ), + ) + commands = [ + "interface Bundle-Ether10", + "no bundle maximum-active links 10", + "no bundle minimum-active links 2", + "no lacp mode active", + "interface GigabitEthernet0/0/0/0", + "no bundle id", + "interface GigabitEthernet0/0/0/1", + "no bundle id", + "interface Bundle-Ether11", + "bundle minimum-active links 5", + "bundle maximum-active links 10", + "interface GigabitEthernet0/0/0/8", + "no bundle id", + "interface GigabitEthernet0/0/0/9", + "no bundle id", + "interface GigabitEthernet0/0/0/0", + "bundle id 11 mode active", + "interface GigabitEthernet0/0/0/1", + "bundle id 11 mode active", + ] + + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_global.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_global.py new file mode 100644 index 00000000..65f749ec --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_global.py @@ -0,0 +1,206 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_lldp_global +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrLldpModule(TestIosxrModule): + module = iosxr_lldp_global + + def setUp(self): + super(TestIosxrLldpModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lldp_global.lldp_global.Lldp_globalFacts.get_config", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrLldpModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def _prepare(self): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_lldp_global_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_lldp_global_merged_idempotent(self): + self._prepare() + set_module_args( + dict( + config=dict( + holdtime=100, + reinit=2, + timer=3000, + subinterfaces=True, + tlv_select=dict( + management_address=False, + system_description=False, + ), + ), + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_lldp_global_merged(self): + set_module_args( + dict( + config=dict( + holdtime=100, + reinit=2, + timer=3000, + subinterfaces=True, + tlv_select=dict( + management_address=False, + system_description=False, + ), + ), + state="merged", + ), + ) + commands = [ + "lldp reinit 2", + "lldp holdtime 100", + "lldp timer 3000", + "lldp subinterfaces enable", + "lldp tlv-select system-description disable", + "lldp tlv-select management-address disable", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lldp_global_replaced(self): + self._prepare() + set_module_args( + dict( + config=dict( + holdtime=100, + tlv_select=dict( + management_address=False, + system_description=False, + port_description=False, + ), + ), + state="replaced", + ), + ) + commands = [ + "no lldp reinit 2", + "no lldp subinterfaces enable", + "no lldp timer 3000", + "lldp tlv-select port-description disable", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lldp_global_deleted(self): + self._prepare() + set_module_args(dict(state="deleted")) + + commands = [ + "no lldp holdtime 100", + "no lldp reinit 2", + "no lldp subinterfaces enable", + "no lldp timer 3000", + "no lldp tlv-select management-address disable", + "no lldp tlv-select system-description disable", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lldp_global_rendered(self): + set_module_args( + dict( + config=dict( + holdtime=100, + reinit=2, + timer=3000, + subinterfaces=True, + tlv_select=dict( + management_address=False, + system_description=False, + ), + ), + state="rendered", + ), + ) + + commands = [ + "lldp reinit 2", + "lldp holdtime 100", + "lldp timer 3000", + "lldp subinterfaces enable", + "lldp tlv-select system-description disable", + "lldp tlv-select management-address disable", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_lag_interfaces_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="lldp reinit 2\nlldp holdtime 100\nlldp timer 3000\nlldp subinterfaces\ + enable\nlldp tlv-select system-description disable\nlldp tlv-select management-address\ + disable\n", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = { + "holdtime": 100, + "reinit": 2, + "timer": 3000, + "tlv_select": {"system_description": False}, + } + self.assertEqual(parsed_list, result["parsed"]) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_interfaces.py new file mode 100644 index 00000000..78b6d79f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_interfaces.py @@ -0,0 +1,206 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_lldp_interfaces +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrLldpInterfacesModule(TestIosxrModule): + module = iosxr_lldp_interfaces + + def setUp(self): + super(TestIosxrLldpInterfacesModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lldp_interfaces.lldp_interfaces.Lldp_interfacesFacts.get_config", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrLldpInterfacesModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def _prepare(self): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_lldp_interfaces_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_lldp_interfaces_merged_idempotent(self): + self._prepare() + set_module_args( + dict( + config=[ + dict(name="GigabitEthernet0/0/0/0", transmit=False), + dict(name="GigabitEthernet0/0/0/1", receive=False), + ], + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_lldp_interfaces_merged(self): + set_module_args( + dict( + config=[ + dict(name="GigabitEthernet0/0/0/0", transmit=False), + dict(name="GigabitEthernet0/0/0/1", receive=False), + ], + state="merged", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/0", + "lldp transmit disable", + "interface GigabitEthernet0/0/0/1", + "lldp receive disable", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lldp_interfaces_replaced(self): + self._prepare() + set_module_args( + dict( + config=[dict(name="GigabitEthernet0/0/0/1", transmit=False)], + state="replaced", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/1", + "no lldp receive disable", + "no lldp destination mac-address ieee-nearest-non-tmpr-bridge", + "lldp transmit disable", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lldp_interfaces_deleted(self): + self._prepare() + set_module_args(dict(state="deleted")) + + commands = [ + "interface GigabitEthernet0/0/0/0", + "no lldp transmit disable", + "no lldp destination mac-address ieee-nearest-bridge", + "interface GigabitEthernet0/0/0/1", + "no lldp destination mac-address ieee-nearest-non-tmpr-bridge", + "no lldp receive disable", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_lldp_interfaces_rendered(self): + set_module_args( + dict( + config=[ + dict(name="GigabitEthernet0/0/0/0", transmit=False), + dict(name="GigabitEthernet0/0/0/1", receive=False), + ], + state="rendered", + ), + ) + + commands = [ + "interface GigabitEthernet0/0/0/0", + "lldp transmit disable", + "interface GigabitEthernet0/0/0/1", + "lldp receive disable", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_lldp_interfaces_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="interface TenGigE0/0/0/0\r\n ipv4 address 192.0.2.11 255.255.255.192\r\n!\r\ninterface preconfigure " + "GigabitEthernet0/0/0/0\r\n lldp\r\n transmit disable\r\n destination mac-address\r\n " + "ieee-nearest-bridge\r\n !\r\n !\r\n!\r\ninterface preconfigure GigabitEthernet0/0/0/1\r\n lldp\r\n " + "receive disable\r\n destination mac-address\r\n ieee-nearest-non-tmpr-bridge\r\n", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + print(result["parsed"]) + parsed_list = [ + {"name": "TenGigE0/0/0/0"}, + { + "destination": {"mac_address": "ieee-nearest-bridge"}, + "name": "GigabitEthernet0/0/0/0", + "transmit": False, + }, + { + "destination": {"mac_address": "ieee-nearest-non-tmpr-bridge"}, + "name": "GigabitEthernet0/0/0/1", + "receive": False, + }, + ] + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_lldp_interfaces_overridden(self): + self.maxDiff = None + self._prepare() + set_module_args( + dict( + config=[dict(name="GigabitEthernet0/0/0/0", transmit=False)], + state="overridden", + ), + ) + commands = [ + "interface GigabitEthernet0/0/0/1", + "no lldp destination mac-address ieee-nearest-non-tmpr-bridge", + "no lldp receive disable", + "interface GigabitEthernet0/0/0/0", + "no lldp destination mac-address ieee-nearest-bridge", + ] + + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_logging_global.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_logging_global.py new file mode 100644 index 00000000..bffee2b1 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_logging_global.py @@ -0,0 +1,1263 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from textwrap import dedent + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_logging_global +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule + + +class TestIosxrLoggingGlobalModule(TestIosxrModule): + module = iosxr_logging_global + + def setUp(self): + super(TestIosxrLoggingGlobalModule, self).setUp() + + self.mock_get_resource_connection = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base." + "get_resource_connection", + ) + self.get_resource_connection = self.mock_get_resource_connection.start() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.logging_global.logging_global." + "Logging_globalFacts.get_config", + ) + self.get_config = self.mock_get_config.start() + + def tearDown(self): + super(TestIosxrLoggingGlobalModule, self).tearDown() + self.get_resource_connection.stop() + self.get_config.stop() + + def test_iosxr_logging_global_merged_idempotent(self): + run_cfg = dedent( + """\ + logging tls-server test + vrf test + trustpoint test2 + tls-hostname test2 + ! + logging file test path test maxfilesize 1024 severity info + logging file test2 path test1 maxfilesize 1024 severity debugging + logging ipv4 dscp af11 + logging ipv6 precedence routine + logging trap informational + logging events filter + match test + match test1 + ! + logging events threshold 10 + logging events buffer-size 1024 + logging events display-location + logging events level warnings + logging format rfc5424 + logging archive + device disk0 + severity alerts + file-size 1 + frequency daily + archive-size 1 + archive-length 1 + ! + logging console warning + logging console discriminator + match1 test + nomatch1 test3 + ! + logging history size 10 + logging monitor errors + logging monitor discriminator + match1 test1 + ! + logging buffered 2097152 + logging buffered warnings + logging buffered discriminator + match2 test + ! + logging 1.1.1.1 vrf default severity critical port default + logging correlator rule test type stateful + reissue-nonbistate + timeout 5 + reparent + context-correlation + ! + logging correlator rule test1 type nonstateful + timeout 6 + context-correlation + ! + logging correlator ruleset test + rulename test + rulename test1 + ! + logging correlator buffer-size 1024 + logging localfilesize 1024 + logging source-interface GigabitEthernet0/0/0/0 vrf test + logging hostnameprefix test + logging suppress duplicates + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + archive=dict( + archive_length=1, + archive_size=1, + device="disk0", + file_size=1, + frequency="daily", + severity="alerts", + ), + buffered=dict( + size=2097152, + severity="warnings", + discriminator=[ + dict(match_params="match2", name="test"), + ], + ), + console=dict( + severity="warning", + discriminator=[ + dict(match_params="match1", name="test"), + dict(match_params="nomatch1", name="test3"), + ], + ), + correlator=dict( + buffer_size=1024, + rule_sets=[ + dict(name="test", rulename=["test1", "test"]), + ], + rules=[ + dict( + rule_name="test", + rule_type="stateful", + timeout=5, + context_correlation=True, + reissue_nonbistate=True, + reparent=True, + ), + dict( + rule_name="test1", + rule_type="nonstateful", + timeout=6, + context_correlation=True, + ), + ], + ), + events=dict( + severity="warnings", + display_location=True, + buffer_size=1024, + filter_match=["test1", "test"], + threshold=10, + ), + format=True, + files=[ + dict( + maxfilesize=1024, + name="test", + path="test", + severity="info", + ), + dict( + maxfilesize=1024, + name="test2", + path="test1", + severity="debugging", + ), + ], + history=dict(size=10), + hostnameprefix="test", + hosts=[ + dict( + host="1.1.1.1", + port="default", + severity="critical", + vrf="default", + ), + ], + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + localfilesize=1024, + monitor=dict( + severity="errors", + discriminator=[ + dict(match_params="match1", name="test1"), + ], + ), + source_interfaces=[ + dict(interface="GigabitEthernet0/0/0/0", vrf="test"), + ], + suppress=dict(duplicates=True), + tls_servers=[ + dict( + name="test", + tls_hostname="test2", + trustpoint="test2", + vrf="test", + ), + ], + trap=dict(severity="informational"), + ), + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_logging_global_merged(self): + set_module_args( + dict( + config=dict( + archive=dict( + archive_length=1, + archive_size=1, + device="disk0", + file_size=1, + frequency="daily", + severity="alerts", + ), + buffered=dict( + size=2097152, + severity="warnings", + discriminator=[ + dict(match_params="match2", name="test"), + ], + ), + console=dict( + severity="warning", + discriminator=[ + dict(match_params="match1", name="test"), + dict(match_params="nomatch1", name="test3"), + ], + ), + correlator=dict( + buffer_size=1024, + rule_sets=[ + dict(name="test", rulename=["test1", "test"]), + ], + rules=[ + dict( + rule_name="test", + rule_type="stateful", + timeout=5, + context_correlation=True, + reissue_nonbistate=True, + reparent=True, + ), + dict( + rule_name="test1", + rule_type="nonstateful", + timeout=6, + context_correlation=True, + ), + ], + ), + events=dict( + severity="warnings", + display_location=True, + buffer_size=1024, + filter_match=["test1", "test"], + threshold=10, + ), + format=True, + files=[ + dict( + maxfilesize=1024, + name="test", + path="test", + severity="info", + ), + dict( + maxfilesize=1024, + name="test2", + path="test1", + severity="debugging", + ), + ], + history=dict(state="disabled", size=10), + hostnameprefix="test", + hosts=[ + dict( + host="1.1.1.1", + port="default", + severity="critical", + vrf="default", + ), + ], + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + localfilesize=1024, + monitor=dict( + severity="errors", + discriminator=[ + dict(match_params="match1", name="test1"), + ], + ), + source_interfaces=[ + dict(interface="GigabitEthernet0/0/0/0", vrf="test"), + ], + suppress=dict(duplicates=True), + tls_servers=[ + dict( + name="test", + tls_hostname="test2", + trustpoint="test2", + vrf="test", + ), + ], + trap=dict(severity="informational"), + ), + state="merged", + ), + ) + commands = [ + "logging archive device disk0", + "logging archive frequency daily", + "logging archive severity alerts", + "logging archive archive-size 1", + "logging archive archive-length 1", + "logging archive file-size 1", + "logging buffered 2097152", + "logging buffered warnings", + "logging console warning", + "logging correlator buffer-size 1024", + "logging events threshold 10", + "logging events buffer-size 1024", + "logging events display-location", + "logging events level warnings", + "logging hostnameprefix test", + "logging format rfc5424", + "logging ipv4 dscp af11", + "logging ipv6 precedence routine", + "logging localfilesize 1024", + "logging suppress duplicates", + "logging monitor errors", + "logging history size 10", + "logging history disable", + "logging trap informational", + "logging 1.1.1.1 vrf default severity critical port default", + "logging file test path test maxfilesize 1024 severity info", + "logging file test2 path test1 maxfilesize 1024 severity debugging", + "logging source-interface GigabitEthernet0/0/0/0 vrf test", + "logging tls-server test tls-hostname test2", + "logging tls-server test trustpoint test2", + "logging tls-server test vrf test", + "logging correlator ruleset test rulename test1", + "logging correlator ruleset test rulename test", + "logging correlator rule test type stateful timeout 5", + "logging correlator rule test type stateful reissue-nonbistate", + "logging correlator rule test type stateful reparent", + "logging correlator rule test type stateful context-correlation", + "logging correlator rule test1 type nonstateful timeout 6", + "logging correlator rule test1 type nonstateful context-correlation", + "logging events filter match test1", + "logging events filter match test", + "logging buffered discriminator match2 test", + "logging monitor discriminator match1 test1", + "logging console discriminator match1 test", + "logging console discriminator nomatch1 test3", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_logging_global_deleted(self): + self.maxDiff = None + run_cfg = dedent( + """\ + logging tls-server test + vrf test + trustpoint test2 + tls-hostname test2 + ! + logging file test path test maxfilesize 1024 severity info + logging file test2 path test1 maxfilesize 1024 severity debugging + logging ipv4 dscp af11 + logging ipv6 precedence routine + logging trap informational + logging events filter + match test + match test1 + ! + logging events threshold 10 + logging events buffer-size 1024 + logging events display-location + logging events level warnings + logging format rfc5424 + logging archive + device disk0 + severity alerts + file-size 1 + frequency daily + archive-size 1 + archive-length 1 + ! + logging console warning + logging console discriminator + match1 test + nomatch1 test3 + ! + logging history size 10 + logging history disable + logging monitor errors + logging monitor discriminator + match1 test1 + ! + logging buffered 2097152 + logging buffered warnings + logging buffered discriminator + match2 test + ! + logging 1.1.1.1 vrf default severity critical port default + logging correlator rule test type stateful + reissue-nonbistate + timeout 5 + reparent + context-correlation + ! + logging correlator rule test1 type nonstateful + timeout 6 + context-correlation + ! + logging correlator ruleset test + rulename test + rulename test1 + ! + logging correlator buffer-size 1024 + logging localfilesize 1024 + logging source-interface GigabitEthernet0/0/0/0 vrf test + logging hostnameprefix test + logging suppress duplicates + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(state="deleted")) + commands = [ + "no logging archive device disk0", + "no logging archive frequency daily", + "no logging archive severity alerts", + "no logging archive archive-size 1", + "no logging archive archive-length 1", + "no logging archive file-size 1", + "no logging buffered 2097152", + "no logging buffered warnings", + "no logging console warning", + "no logging correlator buffer-size 1024", + "no logging events threshold 10", + "no logging events buffer-size 1024", + "no logging events display-location", + "no logging events level warnings", + "no logging hostnameprefix test", + "no logging format rfc5424", + "no logging ipv4 dscp af11", + "no logging ipv6 precedence routine", + "no logging localfilesize 1024", + "no logging suppress duplicates", + "no logging monitor errors", + "no logging history size 10", + "no logging history disable", + "no logging trap informational", + "no logging 1.1.1.1 vrf default severity critical port default", + "no logging file test path test maxfilesize 1024 severity info", + "no logging file test2 path test1 maxfilesize 1024 severity debugging", + "no logging source-interface GigabitEthernet0/0/0/0 vrf test", + "no logging tls-server test", + "no logging correlator ruleset test rulename test", + "no logging correlator ruleset test rulename test1", + "no logging correlator rule test type stateful timeout 5", + "no logging correlator rule test type stateful reissue-nonbistate", + "no logging correlator rule test type stateful reparent", + "no logging correlator rule test type stateful context-correlation", + "no logging correlator rule test1 type nonstateful timeout 6", + "no logging correlator rule test1 type nonstateful context-correlation", + "no logging events filter match test", + "no logging events filter match test1", + "no logging buffered discriminator match2 test", + "no logging monitor discriminator match1 test1", + "no logging console discriminator match1 test", + "no logging console discriminator nomatch1 test3", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_logging_global_replaced(self): + self.maxDiff = None + run_cfg = dedent( + """\ + logging tls-server test + vrf test + trustpoint test2 + tls-hostname test2 + ! + logging file test path test maxfilesize 1024 severity info + logging file test2 path test1 maxfilesize 1024 severity debugging + logging ipv4 dscp af11 + logging ipv6 precedence routine + logging trap informational + logging events filter + match test + match test1 + ! + logging events threshold 10 + logging events buffer-size 1024 + logging events display-location + logging events level warnings + logging format rfc5424 + logging archive + device disk0 + severity alerts + file-size 1 + frequency daily + archive-size 1 + archive-length 1 + ! + logging console warning + logging console discriminator + match1 test + nomatch1 test3 + ! + logging history size 10 + logging history disable + logging monitor errors + logging monitor discriminator + match1 test1 + ! + logging buffered 2097152 + logging buffered warnings + logging buffered discriminator + match2 test + ! + logging 1.1.1.1 vrf default severity critical port default + logging correlator rule test type stateful + reissue-nonbistate + timeout 5 + reparent + context-correlation + ! + logging correlator rule test1 type nonstateful + timeout 6 + context-correlation + ! + logging correlator ruleset test + rulename test + rulename test1 + ! + logging correlator buffer-size 1024 + logging localfilesize 1024 + logging source-interface GigabitEthernet0/0/0/0 vrf test + logging hostnameprefix test + logging suppress duplicates + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + archive=dict( + archive_length=1, + archive_size=1, + device="disk0", + file_size=1, + severity="alerts", + ), + buffered=dict(size=2097152, severity="warnings"), + console=dict( + severity="warning", + discriminator=[ + dict(match_params="match1", name="test1"), + ], + ), + correlator=dict( + buffer_size=1024, + rules=[ + dict( + rule_name="test", + rule_type="stateful", + timeout=6, + context_correlation=True, + reissue_nonbistate=True, + reparent=True, + ), + ], + ), + events=dict( + severity="warnings", + display_location=True, + buffer_size=1024, + filter_match=["test1"], + threshold=12, + ), + format=True, + files=[ + dict( + maxfilesize=1024, + name="test", + path="test1", + severity="info", + ), + ], + history=dict(state="disabled", size=10), + hostnameprefix="test", + hosts=[ + dict( + host="1.1.1.2", + port="default", + severity="critical", + vrf="default", + ), + ], + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + localfilesize=1024, + source_interfaces=[ + dict(interface="GigabitEthernet0/0/0/0", vrf="test"), + ], + tls_servers=[ + dict( + name="test", + tls_hostname="test2", + trustpoint="test3", + vrf="test", + ), + ], + ), + state="replaced", + ), + ) + commands = [ + "logging console discriminator match1 test1", + "logging correlator rule test type stateful timeout 6", + "logging events threshold 12", + "logging 1.1.1.2 vrf default severity critical port default", + "logging file test path test1 maxfilesize 1024 severity info", + "logging tls-server test trustpoint test3", + "no logging 1.1.1.1 vrf default severity critical port default", + "no logging archive frequency daily", + "no logging buffered discriminator match2 test", + "no logging console discriminator match1 test", + "no logging console discriminator nomatch1 test3", + "no logging correlator rule test1 type nonstateful context-correlation", + "no logging correlator rule test1 type nonstateful timeout 6", + "no logging correlator ruleset test rulename test", + "no logging correlator ruleset test rulename test1", + "no logging events filter match test", + "no logging file test2 path test1 maxfilesize 1024 severity debugging", + "no logging monitor discriminator match1 test1", + "no logging monitor errors", + "no logging suppress duplicates", + "no logging trap informational", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_logging_global_rendered(self): + self.maxDiff = None + set_module_args( + dict( + config=dict( + archive=dict( + archive_length=1, + archive_size=1, + device="disk0", + file_size=1, + frequency="daily", + severity="alerts", + ), + buffered=dict( + size=2097152, + severity="warnings", + discriminator=[ + dict(match_params="match2", name="test"), + ], + ), + console=dict( + severity="warning", + discriminator=[ + dict(match_params="match1", name="test"), + dict(match_params="nomatch1", name="test3"), + ], + ), + correlator=dict( + buffer_size=1024, + rule_sets=[ + dict(name="test", rulename=["test1", "test"]), + ], + rules=[ + dict( + rule_name="test", + rule_type="stateful", + timeout=5, + context_correlation=True, + reissue_nonbistate=True, + reparent=True, + ), + dict( + rule_name="test1", + rule_type="nonstateful", + timeout=6, + context_correlation=True, + ), + ], + ), + events=dict( + severity="warnings", + display_location=True, + buffer_size=1024, + filter_match=["test1", "test"], + threshold=10, + ), + format=True, + files=[ + dict( + maxfilesize=1024, + name="test", + path="test", + severity="info", + ), + dict( + maxfilesize=1024, + name="test2", + path="test1", + severity="debugging", + ), + ], + history=dict(state="disabled", size=10), + hostnameprefix="test", + hosts=[ + dict( + host="1.1.1.1", + port="default", + severity="critical", + vrf="default", + ), + ], + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + localfilesize=1024, + monitor=dict( + severity="errors", + discriminator=[ + dict(match_params="match1", name="test1"), + ], + ), + source_interfaces=[ + dict(interface="GigabitEthernet0/0/0/0", vrf="test"), + ], + suppress=dict(duplicates=True), + tls_servers=[ + dict( + name="test", + tls_hostname="test2", + trustpoint="test2", + vrf="test", + ), + ], + trap=dict(severity="informational"), + ), + state="rendered", + ), + ) + commands = [ + "logging archive device disk0", + "logging archive frequency daily", + "logging archive severity alerts", + "logging archive archive-size 1", + "logging archive archive-length 1", + "logging archive file-size 1", + "logging buffered 2097152", + "logging buffered warnings", + "logging console warning", + "logging correlator buffer-size 1024", + "logging events threshold 10", + "logging events buffer-size 1024", + "logging events display-location", + "logging events level warnings", + "logging hostnameprefix test", + "logging format rfc5424", + "logging ipv4 dscp af11", + "logging ipv6 precedence routine", + "logging localfilesize 1024", + "logging suppress duplicates", + "logging monitor errors", + "logging history size 10", + "logging history disable", + "logging trap informational", + "logging 1.1.1.1 vrf default severity critical port default", + "logging file test path test maxfilesize 1024 severity info", + "logging file test2 path test1 maxfilesize 1024 severity debugging", + "logging source-interface GigabitEthernet0/0/0/0 vrf test", + "logging tls-server test tls-hostname test2", + "logging tls-server test trustpoint test2", + "logging tls-server test vrf test", + "logging correlator ruleset test rulename test1", + "logging correlator ruleset test rulename test", + "logging correlator rule test type stateful timeout 5", + "logging correlator rule test type stateful reissue-nonbistate", + "logging correlator rule test type stateful reparent", + "logging correlator rule test type stateful context-correlation", + "logging correlator rule test1 type nonstateful timeout 6", + "logging correlator rule test1 type nonstateful context-correlation", + "logging events filter match test1", + "logging events filter match test", + "logging buffered discriminator match2 test", + "logging monitor discriminator match1 test1", + "logging console discriminator match1 test", + "logging console discriminator nomatch1 test3", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_logging_global_overridden(self): + self.maxDiff = None + run_cfg = dedent( + """\ + logging tls-server test + vrf test + trustpoint test2 + tls-hostname test2 + ! + logging file test path test maxfilesize 1024 severity info + logging file test2 path test1 maxfilesize 1024 severity debugging + logging ipv4 dscp af11 + logging ipv6 precedence routine + logging trap informational + logging events filter + match test + match test1 + ! + logging events threshold 10 + logging events buffer-size 1024 + logging events display-location + logging events level warnings + logging format rfc5424 + logging archive + device disk0 + severity alerts + file-size 1 + frequency daily + archive-size 1 + archive-length 1 + ! + logging console warning + logging console discriminator + match1 test + nomatch1 test3 + ! + logging history size 10 + logging history disable + logging monitor errors + logging monitor discriminator + match1 test1 + ! + logging buffered 2097152 + logging buffered warnings + logging buffered discriminator + match2 test + ! + logging 1.1.1.1 vrf default severity critical port default + logging correlator rule test type stateful + reissue-nonbistate + timeout 5 + reparent + context-correlation + ! + logging correlator rule test1 type nonstateful + timeout 6 + context-correlation + ! + logging correlator ruleset test + rulename test + rulename test1 + ! + logging correlator buffer-size 1024 + logging localfilesize 1024 + logging source-interface GigabitEthernet0/0/0/0 vrf test + logging hostnameprefix test + logging suppress duplicates + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + archive=dict( + archive_length=1, + archive_size=1, + device="disk0", + file_size=1, + severity="alerts", + ), + buffered=dict(size=2097152, severity="warnings"), + console=dict( + severity="warning", + discriminator=[ + dict(match_params="match1", name="test1"), + ], + ), + correlator=dict( + buffer_size=1024, + rules=[ + dict( + rule_name="test", + rule_type="stateful", + timeout=6, + context_correlation=True, + reissue_nonbistate=True, + reparent=True, + ), + ], + ), + events=dict( + severity="warnings", + display_location=True, + buffer_size=1024, + filter_match=["test1"], + threshold=12, + ), + format=True, + files=[ + dict( + maxfilesize=1024, + name="test", + path="test1", + severity="info", + ), + ], + history=dict(state="disabled", size=10), + hostnameprefix="test", + hosts=[ + dict( + host="1.1.1.2", + port="default", + severity="critical", + vrf="default", + ), + ], + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + localfilesize=1024, + source_interfaces=[ + dict(interface="GigabitEthernet0/0/0/0", vrf="test"), + ], + tls_servers=[ + dict( + name="test", + tls_hostname="test2", + trustpoint="test3", + vrf="test", + ), + ], + ), + state="overridden", + ), + ) + commands = [ + "logging console discriminator match1 test1", + "logging correlator rule test type stateful timeout 6", + "logging events threshold 12", + "logging 1.1.1.2 vrf default severity critical port default", + "logging file test path test1 maxfilesize 1024 severity info", + "logging tls-server test trustpoint test3", + "no logging 1.1.1.1 vrf default severity critical port default", + "no logging archive frequency daily", + "no logging buffered discriminator match2 test", + "no logging console discriminator match1 test", + "no logging console discriminator nomatch1 test3", + "no logging correlator rule test1 type nonstateful context-correlation", + "no logging correlator rule test1 type nonstateful timeout 6", + "no logging correlator ruleset test rulename test", + "no logging correlator ruleset test rulename test1", + "no logging events filter match test", + "no logging file test2 path test1 maxfilesize 1024 severity debugging", + "no logging monitor discriminator match1 test1", + "no logging monitor errors", + "no logging suppress duplicates", + "no logging trap informational", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_logging_global_gathered(self): + run_cfg = dedent( + """\ + logging tls-server test + vrf test + trustpoint test2 + tls-hostname test2 + ! + logging file test path test maxfilesize 1024 severity info + logging ipv4 dscp af11 + logging ipv6 precedence routine + logging trap informational + logging events filter + match test + ! + logging events threshold 10 + logging events buffer-size 1024 + logging events display-location + logging events level warnings + logging format rfc5424 + logging archive + device disk0 + severity alerts + file-size 1 + frequency daily + archive-size 1 + archive-length 1 + ! + logging console warning + logging console discriminator + match1 test + ! + logging history size 10 + logging history disable + logging monitor errors + logging monitor discriminator + match1 test1 + ! + logging buffered 2097152 + logging buffered warnings + logging buffered discriminator + match2 test + ! + logging 1.1.1.1 vrf default severity critical port default + logging correlator rule test type stateful + reissue-nonbistate + timeout 5 + reparent + context-correlation + ! + logging correlator ruleset test + rulename test + ! + logging correlator buffer-size 1024 + logging localfilesize 1024 + logging source-interface GigabitEthernet0/0/0/0 vrf test + logging hostnameprefix test + logging suppress duplicates + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(state="gathered")) + gathered = { + "archive": { + "archive_length": 1, + "archive_size": 1, + "device": "disk0", + "file_size": 1, + "frequency": "daily", + "severity": "alerts", + }, + "buffered": { + "discriminator": [{"match_params": "match2", "name": "test"}], + "severity": "warnings", + "size": 2097152, + }, + "console": { + "discriminator": [{"match_params": "match1", "name": "test"}], + "severity": "warning", + }, + "correlator": { + "buffer_size": 1024, + "rule_sets": [{"name": "test", "rulename": ["test"]}], + "rules": [ + { + "context_correlation": True, + "reissue_nonbistate": True, + "reparent": True, + "rule_name": "test", + "rule_type": "stateful", + "timeout": 5, + }, + ], + }, + "events": { + "buffer_size": 1024, + "display_location": True, + "filter_match": ["test"], + "severity": "warnings", + "threshold": 10, + }, + "files": [ + { + "maxfilesize": 1024, + "name": "test", + "path": "test", + "severity": "info", + }, + ], + "format": True, + "history": {"state": "disabled", "size": 10}, + "hostnameprefix": "test", + "hosts": [ + { + "host": "1.1.1.1", + "port": "default", + "severity": "critical", + "vrf": "default", + }, + ], + "ipv4": {"dscp": "af11"}, + "ipv6": {"precedence": "routine"}, + "localfilesize": 1024, + "monitor": { + "discriminator": [{"match_params": "match1", "name": "test1"}], + "severity": "errors", + }, + "source_interfaces": [ + {"interface": "GigabitEthernet0/0/0/0", "vrf": "test"}, + ], + "suppress": {"duplicates": True}, + "tls_servers": [ + { + "name": "test", + "tls_hostname": "test2", + "trustpoint": "test2", + "vrf": "test", + }, + ], + "trap": {"severity": "informational"}, + } + result = self.execute_module(changed=False) + self.assertEqual(gathered, result["gathered"]) + + def test_iosxr_logging_global_parsed(self): + set_module_args( + dict( + running_config="logging tls-server test\n vrf test\n trustpoint test2\n tls-hostname test2" + "\n!\nlogging file test path test maxfilesize 1024 severity info\nlogging ipv4 dscp" + " af11\nlogging ipv6 precedence routine\nlogging trap informational\nlogging events" + " filter\n match test1\n!\nlogging events threshold " + "10\nlogging events buffer-size 1024\nlogging events display-location" + "\nlogging events level warnings" + "\nlogging format rfc5424\nlogging archive\n device disk0" + "\n severity alerts\n file-size 1\n frequency " + "daily\n archive-size 1\n archive-length 1\n!\nlogging console " + "warning\nlogging console discriminator\n " + "match1 test\n!\nlogging history size " + "10\nlogging history disable\nlogging monitor errors" + "\nlogging monitor discriminator\n match1 test1\n!" + "\nlogging buffered 2097152\nlogging buffered warnings\n" + "logging buffered discriminator\n match2 test\n!\nlogging " + "1.1.1.1 vrf default severity critical port default" + "\nlogging correlator rule test type stateful\n reissue-nonbistate\n " + "timeout 5\n reparent\n context-correlation\n!" + "\n!\nlogging correlator ruleset test\n rulename test1" + "\n!\nlogging correlator buffer-size 1024\nlogging " + "localfilesize 1024\nlogging source-interface" + " GigabitEthernet0/0/0/0 vrf test\nlogging hostnameprefix " + "test\nlogging suppress duplicates", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = { + "archive": { + "archive_length": 1, + "archive_size": 1, + "device": "disk0", + "file_size": 1, + "frequency": "daily", + "severity": "alerts", + }, + "buffered": { + "discriminator": [{"match_params": "match2", "name": "test"}], + "severity": "warnings", + "size": 2097152, + }, + "console": { + "discriminator": [{"match_params": "match1", "name": "test"}], + "severity": "warning", + }, + "correlator": { + "buffer_size": 1024, + "rule_sets": [{"name": "test", "rulename": ["test1"]}], + "rules": [ + { + "context_correlation": True, + "reissue_nonbistate": True, + "reparent": True, + "rule_name": "test", + "rule_type": "stateful", + "timeout": 5, + }, + ], + }, + "events": { + "buffer_size": 1024, + "display_location": True, + "filter_match": ["test1"], + "severity": "warnings", + "threshold": 10, + }, + "files": [ + { + "maxfilesize": 1024, + "name": "test", + "path": "test", + "severity": "info", + }, + ], + "format": True, + "history": {"state": "disabled", "size": 10}, + "hostnameprefix": "test", + "hosts": [ + { + "host": "1.1.1.1", + "port": "default", + "severity": "critical", + "vrf": "default", + }, + ], + "ipv4": {"dscp": "af11"}, + "ipv6": {"precedence": "routine"}, + "localfilesize": 1024, + "monitor": { + "discriminator": [{"match_params": "match1", "name": "test1"}], + "severity": "errors", + }, + "source_interfaces": [ + {"interface": "GigabitEthernet0/0/0/0", "vrf": "test"}, + ], + "suppress": {"duplicates": True}, + "tls_servers": [ + { + "name": "test", + "tls_hostname": "test2", + "trustpoint": "test2", + "vrf": "test", + }, + ], + "trap": {"severity": "informational"}, + } + + self.assertEqual(parsed_list, result["parsed"]) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_n540.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_n540.py new file mode 100644 index 00000000..d2820cfa --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_n540.py @@ -0,0 +1,96 @@ +# +# (c) 2022 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. +# +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from os import path + +from ansible.module_utils._text import to_bytes, to_text +from mock import MagicMock + +from ansible_collections.cisco.iosxr.plugins.cliconf import iosxr +from ansible_collections.cisco.iosxr.tests.unit.compat import unittest + + +class TestPluginCLIConfIOSXR(unittest.TestCase): + """Test class for IOSXR CLI Conf Methods""" + + def setUp(self): + self._mock_connection = MagicMock() + self._prepare() + self._cliconf = iosxr.Cliconf(self._mock_connection) + self.maxDiff = None + + def _prepare(self, platform="iosxr"): + b_FIXTURE_DIR = b"%s/fixtures/cliconf_ncs540/%s" % ( + to_bytes( + path.dirname(path.abspath(__file__)), + errors="surrogate_or_strict", + ), + to_bytes(platform), + ) + + def _connection_side_effect(*args, **kwargs): + try: + if args: + value = args[0] + else: + value = kwargs.get("command") + if b"|" in value: + value = value.replace(b"|", b"") + fixture_path = path.abspath( + b"%s/%s" % (b_FIXTURE_DIR, b"_".join(value.split(b" "))), + ) + with open(fixture_path, "rb") as file_desc: + return to_text(file_desc.read()) + except (OSError, IOError): + if args: + value = args[0] + return value + elif kwargs.get("command"): + value = kwargs.get("command") + return value + return "NO-OP" + + self._mock_connection.send.side_effect = _connection_side_effect + + def tearDown(self): + pass + + def test_get_device_info_iosxr(self): + """Test get_device_info for nxos""" + device_info = self._cliconf.get_device_info() + + mock_device_info = { + "network_os_version": "7.5.2 LNT", + "network_os": "iosxr", + "network_os_hostname": "iosxr01", + "network_os_model": "N540X-6Z18G-SYS-A", + } + + self.assertEqual(device_info, mock_device_info) + + def test_get_command_output_iosxr(self): + """Test _get_command_with_output for iosxr""" + self._prepare() + cmd = self._cliconf.get_command_output("show running-config hostname") + + self.assertEqual(cmd, "hostname iosxr01") diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_netconf.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_netconf.py new file mode 100644 index 00000000..bbd61050 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_netconf.py @@ -0,0 +1,115 @@ +# (c) 2017 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_netconf +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule + + +class TestIosxrNetconfModule(TestIosxrModule): + + module = iosxr_netconf + + def setUp(self): + super(TestIosxrNetconfModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_netconf.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_netconf.load_config", + ) + self.load_config = self.mock_load_config.start() + + def tearDown(self): + super(TestIosxrNetconfModule, self).tearDown() + self.mock_get_config.stop() + self.mock_load_config.stop() + + def test_iosxr_disable_netconf_service(self): + self.get_config.return_value = """ + netconf-yang agent + ssh + ! + ssh server netconf vrf default + """ + self.load_config.return_value = "dummy diff" + set_module_args( + dict(netconf_port=830, netconf_vrf="default", state="absent"), + ) + result = self.execute_module(changed=True) + self.assertEqual( + result["commands"], + [ + "no netconf-yang agent ssh", + "no ssh server netconf port 830", + "no ssh server netconf vrf default", + ], + ) + + def test_iosxr_enable_netconf_service(self): + self.get_config.return_value = "" + self.load_config.return_value = "dummy diff" + set_module_args( + dict(netconf_port=830, netconf_vrf="default", state="present"), + ) + result = self.execute_module(changed=True) + self.assertEqual( + result["commands"], + [ + "netconf-yang agent ssh", + "ssh server netconf port 830", + "ssh server netconf vrf default", + ], + ) + + def test_iosxr_change_netconf_port(self): + self.get_config.return_value = """ + netconf-yang agent + ssh + ! + ssh server netconf vrf default + """ + self.load_config.return_value = "dummy diff" + set_module_args(dict(netconf_port=9000, state="present")) + result = self.execute_module(changed=True) + self.assertEqual(result["commands"], ["ssh server netconf port 9000"]) + + def test_iosxr_change_netconf_vrf(self): + self.get_config.return_value = """ + netconf-yang agent + ssh + ! + ssh server netconf vrf default + """ + self.load_config.return_value = "dummy diff" + set_module_args(dict(netconf_vrf="new_default", state="present")) + result = self.execute_module(changed=True) + self.assertEqual( + result["commands"], + ["ssh server netconf vrf new_default"], + ) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ntp_global.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ntp_global.py new file mode 100644 index 00000000..702e2a00 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ntp_global.py @@ -0,0 +1,902 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from textwrap import dedent + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_ntp_global +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule + + +class TestIosxrNtpGlobalModule(TestIosxrModule): + module = iosxr_ntp_global + + def setUp(self): + super(TestIosxrNtpGlobalModule, self).setUp() + + self.mock_get_resource_connection = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base." + "get_resource_connection", + ) + self.get_resource_connection = self.mock_get_resource_connection.start() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ntp_global.ntp_global." + "Ntp_globalFacts.get_config", + ) + self.get_config = self.mock_get_config.start() + + def tearDown(self): + super(TestIosxrNtpGlobalModule, self).tearDown() + self.get_resource_connection.stop() + self.get_config.stop() + + def test_iosxr_ntp_global_merged_idempotent(self): + self.maxDiff = None + run_cfg = dedent( + """\ + ntp + max-associations 10 + interface GigabitEthernet0/0/0/0 vrf siteB + multicast key 1 + ! + interface GigabitEthernet0/0/0/0 + broadcast client + multicast client 224.0.0.8 + multicast destination 224.0.0.8 + ! + authentication-key 1 md5 encrypted testkey + authentication-key 2 md5 encrypted 071B245F5A5B + authenticate + trusted-key 1 + trusted-key 2 + ipv4 dscp af11 + ipv6 precedence routine + peer vrf siteC 192.0.2.1 iburst + server vrf siteD 192.0.2.2 burst + server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0 + drift file apphost + drift aging time 0 + master 1 + access-group vrf siteA ipv4 peer PeerAcl2 + access-group vrf siteA ipv4 serve ServeAcl2 + access-group ipv4 peer PeerAcl1 + access-group ipv4 serve ServeAcl1 + access-group ipv4 serve-only ServeOnlyAcl1 + access-group ipv4 query-only QueryOnlyAcl1 + access-group ipv6 peer PeerAcl2 + source vrf siteE GigabitEthernet0/0/0/0 + source GigabitEthernet0/0/0/0 + passive + broadcastdelay 1 + update-calendar + log-internal-sync + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + access_group=dict( + ipv4=dict( + peer="PeerAcl1", + query_only="QueryOnlyAcl1", + serve="ServeAcl1", + serve_only="ServeOnlyAcl1", + ), + ipv6=dict(peer="PeerAcl2"), + vrfs=[ + dict( + ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"), + name="siteA", + ), + ], + ), + authenticate=True, + authentication_keys=[ + dict(id=1, key="testkey", encryption=True), + dict(id=2, key="071B245F5A5B", encryption=True), + ], + broadcastdelay=1, + drift=dict(aging_time=0, file="apphost"), + interfaces=[ + dict( + name="GigabitEthernet0/0/0/0", + multicast_client="224.0.0.8", + multicast_destination="224.0.0.8", + broadcast_client=True, + ), + dict( + name="GigabitEthernet0/0/0/0", + multicast_key=1, + vrf="siteB", + ), + ], + ipv4=dict(dscp="af11"), + ipv6=dict(precedence="routine"), + log_internal_sync=True, + master=dict(stratum=1), + max_associations=10, + passive=True, + peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")], + servers=[ + dict(burst=True, server="192.0.2.2", vrf="siteD"), + dict( + iburst=True, + burst=True, + server="192.0.2.2", + key_id=1, + maxpoll=5, + minpoll=4, + prefer=True, + source="GigabitEthernet0/0/0/0", + version=2, + ), + ], + source_interface="GigabitEthernet0/0/0/0", + source_vrfs=[ + dict(name="GigabitEthernet0/0/0/0", vrf="siteE"), + ], + trusted_keys=[dict(key_id=1), dict(key_id=2)], + update_calendar=True, + ), + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_ntp_global_merged(self): + self.maxDiff = None + set_module_args( + dict( + config=dict( + access_group=dict( + ipv4=dict( + peer="PeerAcl1", + query_only="QueryOnlyAcl1", + serve="ServeAcl1", + serve_only="ServeOnlyAcl1", + ), + ipv6=dict(peer="PeerAcl2"), + vrfs=[ + dict( + ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"), + name="siteA", + ), + ], + ), + authenticate=True, + authentication_keys=[ + dict(id=1, key="testkey", encryption=True), + dict(id=2, key="071B245F5A5B", encryption=True), + ], + broadcastdelay=1, + drift=dict(aging_time=0, file="apphost"), + interfaces=[ + dict( + name="GigabitEthernet0/0/0/0", + multicast_client="224.0.0.8", + multicast_destination="224.0.0.8", + broadcast_client=True, + ), + dict( + name="GigabitEthernet0/0/0/0", + multicast_key=1, + vrf="siteB", + ), + ], + ipv4=dict(dscp="af11"), + ipv6=dict(precedence="routine"), + log_internal_sync=True, + master=dict(stratum=1), + max_associations=10, + passive=True, + peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")], + servers=[ + dict(burst=True, server="192.0.2.2", vrf="siteD"), + dict( + iburst=True, + burst=True, + server="192.0.2.2", + key_id=1, + maxpoll=5, + minpoll=4, + prefer=True, + source="GigabitEthernet0/0/0/0", + version=2, + ), + ], + source_interface="GigabitEthernet0/0/0/0", + source_vrfs=[ + dict(name="GigabitEthernet0/0/0/0", vrf="siteE"), + ], + trusted_keys=[dict(key_id=1), dict(key_id=2)], + update_calendar=True, + ), + state="merged", + ), + ) + commands = [ + "ntp authentication-key 1 md5 encrypted testkey", + "ntp authentication-key 2 md5 encrypted 071B245F5A5B", + "ntp peer vrf siteC 192.0.2.1 iburst", + "ntp server vrf siteD 192.0.2.2 burst", + "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/0", + "ntp trusted-key 1", + "ntp trusted-key 2", + "ntp interface GigabitEthernet0/0/0/0 broadcast client", + "ntp interface GigabitEthernet0/0/0/0 multicast destination 224.0.0.8", + "ntp interface GigabitEthernet0/0/0/0 multicast client 224.0.0.8", + "ntp interface GigabitEthernet0/0/0/0 vrf siteB multicast key 1", + "ntp vrf siteE source GigabitEthernet0/0/0/0", + "ntp access-group vrf siteA ipv4 serve ServeAcl2", + "ntp access-group vrf siteA ipv4 peer PeerAcl2", + "ntp access-group ipv4 peer PeerAcl1", + "ntp access-group ipv4 serve ServeAcl1", + "ntp access-group ipv4 serve-only ServeOnlyAcl1", + "ntp access-group ipv4 query-only QueryOnlyAcl1", + "ntp access-group ipv6 peer PeerAcl2", + "ntp authenticate", + "ntp log-internal-sync", + "ntp broadcastdelay 1", + "ntp drift aging time 0", + "ntp drift file apphost", + "ntp ipv4 dscp af11", + "ntp ipv6 precedence routine", + "ntp max-associations 10", + "ntp master 1", + "ntp passive", + "ntp update-calendar", + "ntp source GigabitEthernet0/0/0/0", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ntp_global_deleted(self): + self.maxDiff = None + run_cfg = dedent( + """\ + ntp + max-associations 10 + interface GigabitEthernet0/0/0/0 vrf siteB + multicast key 1 + ! + interface GigabitEthernet0/0/0/0 + broadcast client + multicast client 224.0.0.8 + multicast destination 224.0.0.8 + ! + authentication-key 1 md5 encrypted testkey + authentication-key 2 md5 encrypted 071B245F5A5B + authenticate + trusted-key 1 + trusted-key 2 + ipv4 dscp af11 + ipv6 precedence routine + peer vrf siteC 192.0.2.1 iburst + server vrf siteD 192.0.2.2 burst + server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0 + drift file apphost + drift aging time 0 + master 1 + access-group vrf siteA ipv4 peer PeerAcl3 + access-group vrf siteA ipv4 serve ServeAcl2 + access-group ipv4 peer PeerAcl1 + access-group ipv4 serve ServeAcl1 + access-group ipv4 serve-only ServeOnlyAcl1 + access-group ipv4 query-only QueryOnlyAcl1 + access-group ipv6 peer PeerAcl2 + source vrf siteE GigabitEthernet0/0/0/0 + source GigabitEthernet0/0/0/0 + passive + broadcastdelay 1 + update-calendar + log-internal-sync + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(state="deleted")) + commands = [ + "no ntp authentication-key 1 md5 encrypted testkey", + "no ntp authentication-key 2 md5 encrypted 071B245F5A5B", + "no ntp peer vrf siteC 192.0.2.1 iburst", + "no ntp server vrf siteD 192.0.2.2 burst", + "no ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/0", + "no ntp trusted-key 1", + "no ntp trusted-key 2", + "no ntp interface GigabitEthernet0/0/0/0 vrf siteB", + "no ntp interface GigabitEthernet0/0/0/0", + "no ntp vrf siteE source GigabitEthernet0/0/0/0", + "no ntp access-group vrf siteA ipv4 serve ServeAcl2", + "no ntp access-group vrf siteA ipv4 peer PeerAcl3", + "no ntp access-group ipv4 peer PeerAcl1", + "no ntp access-group ipv4 serve ServeAcl1", + "no ntp access-group ipv4 serve-only ServeOnlyAcl1", + "no ntp access-group ipv4 query-only QueryOnlyAcl1", + "no ntp access-group ipv6 peer PeerAcl2", + "no ntp authenticate", + "no ntp log-internal-sync", + "no ntp broadcastdelay 1", + "no ntp drift aging time 0", + "no ntp drift file apphost", + "no ntp ipv4 dscp af11", + "no ntp ipv6 precedence routine", + "no ntp max-associations 10", + "no ntp master 1", + "no ntp passive", + "no ntp update-calendar", + "no ntp source GigabitEthernet0/0/0/0", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ntp_global_replaced(self): + self.maxDiff = None + run_cfg = dedent( + """\ + ntp + max-associations 10 + interface GigabitEthernet0/0/0/0 vrf siteB + multicast key 1 + ! + interface GigabitEthernet0/0/0/0 + broadcast client + multicast client 224.0.0.8 + multicast destination 224.0.0.8 + ! + authentication-key 1 md5 encrypted testkey + authentication-key 2 md5 encrypted 071B245F5A5B + authenticate + trusted-key 1 + trusted-key 2 + ipv4 dscp af11 + ipv6 precedence routine + peer vrf siteC 192.0.2.1 iburst + server vrf siteD 192.0.2.2 burst + server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0 + drift file apphost + drift aging time 0 + master 1 + access-group vrf siteA ipv4 peer PeerAcl3 + access-group vrf siteA ipv4 serve ServeAcl2 + access-group ipv4 peer PeerAcl1 + access-group ipv4 serve ServeAcl1 + access-group ipv4 serve-only ServeOnlyAcl1 + access-group ipv4 query-only QueryOnlyAcl1 + access-group ipv6 peer PeerAcl2 + source vrf siteE GigabitEthernet0/0/0/0 + source GigabitEthernet0/0/0/0 + passive + broadcastdelay 1 + update-calendar + log-internal-sync + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + access_group=dict( + ipv4=dict( + peer="PeerAcl1", + query_only="QueryOnlyAcl2", + serve="ServeAcl1", + serve_only="ServeOnlyAcl1", + ), + ipv6=dict(peer="PeerAcl2"), + vrfs=[ + dict( + ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"), + name="siteA", + ), + ], + ), + authenticate=True, + authentication_keys=[ + dict(id=1, key="testkey1", encryption=True), + dict(id=2, key="071B245F5A5B", encryption=True), + ], + broadcastdelay=1, + drift=dict(aging_time=0, file="apphost"), + interfaces=[ + dict( + name="GigabitEthernet0/0/0/1", + multicast_client="224.0.0.8", + multicast_destination="224.0.0.8", + broadcast_client=True, + ), + dict( + name="GigabitEthernet0/0/0/0", + multicast_key=1, + vrf="siteB", + ), + ], + ipv4=dict(dscp="af12"), + ipv6=dict(precedence="routine"), + log_internal_sync=True, + master=dict(stratum=1), + max_associations=10, + passive=True, + peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")], + servers=[ + dict(burst=True, server="192.0.2.3", vrf="siteD"), + dict( + iburst=True, + burst=True, + server="192.0.2.2", + key_id=1, + maxpoll=5, + minpoll=4, + prefer=True, + source="GigabitEthernet0/0/0/1", + version=2, + ), + ], + source_interface="GigabitEthernet0/0/0/0", + source_vrfs=[ + dict(name="GigabitEthernet0/0/0/0", vrf="siteE"), + ], + trusted_keys=[dict(key_id=1), dict(key_id=2)], + update_calendar=True, + ), + state="replaced", + ), + ) + commands = [ + "no ntp server vrf siteD 192.0.2.2 burst", + "no ntp interface GigabitEthernet0/0/0/0", + "ntp authentication-key 1 md5 encrypted testkey1", + "ntp server vrf siteD 192.0.2.3 burst", + "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/1", + "ntp interface GigabitEthernet0/0/0/1 broadcast client", + "ntp interface GigabitEthernet0/0/0/1 multicast destination 224.0.0.8", + "ntp interface GigabitEthernet0/0/0/1 multicast client 224.0.0.8", + "ntp access-group ipv4 query-only QueryOnlyAcl2", + "ntp access-group vrf siteA ipv4 peer PeerAcl2", + "ntp access-group vrf siteA ipv4 serve ServeAcl2", + "ntp ipv4 dscp af12", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_logging_global_rendered(self): + self.maxDiff = None + set_module_args( + dict( + config=dict( + access_group=dict( + ipv4=dict( + peer="PeerAcl1", + query_only="QueryOnlyAcl1", + serve="ServeAcl1", + serve_only="ServeOnlyAcl1", + ), + ipv6=dict(peer="PeerAcl2"), + vrfs=[ + dict( + ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"), + name="siteA", + ), + ], + ), + authenticate=True, + authentication_keys=[ + dict(id=1, key="testkey", encryption=True), + dict(id=2, key="071B245F5A5B", encryption=True), + ], + broadcastdelay=1, + drift=dict(aging_time=0, file="apphost"), + interfaces=[ + dict( + name="GigabitEthernet0/0/0/0", + multicast_client="224.0.0.8", + multicast_destination="224.0.0.8", + broadcast_client=True, + ), + dict( + name="GigabitEthernet0/0/0/0", + multicast_key=1, + vrf="siteB", + ), + ], + ipv4=dict(dscp="af11"), + ipv6=dict(precedence="routine"), + log_internal_sync=True, + master=dict(stratum=1), + max_associations=10, + passive=True, + peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")], + servers=[ + dict(burst=True, server="192.0.2.2", vrf="siteD"), + dict( + iburst=True, + burst=True, + server="192.0.2.2", + key_id=1, + maxpoll=5, + minpoll=4, + prefer=True, + source="GigabitEthernet0/0/0/0", + version=2, + ), + ], + source_interface="GigabitEthernet0/0/0/0", + source_vrfs=[ + dict(name="GigabitEthernet0/0/0/0", vrf="siteE"), + ], + trusted_keys=[dict(key_id=1), dict(key_id=2)], + update_calendar=True, + ), + state="rendered", + ), + ) + commands = [ + "ntp authentication-key 1 md5 encrypted testkey", + "ntp authentication-key 2 md5 encrypted 071B245F5A5B", + "ntp peer vrf siteC 192.0.2.1 iburst", + "ntp server vrf siteD 192.0.2.2 burst", + "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/0", + "ntp trusted-key 1", + "ntp trusted-key 2", + "ntp interface GigabitEthernet0/0/0/0 broadcast client", + "ntp interface GigabitEthernet0/0/0/0 multicast destination 224.0.0.8", + "ntp interface GigabitEthernet0/0/0/0 multicast client 224.0.0.8", + "ntp interface GigabitEthernet0/0/0/0 vrf siteB multicast key 1", + "ntp vrf siteE source GigabitEthernet0/0/0/0", + "ntp access-group vrf siteA ipv4 serve ServeAcl2", + "ntp access-group vrf siteA ipv4 peer PeerAcl2", + "ntp access-group ipv4 peer PeerAcl1", + "ntp access-group ipv4 serve ServeAcl1", + "ntp access-group ipv4 serve-only ServeOnlyAcl1", + "ntp access-group ipv4 query-only QueryOnlyAcl1", + "ntp access-group ipv6 peer PeerAcl2", + "ntp authenticate", + "ntp log-internal-sync", + "ntp broadcastdelay 1", + "ntp drift aging time 0", + "ntp drift file apphost", + "ntp ipv4 dscp af11", + "ntp ipv6 precedence routine", + "ntp max-associations 10", + "ntp master 1", + "ntp passive", + "ntp update-calendar", + "ntp source GigabitEthernet0/0/0/0", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_ntp_global_overridden(self): + run_cfg = dedent( + """\ + ntp + max-associations 10 + interface GigabitEthernet0/0/0/0 vrf siteB + multicast key 1 + ! + interface GigabitEthernet0/0/0/0 + broadcast client + multicast client 224.0.0.8 + multicast destination 224.0.0.8 + ! + authentication-key 1 md5 encrypted testkey + authentication-key 2 md5 encrypted 071B245F5A5B + authenticate + trusted-key 1 + trusted-key 2 + ipv4 dscp af11 + ipv6 precedence routine + peer vrf siteC 192.0.2.1 iburst + server vrf siteD 192.0.2.2 burst + server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0 + drift file apphost + drift aging time 0 + master 1 + access-group vrf siteA ipv4 peer PeerAcl3 + access-group vrf siteA ipv4 serve ServeAcl2 + access-group ipv4 peer PeerAcl1 + access-group ipv4 serve ServeAcl1 + access-group ipv4 serve-only ServeOnlyAcl1 + access-group ipv4 query-only QueryOnlyAcl1 + access-group ipv6 peer PeerAcl2 + source vrf siteE GigabitEthernet0/0/0/0 + source GigabitEthernet0/0/0/0 + passive + broadcastdelay 1 + update-calendar + log-internal-sync + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + access_group=dict( + ipv4=dict( + peer="PeerAcl1", + query_only="QueryOnlyAcl2", + serve="ServeAcl1", + serve_only="ServeOnlyAcl1", + ), + ipv6=dict(peer="PeerAcl2"), + vrfs=[ + dict( + ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"), + name="siteA", + ), + ], + ), + authenticate=True, + authentication_keys=[ + dict(id=1, key="testkey1", encryption=True), + dict(id=2, key="071B245F5A5B", encryption=True), + ], + broadcastdelay=1, + drift=dict(aging_time=0, file="apphost"), + interfaces=[ + dict( + name="GigabitEthernet0/0/0/1", + multicast_client="224.0.0.8", + multicast_destination="224.0.0.8", + broadcast_client=True, + ), + dict( + name="GigabitEthernet0/0/0/0", + multicast_key=1, + vrf="siteB", + ), + ], + ipv4=dict(dscp="af12"), + ipv6=dict(precedence="routine"), + log_internal_sync=True, + master=dict(stratum=1), + max_associations=10, + passive=True, + peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")], + servers=[ + dict(burst=True, server="192.0.2.3", vrf="siteD"), + dict( + iburst=True, + burst=True, + server="192.0.2.2", + key_id=1, + maxpoll=5, + minpoll=4, + prefer=True, + source="GigabitEthernet0/0/0/1", + version=2, + ), + ], + source_interface="GigabitEthernet0/0/0/0", + source_vrfs=[ + dict(name="GigabitEthernet0/0/0/0", vrf="siteE"), + ], + trusted_keys=[dict(key_id=1), dict(key_id=2)], + update_calendar=True, + ), + state="overridden", + ), + ) + commands = [ + "no ntp server vrf siteD 192.0.2.2 burst", + "no ntp interface GigabitEthernet0/0/0/0", + "ntp authentication-key 1 md5 encrypted testkey1", + "ntp server vrf siteD 192.0.2.3 burst", + "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/1", + "ntp interface GigabitEthernet0/0/0/1 broadcast client", + "ntp interface GigabitEthernet0/0/0/1 multicast destination 224.0.0.8", + "ntp interface GigabitEthernet0/0/0/1 multicast client 224.0.0.8", + "ntp access-group ipv4 query-only QueryOnlyAcl2", + "ntp access-group vrf siteA ipv4 peer PeerAcl2", + "ntp access-group vrf siteA ipv4 serve ServeAcl2", + "ntp ipv4 dscp af12", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ntp_global_gathered(self): + self.maxDiff = None + run_cfg = dedent( + """\ + ntp + max-associations 10 + interface GigabitEthernet0/0/0/0 + broadcast client + multicast client 224.0.0.8 + multicast destination 224.0.0.8 + ! + authentication-key 1 md5 encrypted testkey + authentication-key 2 md5 encrypted 071B245F5A5B + authenticate + trusted-key 1 + trusted-key 2 + ipv4 dscp af11 + ipv6 precedence routine + peer vrf siteC 192.0.2.1 iburst + server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0 + drift file apphost + drift aging time 0 + master 1 + access-group vrf siteA ipv4 peer PeerAcl3 + access-group vrf siteA ipv4 serve ServeAcl2 + access-group ipv4 peer PeerAcl1 + access-group ipv4 serve ServeAcl1 + access-group ipv4 serve-only ServeOnlyAcl1 + access-group ipv4 query-only QueryOnlyAcl1 + access-group ipv6 peer PeerAcl2 + source vrf siteE GigabitEthernet0/0/0/0 + source GigabitEthernet0/0/0/0 + passive + broadcastdelay 1 + update-calendar + log-internal-sync + ! + """, + ) + self.get_config.return_value = run_cfg + print(self.get_config.return_value) + set_module_args(dict(state="gathered")) + gathered = { + "max_associations": 10, + "interfaces": [ + { + "name": "GigabitEthernet0/0/0/0", + "broadcast_client": True, + "multicast_client": "224.0.0.8", + "multicast_destination": "224.0.0.8", + }, + ], + "authentication_keys": [ + {"id": 1, "key": "testkey", "encryption": True}, + {"id": 2, "key": "071B245F5A5B", "encryption": True}, + ], + "authenticate": True, + "trusted_keys": [{"key_id": 1}, {"key_id": 2}], + "ipv4": {"dscp": "af11"}, + "ipv6": {"precedence": "routine"}, + "peers": [{"peer": "192.0.2.1", "vrf": "siteC", "iburst": True}], + "servers": [ + { + "server": "192.0.2.2", + "burst": True, + "iburst": True, + "key_id": 1, + "minpoll": 4, + "maxpoll": 5, + "prefer": True, + "version": 2, + "source": "GigabitEthernet0/0/0/0", + }, + ], + "drift": {"file": "apphost", "aging_time": 0}, + "master": {"stratum": 1}, + "access_group": { + "vrfs": [ + { + "name": "siteA", + "ipv4": {"peer": "PeerAcl3", "serve": "ServeAcl2"}, + }, + ], + "ipv4": { + "peer": "PeerAcl1", + "serve": "ServeAcl1", + "serve_only": "ServeOnlyAcl1", + "query_only": "QueryOnlyAcl1", + }, + "ipv6": {"peer": "PeerAcl2"}, + }, + "source_vrfs": [ + {"name": "GigabitEthernet0/0/0/0", "vrf": "siteE"}, + ], + "source_interface": "GigabitEthernet0/0/0/0", + "passive": True, + "broadcastdelay": 1, + "update_calendar": True, + "log_internal_sync": True, + } + result = self.execute_module(changed=False) + self.assertEqual(gathered, result["gathered"]) + + def test_iosxr_ntp_global_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="ntp\n max-associations 10\n interface GigabitEthernet0/0/0/0\n broadcast client\n" + " multicast client 224.0.0.8\n multicast destination 224.0.0.8\n !\n " + "authentication-key 1 md5 encrypted testkey\n authentication-key 2 md5 " + "encrypted 071B245F5A5B\n authenticate\n trusted-key 1\n trusted-key 2\n ipv4 dscp " + "af11\n ipv6 precedence routine\n peer vrf siteC 192.0.2.1 iburst\n" + " server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer " + "burst iburst source GigabitEthernet0/0/0/0\n drift file apphost\n drift aging time 0\n" + " master 1\n access-group vrf siteA ipv4 peer PeerAcl3\n access-group vrf siteA " + "ipv4 serve ServeAcl2\n access-group ipv4 peer PeerAcl1\n access-group ipv4 serve " + "ServeAcl1\n access-group ipv4 serve-only ServeOnlyAcl1\n access-group ipv4 " + "query-only QueryOnlyAcl1\n access-group ipv6 peer PeerAcl2\n source vrf siteE " + "GigabitEthernet0/0/0/0\n source GigabitEthernet0/0/0/0\n" + " passive\n broadcastdelay " + "1\n update-calendar\n log-internal-sync\n!", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = { + "max_associations": 10, + "interfaces": [ + { + "name": "GigabitEthernet0/0/0/0", + "broadcast_client": True, + "multicast_client": "224.0.0.8", + "multicast_destination": "224.0.0.8", + }, + ], + "authentication_keys": [ + {"id": 1, "key": "testkey", "encryption": True}, + {"id": 2, "key": "071B245F5A5B", "encryption": True}, + ], + "authenticate": True, + "trusted_keys": [{"key_id": 1}, {"key_id": 2}], + "ipv4": {"dscp": "af11"}, + "ipv6": {"precedence": "routine"}, + "peers": [{"peer": "192.0.2.1", "vrf": "siteC", "iburst": True}], + "servers": [ + { + "server": "192.0.2.2", + "burst": True, + "iburst": True, + "key_id": 1, + "minpoll": 4, + "maxpoll": 5, + "prefer": True, + "version": 2, + "source": "GigabitEthernet0/0/0/0", + }, + ], + "drift": {"file": "apphost", "aging_time": 0}, + "master": {"stratum": 1}, + "access_group": { + "vrfs": [{"name": "siteA", "ipv4": {"peer": "PeerAcl3"}}], + "ipv4": { + "peer": "PeerAcl1", + "serve": "ServeAcl1", + "serve_only": "ServeOnlyAcl1", + "query_only": "QueryOnlyAcl1", + }, + "ipv6": {"peer": "PeerAcl2"}, + }, + "source_vrfs": [ + {"name": "GigabitEthernet0/0/0/0", "vrf": "siteE"}, + ], + "source_interface": "GigabitEthernet0/0/0/0", + "passive": True, + "broadcastdelay": 1, + "update_calendar": True, + "log_internal_sync": True, + } + self.assertEqual(parsed_list, result["parsed"]) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospf_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospf_interfaces.py new file mode 100644 index 00000000..8c976944 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospf_interfaces.py @@ -0,0 +1,359 @@ +# +# (c) 2019, Ansible by Red Hat, inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_ospf_interfaces +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrOspf_InterfacesModule(TestIosxrModule): + module = iosxr_ospf_interfaces + + def setUp(self): + super(TestIosxrOspf_InterfacesModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base." + "get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base." + "get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + + self.mock_edit_config = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.providers.CliProvider.edit_config", + ) + self.edit_config = self.mock_edit_config.start() + + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospf_interfaces.ospf_interfaces." + "Ospf_interfacesFacts.get_ospf_interfaces", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrOspf_InterfacesModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_edit_config.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def load_fixtures(self, commands=None): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_ospf_interfaces.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_ospf_interfaces_merged(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/1", + type="gigabitethernet", + address_family=[ + dict( + afi="ipv4", + processes=[ + dict( + process_id="LAB1", + area=dict(area_id="0.0.0.3"), + ), + ], + cost=10, + authentication=dict( + message_digest=dict(keychain="iosxr"), + ), + ), + ], + ), + ], + state="merged", + ), + ) + commands = [ + "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 cost 10", + "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest", + "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest keychain iosxr", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospf_interfaces_merged_idempotent(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + type="gigabitethernet", + address_family=[ + dict( + afi="ipv4", + processes=[ + dict( + process_id="LAB3", + area=dict(area_id="0.0.0.3"), + ), + ], + cost=20, + authentication=dict( + message_digest=dict(keychain="cisco"), + ), + ), + ], + ), + ], + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_ospf_interfaces_replaced(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + type="gigabitethernet", + address_family=[ + dict( + afi="ipv4", + processes=[ + dict( + process_id="LAB3", + area=dict(area_id="0.0.0.3"), + ), + ], + cost=40, + authentication=dict( + message_digest=dict(keychain="ciscoiosxr"), + ), + ), + ], + ), + ], + state="replaced", + ), + ) + commands = [ + "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 cost 40", + "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest", + "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest keychain ciscoiosxr", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospf_interfaces_replaced_idempotent(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + type="gigabitethernet", + address_family=[ + dict( + afi="ipv4", + processes=[ + dict( + process_id="LAB3", + area=dict(area_id="0.0.0.3"), + ), + ], + cost=20, + authentication=dict( + message_digest=dict(keychain="cisco"), + ), + ), + ], + ), + ], + state="replaced", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_ospf_interfaces_overridden(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/4", + type="gigabitethernet", + address_family=[ + dict( + afi="ipv4", + processes=[ + dict( + process_id="LAB4", + area=dict(area_id="0.0.0.4"), + ), + ], + cost=40, + authentication=dict( + message_digest=dict(keychain="iosxr"), + ), + ), + ], + ), + ], + state="overridden", + ), + ) + + commands = [ + "no router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0", + "router ospf LAB4 area 0.0.0.4 interface GigabitEthernet 0/0/0/4 cost 40", + "router ospf LAB4 area 0.0.0.4 interface GigabitEthernet 0/0/0/4 authentication message-digest", + "router ospf LAB4 area 0.0.0.4 interface GigabitEthernet 0/0/0/4 authentication message-digest keychain iosxr", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospf_interfaces_overridden_idempotent(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + type="gigabitethernet", + address_family=[ + dict( + afi="ipv4", + processes=[ + dict( + process_id="LAB3", + area=dict(area_id="0.0.0.3"), + ), + ], + cost=20, + authentication=dict( + message_digest=dict(keychain="cisco"), + ), + ), + ], + ), + ], + state="overridden", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_ospf_interfaces_deleted(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/0", + type="gigabitethernet", + ), + ], + state="deleted", + ), + ) + commands = [ + "no router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospf_interfaces_deleted_idempotent(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/1", + type="gigabitethernet", + ), + ], + state="deleted", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_ospf_interfaces_parsed(self): + set_module_args( + dict( + running_config="router ospf LAB3\n area 0.0.0.3\n interface GigabitEthernet0/0/0/0\n cost 20\n !\n !\n!", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = [ + dict( + name="GigabitEthernet0/0/0/0", + type="gigabitethernet", + address_family=[ + dict( + afi="ipv4", + processes=[ + dict( + process_id="LAB3", + area=dict(area_id="0.0.0.3"), + ), + ], + cost=20, + ), + ], + ), + ] + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_ospf_interfaces_rendered(self): + set_module_args( + dict( + config=[ + dict( + name="GigabitEthernet0/0/0/1", + type="gigabitethernet", + address_family=[ + dict( + afi="ipv4", + processes=[ + dict( + process_id="LAB1", + area=dict(area_id="0.0.0.3"), + ), + ], + cost=10, + authentication=dict( + message_digest=dict(keychain="iosxr"), + ), + ), + ], + ), + ], + state="rendered", + ), + ) + commands = [ + "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 cost 10", + "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest", + "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest keychain iosxr", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv2.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv2.py new file mode 100644 index 00000000..6d00a825 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv2.py @@ -0,0 +1,277 @@ +# +# (c) 2019, Ansible by Red Hat, inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_ospfv2 +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrOspfV2Module(TestIosxrModule): + module = iosxr_ospfv2 + + def setUp(self): + super(TestIosxrOspfV2Module, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base." + "get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base." + "get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + + self.mock_edit_config = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.providers.CliProvider.edit_config", + ) + self.edit_config = self.mock_edit_config.start() + + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospfv2.ospfv2." + "Ospfv2Facts.get_ospfv2_data", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrOspfV2Module, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_edit_config.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def load_fixtures(self, commands=None): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_ospfv2.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_ospfv2_merged(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="300", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + log_adjacency_changes=dict(set=True), + ), + ], + ), + state="merged", + ), + ) + commands = [ + "router ospf 300", + "cost 2", + "default-metric 10", + "area 11 default-cost 5", + "log adjacency changes", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospfv2_merged_idempotent(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="30", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + ), + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_ospfv2_replaced(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="30", + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + dict( + process_id="40", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + ), + state="replaced", + ), + ) + commands = [ + "router ospf 30", + "no default-metric 10", + "router ospf 40", + "cost 2", + "default-metric 10", + "area 11 default-cost 5", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospfv2_replaced_idempotent(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="30", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + ), + state="replaced", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_ospfv2_overridden(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="40", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + log_adjacency_changes=dict(set=True), + ), + ], + ), + state="overridden", + ), + ) + + commands = [ + "router ospf 30", + "no cost 2", + "no default-metric 10", + "no area 11 default-cost 5", + "router ospf 40", + "cost 2", + "default-metric 10", + "area 11 default-cost 5", + "log adjacency changes", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospfv2_overridden_idempotent(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="30", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + ), + state="overridden", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_ospfv2_deleted(self): + set_module_args( + dict( + config=dict(processes=[dict(process_id="30", cost=2)]), + state="deleted", + ), + ) + commands = [ + "router ospf 30", + "no cost 2", + "no default-metric 10", + "no area 11 default-cost 5", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospfv2_parsed(self): + set_module_args( + dict( + running_config="router ospf 50\n cost 2\n area 11\n default-cost 5\n !\n!", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = { + "processes": [ + dict( + process_id="50", + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + } + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_ospfv2_rendered(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="60", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + log_adjacency_changes=dict(set=True), + ), + ], + ), + state="rendered", + ), + ) + commands = [ + "area 11 default-cost 5", + "cost 2", + "log adjacency changes", + "default-metric 10", + "router ospf 60", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv3.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv3.py new file mode 100644 index 00000000..1b8e491f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv3.py @@ -0,0 +1,271 @@ +# +# (c) 2019, Ansible by Red Hat, inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_ospfv3 +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrOspfV3Module(TestIosxrModule): + module = iosxr_ospfv3 + + def setUp(self): + super(TestIosxrOspfV3Module, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base." + "get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base." + "get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + + self.mock_edit_config = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.providers.CliProvider.edit_config", + ) + self.edit_config = self.mock_edit_config.start() + + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospfv3.ospfv3." + "Ospfv3Facts.get_ospfv3_data", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrOspfV3Module, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_edit_config.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def load_fixtures(self, commands=None): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_ospfv3.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_ospfv3_merged(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="300", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + ), + state="merged", + ), + ) + commands = [ + "router ospfv3 300", + "cost 2", + "default-metric 10", + "area 11 default-cost 5", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospfv3_merged_idempotent(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="30", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + ), + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_ospfv3_replaced(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="30", + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + dict( + process_id="40", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + ), + state="replaced", + ), + ) + commands = [ + "router ospfv3 30", + "no default-metric 10", + "router ospfv3 40", + "cost 2", + "default-metric 10", + "area 11 default-cost 5", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospfv3_replaced_idempotent(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="30", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + ), + state="replaced", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_ospfv3_overridden(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="40", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + ), + state="overridden", + ), + ) + + commands = [ + "router ospfv3 30", + "no cost 2", + "no default-metric 10", + "no area 11 default-cost 5", + "router ospfv3 40", + "cost 2", + "default-metric 10", + "area 11 default-cost 5", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospfv3_overridden_idempotent(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="30", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + ), + state="overridden", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_ospfv3_deleted(self): + set_module_args( + dict( + config=dict(processes=[dict(process_id="30", cost=2)]), + state="deleted", + ), + ) + commands = [ + "router ospfv3 30", + "no cost 2", + "no default-metric 10", + "no area 11 default-cost 5", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_ospfv3_parsed(self): + set_module_args( + dict( + running_config="router ospfv3 50\n cost 2\n area 11\n default-cost 5\n !\n!", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = { + "processes": [ + dict( + process_id="50", + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + } + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_ospfv3_rendered(self): + set_module_args( + dict( + config=dict( + processes=[ + dict( + process_id="60", + default_metric=10, + cost=2, + areas=[dict(area_id="11", default_cost=5)], + ), + ], + ), + state="rendered", + ), + ) + commands = [ + "area 11 default-cost 5", + "cost 2", + "default-metric 10", + "router ospfv3 60", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), commands) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ping.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ping.py new file mode 100644 index 00000000..d0ceda0f --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ping.py @@ -0,0 +1,180 @@ +# +# (c) 2022, Ansible by Red Hat, inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from textwrap import dedent + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_ping +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule + + +class TestIosxrPingModule(TestIosxrModule): + module = iosxr_ping + + def setUp(self): + super(TestIosxrPingModule, self).setUp() + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.ping.ping.Ping.run_command", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrPingModule, self).tearDown() + self.mock_execute_show_command.stop() + + def test_iosxr_ping_count(self): + self.execute_show_command.return_value = dedent( + """\ + Type escape sequence to abort. + ending 2, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds: + ! + Success rate is 100 percent (2/2), round-trip min/avg/max = 25/25/25 ms + """, + ) + set_module_args(dict(count=2, dest="8.8.8.8")) + result = self.execute_module() + mock_res = { + "commands": "ping ipv4 8.8.8.8 count 2", + "packet_loss": "0%", + "packets_rx": 2, + "packets_tx": 2, + "rtt": {"min": 25, "avg": 25, "max": 25}, + "changed": False, + } + self.assertEqual(result, mock_res) + + def test_iosxr_ping_v6(self): + self.execute_show_command.return_value = dedent( + """\ + Type escape sequence to abort. + ending 2, 100-byte ICMP Echos to 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff, timeout is 2 seconds: + ! + Success rate is 100 percent (2/2), round-trip min/avg/max = 25/25/25 ms + """, + ) + set_module_args( + dict( + count=2, + dest="2001:db8:ffff:ffff:ffff:ffff:ffff:ffff", + afi="ipv6", + ), + ) + result = self.execute_module() + mock_res = { + "commands": "ping ipv6 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff count 2", + "packet_loss": "0%", + "packets_rx": 2, + "packets_tx": 2, + "rtt": {"min": 25, "avg": 25, "max": 25}, + "changed": False, + } + self.assertEqual(result, mock_res) + + def test_iosxr_ping_options_all(self): + self.execute_show_command.return_value = dedent( + """\ + Type escape sequence to abort. + ending 2, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds: + ! + Success rate is 100 percent (2/2), round-trip min/avg/max = 25/25/25 ms + """, + ) + set_module_args( + { + "afi": "ipv4", + "count": 4, + "dest": "8.8.8.8", + "df_bit": True, + "size": "10", + "source": "Loopback88", + "state": "present", + "sweep": True, + "validate": True, + "vrf": "DummyVrf", + }, + ) + result = self.execute_module() + mock_res = { + "commands": "ping vrf DummyVrf ipv4 8.8.8.8 count 4 df-bit sweep validate size 10 source Loopback88", + "packet_loss": "0%", + "packets_rx": 2, + "packets_tx": 2, + "rtt": {"min": 25, "avg": 25, "max": 25}, + "changed": False, + } + self.assertEqual(result, mock_res) + + def test_iosxr_ping_state_absent_pass(self): + self.execute_show_command.return_value = dedent( + """\ + Type escape sequence to abort. + ending 2, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds: + ! + Success rate is 90 percent (2/2), round-trip min/avg/max = 25/25/25 ms + """, + ) + set_module_args(dict(count=2, dest="8.8.8.8", state="absent")) + result = self.execute_module(failed=True) + mock_res = { + "msg": "Ping succeeded unexpectedly", + "commands": "ping ipv4 8.8.8.8 count 2", + "packet_loss": "10%", + "packets_rx": 2, + "packets_tx": 2, + "rtt": {"min": 25, "avg": 25, "max": 25}, + "failed": True, + } + self.assertEqual(result, mock_res) + + def test_iosxr_ping_state_absent_pass(self): + self.execute_show_command.return_value = dedent( + """\ + Type escape sequence to abort. + Sending 5, 100-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds: + ..... + Success rate is 0 percent (0/5) + """, + ) + set_module_args(dict(count=2, dest="192.0.2.1", state="absent")) + result = self.execute_module(failed=False) + print(result) + mock_res = { + "commands": "ping ipv4 192.0.2.1 count 2", + "packet_loss": "100%", + "packets_rx": 0, + "packets_tx": 5, + "rtt": {}, + "changed": False, + } + self.assertEqual(result, mock_res) + + def test_iosxr_ping_state_absent_present_fail(self): + self.execute_show_command.return_value = dedent( + """\ + Type escape sequence to abort. + ending 2, 100-byte ICMP Echos to 8.8.8.8, timeout is 12 seconds: + ! + Success rate is 0 percent (0/2), round-trip min/avg/max = 25/25/25 ms + """, + ) + set_module_args(dict(count=2, dest="8.8.8.8", state="present")) + result = self.execute_module(failed=True) + mock_res = { + "msg": "Ping failed unexpectedly", + "commands": "ping ipv4 8.8.8.8 count 2", + "packet_loss": "100%", + "packets_rx": 0, + "packets_tx": 2, + "rtt": {"min": 25, "avg": 25, "max": 25}, + "failed": True, + } + self.assertEqual(result, mock_res) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_prefix_lists.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_prefix_lists.py new file mode 100644 index 00000000..6dca5d92 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_prefix_lists.py @@ -0,0 +1,442 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from textwrap import dedent + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_prefix_lists +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule + + +class TestIosxrPrefixListsModule(TestIosxrModule): + module = iosxr_prefix_lists + + def setUp(self): + super(TestIosxrPrefixListsModule, self).setUp() + + self.mock_get_resource_connection = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base." + "get_resource_connection", + ) + self.get_resource_connection = self.mock_get_resource_connection.start() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.prefix_lists.prefix_lists." + "Prefix_listsFacts.get_config", + ) + self.get_config = self.mock_get_config.start() + + def tearDown(self): + super(TestIosxrPrefixListsModule, self).tearDown() + self.get_resource_connection.stop() + self.get_config.stop() + + def test_iosxr_prefix_lists_merged_idempotent(self): + run_cfg = dedent( + """ipv6 prefix-list test2\n 4 remark test\n! + \nipv4 prefix-list test1\n 3 remark test1\n 2 permit 10.0.0.0/24\n! + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=[ + dict( + afi="ipv6", + prefix_lists=[ + dict( + name="test2", + entries=[ + dict( + sequence=4, + action="remark", + description="test", + ), + ], + ), + ], + ), + dict( + afi="ipv4", + prefix_lists=[ + dict( + name="test1", + entries=[ + dict( + sequence=3, + action="remark", + description="test1", + ), + dict( + sequence=2, + action="permit", + prefix="10.0.0.0/24", + ), + ], + ), + ], + ), + ], + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_prefix_lists_merged(self): + set_module_args( + dict( + config=[ + dict( + afi="ipv6", + prefix_lists=[ + dict( + name="test2", + entries=[ + dict( + sequence=4, + action="remark", + description="test", + ), + ], + ), + ], + ), + dict( + afi="ipv4", + prefix_lists=[ + dict( + name="test1", + entries=[ + dict( + sequence=3, + action="remark", + description="test1", + ), + dict( + sequence=2, + action="permit", + prefix="10.0.0.0/24", + ), + ], + ), + dict( + name="test3", + entries=[ + dict( + sequence=5, + action="permit", + eq="3", + prefix="32.0.0.0/8", + ), + ], + ), + ], + ), + ], + state="merged", + ), + ) + commands = [ + "ipv6 prefix-list test2 4 remark test", + "ipv4 prefix-list test1 2 permit 10.0.0.0/24", + "ipv4 prefix-list test1 3 remark test1", + "ipv4 prefix-list test3 5 permit 32.0.0.0/8 eq 3", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_prefix_lists_replaced(self): + run_cfg = dedent( + """ipv6 prefix-list test2\n 4 remark test\n! + \nipv4 prefix-list test1\n 3 remark test1\n 2 permit 10.0.0.0/24\n!""", + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + prefix_lists=[ + dict( + name="test2", + entries=[ + dict( + sequence=2, + action="permit", + prefix="10.0.0.0/24", + ), + ], + ), + dict( + name="test1", + entries=[ + dict( + sequence=2, + action="permit", + prefix="10.0.0.0/24", + ), + ], + ), + dict( + name="test3", + entries=[ + dict( + sequence=5, + action="permit", + eq="3", + prefix="32.0.0.0/8", + ), + ], + ), + ], + ), + ], + state="replaced", + ), + ) + commands = [ + "no ipv4 prefix-list test1 3 remark test1", + "ipv4 prefix-list test2 2 permit 10.0.0.0/24", + "ipv4 prefix-list test3 5 permit 32.0.0.0/8 eq 3", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_prefix_lists_replaced_idempotent(self): + run_cfg = dedent( + """ipv6 prefix-list test2\n 4 remark test\n! + \nipv4 prefix-list test1\n 3 remark test1\n 2 permit 10.0.0.0/24\n!""", + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=[ + dict( + afi="ipv6", + prefix_lists=[ + dict( + name="test2", + entries=[ + dict( + sequence=4, + action="remark", + description="test", + ), + ], + ), + ], + ), + dict( + afi="ipv4", + prefix_lists=[ + dict( + name="test1", + entries=[ + dict( + sequence=3, + action="remark", + description="test1", + ), + dict( + sequence=2, + action="permit", + prefix="10.0.0.0/24", + ), + ], + ), + ], + ), + ], + state="replaced", + ), + ) + + self.execute_module(changed=False, commands=[]) + + def test_iosxr_prefix_list_deleted(self): + run_cfg = dedent( + """ipv6 prefix-list test2\n 4 remark test\n! + \nipv4 prefix-list test1\n 3 remark test1\n 2 permit 10.0.0.0/24\n!""", + ) + self.get_config.return_value = run_cfg + set_module_args(dict(state="deleted")) + + commands = ["no ipv4 prefix-list test1", "no ipv6 prefix-list test2"] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_prefix_list_deleted_idempotent(self): + run_cfg = dedent( + """\ + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(config=[], state="deleted")) + + result = self.execute_module(changed=False) + self.assertEqual(result["commands"], []) + + def test_iosxr_prefix_list_rendered(self): + set_module_args( + dict( + config=[ + dict( + afi="ipv6", + prefix_lists=[ + dict( + name="test2", + entries=[ + dict( + sequence=4, + action="remark", + description="test", + ), + ], + ), + ], + ), + dict( + afi="ipv4", + prefix_lists=[ + dict( + name="test1", + entries=[ + dict( + sequence=3, + action="remark", + description="test1", + ), + dict( + sequence=2, + action="permit", + prefix="10.0.0.0/24", + ), + ], + ), + dict( + name="test3", + entries=[ + dict( + sequence=5, + action="permit", + eq="3", + prefix="32.0.0.0/8", + ), + ], + ), + ], + ), + ], + state="rendered", + ), + ) + + commands = [ + "ipv6 prefix-list test2 4 remark test", + "ipv4 prefix-list test1 2 permit 10.0.0.0/24", + "ipv4 prefix-list test1 3 remark test1", + "ipv4 prefix-list test3 5 permit 32.0.0.0/8 eq 3", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_prefix_list_parsed(self): + set_module_args( + dict( + running_config="ipv4 prefix-list test1\n 3 remark test1\n!", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = [ + { + "afi": "ipv4", + "prefix_lists": [ + { + "name": "test1", + "entries": [ + { + "sequence": 3, + "action": "remark", + "description": "test1", + }, + ], + }, + ], + }, + ] + + self.assertEqual(parsed_list, result["parsed"]) + + def test_iosxr_prefix_list_overridden(self): + run_cfg = dedent( + """ipv6 prefix-list test2\n 4 remark test\n! + \nipv4 prefix-list test1\n 3 remark test1\n 2 permit 10.0.0.0/24\n! + """, + ) + + self.get_config.return_value = run_cfg + + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + prefix_lists=[ + dict( + name="test2", + entries=[ + dict( + sequence=2, + action="permit", + prefix="10.0.0.0/24", + ), + ], + ), + dict( + name="test1", + entries=[ + dict( + sequence=2, + action="permit", + prefix="10.0.0.0/24", + ), + ], + ), + ], + ), + ], + state="overridden", + ), + ) + commands = [ + "no ipv4 prefix-list test1 3 remark test1", + "ipv4 prefix-list test2 2 permit 10.0.0.0/24", + "no ipv6 prefix-list test2", + ] + + result = self.execute_module(changed=True) + self.assertEqual(set(result["commands"]), set(commands)) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_snmp_server.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_snmp_server.py new file mode 100644 index 00000000..14862519 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_snmp_server.py @@ -0,0 +1,3612 @@ +# (c) 2021 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from textwrap import dedent + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_snmp_server +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule + + +class TestIosxrSnmpServerModule(TestIosxrModule): + module = iosxr_snmp_server + + def setUp(self): + super(TestIosxrSnmpServerModule, self).setUp() + + self.mock_get_resource_connection = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base." + "get_resource_connection", + ) + self.get_resource_connection = self.mock_get_resource_connection.start() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.snmp_server.snmp_server." + "Snmp_serverFacts.get_config", + ) + self.get_config = self.mock_get_config.start() + + def tearDown(self): + super(TestIosxrSnmpServerModule, self).tearDown() + self.get_resource_connection.stop() + self.get_config.stop() + + def test_iosxr_snmp_server_merged_idempotent(self): + self.maxDiff = None + run_cfg = dedent( + """\ + snmp-server vrf vrf1 + host 1.1.1.1 traps test1 + ! + snmp-server drop report acl IPv4 test1 + snmp-server drop unknown-user + snmp-server ipv4 dscp af11 + snmp-server ipv6 precedence routine + snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl + snmp-server community test2 RW SystemOwner IPv4 test IPv6 test1 + snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1 + snmp-server queue-length 2 + snmp-server trap-timeout 3 + snmp-server trap throttle-time 12 + snmp-server traps rf + snmp-server traps bfd + snmp-server traps bgp cbgp2 + snmp-server traps pim neighbor-change + snmp-server traps pim invalid-message-received + snmp-server traps pim rp-mapping-change + snmp-server traps pim interface-state-change + snmp-server traps copy-complete + snmp-server traps hsrp + snmp-server traps ipsla + snmp-server traps msdp peer-state-change + snmp-server traps snmp linkup + snmp-server traps snmp linkdown + snmp-server traps snmp coldstart + snmp-server traps snmp warmstart + snmp-server traps snmp authentication + snmp-server traps vrrp events + snmp-server traps flash removal + snmp-server traps flash insertion + snmp-server traps ipsec tunnel stop + snmp-server traps ipsec tunnel start + snmp-server traps power + snmp-server traps config + snmp-server traps entity + snmp-server traps sensor + snmp-server traps selective-vrf-download role-change + snmp-server traps syslog + snmp-server traps system + snmp-server traps ospf lsa lsa-maxage + snmp-server traps ospf lsa lsa-originate + snmp-server traps ospf errors bad-packet + snmp-server traps ospf errors authentication-failure + snmp-server traps ospf errors config-error + snmp-server traps ospf errors virt-bad-packet + snmp-server traps ospf errors virt-authentication-failure + snmp-server traps ospf errors virt-config-error + snmp-server traps ospf retransmit packets + snmp-server traps ospf retransmit virt-packets + snmp-server traps ospf state-change if-state-change + snmp-server traps ospf state-change neighbor-state-change + snmp-server traps ospf state-change virtif-state-change + snmp-server traps ospf state-change virtneighbor-state-change + snmp-server traps rsvp all + snmp-server traps rsvp new-flow + snmp-server traps rsvp lost-flow + snmp-server traps l2tun sessions + snmp-server traps l2tun tunnel-up + snmp-server traps l2tun tunnel-down + snmp-server traps vpls all + snmp-server traps vpls status + snmp-server traps vpls full-clear + snmp-server traps vpls full-raise + snmp-server traps bulkstat collection + snmp-server traps diameter peerup + snmp-server traps diameter peerdown + snmp-server traps diameter protocolerror + snmp-server traps diameter permanentfail + snmp-server traps diameter transientfail + snmp-server traps l2vpn all + snmp-server traps l2vpn vc-up + snmp-server traps l2vpn vc-down + snmp-server traps bridgemib + snmp-server traps ospfv3 errors bad-packet + snmp-server traps ospfv3 errors config-error + snmp-server traps ospfv3 errors virt-config-error + snmp-server traps ospfv3 state-change neighbor-state-change + snmp-server traps ospfv3 state-change virtif-state-change + snmp-server traps ospfv3 state-change virtneighbor-state-change + snmp-server traps ospfv3 state-change restart-status-change + snmp-server traps ospfv3 state-change restart-helper-status-change + snmp-server traps ospfv3 state-change restart-virtual-helper-status-change + snmp-server traps subscriber session-agg node + snmp-server traps subscriber session-agg access-interface + snmp-server traps addrpool low + snmp-server traps addrpool high + snmp-server traps cisco-entity-ext + snmp-server traps entity-state operstatus + snmp-server traps entity-state switchover + snmp-server traps entity-redundancy all + snmp-server traps entity-redundancy status + snmp-server traps entity-redundancy switchover + snmp-server chassis-id test2 + snmp-server contact t1 + snmp-server location test1 + snmp-server target list test host 1.1.1.2 + snmp-server target list test2 vrf vrf2 + snmp-server context c1 + snmp-server context c2 + snmp-server logging threshold oid-processing 1 + snmp-server logging threshold pdu-processing 1 + snmp-server mib bulkstat max-procmem-size 101 + snmp-server mib bulkstat object-list test1 + ! + snmp-server mib bulkstat schema mib1 + object-list test1 + poll-interval 1 + ! + snmp-server mib bulkstat transfer-id test2 + retry 1 + buffer-size 1024 + enable + format schemaASCII + retain 1 + schema test2 + ! + snmp-server timeouts duplicate 0 + snmp-server timeouts inQdrop 0 + snmp-server timeouts subagent 1 + snmp-server timeouts pdu stats 1 + snmp-server timeouts threshold 0 + snmp-server packetsize 490 + snmp-server correlator rule rule1 + timeout 5 + ! + snmp-server correlator ruleset rule1 + ! + snmp-server correlator buffer-size 1024 + snmp-server trap-source GigabitEthernet0/0/0/2 + snmp-server throttle-time 60 + snmp-server community-map cm1 context c1 security-name s1 target-list t1 + snmp-server inform retries 7 + snmp-server overload-control 4 6 + snmp-server ifmib internal cache max-duration 4 + snmp-server mroutemib send-all-vrf + snmp-server notification-log-mib size 5 + snmp-server notification-log-mib GlobalSize 5 + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + vrfs=[ + dict( + vrf="vrf1", + hosts=[ + dict( + community="test1", + host="1.1.1.1", + traps=True, + ), + ], + ), + ], + users=[ + dict( + Ipv4_acl="test1", + Ipv6_acl="test2", + group="test2", + user="u1", + v4_acl="v4acl", + ), + ], + timeouts=dict( + duplicate=0, + inQdrop=0, + pdu_stats=1, + subagent=1, + threshold=0, + ), + trap=dict(throttle_time=12), + targets=[ + dict(name="test2", vrf="vrf2"), + dict(host="1.1.1.2", name="test"), + ], + ifmib=dict(internal_cache_max_duration=4), + inform=dict(retries=7), + chassis_id="test2", + packetsize=490, + queue_length=2, + throttle_time=60, + trap_source="GigabitEthernet0/0/0/2", + trap_timeout=3, + context=["c1", "c2"], + correlator=dict( + buffer_size=1024, + rule_sets=[dict(name="rule1")], + rules=[dict(rule_name="rule1", timeout=5)], + ), + communities=[ + dict( + name="test2", + rw=True, + systemowner=True, + acl_v4="test", + acl_v6="test1", + ), + ], + community_maps=[ + dict( + name="cm1", + context="c1", + target_list="t1", + security_name="s1", + ), + ], + drop=dict(report_IPv4="test1", unknown_user=True), + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + groups=[ + dict( + Ipv4_acl="test", + Ipv6_acl="test1", + context="test3", + group="g2", + read="test1", + version="v1", + write="test2", + ), + ], + location="test1", + logging_threshold_oid_processing=1, + logging_threshold_pdu_processing=1, + mib_bulkstat_max_procmem_size=101, + mroutemib_send_all_vrf=True, + mib_object_lists=["test1"], + overload_control=dict( + overload_drop_time=4, + overload_throttle_rate=6, + ), + mib_schema=[ + dict( + name="mib1", + object_list="test1", + poll_interval=1, + ), + ], + notification_log_mib=dict(GlobalSize=5, size=5), + mib_bulkstat_transfer_ids=[ + dict( + buffer_size=1024, + enable=True, + format_schemaASCI=True, + name="test2", + retain=1, + retry=1, + schema="test2", + ), + ], + traps=dict( + diameter=dict( + peerdown=True, + peerup=True, + permanentfail=True, + protocolerror=True, + transientfail=True, + ), + entity=True, + entity_redundancy=dict( + all=True, + status=True, + switchover=True, + ), + entity_state=dict(operstatus=True, switchover=True), + flash=dict(insertion=True, removal=True), + hsrp=True, + ipsla=True, + ipsec=dict(start=True, stop=True), + bridgemib=True, + bulkstat_collection=True, + cisco_entity_ext=True, + config=True, + copy_complete=True, + addrpool=dict(high=True, low=True), + bfd=True, + bgp=dict(cbgp2=True), + l2tun=dict( + sessions=True, + tunnel_down=True, + tunnel_up=True, + ), + l2vpn=dict(all=True, vc_down=True, vc_up=True), + msdp_peer_state_change=True, + ospf=dict( + errors=dict( + authentication_failure=True, + bad_packet=True, + config_error=True, + virt_authentication_failure=True, + virt_bad_packet=True, + virt_config_error=True, + ), + lsa=dict(lsa_maxage=True, lsa_originate=True), + retransmit=dict(packets=True, virt_packets=True), + state_change=dict( + if_state_change=True, + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + ), + ), + ospfv3=dict( + errors=dict( + bad_packet=True, + config_error=True, + virt_config_error=True, + ), + state_change=dict( + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + restart_helper_status_change=True, + restart_status_change=True, + restart_virtual_helper_status_change=True, + ), + ), + pim=dict( + interface_state_change=True, + invalid_message_received=True, + neighbor_change=True, + rp_mapping_change=True, + ), + power=True, + rf=True, + rsvp=dict(all=True, lost_flow=True, new_flow=True), + selective_vrf_download_role_change=True, + sensor=True, + snmp=dict( + authentication=True, + coldstart=True, + linkdown=True, + linkup=True, + warmstart=True, + ), + subscriber=dict( + session_agg_access_interface=True, + session_agg_node=True, + ), + syslog=True, + system=True, + vpls=dict( + all=True, + full_clear=True, + full_raise=True, + status=True, + ), + vrrp_events=True, + ), + ), + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_snmp_server_merged(self): + self.maxDiff = None + + set_module_args( + dict( + config=dict( + vrfs=[ + dict( + vrf="vrf1", + hosts=[ + dict( + community="test1", + host="1.1.1.1", + traps=True, + ), + ], + ), + ], + users=[ + dict( + Ipv4_acl="test1", + Ipv6_acl="test2", + group="test2", + user="u1", + v4_acl="v4acl", + SystemOwner=True, + ), + ], + timeouts=dict( + duplicate=0, + inQdrop=0, + pdu_stats=1, + subagent=1, + threshold=0, + ), + trap=dict(throttle_time=12, link_ietf=True), + targets=[ + dict(name="test2", vrf="vrf2"), + dict(host="1.1.1.2", name="test"), + ], + ifmib=dict(internal_cache_max_duration=4), + inform=dict(retries=7), + chassis_id="test2", + packetsize=490, + queue_length=2, + throttle_time=60, + trap_source="GigabitEthernet0/0/0/2", + trap_timeout=3, + context=["c1", "c2"], + correlator=dict( + buffer_size=1024, + rule_sets=[dict(name="rule1")], + rules=[dict(rule_name="rule1", timeout=5)], + ), + communities=[ + dict( + name="test2", + ro=True, + sdrowner=True, + acl_v4="test", + acl_v6="test1", + ), + ], + community_maps=[ + dict( + name="cm1", + context="c1", + target_list="t1", + security_name="s1", + ), + ], + drop=dict(report_IPv4="test1", unknown_user=True), + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + groups=[ + dict( + Ipv4_acl="test", + Ipv6_acl="test1", + context="test3", + group="g2", + read="test1", + version="v1", + write="test2", + ), + ], + interfaces=[dict(name=" GigabitEthernet0/0/0/2")], + location="test1", + logging_threshold_oid_processing=1, + logging_threshold_pdu_processing=1, + mib_bulkstat_max_procmem_size=101, + mroutemib_send_all_vrf=True, + mib_object_lists=["test1"], + overload_control=dict( + overload_drop_time=4, + overload_throttle_rate=6, + ), + mib_schema=[ + dict( + name="mib1", + object_list="test1", + poll_interval=1, + ), + ], + notification_log_mib=dict(GlobalSize=5, size=5), + mib_bulkstat_transfer_ids=[ + dict( + buffer_size=1024, + enable=True, + format_schemaASCI=True, + name="test2", + retain=1, + retry=1, + schema="test2", + ), + ], + traps=dict( + diameter=dict( + peerdown=True, + peerup=True, + permanentfail=True, + protocolerror=True, + transientfail=True, + ), + entity=True, + entity_redundancy=dict( + all=True, + status=True, + switchover=True, + ), + entity_state=dict(operstatus=True, switchover=True), + flash=dict(insertion=True, removal=True), + hsrp=True, + ipsla=True, + ipsec=dict(start=True, stop=True), + bridgemib=True, + bulkstat_collection=True, + cisco_entity_ext=True, + config=True, + copy_complete=True, + addrpool=dict(high=True, low=True), + bfd=True, + bgp=dict(cbgp2=True), + l2tun=dict( + sessions=True, + tunnel_down=True, + tunnel_up=True, + ), + l2vpn=dict(all=True, vc_down=True, vc_up=True), + msdp_peer_state_change=True, + ospf=dict( + errors=dict( + authentication_failure=True, + bad_packet=True, + config_error=True, + virt_authentication_failure=True, + virt_bad_packet=True, + virt_config_error=True, + ), + lsa=dict(lsa_maxage=True, lsa_originate=True), + retransmit=dict(packets=True, virt_packets=True), + state_change=dict( + if_state_change=True, + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + ), + ), + ospfv3=dict( + errors=dict( + bad_packet=True, + config_error=True, + virt_config_error=True, + ), + state_change=dict( + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + restart_helper_status_change=True, + restart_status_change=True, + restart_virtual_helper_status_change=True, + ), + ), + pim=dict( + interface_state_change=True, + invalid_message_received=True, + neighbor_change=True, + rp_mapping_change=True, + ), + power=True, + rf=True, + rsvp=dict(all=True, lost_flow=True, new_flow=True), + selective_vrf_download_role_change=True, + sensor=True, + snmp=dict( + authentication=True, + coldstart=True, + linkdown=True, + linkup=True, + warmstart=True, + ), + subscriber=dict( + session_agg_access_interface=True, + session_agg_node=True, + ), + syslog=True, + system=True, + vpls=dict( + all=True, + full_clear=True, + full_raise=True, + status=True, + ), + vrrp_events=True, + isis=dict( + adjacency_change=True, + area_mismatch=True, + attempt_to_exceed_max_sequence=True, + authentication_failure=True, + authentication_type_failure=True, + corrupted_lsp_detected=True, + database_overload=True, + id_len_mismatch=True, + lsp_error_detected=True, + lsp_too_large_to_propagate=True, + manual_address_drops=True, + max_area_addresses_mismatch=True, + orig_lsp_buff_size_mismatch=True, + own_lsp_purge=True, + protocols_supported_mismatch=True, + rejected_adjacency=True, + sequence_number_skip=True, + version_skew=True, + ), + ), + ), + state="merged", + ), + ) + commands = [ + "snmp-server chassis-id test2", + "snmp-server correlator buffer-size 1024", + "snmp-server ipv4 dscp af11", + "snmp-server ipv6 precedence routine", + "snmp-server location test1", + "snmp-server logging threshold oid-processing 1", + "snmp-server logging threshold pdu-processing 1", + "snmp-server mib bulkstat max-procmem-size 101", + "snmp-server mroutemib send-all-vrf", + "snmp-server overload-control 4 6", + "snmp-server packetsize 490", + "snmp-server queue-length 2", + "snmp-server throttle-time 60", + "snmp-server trap-source GigabitEthernet0/0/0/2", + "snmp-server trap-timeout 3", + "snmp-server drop report acl IPv4 test1", + "snmp-server drop unknown-user", + "snmp-server ifmib internal cache max-duration 4", + "snmp-server inform retries 7", + "snmp-server notification-log-mib size 5", + "snmp-server notification-log-mib GlobalSize 5", + "snmp-server trap link ietf", + "snmp-server trap throttle-time 12", + "snmp-server timeouts threshold 0", + "snmp-server timeouts pdu stats 1", + "snmp-server timeouts subagent 1", + "snmp-server timeouts inQdrop 0", + "snmp-server timeouts duplicate 0", + "snmp-server traps addrpool low", + "snmp-server traps addrpool high", + "snmp-server traps bfd", + "snmp-server traps bgp cbgp2", + "snmp-server traps bulkstat collection", + "snmp-server traps bridgemib", + "snmp-server traps copy-complete", + "snmp-server traps cisco-entity-ext", + "snmp-server traps config", + "snmp-server traps diameter peerdown", + "snmp-server traps diameter peerup", + "snmp-server traps diameter protocolerror", + "snmp-server traps diameter permanentfail", + "snmp-server traps diameter transientfail", + "snmp-server traps entity", + "snmp-server traps entity-redundancy all", + "snmp-server traps entity-redundancy status", + "snmp-server traps entity-redundancy switchover", + "snmp-server traps entity-state operstatus", + "snmp-server traps entity-state switchover", + "snmp-server traps flash removal", + "snmp-server traps flash insertion", + "snmp-server traps hsrp", + "snmp-server traps ipsla", + "snmp-server traps ipsec tunnel start", + "snmp-server traps ipsec tunnel stop", + "snmp-server traps isis adjacency-change area-mismatch attempt-to-exceed-max-sequence " + "authentication-failure authentication-type-failure corrupted-lsp-detected database-overload " + "id-len-mismatch lsp-error-detected lsp-too-large-to-propagate manual-address-drops" + " max-area-addresses-mismatch orig-lsp-buff-size-mismatch version-skew own-lsp-purge" + " rejected-adjacency protocols-supported-mismatch sequence-number-skip", + "snmp-server traps l2tun sessions", + "snmp-server traps l2tun tunnel-up", + "snmp-server traps l2tun tunnel-down", + "snmp-server traps l2vpn all", + "snmp-server traps l2vpn vc-up", + "snmp-server traps l2vpn vc-down", + "snmp-server traps msdp peer-state-change", + "snmp-server traps ospf retransmit virt-packets", + "snmp-server traps ospf retransmit packets", + "snmp-server traps ospf lsa lsa-originate", + "snmp-server traps ospf lsa lsa-maxage", + "snmp-server traps ospf errors bad-packet", + "snmp-server traps ospf errors authentication-failure", + "snmp-server traps ospf errors config-error", + "snmp-server traps ospf errors virt-bad-packet", + "snmp-server traps ospf errors virt-authentication-failure", + "snmp-server traps ospf errors virt-config-error", + "snmp-server traps ospf state-change if-state-change", + "snmp-server traps ospf state-change neighbor-state-change", + "snmp-server traps ospf state-change virtif-state-change", + "snmp-server traps ospf state-change virtneighbor-state-change", + "snmp-server traps ospfv3 errors bad-packet", + "snmp-server traps ospfv3 errors config-error", + "snmp-server traps ospfv3 errors virt-config-error", + "snmp-server traps ospfv3 state-change neighbor-state-change", + "snmp-server traps ospfv3 state-change virtif-state-change", + "snmp-server traps ospfv3 state-change virtneighbor-state-change", + "snmp-server traps ospfv3 state-change restart-status-change", + "snmp-server traps ospfv3 state-change restart-helper-status-change", + "snmp-server traps ospfv3 state-change restart-virtual-helper-status-change", + "snmp-server traps power", + "snmp-server traps rf", + "snmp-server traps pim neighbor-change", + "snmp-server traps pim invalid-message-received", + "snmp-server traps pim rp-mapping-change", + "snmp-server traps pim interface-state-change", + "snmp-server traps rsvp lost-flow", + "snmp-server traps rsvp new-flow", + "snmp-server traps rsvp all", + "snmp-server traps selective-vrf-download role-change", + "snmp-server traps sensor", + "snmp-server traps vrrp events", + "snmp-server traps syslog", + "snmp-server traps system", + "snmp-server traps subscriber session-agg access-interface", + "snmp-server traps subscriber session-agg node", + "snmp-server traps vpls all", + "snmp-server traps vpls full-clear", + "snmp-server traps vpls full-raise", + "snmp-server traps vpls status", + "snmp-server traps snmp linkup", + "snmp-server traps snmp linkdown", + "snmp-server traps snmp coldstart", + "snmp-server traps snmp warmstart", + "snmp-server traps snmp authentication", + "snmp-server community test2 RO SDROwner IPv4 test IPv6 test1", + "snmp-server community-map cm1 context c1 security-name s1 target-list t1", + "snmp-server correlator ruleset rule1", + "snmp-server correlator rule rule1 timeout 5", + "snmp-server context c1", + "snmp-server context c2", + "snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1", + "snmp-server interface GigabitEthernet0/0/0/2", + "snmp-server mib bulkstat object-list test1", + "snmp-server mib bulkstat schema mib1 object-list test1", + "snmp-server mib bulkstat schema mib1 poll-interval 1", + "snmp-server mib bulkstat transfer-id test2 buffer-size 1024", + "snmp-server mib bulkstat transfer-id test2 enable", + "snmp-server mib bulkstat transfer-id test2 format schemaASCII", + "snmp-server mib bulkstat transfer-id test2 retain 1", + "snmp-server mib bulkstat transfer-id test2 retry 1", + "snmp-server mib bulkstat transfer-id test2 schema test2", + "snmp-server user u1 test2 IPv4 test1 IPv6 test2 v4acl SystemOwner", + "snmp-server target list test2 vrf vrf2", + "snmp-server target list test host 1.1.1.2", + "snmp-server vrf vrf1", + "host 1.1.1.1 traps test1", + ] + result = self.execute_module(changed=True) + print(result["commands"]) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_snmp_server_deleted(self): + self.maxDiff = None + run_cfg = dedent( + """\ + snmp-server vrf vrf1 + host 1.1.1.1 traps test1 + ! + snmp-server drop report acl IPv4 test1 + snmp-server drop unknown-user + snmp-server ipv4 dscp af11 + snmp-server ipv6 precedence routine + snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl + snmp-server community test2 RW SystemOwner IPv4 test IPv6 test1 + snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1 + snmp-server queue-length 2 + snmp-server trap-timeout 3 + snmp-server trap throttle-time 12 + snmp-server traps rf + snmp-server traps bfd + snmp-server traps bgp cbgp2 + snmp-server traps pim neighbor-change + snmp-server traps pim invalid-message-received + snmp-server traps pim rp-mapping-change + snmp-server traps pim interface-state-change + snmp-server traps copy-complete + snmp-server traps hsrp + snmp-server traps ipsla + snmp-server traps msdp peer-state-change + snmp-server traps snmp linkup + snmp-server traps snmp linkdown + snmp-server traps snmp coldstart + snmp-server traps snmp warmstart + snmp-server traps snmp authentication + snmp-server traps vrrp events + snmp-server traps flash removal + snmp-server traps flash insertion + snmp-server traps ipsec tunnel stop + snmp-server traps ipsec tunnel start + snmp-server traps power + snmp-server traps config + snmp-server traps entity + snmp-server traps sensor + snmp-server traps selective-vrf-download role-change + snmp-server traps syslog + snmp-server traps system + snmp-server traps ospf lsa lsa-maxage + snmp-server traps ospf lsa lsa-originate + snmp-server traps ospf errors bad-packet + snmp-server traps ospf errors authentication-failure + snmp-server traps ospf errors config-error + snmp-server traps ospf errors virt-bad-packet + snmp-server traps ospf errors virt-authentication-failure + snmp-server traps ospf errors virt-config-error + snmp-server traps ospf retransmit packets + snmp-server traps ospf retransmit virt-packets + snmp-server traps ospf state-change if-state-change + snmp-server traps ospf state-change neighbor-state-change + snmp-server traps ospf state-change virtif-state-change + snmp-server traps ospf state-change virtneighbor-state-change + snmp-server traps rsvp all + snmp-server traps rsvp new-flow + snmp-server traps rsvp lost-flow + snmp-server traps l2tun sessions + snmp-server traps l2tun tunnel-up + snmp-server traps l2tun tunnel-down + snmp-server traps vpls all + snmp-server traps vpls status + snmp-server traps vpls full-clear + snmp-server traps vpls full-raise + snmp-server traps bulkstat collection + snmp-server traps diameter peerup + snmp-server traps diameter peerdown + snmp-server traps diameter protocolerror + snmp-server traps diameter permanentfail + snmp-server traps diameter transientfail + snmp-server traps l2vpn all + snmp-server traps l2vpn vc-up + snmp-server traps l2vpn vc-down + snmp-server traps bridgemib + snmp-server traps ospfv3 errors bad-packet + snmp-server traps ospfv3 errors config-error + snmp-server traps ospfv3 errors virt-config-error + snmp-server traps ospfv3 state-change neighbor-state-change + snmp-server traps ospfv3 state-change virtif-state-change + snmp-server traps ospfv3 state-change virtneighbor-state-change + snmp-server traps ospfv3 state-change restart-status-change + snmp-server traps ospfv3 state-change restart-helper-status-change + snmp-server traps ospfv3 state-change restart-virtual-helper-status-change + snmp-server traps subscriber session-agg node + snmp-server traps subscriber session-agg access-interface + snmp-server traps addrpool low + snmp-server traps addrpool high + snmp-server traps cisco-entity-ext + snmp-server traps entity-state operstatus + snmp-server traps entity-state switchover + snmp-server traps entity-redundancy all + snmp-server traps entity-redundancy status + snmp-server traps entity-redundancy switchover + snmp-server chassis-id test2 + snmp-server contact t1 + snmp-server location test1 + snmp-server target list test host 1.1.1.2 + snmp-server target list test2 vrf vrf2 + snmp-server context c1 + snmp-server context c2 + snmp-server logging threshold oid-processing 1 + snmp-server logging threshold pdu-processing 1 + snmp-server mib bulkstat max-procmem-size 101 + snmp-server mib bulkstat object-list test1 + ! + snmp-server timeouts duplicate 0 + snmp-server timeouts inQdrop 0 + snmp-server timeouts subagent 1 + snmp-server timeouts pdu stats 1 + snmp-server timeouts threshold 0 + snmp-server packetsize 490 + snmp-server correlator buffer-size 1024 + snmp-server trap-source GigabitEthernet0/0/0/2 + snmp-server throttle-time 60 + snmp-server community-map cm1 context c1 security-name s1 target-list t1 + snmp-server inform retries 7 + snmp-server overload-control 4 6 + snmp-server interface GigabitEthernet0/0/0/2 + ! + snmp-server ifmib internal cache max-duration 4 + snmp-server mroutemib send-all-vrf + snmp-server notification-log-mib size 5 + snmp-server notification-log-mib GlobalSize 5 + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(state="deleted")) + commands = [ + "no snmp-server chassis-id test2", + "no snmp-server correlator buffer-size 1024", + "no snmp-server contact t1", + "no snmp-server ipv4 dscp af11", + "no snmp-server ipv6 precedence routine", + "no snmp-server location test1", + "no snmp-server logging threshold oid-processing 1", + "no snmp-server logging threshold pdu-processing 1", + "no snmp-server mib bulkstat max-procmem-size 101", + "no snmp-server mroutemib send-all-vrf", + "no snmp-server overload-control 4 6", + "no snmp-server packetsize 490", + "no snmp-server queue-length 2", + "no snmp-server throttle-time 60", + "no snmp-server trap-source GigabitEthernet0/0/0/2", + "no snmp-server trap-timeout 3", + "no snmp-server drop report acl IPv4 test1", + "no snmp-server drop unknown-user", + "no snmp-server ifmib internal cache max-duration 4", + "no snmp-server inform retries 7", + "no snmp-server notification-log-mib size 5", + "no snmp-server notification-log-mib GlobalSize 5", + "no snmp-server trap throttle-time 12", + "no snmp-server timeouts threshold 0", + "no snmp-server timeouts pdu stats 1", + "no snmp-server timeouts subagent 1", + "no snmp-server timeouts inQdrop 0", + "no snmp-server timeouts duplicate 0", + "no snmp-server traps addrpool low", + "no snmp-server traps addrpool high", + "no snmp-server traps bfd", + "no snmp-server traps bgp cbgp2", + "no snmp-server traps bulkstat collection", + "no snmp-server traps bridgemib", + "no snmp-server traps copy-complete", + "no snmp-server traps cisco-entity-ext", + "no snmp-server traps config", + "no snmp-server traps diameter peerdown", + "no snmp-server traps diameter peerup", + "no snmp-server traps diameter protocolerror", + "no snmp-server traps diameter permanentfail", + "no snmp-server traps diameter transientfail", + "no snmp-server traps entity", + "no snmp-server traps entity-redundancy all", + "no snmp-server traps entity-redundancy status", + "no snmp-server traps entity-redundancy switchover", + "no snmp-server traps entity-state operstatus", + "no snmp-server traps entity-state switchover", + "no snmp-server traps flash removal", + "no snmp-server traps flash insertion", + "no snmp-server traps hsrp", + "no snmp-server traps ipsla", + "no snmp-server traps ipsec tunnel start", + "no snmp-server traps ipsec tunnel stop", + "no snmp-server traps l2tun sessions", + "no snmp-server traps l2tun tunnel-up", + "no snmp-server traps l2tun tunnel-down", + "no snmp-server traps l2vpn all", + "no snmp-server traps l2vpn vc-up", + "no snmp-server traps l2vpn vc-down", + "no snmp-server traps msdp peer-state-change", + "no snmp-server traps ospf retransmit virt-packets", + "no snmp-server traps ospf retransmit packets", + "no snmp-server traps ospf lsa lsa-originate", + "no snmp-server traps ospf lsa lsa-maxage", + "no snmp-server traps ospf errors bad-packet", + "no snmp-server traps ospf errors authentication-failure", + "no snmp-server traps ospf errors config-error", + "no snmp-server traps ospf errors virt-bad-packet", + "no snmp-server traps ospf errors virt-authentication-failure", + "no snmp-server traps ospf errors virt-config-error", + "no snmp-server traps ospf state-change if-state-change", + "no snmp-server traps ospf state-change neighbor-state-change", + "no snmp-server traps ospf state-change virtif-state-change", + "no snmp-server traps ospf state-change virtneighbor-state-change", + "no snmp-server traps ospfv3 errors bad-packet", + "no snmp-server traps ospfv3 errors config-error", + "no snmp-server traps ospfv3 errors virt-config-error", + "no snmp-server traps ospfv3 state-change neighbor-state-change", + "no snmp-server traps ospfv3 state-change virtif-state-change", + "no snmp-server traps ospfv3 state-change virtneighbor-state-change", + "no snmp-server traps ospfv3 state-change restart-status-change", + "no snmp-server traps ospfv3 state-change restart-helper-status-change", + "no snmp-server traps ospfv3 state-change restart-virtual-helper-status-change", + "no snmp-server traps power", + "no snmp-server traps rf", + "no snmp-server traps pim neighbor-change", + "no snmp-server traps pim invalid-message-received", + "no snmp-server traps pim rp-mapping-change", + "no snmp-server traps pim interface-state-change", + "no snmp-server traps rsvp lost-flow", + "no snmp-server traps rsvp new-flow", + "no snmp-server traps rsvp all", + "no snmp-server traps selective-vrf-download role-change", + "no snmp-server traps sensor", + "no snmp-server traps vrrp events", + "no snmp-server traps syslog", + "no snmp-server traps system", + "no snmp-server traps subscriber session-agg access-interface", + "no snmp-server traps subscriber session-agg node", + "no snmp-server traps vpls all", + "no snmp-server traps vpls full-clear", + "no snmp-server traps vpls full-raise", + "no snmp-server traps vpls status", + "no snmp-server traps snmp linkup", + "no snmp-server traps snmp linkdown", + "no snmp-server traps snmp coldstart", + "no snmp-server traps snmp warmstart", + "no snmp-server traps snmp authentication", + "no snmp-server community test2 RW SystemOwner IPv4 test IPv6 test1", + "no snmp-server community-map cm1 context c1 security-name s1 target-list t1", + "no snmp-server context c1", + "no snmp-server context c2", + "no snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1", + "no snmp-server interface GigabitEthernet0/0/0/2", + "no snmp-server mib bulkstat object-list test1", + "no snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl", + "no snmp-server target list test host 1.1.1.2", + "no snmp-server target list test2 vrf vrf2", + "no snmp-server vrf vrf1", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_snmp_server_replaced(self): + self.maxDiff = None + run_cfg = dedent( + """\ + snmp-server vrf vrf1 + host 1.1.1.1 traps test1 + ! + snmp-server drop report acl IPv4 test1 + snmp-server drop unknown-user + snmp-server ipv4 dscp af11 + snmp-server ipv6 precedence routine + snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl + snmp-server community test2 RO SDROwner IPv4 test IPv6 test1 + snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1 + snmp-server queue-length 2 + snmp-server trap-timeout 3 + snmp-server trap throttle-time 12 + snmp-server traps rf + snmp-server traps bfd + snmp-server traps bgp cbgp2 + snmp-server traps pim neighbor-change + snmp-server traps pim invalid-message-received + snmp-server traps pim rp-mapping-change + snmp-server traps pim interface-state-change + snmp-server traps copy-complete + snmp-server traps hsrp + snmp-server traps ipsla + snmp-server traps msdp peer-state-change + snmp-server traps snmp linkup + snmp-server traps snmp linkdown + snmp-server traps snmp coldstart + snmp-server traps snmp warmstart + snmp-server traps snmp authentication + snmp-server traps vrrp events + snmp-server traps flash removal + snmp-server traps flash insertion + snmp-server traps ipsec tunnel stop + snmp-server traps ipsec tunnel start + snmp-server traps power + snmp-server traps config + snmp-server traps entity + snmp-server traps sensor + snmp-server traps selective-vrf-download role-change + snmp-server traps syslog + snmp-server traps system + snmp-server traps ospf lsa lsa-maxage + snmp-server traps ospf lsa lsa-originate + snmp-server traps ospf errors bad-packet + snmp-server traps ospf errors authentication-failure + snmp-server traps ospf errors config-error + snmp-server traps ospf errors virt-bad-packet + snmp-server traps ospf errors virt-authentication-failure + snmp-server traps ospf errors virt-config-error + snmp-server traps ospf retransmit packets + snmp-server traps ospf retransmit virt-packets + snmp-server traps ospf state-change if-state-change + snmp-server traps ospf state-change neighbor-state-change + snmp-server traps ospf state-change virtif-state-change + snmp-server traps ospf state-change virtneighbor-state-change + snmp-server traps rsvp all + snmp-server traps rsvp new-flow + snmp-server traps rsvp lost-flow + snmp-server traps l2tun sessions + snmp-server traps l2tun tunnel-up + snmp-server traps l2tun tunnel-down + snmp-server traps vpls all + snmp-server traps vpls status + snmp-server traps vpls full-clear + snmp-server traps vpls full-raise + snmp-server traps bulkstat collection + snmp-server traps diameter peerup + snmp-server traps diameter peerdown + snmp-server traps diameter protocolerror + snmp-server traps diameter permanentfail + snmp-server traps diameter transientfail + snmp-server traps l2vpn all + snmp-server traps l2vpn vc-up + snmp-server traps l2vpn vc-down + snmp-server traps bridgemib + snmp-server traps ospfv3 errors bad-packet + snmp-server traps ospfv3 errors config-error + snmp-server traps ospfv3 errors virt-config-error + snmp-server traps ospfv3 state-change neighbor-state-change + snmp-server traps ospfv3 state-change virtif-state-change + snmp-server traps ospfv3 state-change virtneighbor-state-change + snmp-server traps ospfv3 state-change restart-status-change + snmp-server traps ospfv3 state-change restart-helper-status-change + snmp-server traps ospfv3 state-change restart-virtual-helper-status-change + snmp-server traps subscriber session-agg node + snmp-server traps subscriber session-agg access-interface + snmp-server traps addrpool low + snmp-server traps addrpool high + snmp-server traps cisco-entity-ext + snmp-server traps entity-state operstatus + snmp-server traps entity-state switchover + snmp-server traps entity-redundancy all + snmp-server traps entity-redundancy status + snmp-server traps entity-redundancy switchover + snmp-server chassis-id test2 + snmp-server contact t1 + snmp-server location test1 + snmp-server target list test host 1.1.1.2 + snmp-server target list test2 vrf vrf2 + snmp-server context c1 + snmp-server context c2 + snmp-server logging threshold oid-processing 1 + snmp-server logging threshold pdu-processing 1 + snmp-server mib bulkstat max-procmem-size 101 + snmp-server mib bulkstat object-list test1 + ! + snmp-server mib bulkstat schema mib1 + object-list test1 + poll-interval 1 + ! + snmp-server mib bulkstat transfer-id test2 + retry 1 + buffer-size 1024 + enable + format schemaASCII + retain 1 + schema test2 + ! + snmp-server timeouts duplicate 0 + snmp-server timeouts inQdrop 0 + snmp-server timeouts subagent 1 + snmp-server timeouts pdu stats 1 + snmp-server timeouts threshold 0 + snmp-server packetsize 490 + snmp-server correlator rule rule1 + timeout 5 + ! + snmp-server correlator ruleset rule1 + ! + snmp-server correlator buffer-size 1024 + snmp-server trap-source GigabitEthernet0/0/0/2 + snmp-server throttle-time 60 + snmp-server community-map cm1 context c1 security-name s1 target-list t1 + snmp-server inform retries 7 + snmp-server overload-control 4 6 + snmp-server ifmib internal cache max-duration 4 + snmp-server mroutemib send-all-vrf + snmp-server notification-log-mib size 5 + snmp-server notification-log-mib GlobalSize 5 + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + vrfs=[ + dict( + vrf="vrf2", + hosts=[ + dict( + community="test1", + host="1.1.1.1", + traps=True, + ), + ], + ), + ], + users=[ + dict( + Ipv4_acl="test1", + Ipv6_acl="test2", + group="test2", + user="u1", + v4_acl="v4acl", + ), + ], + timeouts=dict( + duplicate=0, + inQdrop=0, + pdu_stats=1, + subagent=1, + threshold=0, + ), + trap=dict(throttle_time=12), + targets=[ + dict(name="test2", vrf="vrf2"), + dict(host="1.1.1.2", name="test"), + ], + ifmib=dict(internal_cache_max_duration=4), + inform=dict(retries=7), + chassis_id="test2", + packetsize=490, + queue_length=2, + throttle_time=60, + trap_source="GigabitEthernet0/0/0/2", + trap_timeout=3, + context=["c1", "c2"], + correlator=dict( + buffer_size=1024, + rule_sets=[dict(name="rule1")], + rules=[dict(rule_name="rule1", timeout=5)], + ), + communities=[ + dict( + name="test2", + ro=True, + sdrowner=True, + acl_v4="test", + acl_v6="test1", + ), + ], + community_maps=[ + dict( + name="cm1", + context="c1", + target_list="t1", + security_name="s1", + ), + ], + drop=dict(report_IPv4="test1", unknown_user=True), + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + groups=[ + dict( + Ipv4_acl="test", + Ipv6_acl="test1", + context="test3", + group="g2", + read="test1", + version="v1", + write="test2", + ), + ], + location="test", + logging_threshold_oid_processing=2, + logging_threshold_pdu_processing=1, + mib_bulkstat_max_procmem_size=101, + mroutemib_send_all_vrf=True, + mib_object_lists=["test1"], + overload_control=dict( + overload_drop_time=4, + overload_throttle_rate=6, + ), + mib_schema=[ + dict( + name="mib1", + object_list="test1", + poll_interval=1, + ), + ], + notification_log_mib=dict(GlobalSize=5, size=5), + mib_bulkstat_transfer_ids=[ + dict( + buffer_size=1024, + enable=True, + format_schemaASCI=True, + name="test2", + retain=1, + retry=1, + schema="test2", + ), + ], + traps=dict( + diameter=dict( + peerdown=True, + peerup=True, + permanentfail=True, + protocolerror=True, + transientfail=True, + ), + entity=True, + entity_redundancy=dict( + all=True, + status=True, + switchover=True, + ), + entity_state=dict(operstatus=True, switchover=True), + flash=dict(insertion=True, removal=True), + ipsec=dict(start=True, stop=True), + bridgemib=True, + bulkstat_collection=True, + cisco_entity_ext=True, + config=True, + copy_complete=True, + addrpool=dict(high=True, low=True), + bfd=True, + bgp=dict(cbgp2=True), + l2tun=dict( + sessions=True, + tunnel_down=True, + tunnel_up=True, + ), + l2vpn=dict(all=True, vc_down=True, vc_up=True), + msdp_peer_state_change=True, + ospf=dict( + errors=dict( + authentication_failure=True, + bad_packet=True, + config_error=True, + virt_authentication_failure=True, + virt_bad_packet=True, + virt_config_error=True, + ), + lsa=dict(lsa_maxage=True, lsa_originate=True), + retransmit=dict(packets=True, virt_packets=True), + state_change=dict( + if_state_change=True, + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + ), + ), + ospfv3=dict( + errors=dict( + bad_packet=True, + config_error=True, + virt_config_error=True, + ), + ), + pim=dict( + interface_state_change=True, + invalid_message_received=True, + neighbor_change=True, + rp_mapping_change=True, + ), + power=True, + rf=True, + rsvp=dict(all=True, lost_flow=True, new_flow=True), + selective_vrf_download_role_change=True, + sensor=True, + snmp=dict( + authentication=True, + coldstart=True, + linkdown=True, + linkup=True, + warmstart=True, + ), + subscriber=dict( + session_agg_access_interface=True, + session_agg_node=True, + ), + syslog=True, + system=True, + vpls=dict( + all=True, + full_clear=True, + full_raise=True, + status=True, + ), + vrrp_events=True, + ), + ), + state="replaced", + ), + ) + commands = [ + "no snmp-server contact t1", + "no snmp-server traps hsrp", + "no snmp-server traps ipsla", + "no snmp-server traps ospfv3 state-change neighbor-state-change", + "no snmp-server traps ospfv3 state-change virtif-state-change", + "no snmp-server traps ospfv3 state-change virtneighbor-state-change", + "no snmp-server traps ospfv3 state-change restart-status-change", + "no snmp-server traps ospfv3 state-change restart-helper-status-change", + "no snmp-server traps ospfv3 state-change restart-virtual-helper-status-change", + "no snmp-server vrf vrf1", + "snmp-server location test", + "snmp-server logging threshold oid-processing 2", + "snmp-server user u1 test2 IPv4 test1 IPv6 test2 v4acl", + "snmp-server vrf vrf2", + "host 1.1.1.1 traps test1", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_snmp_server_replaced_idempotent(self): + self.maxDiff = None + run_cfg = dedent( + """\ + snmp-server vrf vrf1 + host 1.1.1.1 traps test1 + ! + snmp-server drop report acl IPv4 test1 + snmp-server drop unknown-user + snmp-server ipv4 dscp af11 + snmp-server ipv6 precedence routine + snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl + snmp-server community test2 RW SystemOwner IPv4 test IPv6 test1 + snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1 + snmp-server queue-length 2 + snmp-server trap-timeout 3 + snmp-server trap throttle-time 12 + snmp-server traps rf + snmp-server traps bfd + snmp-server traps bgp cbgp2 + snmp-server traps pim neighbor-change + snmp-server traps pim invalid-message-received + snmp-server traps pim rp-mapping-change + snmp-server traps pim interface-state-change + snmp-server traps copy-complete + snmp-server traps hsrp + snmp-server traps ipsla + snmp-server traps msdp peer-state-change + snmp-server traps snmp linkup + snmp-server traps snmp linkdown + snmp-server traps snmp coldstart + snmp-server traps snmp warmstart + snmp-server traps snmp authentication + snmp-server traps vrrp events + snmp-server traps flash removal + snmp-server traps flash insertion + snmp-server traps ipsec tunnel stop + snmp-server traps ipsec tunnel start + snmp-server traps power + snmp-server traps config + snmp-server traps entity + snmp-server traps sensor + snmp-server traps selective-vrf-download role-change + snmp-server traps syslog + snmp-server traps system + snmp-server traps ospf lsa lsa-maxage + snmp-server traps ospf lsa lsa-originate + snmp-server traps ospf errors bad-packet + snmp-server traps ospf errors authentication-failure + snmp-server traps ospf errors config-error + snmp-server traps ospf errors virt-bad-packet + snmp-server traps ospf errors virt-authentication-failure + snmp-server traps ospf errors virt-config-error + snmp-server traps ospf retransmit packets + snmp-server traps ospf retransmit virt-packets + snmp-server traps ospf state-change if-state-change + snmp-server traps ospf state-change neighbor-state-change + snmp-server traps ospf state-change virtif-state-change + snmp-server traps ospf state-change virtneighbor-state-change + snmp-server traps rsvp all + snmp-server traps rsvp new-flow + snmp-server traps rsvp lost-flow + snmp-server traps l2tun sessions + snmp-server traps l2tun tunnel-up + snmp-server traps l2tun tunnel-down + snmp-server traps vpls all + snmp-server traps vpls status + snmp-server traps vpls full-clear + snmp-server traps vpls full-raise + snmp-server traps bulkstat collection + snmp-server traps diameter peerup + snmp-server traps diameter peerdown + snmp-server traps diameter protocolerror + snmp-server traps diameter permanentfail + snmp-server traps diameter transientfail + snmp-server traps l2vpn all + snmp-server traps l2vpn vc-up + snmp-server traps l2vpn vc-down + snmp-server traps bridgemib + snmp-server traps ospfv3 errors bad-packet + snmp-server traps ospfv3 errors config-error + snmp-server traps ospfv3 errors virt-config-error + snmp-server traps ospfv3 state-change neighbor-state-change + snmp-server traps ospfv3 state-change virtif-state-change + snmp-server traps ospfv3 state-change virtneighbor-state-change + snmp-server traps ospfv3 state-change restart-status-change + snmp-server traps ospfv3 state-change restart-helper-status-change + snmp-server traps ospfv3 state-change restart-virtual-helper-status-change + snmp-server traps subscriber session-agg node + snmp-server traps subscriber session-agg access-interface + snmp-server traps addrpool low + snmp-server traps addrpool high + snmp-server traps cisco-entity-ext + snmp-server traps entity-state operstatus + snmp-server traps entity-state switchover + snmp-server traps entity-redundancy all + snmp-server traps entity-redundancy status + snmp-server traps entity-redundancy switchover + snmp-server chassis-id test2 + snmp-server location test1 + snmp-server target list test host 1.1.1.2 + snmp-server target list test2 vrf vrf2 + snmp-server context c1 + snmp-server context c2 + snmp-server logging threshold oid-processing 1 + snmp-server logging threshold pdu-processing 1 + snmp-server mib bulkstat max-procmem-size 101 + snmp-server mib bulkstat object-list test1 + ! + snmp-server mib bulkstat schema mib1 + object-list test1 + poll-interval 1 + ! + snmp-server mib bulkstat transfer-id test2 + retry 1 + buffer-size 1024 + enable + format schemaASCII + retain 1 + schema test2 + ! + snmp-server timeouts duplicate 0 + snmp-server timeouts inQdrop 0 + snmp-server timeouts subagent 1 + snmp-server timeouts pdu stats 1 + snmp-server timeouts threshold 0 + snmp-server packetsize 490 + snmp-server correlator rule rule1 + timeout 5 + ! + snmp-server correlator ruleset rule1 + ! + snmp-server correlator buffer-size 1024 + snmp-server trap-source GigabitEthernet0/0/0/2 + snmp-server throttle-time 60 + snmp-server community-map cm1 context c1 security-name s1 target-list t1 + snmp-server inform retries 7 + snmp-server overload-control 4 6 + snmp-server ifmib internal cache max-duration 4 + snmp-server mroutemib send-all-vrf + snmp-server notification-log-mib size 5 + snmp-server notification-log-mib GlobalSize 5 + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + vrfs=[ + dict( + vrf="vrf1", + hosts=[ + dict( + community="test1", + host="1.1.1.1", + traps=True, + ), + ], + ), + ], + users=[ + dict( + Ipv4_acl="test1", + Ipv6_acl="test2", + group="test2", + user="u1", + v4_acl="v4acl", + version="v1", + ), + ], + timeouts=dict( + duplicate=0, + inQdrop=0, + pdu_stats=1, + subagent=1, + threshold=0, + ), + trap=dict(throttle_time=12), + targets=[ + dict(name="test2", vrf="vrf2"), + dict(host="1.1.1.2", name="test"), + ], + ifmib=dict(internal_cache_max_duration=4), + inform=dict(retries=7), + chassis_id="test2", + packetsize=490, + queue_length=2, + throttle_time=60, + trap_source="GigabitEthernet0/0/0/2", + trap_timeout=3, + context=["c1", "c2"], + correlator=dict( + buffer_size=1024, + rule_sets=[dict(name="rule1")], + rules=[dict(rule_name="rule1", timeout=5)], + ), + communities=[ + dict( + name="test2", + rw=True, + systemowner=True, + acl_v4="test", + acl_v6="test1", + ), + ], + community_maps=[ + dict( + name="cm1", + context="c1", + target_list="t1", + security_name="s1", + ), + ], + drop=dict(report_IPv4="test1", unknown_user=True), + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + groups=[ + dict( + Ipv4_acl="test", + Ipv6_acl="test1", + context="test3", + group="g2", + read="test1", + version="v1", + write="test2", + ), + ], + location="test1", + logging_threshold_oid_processing=1, + logging_threshold_pdu_processing=1, + mib_bulkstat_max_procmem_size=101, + mroutemib_send_all_vrf=True, + mib_object_lists=["test1"], + overload_control=dict( + overload_drop_time=4, + overload_throttle_rate=6, + ), + mib_schema=[ + dict( + name="mib1", + object_list="test1", + poll_interval=1, + ), + ], + notification_log_mib=dict(GlobalSize=5, size=5), + mib_bulkstat_transfer_ids=[ + dict( + buffer_size=1024, + enable=True, + format_schemaASCI=True, + name="test2", + retain=1, + retry=1, + schema="test2", + ), + ], + traps=dict( + diameter=dict( + peerdown=True, + peerup=True, + permanentfail=True, + protocolerror=True, + transientfail=True, + ), + entity=True, + entity_redundancy=dict( + all=True, + status=True, + switchover=True, + ), + entity_state=dict(operstatus=True, switchover=True), + flash=dict(insertion=True, removal=True), + hsrp=True, + ipsla=True, + ipsec=dict(start=True, stop=True), + bridgemib=True, + bulkstat_collection=True, + cisco_entity_ext=True, + config=True, + copy_complete=True, + addrpool=dict(high=True, low=True), + bfd=True, + bgp=dict(cbgp2=True), + l2tun=dict( + sessions=True, + tunnel_down=True, + tunnel_up=True, + ), + l2vpn=dict(all=True, vc_down=True, vc_up=True), + msdp_peer_state_change=True, + ospf=dict( + errors=dict( + authentication_failure=True, + bad_packet=True, + config_error=True, + virt_authentication_failure=True, + virt_bad_packet=True, + virt_config_error=True, + ), + lsa=dict(lsa_maxage=True, lsa_originate=True), + retransmit=dict(packets=True, virt_packets=True), + state_change=dict( + if_state_change=True, + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + ), + ), + ospfv3=dict( + errors=dict( + bad_packet=True, + config_error=True, + virt_config_error=True, + ), + state_change=dict( + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + restart_helper_status_change=True, + restart_status_change=True, + restart_virtual_helper_status_change=True, + ), + ), + pim=dict( + interface_state_change=True, + invalid_message_received=True, + neighbor_change=True, + rp_mapping_change=True, + ), + power=True, + rf=True, + rsvp=dict(all=True, lost_flow=True, new_flow=True), + selective_vrf_download_role_change=True, + sensor=True, + snmp=dict( + authentication=True, + coldstart=True, + linkdown=True, + linkup=True, + warmstart=True, + ), + subscriber=dict( + session_agg_access_interface=True, + session_agg_node=True, + ), + syslog=True, + system=True, + vpls=dict( + all=True, + full_clear=True, + full_raise=True, + status=True, + ), + vrrp_events=True, + ), + ), + state="replaced", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_snmp_server_overridden(self): + self.maxDiff = None + run_cfg = dedent( + """\ + snmp-server vrf vrf1 + host 1.1.1.1 traps test1 + ! + snmp-server drop report acl IPv4 test1 + snmp-server drop unknown-user + snmp-server ipv4 dscp af11 + snmp-server ipv6 precedence routine + snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl + snmp-server community test2 RO SDROwner IPv4 test IPv6 test1 + snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1 + snmp-server queue-length 2 + snmp-server trap-timeout 3 + snmp-server trap throttle-time 12 + snmp-server traps rf + snmp-server traps bfd + snmp-server traps bgp cbgp2 + snmp-server traps pim neighbor-change + snmp-server traps pim invalid-message-received + snmp-server traps pim rp-mapping-change + snmp-server traps pim interface-state-change + snmp-server traps copy-complete + snmp-server traps hsrp + snmp-server traps ipsla + snmp-server traps msdp peer-state-change + snmp-server traps snmp linkup + snmp-server traps snmp linkdown + snmp-server traps snmp coldstart + snmp-server traps snmp warmstart + snmp-server traps snmp authentication + snmp-server traps vrrp events + snmp-server traps flash removal + snmp-server traps flash insertion + snmp-server traps ipsec tunnel stop + snmp-server traps ipsec tunnel start + snmp-server traps power + snmp-server traps config + snmp-server traps entity + snmp-server traps sensor + snmp-server traps selective-vrf-download role-change + snmp-server traps syslog + snmp-server traps system + snmp-server traps ospf lsa lsa-maxage + snmp-server traps ospf lsa lsa-originate + snmp-server traps ospf errors bad-packet + snmp-server traps ospf errors authentication-failure + snmp-server traps ospf errors config-error + snmp-server traps ospf errors virt-bad-packet + snmp-server traps ospf errors virt-authentication-failure + snmp-server traps ospf errors virt-config-error + snmp-server traps ospf retransmit packets + snmp-server traps ospf retransmit virt-packets + snmp-server traps ospf state-change if-state-change + snmp-server traps ospf state-change neighbor-state-change + snmp-server traps ospf state-change virtif-state-change + snmp-server traps ospf state-change virtneighbor-state-change + snmp-server traps rsvp all + snmp-server traps rsvp new-flow + snmp-server traps rsvp lost-flow + snmp-server traps l2tun sessions + snmp-server traps l2tun tunnel-up + snmp-server traps l2tun tunnel-down + snmp-server traps vpls all + snmp-server traps vpls status + snmp-server traps vpls full-clear + snmp-server traps vpls full-raise + snmp-server traps bulkstat collection + snmp-server traps diameter peerup + snmp-server traps diameter peerdown + snmp-server traps diameter protocolerror + snmp-server traps diameter permanentfail + snmp-server traps diameter transientfail + snmp-server traps l2vpn all + snmp-server traps l2vpn vc-up + snmp-server traps l2vpn vc-down + snmp-server traps bridgemib + snmp-server traps ospfv3 errors bad-packet + snmp-server traps ospfv3 errors config-error + snmp-server traps ospfv3 errors virt-config-error + snmp-server traps ospfv3 state-change neighbor-state-change + snmp-server traps ospfv3 state-change virtif-state-change + snmp-server traps ospfv3 state-change virtneighbor-state-change + snmp-server traps ospfv3 state-change restart-status-change + snmp-server traps ospfv3 state-change restart-helper-status-change + snmp-server traps ospfv3 state-change restart-virtual-helper-status-change + snmp-server traps subscriber session-agg node + snmp-server traps subscriber session-agg access-interface + snmp-server traps addrpool low + snmp-server traps addrpool high + snmp-server traps cisco-entity-ext + snmp-server traps entity-state operstatus + snmp-server traps entity-state switchover + snmp-server traps entity-redundancy all + snmp-server traps entity-redundancy status + snmp-server traps entity-redundancy switchover + snmp-server chassis-id test2 + snmp-server contact t1 + snmp-server location test1 + snmp-server target list test host 1.1.1.2 + snmp-server target list test2 vrf vrf2 + snmp-server context c1 + snmp-server context c2 + snmp-server logging threshold oid-processing 1 + snmp-server logging threshold pdu-processing 1 + snmp-server mib bulkstat max-procmem-size 101 + snmp-server mib bulkstat object-list test1 + ! + snmp-server mib bulkstat schema mib1 + object-list test1 + poll-interval 1 + ! + snmp-server mib bulkstat transfer-id test2 + retry 1 + buffer-size 1024 + enable + format schemaASCII + retain 1 + schema test2 + ! + snmp-server timeouts duplicate 0 + snmp-server timeouts inQdrop 0 + snmp-server timeouts subagent 1 + snmp-server timeouts pdu stats 1 + snmp-server timeouts threshold 0 + snmp-server packetsize 490 + snmp-server correlator rule rule1 + timeout 5 + ! + snmp-server correlator ruleset rule1 + ! + snmp-server correlator buffer-size 1024 + snmp-server trap-source GigabitEthernet0/0/0/2 + snmp-server throttle-time 60 + snmp-server community-map cm1 context c1 security-name s1 target-list t1 + snmp-server inform retries 7 + snmp-server overload-control 4 6 + snmp-server ifmib internal cache max-duration 4 + snmp-server mroutemib send-all-vrf + snmp-server notification-log-mib size 5 + snmp-server notification-log-mib GlobalSize 5 + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + vrfs=[ + dict( + vrf="vrf2", + hosts=[ + dict( + community="test1", + host="1.1.1.1", + traps=True, + ), + ], + ), + ], + users=[ + dict( + Ipv4_acl="test1", + Ipv6_acl="test2", + group="test2", + user="u1", + v4_acl="v4acl", + ), + ], + timeouts=dict( + duplicate=0, + inQdrop=0, + pdu_stats=1, + subagent=1, + threshold=0, + ), + trap=dict(throttle_time=12), + targets=[ + dict(name="test2", vrf="vrf2"), + dict(host="1.1.1.2", name="test"), + ], + ifmib=dict(internal_cache_max_duration=4), + inform=dict(retries=7), + chassis_id="test2", + packetsize=490, + queue_length=2, + throttle_time=60, + trap_source="GigabitEthernet0/0/0/2", + trap_timeout=3, + context=["c1", "c2"], + correlator=dict( + buffer_size=1024, + rule_sets=[dict(name="rule1")], + rules=[dict(rule_name="rule1", timeout=5)], + ), + communities=[ + dict( + name="test2", + ro=True, + sdrowner=True, + acl_v4="test", + acl_v6="test1", + ), + ], + community_maps=[ + dict( + name="cm1", + context="c1", + target_list="t1", + security_name="s1", + ), + ], + drop=dict(report_IPv4="test1", unknown_user=True), + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + groups=[ + dict( + Ipv4_acl="test", + Ipv6_acl="test1", + context="test3", + group="g2", + read="test1", + version="v1", + write="test2", + ), + ], + location="test", + logging_threshold_oid_processing=2, + logging_threshold_pdu_processing=1, + mib_bulkstat_max_procmem_size=101, + mroutemib_send_all_vrf=True, + mib_object_lists=["test1"], + overload_control=dict( + overload_drop_time=4, + overload_throttle_rate=6, + ), + mib_schema=[ + dict( + name="mib1", + object_list="test1", + poll_interval=1, + ), + ], + notification_log_mib=dict(GlobalSize=5, size=5), + mib_bulkstat_transfer_ids=[ + dict( + buffer_size=1024, + enable=True, + format_schemaASCI=True, + name="test2", + retain=1, + retry=1, + schema="test2", + ), + ], + traps=dict( + diameter=dict( + peerdown=True, + peerup=True, + permanentfail=True, + protocolerror=True, + transientfail=True, + ), + entity=True, + entity_redundancy=dict( + all=True, + status=True, + switchover=True, + ), + entity_state=dict(operstatus=True, switchover=True), + flash=dict(insertion=True, removal=True), + ipsec=dict(start=True, stop=True), + bridgemib=True, + bulkstat_collection=True, + cisco_entity_ext=True, + config=True, + copy_complete=True, + addrpool=dict(high=True, low=True), + bfd=True, + bgp=dict(cbgp2=True), + l2tun=dict( + sessions=True, + tunnel_down=True, + tunnel_up=True, + ), + l2vpn=dict(all=True, vc_down=True, vc_up=True), + msdp_peer_state_change=True, + ospf=dict( + errors=dict( + authentication_failure=True, + bad_packet=True, + config_error=True, + virt_authentication_failure=True, + virt_bad_packet=True, + virt_config_error=True, + ), + lsa=dict(lsa_maxage=True, lsa_originate=True), + retransmit=dict(packets=True, virt_packets=True), + state_change=dict( + if_state_change=True, + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + ), + ), + ospfv3=dict( + errors=dict( + bad_packet=True, + config_error=True, + virt_config_error=True, + ), + ), + pim=dict( + interface_state_change=True, + invalid_message_received=True, + neighbor_change=True, + rp_mapping_change=True, + ), + power=True, + rf=True, + rsvp=dict(all=True, lost_flow=True, new_flow=True), + selective_vrf_download_role_change=True, + sensor=True, + snmp=dict( + authentication=True, + coldstart=True, + linkdown=True, + linkup=True, + warmstart=True, + ), + subscriber=dict( + session_agg_access_interface=True, + session_agg_node=True, + ), + syslog=True, + system=True, + vpls=dict( + all=True, + full_clear=True, + full_raise=True, + status=True, + ), + vrrp_events=True, + ), + ), + state="overridden", + ), + ) + commands = [ + "no snmp-server contact t1", + "no snmp-server traps hsrp", + "no snmp-server traps ipsla", + "no snmp-server traps ospfv3 state-change neighbor-state-change", + "no snmp-server traps ospfv3 state-change virtif-state-change", + "no snmp-server traps ospfv3 state-change virtneighbor-state-change", + "no snmp-server traps ospfv3 state-change restart-status-change", + "no snmp-server traps ospfv3 state-change restart-helper-status-change", + "no snmp-server traps ospfv3 state-change restart-virtual-helper-status-change", + "no snmp-server vrf vrf1", + "snmp-server location test", + "snmp-server logging threshold oid-processing 2", + "snmp-server user u1 test2 IPv4 test1 IPv6 test2 v4acl", + "snmp-server vrf vrf2", + "host 1.1.1.1 traps test1", + ] + result = self.execute_module(changed=True) + self.assertEqual(sorted(result["commands"]), sorted(commands)) + + def test_iosxr_snmp_server_overridden_idempotent(self): + self.maxDiff = None + run_cfg = dedent( + """\ + snmp-server vrf vrf1 + host 1.1.1.1 traps test1 + ! + snmp-server drop report acl IPv4 test1 + snmp-server drop unknown-user + snmp-server ipv4 dscp af11 + snmp-server ipv6 precedence routine + snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl + snmp-server community test2 RW SystemOwner IPv4 test IPv6 test1 + snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1 + snmp-server queue-length 2 + snmp-server trap-timeout 3 + snmp-server trap throttle-time 12 + snmp-server traps rf + snmp-server traps bfd + snmp-server traps bgp cbgp2 + snmp-server traps pim neighbor-change + snmp-server traps pim invalid-message-received + snmp-server traps pim rp-mapping-change + snmp-server traps pim interface-state-change + snmp-server traps copy-complete + snmp-server traps hsrp + snmp-server traps ipsla + snmp-server traps msdp peer-state-change + snmp-server traps snmp linkup + snmp-server traps snmp linkdown + snmp-server traps snmp coldstart + snmp-server traps snmp warmstart + snmp-server traps snmp authentication + snmp-server traps vrrp events + snmp-server traps flash removal + snmp-server traps flash insertion + snmp-server traps ipsec tunnel stop + snmp-server traps ipsec tunnel start + snmp-server traps power + snmp-server traps config + snmp-server traps entity + snmp-server traps sensor + snmp-server traps selective-vrf-download role-change + snmp-server traps syslog + snmp-server traps system + snmp-server traps ospf lsa lsa-maxage + snmp-server traps ospf lsa lsa-originate + snmp-server traps ospf errors bad-packet + snmp-server traps ospf errors authentication-failure + snmp-server traps ospf errors config-error + snmp-server traps ospf errors virt-bad-packet + snmp-server traps ospf errors virt-authentication-failure + snmp-server traps ospf errors virt-config-error + snmp-server traps ospf retransmit packets + snmp-server traps ospf retransmit virt-packets + snmp-server traps ospf state-change if-state-change + snmp-server traps ospf state-change neighbor-state-change + snmp-server traps ospf state-change virtif-state-change + snmp-server traps ospf state-change virtneighbor-state-change + snmp-server traps rsvp all + snmp-server traps rsvp new-flow + snmp-server traps rsvp lost-flow + snmp-server traps l2tun sessions + snmp-server traps l2tun tunnel-up + snmp-server traps l2tun tunnel-down + snmp-server traps vpls all + snmp-server traps vpls status + snmp-server traps vpls full-clear + snmp-server traps vpls full-raise + snmp-server traps bulkstat collection + snmp-server traps diameter peerup + snmp-server traps diameter peerdown + snmp-server traps diameter protocolerror + snmp-server traps diameter permanentfail + snmp-server traps diameter transientfail + snmp-server traps l2vpn all + snmp-server traps l2vpn vc-up + snmp-server traps l2vpn vc-down + snmp-server traps bridgemib + snmp-server traps ospfv3 errors bad-packet + snmp-server traps ospfv3 errors config-error + snmp-server traps ospfv3 errors virt-config-error + snmp-server traps ospfv3 state-change neighbor-state-change + snmp-server traps ospfv3 state-change virtif-state-change + snmp-server traps ospfv3 state-change virtneighbor-state-change + snmp-server traps ospfv3 state-change restart-status-change + snmp-server traps ospfv3 state-change restart-helper-status-change + snmp-server traps ospfv3 state-change restart-virtual-helper-status-change + snmp-server traps subscriber session-agg node + snmp-server traps subscriber session-agg access-interface + snmp-server traps addrpool low + snmp-server traps addrpool high + snmp-server traps cisco-entity-ext + snmp-server traps entity-state operstatus + snmp-server traps entity-state switchover + snmp-server traps entity-redundancy all + snmp-server traps entity-redundancy status + snmp-server traps entity-redundancy switchover + snmp-server chassis-id test2 + snmp-server location test1 + snmp-server target list test host 1.1.1.2 + snmp-server target list test2 vrf vrf2 + snmp-server context c1 + snmp-server context c2 + snmp-server logging threshold oid-processing 1 + snmp-server logging threshold pdu-processing 1 + snmp-server mib bulkstat max-procmem-size 101 + snmp-server mib bulkstat object-list test1 + ! + snmp-server mib bulkstat schema mib1 + object-list test1 + poll-interval 1 + ! + snmp-server mib bulkstat transfer-id test2 + retry 1 + buffer-size 1024 + enable + format schemaASCII + retain 1 + schema test2 + ! + snmp-server timeouts duplicate 0 + snmp-server timeouts inQdrop 0 + snmp-server timeouts subagent 1 + snmp-server timeouts pdu stats 1 + snmp-server timeouts threshold 0 + snmp-server packetsize 490 + snmp-server correlator rule rule1 + timeout 5 + ! + snmp-server correlator ruleset rule1 + ! + snmp-server correlator buffer-size 1024 + snmp-server trap-source GigabitEthernet0/0/0/2 + snmp-server throttle-time 60 + snmp-server community-map cm1 context c1 security-name s1 target-list t1 + snmp-server inform retries 7 + snmp-server overload-control 4 6 + snmp-server ifmib internal cache max-duration 4 + snmp-server mroutemib send-all-vrf + snmp-server notification-log-mib size 5 + snmp-server notification-log-mib GlobalSize 5 + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args( + dict( + config=dict( + vrfs=[ + dict( + vrf="vrf1", + hosts=[ + dict( + community="test1", + host="1.1.1.1", + traps=True, + ), + ], + ), + ], + users=[ + dict( + Ipv4_acl="test1", + Ipv6_acl="test2", + group="test2", + user="u1", + v4_acl="v4acl", + version="v1", + ), + ], + timeouts=dict( + duplicate=0, + inQdrop=0, + pdu_stats=1, + subagent=1, + threshold=0, + ), + trap=dict(throttle_time=12), + targets=[ + dict(name="test2", vrf="vrf2"), + dict(host="1.1.1.2", name="test"), + ], + ifmib=dict(internal_cache_max_duration=4), + inform=dict(retries=7), + chassis_id="test2", + packetsize=490, + queue_length=2, + throttle_time=60, + trap_source="GigabitEthernet0/0/0/2", + trap_timeout=3, + context=["c1", "c2"], + correlator=dict( + buffer_size=1024, + rule_sets=[dict(name="rule1")], + rules=[dict(rule_name="rule1", timeout=5)], + ), + communities=[ + dict( + name="test2", + rw=True, + systemowner=True, + acl_v4="test", + acl_v6="test1", + ), + ], + community_maps=[ + dict( + name="cm1", + context="c1", + target_list="t1", + security_name="s1", + ), + ], + drop=dict(report_IPv4="test1", unknown_user=True), + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + groups=[ + dict( + Ipv4_acl="test", + Ipv6_acl="test1", + context="test3", + group="g2", + read="test1", + version="v1", + write="test2", + ), + ], + location="test1", + logging_threshold_oid_processing=1, + logging_threshold_pdu_processing=1, + mib_bulkstat_max_procmem_size=101, + mroutemib_send_all_vrf=True, + mib_object_lists=["test1"], + overload_control=dict( + overload_drop_time=4, + overload_throttle_rate=6, + ), + mib_schema=[ + dict( + name="mib1", + object_list="test1", + poll_interval=1, + ), + ], + notification_log_mib=dict(GlobalSize=5, size=5), + mib_bulkstat_transfer_ids=[ + dict( + buffer_size=1024, + enable=True, + format_schemaASCI=True, + name="test2", + retain=1, + retry=1, + schema="test2", + ), + ], + traps=dict( + diameter=dict( + peerdown=True, + peerup=True, + permanentfail=True, + protocolerror=True, + transientfail=True, + ), + entity=True, + entity_redundancy=dict( + all=True, + status=True, + switchover=True, + ), + entity_state=dict(operstatus=True, switchover=True), + flash=dict(insertion=True, removal=True), + hsrp=True, + ipsla=True, + ipsec=dict(start=True, stop=True), + bridgemib=True, + bulkstat_collection=True, + cisco_entity_ext=True, + config=True, + copy_complete=True, + addrpool=dict(high=True, low=True), + bfd=True, + bgp=dict(cbgp2=True), + l2tun=dict( + sessions=True, + tunnel_down=True, + tunnel_up=True, + ), + l2vpn=dict(all=True, vc_down=True, vc_up=True), + msdp_peer_state_change=True, + ospf=dict( + errors=dict( + authentication_failure=True, + bad_packet=True, + config_error=True, + virt_authentication_failure=True, + virt_bad_packet=True, + virt_config_error=True, + ), + lsa=dict(lsa_maxage=True, lsa_originate=True), + retransmit=dict(packets=True, virt_packets=True), + state_change=dict( + if_state_change=True, + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + ), + ), + ospfv3=dict( + errors=dict( + bad_packet=True, + config_error=True, + virt_config_error=True, + ), + state_change=dict( + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + restart_helper_status_change=True, + restart_status_change=True, + restart_virtual_helper_status_change=True, + ), + ), + pim=dict( + interface_state_change=True, + invalid_message_received=True, + neighbor_change=True, + rp_mapping_change=True, + ), + power=True, + rf=True, + rsvp=dict(all=True, lost_flow=True, new_flow=True), + selective_vrf_download_role_change=True, + sensor=True, + snmp=dict( + authentication=True, + coldstart=True, + linkdown=True, + linkup=True, + warmstart=True, + ), + subscriber=dict( + session_agg_access_interface=True, + session_agg_node=True, + ), + syslog=True, + system=True, + vpls=dict( + all=True, + full_clear=True, + full_raise=True, + status=True, + ), + vrrp_events=True, + ), + ), + state="overridden", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_snmp_server_rendered(self): + self.maxDiff = None + set_module_args( + dict( + config=dict( + vrfs=[ + dict( + vrf="vrf1", + hosts=[ + dict( + community="test1", + host="1.1.1.1", + traps=True, + ), + ], + ), + ], + users=[ + dict( + Ipv4_acl="test1", + Ipv6_acl="test2", + group="test2", + user="u1", + v4_acl="v4acl", + ), + ], + timeouts=dict( + duplicate=0, + inQdrop=0, + pdu_stats=1, + subagent=1, + threshold=0, + ), + trap=dict(throttle_time=12), + targets=[ + dict(name="test2", vrf="vrf2"), + dict(host="1.1.1.2", name="test"), + ], + ifmib=dict(internal_cache_max_duration=4), + inform=dict(retries=7), + chassis_id="test2", + packetsize=490, + queue_length=2, + throttle_time=60, + trap_source="GigabitEthernet0/0/0/2", + trap_timeout=3, + context=["c1", "c2"], + correlator=dict( + buffer_size=1024, + rule_sets=[dict(name="rule1")], + rules=[dict(rule_name="rule1", timeout=5)], + ), + communities=[ + dict( + name="test2", + ro=True, + sdrowner=True, + acl_v4="test", + acl_v6="test1", + ), + ], + community_maps=[ + dict( + name="cm1", + context="c1", + target_list="t1", + security_name="s1", + ), + ], + drop=dict(report_IPv4="test1", unknown_user=True), + ipv6=dict(precedence="routine"), + ipv4=dict(dscp="af11"), + groups=[ + dict( + Ipv4_acl="test", + Ipv6_acl="test1", + context="test3", + group="g2", + read="test1", + version="v1", + write="test2", + ), + ], + interfaces=[dict(name=" GigabitEthernet0/0/0/2")], + location="test1", + logging_threshold_oid_processing=1, + logging_threshold_pdu_processing=1, + mib_bulkstat_max_procmem_size=101, + mroutemib_send_all_vrf=True, + mib_object_lists=["test1"], + overload_control=dict( + overload_drop_time=4, + overload_throttle_rate=6, + ), + mib_schema=[ + dict( + name="mib1", + object_list="test1", + poll_interval=1, + ), + ], + notification_log_mib=dict(GlobalSize=5, size=5), + mib_bulkstat_transfer_ids=[ + dict( + buffer_size=1024, + enable=True, + format_schemaASCI=True, + name="test2", + retain=1, + retry=1, + schema="test2", + ), + ], + traps=dict( + diameter=dict( + peerdown=True, + peerup=True, + permanentfail=True, + protocolerror=True, + transientfail=True, + ), + entity=True, + entity_redundancy=dict( + all=True, + status=True, + switchover=True, + ), + entity_state=dict(operstatus=True, switchover=True), + flash=dict(insertion=True, removal=True), + hsrp=True, + ipsla=True, + ipsec=dict(start=True, stop=True), + bridgemib=True, + bulkstat_collection=True, + cisco_entity_ext=True, + config=True, + copy_complete=True, + addrpool=dict(high=True, low=True), + bfd=True, + bgp=dict(cbgp2=True), + l2tun=dict( + sessions=True, + tunnel_down=True, + tunnel_up=True, + ), + l2vpn=dict(all=True, vc_down=True, vc_up=True), + msdp_peer_state_change=True, + ospf=dict( + errors=dict( + authentication_failure=True, + bad_packet=True, + config_error=True, + virt_authentication_failure=True, + virt_bad_packet=True, + virt_config_error=True, + ), + lsa=dict(lsa_maxage=True, lsa_originate=True), + retransmit=dict(packets=True, virt_packets=True), + state_change=dict( + if_state_change=True, + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + ), + ), + ospfv3=dict( + errors=dict( + bad_packet=True, + config_error=True, + virt_config_error=True, + ), + state_change=dict( + neighbor_state_change=True, + virtif_state_change=True, + virtneighbor_state_change=True, + restart_helper_status_change=True, + restart_status_change=True, + restart_virtual_helper_status_change=True, + ), + ), + pim=dict( + interface_state_change=True, + invalid_message_received=True, + neighbor_change=True, + rp_mapping_change=True, + ), + power=True, + rf=True, + rsvp=dict(all=True, lost_flow=True, new_flow=True), + selective_vrf_download_role_change=True, + sensor=True, + snmp=dict( + authentication=True, + coldstart=True, + linkdown=True, + linkup=True, + warmstart=True, + ), + subscriber=dict( + session_agg_access_interface=True, + session_agg_node=True, + ), + syslog=True, + system=True, + vpls=dict( + all=True, + full_clear=True, + full_raise=True, + status=True, + ), + vrrp_events=True, + ), + ), + state="rendered", + ), + ) + commands = [ + "snmp-server chassis-id test2", + "snmp-server correlator buffer-size 1024", + "snmp-server ipv4 dscp af11", + "snmp-server ipv6 precedence routine", + "snmp-server location test1", + "snmp-server logging threshold oid-processing 1", + "snmp-server logging threshold pdu-processing 1", + "snmp-server mib bulkstat max-procmem-size 101", + "snmp-server mroutemib send-all-vrf", + "snmp-server overload-control 4 6", + "snmp-server packetsize 490", + "snmp-server queue-length 2", + "snmp-server throttle-time 60", + "snmp-server trap-source GigabitEthernet0/0/0/2", + "snmp-server trap-timeout 3", + "snmp-server drop report acl IPv4 test1", + "snmp-server drop unknown-user", + "snmp-server ifmib internal cache max-duration 4", + "snmp-server inform retries 7", + "snmp-server notification-log-mib size 5", + "snmp-server notification-log-mib GlobalSize 5", + "snmp-server trap throttle-time 12", + "snmp-server timeouts threshold 0", + "snmp-server timeouts pdu stats 1", + "snmp-server timeouts subagent 1", + "snmp-server timeouts inQdrop 0", + "snmp-server timeouts duplicate 0", + "snmp-server traps addrpool low", + "snmp-server traps addrpool high", + "snmp-server traps bfd", + "snmp-server traps bgp cbgp2", + "snmp-server traps bulkstat collection", + "snmp-server traps bridgemib", + "snmp-server traps copy-complete", + "snmp-server traps cisco-entity-ext", + "snmp-server traps config", + "snmp-server traps diameter peerdown", + "snmp-server traps diameter peerup", + "snmp-server traps diameter protocolerror", + "snmp-server traps diameter permanentfail", + "snmp-server traps diameter transientfail", + "snmp-server traps entity", + "snmp-server traps entity-redundancy all", + "snmp-server traps entity-redundancy status", + "snmp-server traps entity-redundancy switchover", + "snmp-server traps entity-state operstatus", + "snmp-server traps entity-state switchover", + "snmp-server traps flash removal", + "snmp-server traps flash insertion", + "snmp-server traps hsrp", + "snmp-server traps ipsla", + "snmp-server traps ipsec tunnel start", + "snmp-server traps ipsec tunnel stop", + "snmp-server traps l2tun sessions", + "snmp-server traps l2tun tunnel-up", + "snmp-server traps l2tun tunnel-down", + "snmp-server traps l2vpn all", + "snmp-server traps l2vpn vc-up", + "snmp-server traps l2vpn vc-down", + "snmp-server traps msdp peer-state-change", + "snmp-server traps ospf retransmit virt-packets", + "snmp-server traps ospf retransmit packets", + "snmp-server traps ospf lsa lsa-originate", + "snmp-server traps ospf lsa lsa-maxage", + "snmp-server traps ospf errors bad-packet", + "snmp-server traps ospf errors authentication-failure", + "snmp-server traps ospf errors config-error", + "snmp-server traps ospf errors virt-bad-packet", + "snmp-server traps ospf errors virt-authentication-failure", + "snmp-server traps ospf errors virt-config-error", + "snmp-server traps ospf state-change if-state-change", + "snmp-server traps ospf state-change neighbor-state-change", + "snmp-server traps ospf state-change virtif-state-change", + "snmp-server traps ospf state-change virtneighbor-state-change", + "snmp-server traps ospfv3 errors bad-packet", + "snmp-server traps ospfv3 errors config-error", + "snmp-server traps ospfv3 errors virt-config-error", + "snmp-server traps ospfv3 state-change neighbor-state-change", + "snmp-server traps ospfv3 state-change virtif-state-change", + "snmp-server traps ospfv3 state-change virtneighbor-state-change", + "snmp-server traps ospfv3 state-change restart-status-change", + "snmp-server traps ospfv3 state-change restart-helper-status-change", + "snmp-server traps ospfv3 state-change restart-virtual-helper-status-change", + "snmp-server traps power", + "snmp-server traps rf", + "snmp-server traps pim neighbor-change", + "snmp-server traps pim invalid-message-received", + "snmp-server traps pim rp-mapping-change", + "snmp-server traps pim interface-state-change", + "snmp-server traps rsvp lost-flow", + "snmp-server traps rsvp new-flow", + "snmp-server traps rsvp all", + "snmp-server traps selective-vrf-download role-change", + "snmp-server traps sensor", + "snmp-server traps vrrp events", + "snmp-server traps syslog", + "snmp-server traps system", + "snmp-server traps subscriber session-agg access-interface", + "snmp-server traps subscriber session-agg node", + "snmp-server traps vpls all", + "snmp-server traps vpls full-clear", + "snmp-server traps vpls full-raise", + "snmp-server traps vpls status", + "snmp-server traps snmp linkup", + "snmp-server traps snmp linkdown", + "snmp-server traps snmp coldstart", + "snmp-server traps snmp warmstart", + "snmp-server traps snmp authentication", + "snmp-server community test2 RO SDROwner IPv4 test IPv6 test1", + "snmp-server community-map cm1 context c1 security-name s1 target-list t1", + "snmp-server correlator ruleset rule1", + "snmp-server correlator rule rule1 timeout 5", + "snmp-server context c1", + "snmp-server context c2", + "snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1", + "snmp-server interface GigabitEthernet0/0/0/2", + "snmp-server mib bulkstat object-list test1", + "snmp-server mib bulkstat schema mib1 object-list test1", + "snmp-server mib bulkstat schema mib1 poll-interval 1", + "snmp-server mib bulkstat transfer-id test2 buffer-size 1024", + "snmp-server mib bulkstat transfer-id test2 enable", + "snmp-server mib bulkstat transfer-id test2 format schemaASCII", + "snmp-server mib bulkstat transfer-id test2 retain 1", + "snmp-server mib bulkstat transfer-id test2 retry 1", + "snmp-server mib bulkstat transfer-id test2 schema test2", + "snmp-server user u1 test2 IPv4 test1 IPv6 test2 v4acl", + "snmp-server target list test2 vrf vrf2", + "snmp-server target list test host 1.1.1.2", + "snmp-server vrf vrf1", + "host 1.1.1.1 traps test1", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands)) + + def test_iosxr_snmp_server_gathered(self): + self.maxDiff = None + run_cfg = dedent( + """\ + snmp-server vrf vrf1 + host 1.1.1.1 traps test1 + ! + snmp-server drop report acl IPv4 test1 + snmp-server drop unknown-user + snmp-server ipv4 dscp af11 + snmp-server ipv6 precedence routine + snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl + snmp-server community test2 RO SDROwner IPv4 test IPv6 test1 + snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1 + snmp-server queue-length 2 + snmp-server trap-timeout 3 + snmp-server trap throttle-time 12 + snmp-server traps rf + snmp-server traps bfd + snmp-server traps bgp cbgp2 + snmp-server traps pim neighbor-change + snmp-server traps pim invalid-message-received + snmp-server traps pim rp-mapping-change + snmp-server traps pim interface-state-change + snmp-server traps copy-complete + snmp-server traps hsrp + snmp-server traps ipsla + snmp-server traps msdp peer-state-change + snmp-server traps snmp linkup + snmp-server traps snmp linkdown + snmp-server traps snmp coldstart + snmp-server traps snmp warmstart + snmp-server traps snmp authentication + snmp-server traps vrrp events + snmp-server traps flash removal + snmp-server traps flash insertion + snmp-server traps ipsec tunnel stop + snmp-server traps ipsec tunnel start + snmp-server traps power + snmp-server traps config + snmp-server traps entity + snmp-server traps sensor + snmp-server traps selective-vrf-download role-change + snmp-server traps syslog + snmp-server traps system + snmp-server traps ospf lsa lsa-maxage + snmp-server traps ospf lsa lsa-originate + snmp-server traps ospf errors bad-packet + snmp-server traps ospf errors authentication-failure + snmp-server traps ospf errors config-error + snmp-server traps ospf errors virt-bad-packet + snmp-server traps ospf errors virt-authentication-failure + snmp-server traps ospf errors virt-config-error + snmp-server traps ospf retransmit packets + snmp-server traps ospf retransmit virt-packets + snmp-server traps ospf state-change if-state-change + snmp-server traps ospf state-change neighbor-state-change + snmp-server traps ospf state-change virtif-state-change + snmp-server traps ospf state-change virtneighbor-state-change + snmp-server traps rsvp all + snmp-server traps rsvp new-flow + snmp-server traps rsvp lost-flow + snmp-server traps l2tun sessions + snmp-server traps l2tun tunnel-up + snmp-server traps l2tun tunnel-down + snmp-server traps vpls all + snmp-server traps vpls status + snmp-server traps vpls full-clear + snmp-server traps vpls full-raise + snmp-server traps bulkstat collection + snmp-server traps diameter peerup + snmp-server traps diameter peerdown + snmp-server traps diameter protocolerror + snmp-server traps diameter permanentfail + snmp-server traps diameter transientfail + snmp-server traps l2vpn all + snmp-server traps l2vpn vc-up + snmp-server traps l2vpn vc-down + snmp-server traps bridgemib + snmp-server traps ospfv3 errors bad-packet + snmp-server traps ospfv3 errors config-error + snmp-server traps ospfv3 errors virt-config-error + snmp-server traps ospfv3 state-change neighbor-state-change + snmp-server traps ospfv3 state-change virtif-state-change + snmp-server traps ospfv3 state-change virtneighbor-state-change + snmp-server traps ospfv3 state-change restart-status-change + snmp-server traps ospfv3 state-change restart-helper-status-change + snmp-server traps ospfv3 state-change restart-virtual-helper-status-change + snmp-server traps subscriber session-agg node + snmp-server traps subscriber session-agg access-interface + snmp-server traps addrpool low + snmp-server traps addrpool high + snmp-server traps cisco-entity-ext + snmp-server traps entity-state operstatus + snmp-server traps entity-state switchover + snmp-server traps entity-redundancy all + snmp-server traps entity-redundancy status + snmp-server traps entity-redundancy switchover + snmp-server chassis-id test2 + snmp-server contact t1 + snmp-server location test1 + snmp-server target list test host 1.1.1.2 + snmp-server target list test2 vrf vrf2 + snmp-server context c1 + snmp-server logging threshold oid-processing 1 + snmp-server logging threshold pdu-processing 1 + snmp-server mib bulkstat max-procmem-size 101 + snmp-server mib bulkstat object-list test1 + ! + snmp-server mib bulkstat schema mib1 + object-list test1 + poll-interval 1 + ! + snmp-server mib bulkstat transfer-id test2 + retry 1 + buffer-size 1024 + enable + format schemaASCII + retain 1 + schema test2 + ! + snmp-server timeouts duplicate 0 + snmp-server timeouts inQdrop 0 + snmp-server timeouts subagent 1 + snmp-server timeouts pdu stats 1 + snmp-server timeouts threshold 0 + snmp-server packetsize 490 + snmp-server correlator rule rule1 + timeout 5 + ! + snmp-server correlator ruleset rule1 + ! + snmp-server correlator buffer-size 1024 + snmp-server trap-source GigabitEthernet0/0/0/2 + snmp-server throttle-time 60 + snmp-server community-map cm1 context c1 security-name s1 target-list t1 + snmp-server inform retries 7 + snmp-server overload-control 4 6 + snmp-server ifmib internal cache max-duration 4 + snmp-server mroutemib send-all-vrf + snmp-server notification-log-mib size 5 + snmp-server notification-log-mib GlobalSize 5 + ! + """, + ) + self.get_config.return_value = run_cfg + set_module_args(dict(state="gathered")) + gathered = { + "vrfs": [ + { + "vrf": "vrf1", + "hosts": [ + { + "host": "1.1.1.1", + "traps": True, + "community": "test1", + }, + ], + }, + ], + "drop": {"report_IPv4": "test1", "unknown_user": True}, + "ipv4": {"dscp": "af11"}, + "ipv6": {"precedence": "routine"}, + "users": [ + { + "user": "u1", + "group": "test2", + "acl_v4": "test1", + "acl_v6": "test2", + "v4_acl": "v4acl", + "version": "v1", + }, + ], + "communities": [ + { + "name": "test2", + "ro": True, + "acl_v4": "test", + "acl_v6": "test1", + "sdrowner": True, + }, + ], + "groups": [ + { + "group": "g2", + "acl_v4": "test", + "acl_v6": "test1", + "context": "test3", + "read": "test1", + "write": "test2", + "version": "v1", + }, + ], + "queue_length": 2, + "trap_timeout": 3, + "trap": {"throttle_time": 12}, + "traps": { + "rf": True, + "bfd": True, + "bgp": {"cbgp2": True}, + "pim": { + "neighbor_change": True, + "invalid_message_received": True, + "rp_mapping_change": True, + "interface_state_change": True, + }, + "copy_complete": True, + "hsrp": True, + "ipsla": True, + "msdp_peer_state_change": True, + "snmp": { + "linkup": True, + "linkdown": True, + "coldstart": True, + "warmstart": True, + "authentication": True, + }, + "vrrp_events": True, + "flash": {"removal": True, "insertion": True}, + "ipsec": {"stop": True, "start": True}, + "power": True, + "config": True, + "entity": True, + "sensor": True, + "selective_vrf_download_role_change": True, + "syslog": True, + "system": True, + "ospf": { + "lsa": {"lsa_maxage": True, "lsa_originate": True}, + "errors": { + "bad_packet": True, + "authentication_failure": True, + "config_error": True, + "virt_bad_packet": True, + "virt_authentication_failure": True, + "virt_config_error": True, + }, + "retransmit": {"packets": True, "virt_packets": True}, + "state_change": { + "if_state_change": True, + "neighbor_state_change": True, + "virtif_state_change": True, + "virtneighbor_state_change": True, + }, + }, + "rsvp": {"all": True, "new_flow": True, "lost_flow": True}, + "l2tun": { + "sessions": True, + "tunnel_up": True, + "tunnel_down": True, + }, + "vpls": { + "all": True, + "status": True, + "full_clear": True, + "full_raise": True, + }, + "bulkstat_collection": True, + "diameter": { + "peerup": True, + "peerdown": True, + "protocolerror": True, + "permanentfail": True, + "transientfail": True, + }, + "l2vpn": {"all": True, "vc_up": True, "vc_down": True}, + "bridgemib": True, + "ospfv3": { + "errors": { + "bad_packet": True, + "config_error": True, + "virt_config_error": True, + }, + "state_change": { + "neighbor_state_change": True, + "virtif_state_change": True, + "virtneighbor_state_change": True, + "restart_status_change": True, + "restart_helper_status_change": True, + "restart_virtual_helper_status_change": True, + }, + }, + "subscriber": { + "session_agg_node": True, + "session_agg_access_interface": True, + }, + "addrpool": {"low": True, "high": True}, + "cisco_entity_ext": True, + "entity_state": {"operstatus": True, "switchover": True}, + "entity_redundancy": { + "all": True, + "status": True, + "switchover": True, + }, + }, + "chassis_id": "test2", + "contact": "t1", + "location": "test1", + "targets": [ + {"name": "test", "host": "1.1.1.2"}, + {"name": "test2", "vrf": "vrf2"}, + ], + "context": ["c1"], + "logging_threshold_oid_processing": 1, + "logging_threshold_pdu_processing": 1, + "mib_bulkstat_max_procmem_size": 101, + "mib_object_lists": ["test1"], + "mib_schema": [ + {"name": "mib1", "object_list": "test1", "poll_interval": 1}, + ], + "mib_bulkstat_transfer_ids": [ + { + "name": "test2", + "retry": 1, + "buffer_size": 1024, + "enable": True, + "format_schemaASCI": True, + "retain": 1, + "schema": "test2", + }, + ], + "timeouts": { + "duplicate": 0, + "inQdrop": 0, + "subagent": 1, + "pdu_stats": 1, + "threshold": 0, + }, + "packetsize": 490, + "correlator": { + "rules": [ + {"rule_name": "rule1"}, + {"rule_name": "rule1", "timeout": 5}, + ], + "rule_sets": [{"name": "rule1"}], + "buffer_size": 1024, + }, + "trap_source": "GigabitEthernet0/0/0/2", + "throttle_time": 60, + "community_maps": [ + { + "name": "cm1", + "context": "c1", + "security_name": "s1", + "target_list": "t1", + }, + ], + "inform": {"retries": 7}, + "overload_control": { + "overload_drop_time": 4, + "overload_throttle_rate": 6, + }, + "ifmib": {"internal_cache_max_duration": 4}, + "mroutemib_send_all_vrf": True, + "notification_log_mib": {"size": 5, "GlobalSize": 5}, + } + result = self.execute_module(changed=False) + self.assertEqual(gathered, result["gathered"]) + + def test_iosxr_snmp_server_parsed(self): + self.maxDiff = None + set_module_args( + dict( + running_config="snmp-server vrf test1\n host 1.1.1.1 traps test1\n host 1.1.1.2 traps test1\n " + "context test2\n!\nsnmp-server drop report acl IPv6 test\nsnmp-server drop unknown-user" + "\nsnmp-server host 1.1.1.1 traps test udp-port 1\nsnmp-server host 1.1.1.2 informs " + "version 2c test\nsnmp-server host 1.1.1.3 traps test\nsnmp-server user test1 test2 v1 " + "IPv4 test1 IPv6 test2 SDROwner\nsnmp-server " + "community test RO IPv4 test IPv6 test\nsnmp-" + "server community test1 RO\nsnmp-server group " + "test v1 notify test1\nsnmp-server group test1 " + "v1 read test1 write test2 context test3 IPv4 test" + " IPv6 test1\nsnmp-server group test2 v1 " + "notify test read test1\nsnmp-server group test4 " + "v1 notify t1 context test\nsnmp-server queue-length " + "1\nsnmp-server trap-timeout 1\nsnmp-server trap " + "throttle-time 10\nsnmp-server traps rf\nsnmp-server traps " + "bfd\nsnmp-server traps bgp cbgp2\nsnmp-server " + "traps bgp updown\nsnmp-server traps ntp\nsnmp-server " + "traps pim neighbor-change\nsnmp-server traps " + "pim invalid-message-received\nsnmp-server traps pim " + "rp-mapping-change\nsnmp-server traps pim interface-state-change" + "\nsnmp-server traps copy-complete\nsnmp-server " + "traps hsrp\nsnmp-server traps ipsla\nsnmp-server traps msdp " + "peer-state-change\nsnmp-server traps vrrp events\nsnmp-server " + "traps flash removal\nsnmp-server traps flash insertion\nsnmp-server " + "traps ipsec tunnel stop\nsnmp-server traps ipsec tunnel start\nsnmp-server " + "traps power\nsnmp-server traps config\nsnmp-server traps entity\nsnmp-server " + "traps isakmp tunnel stop\nsnmp-server traps isakmp tunnel start\nsnmp-server " + "traps isis database-overload manual-address-drops corrupted-lsp-detected " + "attempt-to-exceed-max-sequence id-len-mismatch max-area-addresses-mismatch" + " own-lsp-purge sequence-number-skip authentication-type-failure " + "authentication-failure version-skew area-mismatch rejected-adjacency " + "lsp-too-large-to-propagate orig-lsp-buff-size-mismatch protocols-supported-mismatch" + " adjacency-change lsp-error-detected\nsnmp-server traps sensor\nsnmp-server" + " traps selective-vrf-download role-change\nsnmp-server traps syslog" + "\nsnmp-server traps system\nsnmp-server traps ospf lsa lsa-maxage" + "\nsnmp-server traps ospf lsa lsa-originate\nsnmp-server traps ospf" + " errors bad-packet\nsnmp-server traps ospf errors authentication-failure" + "\nsnmp-server traps ospf errors config-error\nsnmp-server traps ospf" + " errors virt-bad-packet\nsnmp-server traps ospf errors " + "virt-authentication-failure\nsnmp-server traps ospf errors" + " virt-config-error\nsnmp-server traps ospf retransmit" + " packets\nsnmp-server traps ospf retransmit virt-packets" + "\nsnmp-server traps ospf state-change if-state-change" + "\nsnmp-server traps ospf state-change neighbor-state-change" + "\nsnmp-server traps ospf state-change virtif-state-change\n" + "snmp-server traps ospf state-change virtneighbor-state-change" + "\nsnmp-server traps rsvp all\nsnmp-server traps rsvp new-flow\n" + "snmp-server traps rsvp lost-flow\nsnmp-server traps l2tun sessions\n" + "snmp-server traps l2tun tunnel-up\nsnmp-server traps l2tun tunnel-down" + "\nsnmp-server traps l2tun pseudowire status\nsnmp-server traps vpls all\n" + "snmp-server traps vpls status\nsnmp-server traps vpls full-clear\nsnmp-server " + "traps vpls full-raise\nsnmp-server traps snmp linkup\nsnmp-server traps snmp " + "linkdown\nsnmp-server traps snmp coldstart\nsnmp-server traps snmp warmstart" + "\nsnmp-server traps snmp authentication\nsnmp-server traps bulkstat transfer" + "\nsnmp-server traps bulkstat collection\nsnmp-server traps diameter peerup\ + nsnmp-server traps diameter peerdown\nsnmp-server traps diameter protocolerror" + "\nsnmp-server traps diameter permanentfail\nsnmp-server traps diameter transientfail" + "\nsnmp-server traps l2vpn all\nsnmp-server traps l2vpn cisco\nsnmp-server traps " + "l2vpn vc-up\nsnmp-server traps l2vpn vc-down\nsnmp-server traps bridgemib\nsnmp-" + "server traps ospfv3 errors bad-packet\nsnmp-server traps ospfv3 errors config-error" + "\nsnmp-server traps ospfv3 errors virt-bad-packet\nsnmp-server traps ospfv3 errors " + "virt-config-error\nsnmp-server traps ospfv3 state-change if-state-change\nsnmp-" + "server traps ospfv3 state-change neighbor-state-change\nsnmp-server traps ospfv3 " + "state-change nssa-state-change\nsnmp-server traps ospfv3 state-change " + "virtif-state-change\nsnmp-server traps ospfv3 state-change " + "virtneighbor-state-change\nsnmp-server traps ospfv3 state-change " + "restart-status-change\nsnmp-server traps ospfv3 state-change " + "restart-helper-status-change\nsnmp-server traps ospfv3 state-change " + "restart-virtual-helper-status-change\nsnmp-server traps fru-ctrl" + "\nsnmp-server traps subscriber session-agg node\nsnmp-server traps " + "subscriber session-agg access-interface\nsnmp-server traps addrpool " + "low\nsnmp-server traps addrpool high\nsnmp-server traps cisco-entity-ext" + "\nsnmp-server traps entity-state operstatus\nsnmp-server traps entity-state " + "switchover\nsnmp-server traps entity-redundancy all" + "\nsnmp-server traps entity-redundancy " + "status\nsnmp-server traps entity-redundancy switchover\nsnmp-server chassis-id test2" + "\nsnmp-server contact test\nsnmp-server location test\nsnmp-server target list test1 " + "vrf vrf1\nsnmp-server target list test1 host 1.1.1.1\nsnmp-server context test\n" + "snmp-server context test2\nsnmp-server logging threshold oid-processing 0\n" + "snmp-server logging threshold pdu-processing 0\nsnmp-server mib bulkstat max-" + "procmem-size 100\nsnmp-server mib bulkstat object-list test\n!\nsnmp-server mib " + "bulkstat transfer-id test1\n retry 1\n buffer-size 1024\n enable\n format schemaASCII\n" + " retain 1\n schema test\n!\nsnmp-server timeouts duplicate 0\nsnmp-server timeouts" + " inQdrop 0\nsnmp-server timeouts subagent 1\nsnmp-server timeouts pdu stats" + " 1\nsnmp-server timeouts threshold 0\nsnmp-server packetsize 485\nsnmp-server" + " correlator buffer-size 1024\nsnmp-server trap-source GigabitEthernet0/0/0/1" + "\nsnmp-server throttle-time 50\nsnmp-server community-map test context test " + "security-name test2\nsnmp-server community-map test1 context test security-name " + "test2\nsnmp-server inform pending 1\nsnmp-server inform retries 1\nsnmp-server " + "inform timeout 1\nsnmp-server oid-poll-stats\nsnmp-server overload-control 0 0" + "\nsnmp-server trap authentication vrf disable\nsnmp-server " + "interface GigabitEthernet0/0/0/0\n notification linkupdown disable\n " + "index persistence\n!\nsnmp-server ifmib ifalias long\nsnmp-server " + "ifindex persist\nsnmp-server ifmib internal cache max-duration " + "0\nsnmp-server ifmib ipsubscriber\nsnmp-server ifmib stats cache" + "\nsnmp-server trap link ietf\nsnmp-server location test\nsnmp-server" + " mroutemib send-all-vrf\nsnmp-server notification-log-mib size 1\nsnmp-server " + "notification-log-mib default\nsnmp-server notification-log-mib disable\nsnmp-server" + " notification-log-mib GlobalSize 1", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = { + "vrfs": [ + { + "vrf": "test1", + "context": ["test2"], + "hosts": [ + { + "host": "1.1.1.1", + "traps": True, + "community": "test1", + }, + { + "host": "1.1.1.2", + "traps": True, + "community": "test1", + }, + ], + }, + ], + "drop": {"report_IPv6": "test", "unknown_user": True}, + "hosts": [ + { + "host": "1.1.1.1", + "traps": True, + "community": "test", + "udp_port": 1, + }, + { + "host": "1.1.1.2", + "informs": True, + "community": "test", + "version": "2c", + }, + {"host": "1.1.1.3", "traps": True, "community": "test"}, + ], + "users": [ + { + "user": "test1", + "group": "test2", + "acl_v4": "test1", + "acl_v6": "test2", + "v4_acl": "SDROwner", + "version": "v1", + }, + ], + "communities": [ + { + "name": "test", + "ro": True, + "acl_v4": "test", + "acl_v6": "test", + }, + {"name": "test1", "ro": True}, + ], + "groups": [ + {"group": "test", "notify": "test1", "version": "v1"}, + { + "group": "test1", + "acl_v4": "test", + "acl_v6": "test1", + "context": "test3", + "read": "test1", + "write": "test2", + "version": "v1", + }, + { + "group": "test2", + "notify": "test", + "read": "test1", + "version": "v1", + }, + { + "group": "test4", + "context": "test", + "notify": "t1", + "version": "v1", + }, + ], + "queue_length": 1, + "trap_timeout": 1, + "trap": { + "throttle_time": 10, + "authentication_vrf_disable": True, + "link_ietf": True, + }, + "traps": { + "rf": True, + "bfd": True, + "bgp": {"cbgp2": True}, + "pim": { + "neighbor_change": True, + "invalid_message_received": True, + "rp_mapping_change": True, + "interface_state_change": True, + }, + "copy_complete": True, + "hsrp": True, + "ipsla": True, + "msdp_peer_state_change": True, + "vrrp_events": True, + "flash": {"removal": True, "insertion": True}, + "ipsec": {"stop": True, "start": True}, + "power": True, + "config": True, + "entity": True, + "isakmp": {"stop": True, "start": True}, + "isis": { + "id_len_mismatch": True, + "database_overload": True, + "manual_address_drops": True, + "corrupted_lsp_detected": True, + "attempt_to_exceed_max_sequence": True, + "max_area_addresses_mismatch": True, + "own_lsp_purge": True, + "sequence_number_skip": True, + "authentication_type_failure": True, + "authentication_failure": True, + "version_skew": True, + "area_mismatch": True, + "rejected_adjacency": True, + "lsp_too_large_to_propagate": True, + "orig_lsp_buff_size_mismatch": True, + "protocols_supported_mismatch": True, + "adjacency_change": True, + "lsp_error_detected": True, + }, + "sensor": True, + "selective_vrf_download_role_change": True, + "syslog": True, + "system": True, + "ospf": { + "lsa": {"lsa_maxage": True, "lsa_originate": True}, + "errors": { + "bad_packet": True, + "authentication_failure": True, + "config_error": True, + "virt_bad_packet": True, + "virt_authentication_failure": True, + "virt_config_error": True, + }, + "retransmit": {"packets": True, "virt_packets": True}, + "state_change": { + "if_state_change": True, + "neighbor_state_change": True, + "virtif_state_change": True, + "virtneighbor_state_change": True, + }, + }, + "rsvp": {"all": True, "new_flow": True, "lost_flow": True}, + "l2tun": { + "sessions": True, + "tunnel_up": True, + "tunnel_down": True, + }, + "vpls": { + "all": True, + "status": True, + "full_clear": True, + "full_raise": True, + }, + "snmp": { + "linkup": True, + "linkdown": True, + "coldstart": True, + "warmstart": True, + "authentication": True, + }, + "bulkstat_transfer": True, + "bulkstat_collection": True, + "diameter": { + "protocolerror": True, + "permanentfail": True, + "transientfail": True, + }, + "l2vpn": { + "all": True, + "cisco": True, + "vc_up": True, + "vc_down": True, + }, + "bridgemib": True, + "ospfv3": { + "errors": { + "bad_packet": True, + "config_error": True, + "virt_bad_packet": True, + "virt_config_error": True, + }, + "state_change": { + "if_state_change": True, + "neighbor_state_change": True, + "nssa_state_change": True, + "virtif_state_change": True, + "virtneighbor_state_change": True, + "restart_status_change": True, + "restart_helper_status_change": True, + "restart_virtual_helper_status_change": True, + }, + }, + "fru_ctrl": True, + "subscriber": { + "session_agg_node": True, + "session_agg_access_interface": True, + }, + "addrpool": {"low": True, "high": True}, + "cisco_entity_ext": True, + "entity_state": {"operstatus": True, "switchover": True}, + "entity_redundancy": { + "all": True, + "status": True, + "switchover": True, + }, + }, + "chassis_id": "test2", + "contact": "test", + "location": "test", + "targets": [ + {"name": "test1", "vrf": "vrf1"}, + {"name": "test1", "host": "1.1.1.1"}, + ], + "context": ["test", "test2"], + "logging_threshold_oid_processing": 0, + "logging_threshold_pdu_processing": 0, + "mib_bulkstat_max_procmem_size": 100, + "mib_object_lists": ["test"], + "mib_bulkstat_transfer_ids": [ + { + "name": "test1", + "retry": 1, + "buffer_size": 1024, + "enable": True, + "format_schemaASCI": True, + "retain": 1, + "schema": "test", + }, + ], + "timeouts": { + "duplicate": 0, + "inQdrop": 0, + "subagent": 1, + "pdu_stats": 1, + "threshold": 0, + }, + "packetsize": 485, + "correlator": {"buffer_size": 1024}, + "trap_source": "GigabitEthernet0/0/0/1", + "throttle_time": 50, + "community_maps": [ + {"name": "test", "context": "test", "security_name": "test2"}, + {"name": "test1", "context": "test", "security_name": "test2"}, + ], + "inform": {"pending": 1, "retries": 1, "timeout": 1}, + "oid_poll_stats": True, + "overload_control": { + "overload_drop_time": 0, + "overload_throttle_rate": 0, + }, + "interfaces": [ + { + "name": "GigabitEthernet0/0/0/0", + "notification_linkupdown_disable": True, + }, + ], + "ifmib": { + "ifalias_long": True, + "internal_cache_max_duration": 0, + "ipsubscriber": True, + "stats": True, + }, + "ifindex": True, + "mroutemib_send_all_vrf": True, + "notification_log_mib": { + "size": 1, + "default": True, + "disable": True, + "GlobalSize": 1, + }, + } + self.assertEqual(parsed_list, result["parsed"]) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_static_routes.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_static_routes.py new file mode 100644 index 00000000..ba91d7f3 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_static_routes.py @@ -0,0 +1,380 @@ +# +# (c) 2019, Ansible by Red Hat, inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_static_routes +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrStaticRoutesModule(TestIosxrModule): + module = iosxr_static_routes + + def setUp(self): + super(TestIosxrStaticRoutesModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + + self.mock_execute_show_command = patch( + "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.static_routes.static_routes.Static_routesFacts.get_device_data", + ) + self.execute_show_command = self.mock_execute_show_command.start() + + def tearDown(self): + super(TestIosxrStaticRoutesModule, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + + def load_fixtures(self, commands=None): + def load_from_file(*args, **kwargs): + return load_fixture("iosxr_static_routes_config.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_iosxr_static_routes_merged(self): + set_module_args( + dict( + config=[ + dict( + vrf="dev_site", + address_families=[ + dict( + afi="ipv6", + safi="unicast", + routes=[ + dict( + dest="1200:10::/64", + next_hops=[ + dict( + interface="GigabitEthernet0/0/0/1", + admin_distance=55, + ), + ], + ), + ], + ), + ], + ), + ], + state="merged", + ), + ) + commands = [ + "router static", + "vrf dev_site", + "address-family ipv6 unicast", + "1200:10::/64 GigabitEthernet0/0/0/1 55", + ] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_static_routes_merged_idempotent(self): + set_module_args( + dict( + config=[ + dict( + vrf="DEV_SITE", + address_families=[ + dict( + afi="ipv4", + safi="unicast", + routes=[ + dict( + dest="192.0.2.48/28", + next_hops=[ + dict( + interface="192.0.2.12", + description="DEV", + dest_vrf="test_1", + ), + ], + ), + ], + ), + ], + ), + ], + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_static_routes_default(self): + set_module_args( + dict( + config=[ + dict( + address_families=[ + dict( + afi="ipv4", + safi="unicast", + routes=[ + dict( + dest="192.168.1.0/24", + next_hops=[ + dict( + interface="GigabitEthernet0/0/0/2", + track="ip_sla_2", + vrflabel=1200, + ), + ], + ), + ], + ), + ], + ), + ], + ), + ) + commands = [ + "router static", + "address-family ipv4 unicast", + "192.168.1.0/24 GigabitEthernet0/0/0/2 track ip_sla_2 vrflabel 1200", + ] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_static_routes_default_idempotent(self): + set_module_args( + dict( + config=[ + dict( + address_families=[ + dict( + afi="ipv4", + safi="unicast", + routes=[ + dict( + dest="192.0.2.32/28", + next_hops=[ + dict( + forward_router_address="192.0.2.11", + admin_distance=100, + ), + ], + ), + ], + ), + ], + ), + ], + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_static_routes_replaced(self): + set_module_args( + dict( + config=[ + dict( + address_families=[ + dict( + afi="ipv4", + safi="unicast", + routes=[ + dict( + dest="192.0.2.16/28", + next_hops=[ + dict( + forward_router_address="192.0.2.11", + admin_distance=100, + ), + ], + ), + ], + ), + ], + ), + ], + state="replaced", + ), + ) + commands = [ + "router static", + "address-family ipv4 unicast", + "no 192.0.2.16/28 192.0.2.10 FastEthernet0/0/0/1", + "no 192.0.2.16/28 FastEthernet0/0/0/5", + "192.0.2.16/28 192.0.2.11 100", + ] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_static_routes_replaced_idempotent(self): + set_module_args( + dict( + config=[ + dict( + address_families=[ + dict( + afi="ipv4", + safi="unicast", + routes=[ + dict( + dest="192.0.2.16/28", + next_hops=[ + dict( + interface="FastEthernet0/0/0/5", + track="ip_sla_1", + ), + dict( + interface="FastEthernet0/0/0/1", + forward_router_address="192.0.2.10", + tag=10, + description="LAB", + metric=120, + ), + ], + ), + ], + ), + ], + ), + ], + state="replaced", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_iosxr_static_routes_overridden(self): + set_module_args( + dict( + config=[ + dict( + vrf="DEV_SITE_NEW", + address_families=[ + dict( + afi="ipv4", + safi="unicast", + routes=[ + dict( + dest="192.0.4.16/28", + next_hops=[ + dict( + interface="FastEthernet0/0/0/5", + track="ip_sla_1", + ), + dict( + interface="FastEthernet0/0/0/1", + forward_router_address="192.0.2.10", + tag=10, + description="LAB", + metric=120, + ), + ], + ), + ], + ), + ], + ), + ], + state="overridden", + ), + ) + commands = [ + "router static", + "no address-family ipv4 unicast", + "no address-family ipv6 unicast", + "no vrf DEV_SITE", + "vrf DEV_SITE_NEW", + "address-family ipv4 unicast", + "192.0.4.16/28 192.0.2.10 FastEthernet0/0/0/1 description LAB metric 120 tag 10", + "192.0.4.16/28 FastEthernet0/0/0/5 track ip_sla_1", + ] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_static_routes_deleted_afi(self): + set_module_args( + dict( + config=[ + dict(address_families=[dict(afi="ipv4", safi="unicast")]), + ], + state="deleted", + ), + ) + + commands = ["router static", "no address-family ipv4 unicast"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_static_routes_deleted_vrf(self): + set_module_args(dict(config=[dict(vrf="DEV_SITE")], state="deleted")) + + commands = ["router static", "no vrf DEV_SITE"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_static_routes_deleted_all(self): + set_module_args(dict(state="deleted")) + + commands = ["no router static"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_static_routes_parsed(self): + set_module_args( + dict( + running_config="router static\n address-family ipv4 unicast\n 0.0.0.0/0 172.31.32.1\n " + "10.0.0.0/8 Null0 200\n 11.0.0.0/8 Loopback888\n 203.0.113.0/24 TenGigE0/0/0/0\n !\n!", + state="parsed", + ), + ) + result = self.execute_module(changed=False) + parsed_list = [ + { + "address_families": [ + { + "afi": "ipv4", + "routes": [ + { + "dest": "0.0.0.0/0", + "next_hops": [ + {"forward_router_address": "172.31.32.1"}, + ], + }, + { + "dest": "10.0.0.0/8", + "next_hops": [ + { + "admin_distance": 200, + "interface": "Null0", + }, + ], + }, + { + "dest": "11.0.0.0/8", + "next_hops": [{"interface": "Loopback888"}], + }, + { + "dest": "203.0.113.0/24", + "next_hops": [{"interface": "TenGigE0/0/0/0"}], + }, + ], + "safi": "unicast", + }, + ], + }, + ] + self.assertEqual(parsed_list, result["parsed"]) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_system.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_system.py new file mode 100644 index 00000000..4e09671e --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_system.py @@ -0,0 +1,123 @@ +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_system +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrSystemModule(TestIosxrModule): + + module = iosxr_system + + def setUp(self): + super(TestIosxrSystemModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_system.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_system.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_is_cliconf = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_system.is_cliconf", + ) + self.is_cliconf = self.mock_is_cliconf.start() + + def tearDown(self): + super(TestIosxrSystemModule, self).tearDown() + + self.mock_get_config.stop() + self.mock_load_config.stop() + + def load_fixtures(self, commands=None): + self.get_config.return_value = load_fixture("iosxr_system_config.cfg") + self.load_config.return_value = dict(diff=None, session="session") + self.is_cliconf.return_value = True + + def test_iosxr_system_hostname_changed(self): + set_module_args(dict(hostname="foo")) + commands = ["hostname foo", "no domain lookup disable"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_system_domain_name(self): + set_module_args(dict(domain_name="test.com")) + commands = ["domain name test.com", "no domain lookup disable"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_system_domain_search(self): + set_module_args(dict(domain_search=["ansible.com", "redhat.com"])) + commands = [ + "domain list ansible.com", + "no domain list cisco.com", + "no domain lookup disable", + ] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_system_lookup_source(self): + set_module_args(dict(lookup_source="Ethernet1")) + commands = [ + "domain lookup source-interface Ethernet1", + "no domain lookup disable", + ] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_system_lookup_enabled(self): + set_module_args(dict(lookup_enabled=True)) + commands = ["no domain lookup disable"] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_system_name_servers(self): + name_servers = ["8.8.8.8", "8.8.4.4", "1.1.1.1"] + set_module_args(dict(name_servers=name_servers)) + self.execute_module(changed=True) + + def test_iosxr_system_state_absent(self): + set_module_args(dict(state="absent")) + commands = [ + "no hostname", + "no domain name", + "no domain lookup disable", + "no domain lookup source-interface MgmtEth0/0/CPU0/0", + "no domain list redhat.com", + "no domain list cisco.com", + "no domain name-server 8.8.8.8", + "no domain name-server 8.8.4.4", + ] + self.execute_module(changed=True, commands=commands) + + def test_iosxr_system_no_change(self): + set_module_args( + dict( + hostname="iosxr01", + domain_name="eng.ansible.com", + lookup_enabled=False, + ), + ) + self.execute_module() diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_user.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_user.py new file mode 100644 index 00000000..3bb6f504 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_user.py @@ -0,0 +1,131 @@ +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from ansible_collections.cisco.iosxr.plugins.modules import iosxr_user +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch +from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args + +from .iosxr_module import TestIosxrModule, load_fixture + + +class TestIosxrUserModule(TestIosxrModule): + + module = iosxr_user + + def setUp(self): + super(TestIosxrUserModule, self).setUp() + + self.mock_get_config = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_user.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_user.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_is_cliconf = patch( + "ansible_collections.cisco.iosxr.plugins.modules.iosxr_user.is_cliconf", + ) + self.is_cliconf = self.mock_is_cliconf.start() + + def tearDown(self): + super(TestIosxrUserModule, self).tearDown() + + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_is_cliconf.stop() + + def load_fixtures(self, commands=None, transport="cli"): + self.get_config.return_value = load_fixture("iosxr_user_config.cfg") + self.load_config.return_value = dict(diff=None, session="session") + self.is_cliconf.return_value = True + + def test_iosxr_user_delete(self): + set_module_args(dict(name="ansible", state="absent")) + result = self.execute_module(changed=True) + self.assertEqual(result["commands"], ["no username ansible"]) + + def test_iosxr_user_password(self): + set_module_args(dict(name="ansible", configured_password="test")) + result = self.execute_module(changed=True) + self.assertEqual(result["commands"], ["username ansible secret test"]) + + def test_iosxr_user_purge(self): + set_module_args(dict(purge=True)) + result = self.execute_module(changed=True) + self.assertEqual(result["commands"], ["no username ansible"]) + + def test_iosxr_user_group(self): + set_module_args(dict(name="ansible", group="sysadmin")) + result = self.execute_module(changed=True) + self.assertEqual( + result["commands"], + ["username ansible group sysadmin"], + ) + + def test_iosxr_user_update_password_changed(self): + set_module_args( + dict( + name="test", + configured_password="test", + update_password="on_create", + ), + ) + result = self.execute_module(changed=True) + self.assertEqual( + result["commands"], + ["username test", "username test secret test"], + ) + + def test_iosxr_user_update_password_on_create_ok(self): + set_module_args( + dict( + name="ansible", + configured_password="test", + update_password="on_create", + ), + ) + self.execute_module() + + def test_iosxr_user_update_password_always(self): + set_module_args( + dict( + name="ansible", + configured_password="test", + update_password="always", + ), + ) + result = self.execute_module(changed=True) + self.assertEqual(result["commands"], ["username ansible secret test"]) + + def test_iosxr_user_admin_mode(self): + set_module_args( + dict(name="ansible-2", configured_password="test-2", admin=True), + ) + result = self.execute_module(changed=True) + self.assertEqual( + result["commands"], + ["username ansible-2", "username ansible-2 secret test-2"], + ) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_utils.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_utils.py new file mode 100644 index 00000000..7707adf4 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_utils.py @@ -0,0 +1,28 @@ +# +# (c) 2022, Ansible by Red Hat, inc +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type +from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import Version +from ansible_collections.cisco.iosxr.tests.unit.compat import unittest + + +class TestIosxrUtils(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + def test_VersionOperation(self): + self.assertEqual(Version("3.0.1") < Version("3.1.0"), True) + self.assertEqual(Version("0.0.1") < Version("3.1.0"), True) + self.assertEqual(Version("3.0.1") < Version("3.0.1"), False) + self.assertEqual(Version("3.0.1") <= Version("3.0.1"), True) + self.assertEqual(Version("4.0.1") > Version("3.0.1"), True) + self.assertEqual(Version("4.1.1") > Version("4.1.0"), True) + self.assertEqual(Version("4.1.1") == Version("4.1.1"), True) diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/utils.py b/ansible_collections/cisco/iosxr/tests/unit/modules/utils.py new file mode 100644 index 00000000..d63a8692 --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/modules/utils.py @@ -0,0 +1,55 @@ +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type +import json + +from ansible.module_utils import basic +from ansible.module_utils._text import to_bytes + +from ansible_collections.cisco.iosxr.tests.unit.compat import unittest +from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch + + +def set_module_args(args): + if "_ansible_remote_tmp" not in args: + args["_ansible_remote_tmp"] = "/tmp" + if "_ansible_keep_remote_files" not in args: + args["_ansible_keep_remote_files"] = False + + args = json.dumps({"ANSIBLE_MODULE_ARGS": args}) + basic._ANSIBLE_ARGS = to_bytes(args) + + +class AnsibleExitJson(Exception): + pass + + +class AnsibleFailJson(Exception): + pass + + +def exit_json(*args, **kwargs): + if "changed" not in kwargs: + kwargs["changed"] = False + raise AnsibleExitJson(kwargs) + + +def fail_json(*args, **kwargs): + kwargs["failed"] = True + raise AnsibleFailJson(kwargs) + + +class ModuleTestCase(unittest.TestCase): + def setUp(self): + self.mock_module = patch.multiple( + basic.AnsibleModule, + exit_json=exit_json, + fail_json=fail_json, + ) + self.mock_module.start() + self.mock_sleep = patch("time.sleep") + self.mock_sleep.start() + set_module_args({}) + self.addCleanup(self.mock_module.stop) + self.addCleanup(self.mock_sleep.stop) diff --git a/ansible_collections/cisco/iosxr/tests/unit/requirements.txt b/ansible_collections/cisco/iosxr/tests/unit/requirements.txt new file mode 100644 index 00000000..a9772bea --- /dev/null +++ b/ansible_collections/cisco/iosxr/tests/unit/requirements.txt @@ -0,0 +1,42 @@ +boto3 +placebo +pycrypto +passlib +pypsrp +python-memcached +pytz +pyvmomi +redis +requests +setuptools > 0.6 # pytest-xdist installed via requirements does not work with very old setuptools (sanity_ok) +unittest2 ; python_version < '2.7' +importlib ; python_version < '2.7' +netaddr +ipaddress +netapp-lib +solidfire-sdk-python + +# requirements for F5 specific modules +f5-sdk ; python_version >= '2.7' +f5-icontrol-rest ; python_version >= '2.7' +deepdiff + +# requirement for Fortinet specific modules +pyFMG + +# requirement for aci_rest module +xmljson + +# requirement for winrm connection plugin tests +pexpect + +# requirement for the linode module +linode-python # APIv3 +linode_api4 ; python_version > '2.6' # APIv4 + +# requirement for the gitlab module +python-gitlab +httmock + +# requirment for kubevirt modules +openshift ; python_version >= '2.7' |