From 4f83f5cf80ca92bf91792a0cd4621744b4f1c37e Mon Sep 17 00:00:00 2001
From: GomathiselviS <gomathiselvi@gmail.com>
Date: Fri, 26 Mar 2021 20:48:39 -0400
Subject: Add vyos_bgp_address_family resource module. (#132)

Add vyos_bgp_address_family resource module.

Reviewed-by: https://github.com/apps/ansible-zuul
---
 .../vyos_bgp_address_family/defaults/main.yaml     |   3 +
 .../targets/vyos_bgp_address_family/meta/main.yaml |   3 +
 .../targets/vyos_bgp_address_family/tasks/cli.yaml |  19 +
 .../vyos_bgp_address_family/tasks/main.yaml        |   4 +
 .../tests/cli/_parsed_config.cfg                   |   9 +
 .../tests/cli/_populate.yaml                       |  17 +
 .../tests/cli/_preconfig.yaml                      |  11 +
 .../tests/cli/_remove_config.yaml                  |  12 +
 .../vyos_bgp_address_family/tests/cli/deleted.yaml |  49 ++
 .../tests/cli/empty_config.yaml                    |  60 ++
 .../tests/cli/gathered.yaml                        |  24 +
 .../vyos_bgp_address_family/tests/cli/merged.yaml  |  70 +++
 .../tests/cli/overridden.yaml                      |  58 ++
 .../vyos_bgp_address_family/tests/cli/parsed.yaml  |  16 +
 .../tests/cli/rendered.yaml                        |  44 ++
 .../tests/cli/replaced.yaml                        |  58 ++
 .../vyos_bgp_address_family/tests/cli/rtt.yaml     |  90 +++
 .../targets/vyos_bgp_address_family/vars/main.yaml |  99 +++
 .../fixtures/vyos_bgp_address_family_config.cfg    |   7 +
 .../network/vyos/test_vyos_bgp_address_family.py   | 684 +++++++++++++++++++++
 20 files changed, 1337 insertions(+)
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/defaults/main.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/meta/main.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tasks/cli.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tasks/main.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/_parsed_config.cfg
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/_populate.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/_preconfig.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/_remove_config.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/deleted.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/empty_config.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/gathered.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/merged.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/overridden.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/parsed.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/rendered.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/replaced.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/tests/cli/rtt.yaml
 create mode 100644 tests/integration/targets/vyos_bgp_address_family/vars/main.yaml
 create mode 100644 tests/unit/modules/network/vyos/fixtures/vyos_bgp_address_family_config.cfg
 create mode 100644 tests/unit/modules/network/vyos/test_vyos_bgp_address_family.py

(limited to 'tests')

diff --git a/tests/integration/targets/vyos_bgp_address_family/defaults/main.yaml b/tests/integration/targets/vyos_bgp_address_family/defaults/main.yaml
new file mode 100644
index 00000000..852a6bee
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/defaults/main.yaml
@@ -0,0 +1,3 @@
+---
+testcase: '[^_].*'
+test_items: []
diff --git a/tests/integration/targets/vyos_bgp_address_family/meta/main.yaml b/tests/integration/targets/vyos_bgp_address_family/meta/main.yaml
new file mode 100644
index 00000000..7413320e
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/meta/main.yaml
@@ -0,0 +1,3 @@
+---
+dependencies:
+  - prepare_vyos_tests
diff --git a/tests/integration/targets/vyos_bgp_address_family/tasks/cli.yaml b/tests/integration/targets/vyos_bgp_address_family/tasks/cli.yaml
new file mode 100644
index 00000000..93eb2fe4
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tasks/cli.yaml
@@ -0,0 +1,19 @@
+---
+- name: Collect all cli test cases
+  find:
+    paths: '{{ role_path }}/tests/cli'
+    patterns: '{{ testcase }}.yaml'
+    use_regex: true
+  register: test_cases
+  delegate_to: localhost
+
+- name: Set test_items
+  set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
+
+- name: Run test case (connection=ansible.netcommon.network_cli)
+  include: '{{ 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/tests/integration/targets/vyos_bgp_address_family/tasks/main.yaml b/tests/integration/targets/vyos_bgp_address_family/tasks/main.yaml
new file mode 100644
index 00000000..b957d2f4
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tasks/main.yaml
@@ -0,0 +1,4 @@
+---
+- include: cli.yaml
+  tags:
+    - network_cli
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/_parsed_config.cfg b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_parsed_config.cfg
new file mode 100644
index 00000000..2aecc805
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_parsed_config.cfg
@@ -0,0 +1,9 @@
+set policy access-list 20 description 'acl20'
+set policy access-list 40 description 'acl40'
+set policy route-map map01 description 'map01'
+set protocols bgp 65536 address-family ipv6-unicast aggregate-address 5000:1:1::/64 summary-only
+set protocols bgp 65536 address-family ipv6-unicast network 21e0:1:1::/64 route-map 'map01'
+set protocols bgp 65536 address-family ipv6-unicast redistribute ripng metric '20'
+set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast route-map export 'map01'
+set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast soft-reconfiguration inbound
+set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged next-hop
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/_populate.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_populate.yaml
new file mode 100644
index 00000000..3aca9161
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_populate.yaml
@@ -0,0 +1,17 @@
+---
+- name: setup
+  vyos.vyos.vyos_config:
+    lines:
+      - set policy access-list 20 description 'acl20'
+      - set policy access-list 40 description 'acl40'
+      - set policy access-list6 10 description 'acl10'
+      - set policy route-map map01 description 'map01'
+      - set protocols bgp 65536 address-family ipv6-unicast aggregate-address 5000:1:1::/64 summary-only
+      - set protocols bgp 65536 address-family ipv6-unicast network 21e0:1:1::/64 route-map 'map01'
+      - set protocols bgp 65536 address-family ipv6-unicast redistribute ripng metric '20'
+      - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast route-map export 'map01'
+      - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast soft-reconfiguration inbound
+      - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged next-hop
+  ignore_errors: true
+  vars:
+    ansible_connection: ansible.netcommon.network_cli
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/_preconfig.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_preconfig.yaml
new file mode 100644
index 00000000..5024a70f
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_preconfig.yaml
@@ -0,0 +1,11 @@
+---
+- name: setup
+  vyos.vyos.vyos_config:
+    lines:
+      - set policy access-list 20 description 'acl20'
+      - set policy access-list 40 description 'acl40'
+      - set policy access-list6 10 description 'acl10'
+      - set policy route-map map01 description 'map01'
+  ignore_errors: true
+  vars:
+    ansible_connection: ansible.netcommon.network_cli
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/_remove_config.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_remove_config.yaml
new file mode 100644
index 00000000..39d8bd02
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_remove_config.yaml
@@ -0,0 +1,12 @@
+---
+- name: Remove pre-existing bgp processes
+  vyos.vyos.vyos_config:
+    lines:
+      - delete protocols bgp 65536
+      - delete policy access-list 20
+      - delete policy access-list 40
+      - delete policy access-list6 10
+      - delete policy route-map map01
+  ignore_errors: true
+  vars:
+    ansible_connection: ansible.netcommon.network_cli
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/deleted.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/deleted.yaml
new file mode 100644
index 00000000..7fb8e109
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/deleted.yaml
@@ -0,0 +1,49 @@
+---
+- debug:
+    msg: START vyos_bgp_address_family deleted integration tests on connection={{
+      ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+    - name: Delete the provided configuration
+      register: result
+      vyos.vyos.vyos_bgp_address_family: &id001
+        config:
+          as_number: "65536"
+          address_family:
+            - afi: "ipv6"
+          neighbors:
+            - neighbor_address: "203.0.113.5"
+            - neighbor_address: "192.0.2.25"
+              address_family:
+                - afi: "ipv6"
+        state: deleted
+
+    - become: true
+      vyos.vyos.vyos_facts:
+        gather_network_resources: bgp_address_family
+
+    - assert:
+        that:
+          - result.commands|length == 3
+          - result.changed == true
+          - result.commands|symmetric_difference(deleted.commands) == []
+          - result.after == ansible_facts['network_resources']['bgp_address_family']
+
+    - name: Delete the existing configuration with the provided running configuration
+        (IDEMPOTENT)
+      register: result
+      vyos.vyos.vyos_bgp_address_family: *id001
+
+    - name: Assert that the previous task was idempotent
+      assert:
+        that:
+          - result['changed'] == false
+
+  always:
+
+    - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/empty_config.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/empty_config.yaml
new file mode 100644
index 00000000..3a12be92
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/empty_config.yaml
@@ -0,0 +1,60 @@
+---
+- debug:
+    msg: START vyos_bgp_address_family empty_config integration tests on connection={{
+      ansible_connection }}
+
+- name: Merged with empty config should give appropriate error message
+  register: result
+  ignore_errors: true
+  vyos.vyos.vyos_bgp_address_family:
+    config:
+    state: merged
+
+- assert:
+    that:
+      - result.msg == 'value of config parameter must not be empty for state merged'
+
+- name: Replaced with empty config should give appropriate error message
+  register: result
+  ignore_errors: true
+  vyos.vyos.vyos_bgp_address_family:
+    config:
+    state: replaced
+
+- assert:
+    that:
+      - result.msg == 'value of config parameter must not be empty for state replaced'
+
+- name: OVerridden with empty config should give appropriate error message
+  register: result
+  ignore_errors: true
+  vyos.vyos.vyos_bgp_address_family:
+    config:
+    state: overridden
+
+- 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
+  vyos.vyos.vyos_bgp_address_family:
+    running_config:
+    state: parsed
+
+- assert:
+    that:
+      - result.msg == 'value of running_config parameter must not be empty for state
+        parsed'
+
+- name: Rendered with empty config should give appropriate error message
+  register: result
+  ignore_errors: true
+  vyos.vyos.vyos_bgp_address_family:
+    config:
+    state: rendered
+
+- assert:
+    that:
+      - result.msg == 'value of config parameter must not be empty for state rendered'
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/gathered.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/gathered.yaml
new file mode 100644
index 00000000..7176a488
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/gathered.yaml
@@ -0,0 +1,24 @@
+---
+- debug:
+    msg: START vyos_bgp_address_family gathered integration tests on connection={{
+      ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+    - name: Gather config from the device in structured format.
+      register: result
+      vyos.vyos.vyos_bgp_address_family:
+        state: gathered
+
+    - become: true
+      vyos.vyos.vyos_facts:
+        gather_network_resources: bgp_address_family
+
+    - assert:
+        that:
+          - result.changed == false
+          - result.gathered == ansible_facts['network_resources']['bgp_address_family']
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/merged.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/merged.yaml
new file mode 100644
index 00000000..45870c6b
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/merged.yaml
@@ -0,0 +1,70 @@
+---
+- debug:
+    msg: START vyos_bgp_address_family merged integration tests on connection={{
+      ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _preconfig.yaml
+
+- block:
+
+    - name: Merge the provided configuration with the exisiting running configuration
+      register: result
+      vyos.vyos.vyos_bgp_address_family: &id001
+        config:
+          as_number: "65536"
+          address_family:
+            - afi: "ipv6"
+              redistribute:
+                - protocol: "static"
+                  metric: 50
+          neighbors:
+            - neighbor_address: "203.0.113.5"
+              address_family:
+                - afi: "ipv6"
+                  allowas_in: 4
+                  attribute_unchanged:
+                    med: true
+                  default_originate: "map01"
+                  distribute_list:
+                    - action: "export"
+                      acl: 10
+            - neighbor_address: "192.0.2.25"
+              address_family:
+                - afi: "ipv6"
+                  maximum_prefix: 45
+                  nexthop_self: true
+                  route_map:
+                    - action: "export"
+                      route_map: "map01"
+                    - action: "import"
+                      route_map: "map01"
+        state: merged
+
+    - become: true
+      vyos.vyos.vyos_facts:
+        gather_network_resources: bgp_address_family
+
+    - assert:
+        that:
+          - result.commands|length == 9
+          - result.changed == true
+          - result.commands|symmetric_difference(merged.commands) == []
+          - result.after == ansible_facts['network_resources']['bgp_address_family']
+          - result.before == {}
+          - result.after == merged.after
+
+    - name: Merge the provided configuration with the existing running configuration
+        (IDEMPOTENT)
+      register: result
+      vyos.vyos.vyos_bgp_address_family: *id001
+
+    - name: Assert that the previous task was idempotent
+      assert:
+        that:
+          - result['changed'] == false
+
+  always:
+
+    - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/overridden.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/overridden.yaml
new file mode 100644
index 00000000..77ba5b49
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/overridden.yaml
@@ -0,0 +1,58 @@
+---
+- debug:
+    msg: START vyos_bgp_address_family overridden integration tests on connection={{
+      ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+    - name: Replace the existing configuration with the provided running configuration
+      register: result
+      vyos.vyos.vyos_bgp_address_family: &id001
+        config:
+          as_number: "65536"
+          address_family:
+            - afi: "ipv6"
+              redistribute:
+                - protocol: "static"
+                  metric: 50
+          neighbors:
+            - neighbor_address: "203.0.113.5"
+              address_family:
+                - afi: "ipv6"
+                  allowas_in: 4
+                  attribute_unchanged:
+                    med: true
+                  default_originate: "map01"
+                  distribute_list:
+                    - action: "export"
+                      acl: 10
+        state: overridden
+
+    - become: true
+      vyos.vyos.vyos_facts:
+        gather_network_resources: bgp_address_family
+
+    - assert:
+        that:
+          - result.commands|length == 10
+          - result.changed == true
+          - result.commands|symmetric_difference(overridden.commands) == []
+          - result.after == ansible_facts['network_resources']['bgp_address_family']
+
+    - name: Replace the existing configuration with the provided running configuration
+        (IDEMPOTENT)
+      register: result
+      vyos.vyos.vyos_bgp_address_family: *id001
+
+    - name: Assert that the previous task was idempotent
+      assert:
+        that:
+          - result['changed'] == false
+
+  always:
+
+    - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/parsed.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/parsed.yaml
new file mode 100644
index 00000000..d20684f0
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/parsed.yaml
@@ -0,0 +1,16 @@
+---
+- debug:
+    msg: START vyos_bgp_address_family parsed integration tests on connection={{ ansible_connection
+      }}
+
+- name: Provide the running configuration for parsing (config to be parsed)
+  become: true
+  register: result
+  vyos.vyos.vyos_bgp_address_family:
+    running_config: "{{ lookup('file', '_parsed_config.cfg') }}"
+    state: parsed
+
+- assert:
+    that:
+      - result.changed == false
+      - result.parsed == populate.config
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/rendered.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/rendered.yaml
new file mode 100644
index 00000000..1071657c
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/rendered.yaml
@@ -0,0 +1,44 @@
+---
+- debug:
+    msg: START vyos_bgp_address_family rendered integration tests on connection={{
+      ansible_connection }}
+
+- block:
+
+    - name: Render the given config in the form of native config.
+      register: result
+      vyos.vyos.vyos_bgp_address_family: &id001
+        config:
+          as_number: "65536"
+          address_family:
+            - afi: "ipv6"
+              redistribute:
+                - protocol: "static"
+                  metric: 50
+          neighbors:
+            - neighbor_address: "203.0.113.5"
+              address_family:
+                - afi: "ipv6"
+                  allowas_in: 4
+                  attribute_unchanged:
+                    med: true
+                  default_originate: "map01"
+                  distribute_list:
+                    - action: "export"
+                      acl: 10
+            - neighbor_address: "192.0.2.25"
+              address_family:
+                - afi: "ipv6"
+                  maximum_prefix: 45
+                  nexthop_self: true
+                  route_map:
+                    - action: "export"
+                      route_map: "map01"
+                    - action: "import"
+                      route_map: "map01"
+        state: rendered
+
+    - assert:
+        that:
+          - result.changed == false
+          - result.rendered|symmetric_difference(merged.commands) == []
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/replaced.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/replaced.yaml
new file mode 100644
index 00000000..001c9971
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/replaced.yaml
@@ -0,0 +1,58 @@
+---
+- debug:
+    msg: START vyos_bgp_address_family replaced integration tests on connection={{
+      ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+    - name: Replace the existing configuration with the provided running configuration
+      register: result
+      vyos.vyos.vyos_bgp_address_family: &id001
+        config:
+          as_number: "65536"
+          address_family:
+            - afi: "ipv6"
+              redistribute:
+                - protocol: "static"
+                  metric: 50
+          neighbors:
+            - neighbor_address: "203.0.113.5"
+              address_family:
+                - afi: "ipv6"
+                  allowas_in: 4
+                  attribute_unchanged:
+                    med: true
+                  default_originate: "map01"
+                  distribute_list:
+                    - action: "export"
+                      acl: 10
+        state: replaced
+
+    - become: true
+      vyos.vyos.vyos_facts:
+        gather_network_resources: bgp_address_family
+
+    - assert:
+        that:
+          - result.commands|length == 9
+          - result.changed == true
+          - result.commands|symmetric_difference(replaced.commands) == []
+          - result.after == ansible_facts['network_resources']['bgp_address_family']
+
+    - name: Replace the existing configuration with the provided running configuration
+        (IDEMPOTENT)
+      register: result
+      vyos.vyos.vyos_bgp_address_family: *id001
+
+    - name: Assert that the previous task was idempotent
+      assert:
+        that:
+          - result['changed'] == false
+
+  always:
+
+    - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/rtt.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/rtt.yaml
new file mode 100644
index 00000000..3ef93c40
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/rtt.yaml
@@ -0,0 +1,90 @@
+---
+- debug:
+    msg: START vyos_bgp_address_family rtt integration tests on connection={{
+      ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _preconfig.yaml
+
+- block:
+
+    - name: Merge the provided configuration with the exisiting running configuration
+      register: baseconfig
+      vyos.vyos.vyos_bgp_address_family:
+        config:
+          as_number: "65536"
+          address_family:
+            - afi: "ipv6"
+              redistribute:
+                - protocol: "static"
+                  metric: 50
+          neighbors:
+            - neighbor_address: "203.0.113.5"
+              address_family:
+                - afi: "ipv6"
+                  allowas_in: 4
+                  attribute_unchanged:
+                    med: true
+                  default_originate: "map01"
+                  distribute_list:
+                    - action: "export"
+                      acl: 10
+            - neighbor_address: "192.0.2.25"
+              address_family:
+                - afi: "ipv6"
+                  maximum_prefix: 45
+                  nexthop_self: true
+                  route_map:
+                    - action: "export"
+                      route_map: "map01"
+                    - action: "import"
+                      route_map: "map01"
+        state: merged
+
+    - become: true
+      vyos.vyos.vyos_facts:
+        gather_network_resources: bgp_address_family
+
+    - assert:
+        that:
+          - baseconfig.commands|length == 9
+          - baseconfig.changed == true
+          - baseconfig.commands|symmetric_difference(merged.commands) == []
+          - baseconfig.after == ansible_facts['network_resources']['bgp_address_family']
+
+    - name: Apply the provided configuration (config to be reverted)
+      become: true
+      register: result
+      vyos.vyos.vyos_bgp_address_family:
+        config:
+          as_number: "65536"
+          address_family:
+            - afi: "ipv6"
+              aggregate_address:
+                - summary_only: true
+                  prefix: "21e0:1:1::/64"
+              networks:
+                - prefix: "21e0:1:1::/64"
+                  route_map: "map01"
+          neighbors:
+            - address_family:
+                - afi: "ipv6"
+                  remove_private_as: true
+              neighbor_address: "203.0.113.5"
+
+    - name: Revert back to base config using facts round trip
+      become: true
+      register: revert
+      vyos.vyos.vyos_bgp_address_family:
+        config: "{{ ansible_facts['network_resources']['bgp_address_family'] }}"
+        state: overridden
+
+    - name: Assert that config was reverted
+      assert:
+        that: baseconfig.after == revert.after
+
+
+  always:
+
+    - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_bgp_address_family/vars/main.yaml b/tests/integration/targets/vyos_bgp_address_family/vars/main.yaml
new file mode 100644
index 00000000..aed6de63
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/vars/main.yaml
@@ -0,0 +1,99 @@
+---
+merged:
+  commands:
+    - set protocols bgp 65536 address-family ipv6-unicast redistribute static metric 50
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast allowas-in number 4
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged med
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast default-originate route-map map01
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast distribute-list export 10
+    - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast maximum-prefix 45
+    - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast nexthop-self
+    - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast route-map export map01
+    - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast route-map import map01
+  after:
+    address_family:
+      - afi: "ipv6"
+        redistribute:
+          - metric: 50
+            protocol: "static"
+    as_number: 65536
+    neighbors:
+      - address_family:
+          - afi: "ipv6"
+            maximum_prefix: 45
+            nexthop_self: true
+            route_map:
+              - action: "export"
+                route_map: "map01"
+              - action: "import"
+                route_map: "map01"
+        neighbor_address: "192.0.2.25"
+      - address_family:
+          - afi: "ipv6"
+            allowas_in: 4
+            attribute_unchanged:
+              med: true
+            default_originate: "map01"
+            distribute_list:
+              - acl: 10
+                action: "export"
+        neighbor_address: "203.0.113.5"
+
+replaced:
+  commands:
+    - delete protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged
+    - delete protocols bgp 65536 address-family ipv6 aggregate-address
+    - delete protocols bgp 65536 address-family ipv6 network
+    - delete protocols bgp 65536 address-family ipv6-unicast redistribute ripng
+    - set protocols bgp 65536 address-family ipv6-unicast redistribute static metric 50
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast allowas-in number 4
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged med
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast default-originate route-map map01
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast distribute-list export 10
+
+overridden:
+  commands:
+    - delete protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged
+    - delete protocols bgp 65536 neighbor 192.0.2.25 address-family
+    - delete protocols bgp 65536 address-family ipv6-unicast redistribute ripng
+    - delete protocols bgp 65536 address-family ipv6 aggregate-address
+    - delete protocols bgp 65536 address-family ipv6 network
+    - set protocols bgp 65536 address-family ipv6-unicast redistribute static metric 50
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast allowas-in number 4
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged med
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast default-originate route-map map01
+    - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast distribute-list export 10
+
+deleted:
+  commands:
+    - delete protocols bgp 65536 address-family ipv6-unicast
+    - delete protocols bgp 65536 neighbor 203.0.113.5 address-family
+    - delete protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast
+
+populate:
+  config:
+    address_family:
+      - afi: "ipv6"
+        aggregate_address:
+          - summary_only: true
+            prefix: "5000:1:1::/64"
+        networks:
+          - prefix: "21e0:1:1::/64"
+            route_map: "map01"
+        redistribute:
+          - metric: 20
+            protocol: "ripng"
+    as_number: 65536
+    neighbors:
+      - address_family:
+          - afi: "ipv6"
+            route_map:
+              - action: "export"
+                route_map: "map01"
+            soft_reconfiguration: true
+        neighbor_address: "192.0.2.25"
+      - address_family:
+          - afi: "ipv6"
+            attribute_unchanged:
+              next_hop: true
+        neighbor_address: "203.0.113.5"
diff --git a/tests/unit/modules/network/vyos/fixtures/vyos_bgp_address_family_config.cfg b/tests/unit/modules/network/vyos/fixtures/vyos_bgp_address_family_config.cfg
new file mode 100644
index 00000000..a59878f3
--- /dev/null
+++ b/tests/unit/modules/network/vyos/fixtures/vyos_bgp_address_family_config.cfg
@@ -0,0 +1,7 @@
+set protocols bgp 65536 address-family ipv4-unicast aggregate-address 192.0.2.0/24 as-set
+set protocols bgp 65536 address-family ipv4-unicast network 192.1.13.0/24 route-map 'map01'
+set protocols bgp 65536 address-family ipv4-unicast network 192.2.13.0/24 backdoor
+set protocols bgp 65536 address-family ipv6-unicast redistribute ripng metric '20'
+set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast route-map export 'map01'
+set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast soft-reconfiguration inbound
+set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged next-hop
diff --git a/tests/unit/modules/network/vyos/test_vyos_bgp_address_family.py b/tests/unit/modules/network/vyos/test_vyos_bgp_address_family.py
new file mode 100644
index 00000000..5fc7e358
--- /dev/null
+++ b/tests/unit/modules/network/vyos/test_vyos_bgp_address_family.py
@@ -0,0 +1,684 @@
+# (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.vyos.vyos.tests.unit.compat.mock import patch
+from ansible_collections.vyos.vyos.plugins.modules import (
+    vyos_bgp_address_family,
+)
+from ansible_collections.vyos.vyos.tests.unit.modules.utils import (
+    set_module_args,
+)
+from .vyos_module import TestVyosModule, load_fixture
+
+
+class TestVyosBgpafModule(TestVyosModule):
+
+    module = vyos_bgp_address_family
+
+    def setUp(self):
+        super(TestVyosBgpafModule, self).setUp()
+        self.mock_get_resource_connection_config = patch(
+            "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base.get_resource_connection"
+        )
+        self.get_resource_connection_config = (
+            self.mock_get_resource_connection_config.start()
+        )
+
+        self.mock_execute_show_command = patch(
+            "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts."
+            + "bgp_address_family.bgp_address_family.Bgp_address_familyFacts.get_device_data"
+        )
+        self.execute_show_command = self.mock_execute_show_command.start()
+
+    def tearDown(self):
+        super(TestVyosBgpafModule, self).tearDown()
+        self.mock_get_resource_connection_config.stop()
+        self.mock_execute_show_command.stop()
+
+    def load_fixtures(self, commands=None, transport="cli", filename=None):
+        if filename is None:
+            filename = "vyos_bgp_address_family_config.cfg"
+
+        def load_from_file(*args, **kwargs):
+            output = load_fixture(filename)
+            return output
+
+        self.execute_show_command.side_effect = load_from_file
+
+    def test_vyos_bgp_address_family_merged_idempotent(self):
+        set_module_args(
+            dict(
+                config=dict(
+                    as_number=65536,
+                    address_family=[
+                        dict(
+                            afi="ipv4",
+                            aggregate_address=[
+                                dict(prefix="192.0.2.0/24", as_set=True)
+                            ],
+                            networks=[
+                                dict(
+                                    prefix="192.1.13.0/24", route_map="map01"
+                                ),
+                                dict(prefix="192.2.13.0/24", backdoor=True),
+                            ],
+                        ),
+                        dict(
+                            afi="ipv6",
+                            redistribute=[dict(protocol="ripng", metric=20)],
+                        ),
+                    ],
+                    neighbors=[
+                        dict(
+                            neighbor_address="192.0.2.25",
+                            address_family=[
+                                dict(
+                                    afi="ipv4",
+                                    route_map=[
+                                        dict(
+                                            action="export", route_map="map01"
+                                        )
+                                    ],
+                                    soft_reconfiguration=True,
+                                ),
+                            ],
+                        ),
+                        dict(
+                            neighbor_address="203.0.113.5",
+                            address_family=[
+                                dict(
+                                    afi="ipv6",
+                                    attribute_unchanged=dict(next_hop=True),
+                                )
+                            ],
+                        ),
+                    ],
+                )
+            )
+        )
+        self.execute_module(changed=False, commands=[])
+
+    def test_vyos_bgp_address_family_merged(self):
+        set_module_args(
+            dict(
+                config=dict(
+                    as_number=65536,
+                    address_family=[
+                        dict(
+                            afi="ipv4",
+                            aggregate_address=[
+                                dict(prefix="192.0.2.0/24", summary_only=True)
+                            ],
+                            networks=[
+                                dict(
+                                    prefix="192.1.13.0/24", route_map="map01"
+                                ),
+                            ],
+                        ),
+                        dict(
+                            afi="ipv6",
+                            redistribute=[dict(protocol="ospfv3", metric=20)],
+                        ),
+                    ],
+                    neighbors=[
+                        dict(
+                            neighbor_address="192.10.21.25",
+                            address_family=[
+                                dict(
+                                    afi="ipv6",
+                                    distribute_list=[
+                                        dict(action="export", acl=10)
+                                    ],
+                                    route_server_client=True,
+                                ),
+                            ],
+                        ),
+                        dict(
+                            neighbor_address="203.0.113.5",
+                            address_family=[
+                                dict(
+                                    afi="ipv4",
+                                    filter_list=[
+                                        dict(
+                                            action="export", path_list="list01"
+                                        ),
+                                    ],
+                                    capability=dict(orf="send"),
+                                )
+                            ],
+                        ),
+                    ],
+                )
+            )
+        )
+        commands = [
+            "set protocols bgp 65536 address-family ipv4-unicast aggregate-address 192.0.2.0/24 as-setipv4-unicast aggregate-address 192.0.2.0/24 summary-only",
+            "set protocols bgp 65536 address-family ipv6-unicast redistribute ospfv3 metric 20",
+            "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv4-unicast filter-list export list01",
+            "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv4-unicast capability  prefix-list send",
+            "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast distribute-list export 10",
+            "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast route-server-client",
+        ]
+        self.execute_module(changed=True, commands=commands)
+
+    def test_vyos_bgp_address_family_replaced_idempotent(self):
+        set_module_args(
+            dict(
+                state="replaced",
+                config=dict(
+                    as_number=65536,
+                    address_family=[
+                        dict(
+                            afi="ipv4",
+                            aggregate_address=[
+                                dict(prefix="192.0.2.0/24", as_set=True)
+                            ],
+                            networks=[
+                                dict(
+                                    prefix="192.1.13.0/24", route_map="map01"
+                                ),
+                                dict(prefix="192.2.13.0/24", backdoor=True),
+                            ],
+                        ),
+                        dict(
+                            afi="ipv6",
+                            redistribute=[dict(protocol="ripng", metric=20)],
+                        ),
+                    ],
+                    neighbors=[
+                        dict(
+                            neighbor_address="192.0.2.25",
+                            address_family=[
+                                dict(
+                                    afi="ipv4",
+                                    route_map=[
+                                        dict(
+                                            action="export", route_map="map01"
+                                        )
+                                    ],
+                                    soft_reconfiguration=True,
+                                ),
+                            ],
+                        ),
+                        dict(
+                            neighbor_address="203.0.113.5",
+                            address_family=[
+                                dict(
+                                    afi="ipv6",
+                                    attribute_unchanged=dict(next_hop=True),
+                                )
+                            ],
+                        ),
+                    ],
+                ),
+            )
+        )
+        self.execute_module(changed=False, commands=[])
+
+    def test_vyos_bgp_address_family_replaced(self):
+        set_module_args(
+            dict(
+                state="replaced",
+                config=dict(
+                    as_number=65536,
+                    address_family=[
+                        dict(
+                            afi="ipv4",
+                            aggregate_address=[
+                                dict(prefix="192.0.2.0/24", summary_only=True)
+                            ],
+                            networks=[
+                                dict(
+                                    prefix="192.1.13.0/24", route_map="map01"
+                                ),
+                            ],
+                        ),
+                        dict(
+                            afi="ipv6",
+                            redistribute=[dict(protocol="ospfv3", metric=20)],
+                        ),
+                    ],
+                    neighbors=[
+                        dict(
+                            neighbor_address="192.10.21.25",
+                            address_family=[
+                                dict(
+                                    afi="ipv4",
+                                    route_map=[
+                                        dict(
+                                            action="import", route_map="map01"
+                                        )
+                                    ],
+                                ),
+                                dict(
+                                    afi="ipv6",
+                                    distribute_list=[
+                                        dict(action="export", acl=10)
+                                    ],
+                                    route_server_client=True,
+                                ),
+                            ],
+                        ),
+                        dict(
+                            neighbor_address="192.0.2.25",
+                            address_family=[
+                                dict(
+                                    afi="ipv4",
+                                    route_map=[
+                                        dict(
+                                            action="export", route_map="map01"
+                                        )
+                                    ],
+                                ),
+                            ],
+                        ),
+                        dict(
+                            neighbor_address="203.0.113.5",
+                            address_family=[
+                                dict(
+                                    afi="ipv4",
+                                    filter_list=[
+                                        dict(
+                                            action="export", path_list="list01"
+                                        ),
+                                    ],
+                                    capability=dict(orf="send"),
+                                )
+                            ],
+                        ),
+                    ],
+                ),
+            )
+        )
+        commands = [
+            "delete protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged",
+            "delete protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast soft-reconfiguration",
+            "delete protocols bgp 65536 address-family ipv6-unicast redistribute ripng",
+            "delete protocols bgp 65536 address-family ipv4-unicast network 192.2.13.0/24",
+            "set protocols bgp 65536 address-family ipv4-unicast aggregate-address 192.0.2.0/24 summary-only",
+            "set protocols bgp 65536 address-family ipv6-unicast redistribute ospfv3 metric 20",
+            "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv4-unicast route-map import map01",
+            "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast distribute-list export 10",
+            "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast route-server-client",
+            "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv4-unicast filter-list export list01",
+            "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv4-unicast capability  prefix-list send",
+        ]
+        self.execute_module(changed=True, commands=commands)
+
+    def test_vyos_bgp_address_family_overridden_idempotent(self):
+        set_module_args(
+            dict(
+                state="overridden",
+                config=dict(
+                    as_number=65536,
+                    address_family=[
+                        dict(
+                            afi="ipv4",
+                            aggregate_address=[
+                                dict(prefix="192.0.2.0/24", as_set=True)
+                            ],
+                            networks=[
+                                dict(
+                                    prefix="192.1.13.0/24", route_map="map01"
+                                ),
+                                dict(prefix="192.2.13.0/24", backdoor=True),
+                            ],
+                        ),
+                        dict(
+                            afi="ipv6",
+                            redistribute=[dict(protocol="ripng", metric=20)],
+                        ),
+                    ],
+                    neighbors=[
+                        dict(
+                            neighbor_address="192.0.2.25",
+                            address_family=[
+                                dict(
+                                    afi="ipv4",
+                                    route_map=[
+                                        dict(
+                                            action="export", route_map="map01"
+                                        )
+                                    ],
+                                    soft_reconfiguration=True,
+                                ),
+                            ],
+                        ),
+                        dict(
+                            neighbor_address="203.0.113.5",
+                            address_family=[
+                                dict(
+                                    afi="ipv6",
+                                    attribute_unchanged=dict(next_hop=True),
+                                )
+                            ],
+                        ),
+                    ],
+                ),
+            )
+        )
+        self.execute_module(changed=False, commands=[])
+
+    def test_vyos_bgp_address_family_overridden(self):
+        set_module_args(
+            dict(
+                state="overridden",
+                config=dict(
+                    as_number=65536,
+                    address_family=[
+                        dict(
+                            afi="ipv4",
+                            networks=[
+                                dict(
+                                    prefix="192.1.13.0/24", route_map="map01"
+                                ),
+                            ],
+                        ),
+                        dict(
+                            afi="ipv6",
+                            redistribute=[dict(protocol="ospfv3", metric=20)],
+                        ),
+                    ],
+                    neighbors=[
+                        dict(
+                            neighbor_address="192.10.21.25",
+                            address_family=[
+                                dict(
+                                    afi="ipv4",
+                                    route_map=[
+                                        dict(
+                                            action="import", route_map="map01"
+                                        )
+                                    ],
+                                ),
+                                dict(
+                                    afi="ipv6",
+                                    distribute_list=[
+                                        dict(action="export", acl=10)
+                                    ],
+                                    route_server_client=True,
+                                ),
+                            ],
+                        ),
+                    ],
+                ),
+            )
+        )
+        commands = [
+            "delete protocols bgp 65536 neighbor 203.0.113.5 address-family",
+            "delete protocols bgp 65536 neighbor 192.0.2.25 address-family",
+            "delete protocols bgp 65536 address-family ipv6-unicast redistribute ripng",
+            "delete protocols bgp 65536 address-family ipv4 aggregate-address",
+            "delete protocols bgp 65536 address-family ipv4-unicast network 192.2.13.0/24",
+            "set protocols bgp 65536 address-family ipv6-unicast redistribute ospfv3 metric 20",
+            "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv4-unicast route-map import map01",
+            "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast distribute-list export 10",
+            "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast route-server-client",
+        ]
+        self.execute_module(changed=True, commands=commands)
+
+    def test_vyos_bgp_address_family_deleted(self):
+        set_module_args(
+            dict(
+                state="deleted",
+                config=dict(
+                    as_number=65536,
+                    address_family=[
+                        dict(
+                            afi="ipv4",
+                        ),
+                    ],
+                    neighbors=[
+                        dict(
+                            neighbor_address="192.0.2.25",
+                            address_family=[
+                                dict(
+                                    afi="ipv4",
+                                ),
+                            ],
+                        ),
+                        dict(
+                            neighbor_address="203.0.113.5",
+                        ),
+                    ],
+                ),
+            )
+        )
+        commands = [
+            "delete protocols bgp 65536 address-family ipv4-unicast",
+            "delete protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast",
+            "delete protocols bgp 65536 neighbor 203.0.113.5 address-family",
+        ]
+
+        self.execute_module(changed=True, commands=commands)
+
+    def test_vyos_bgp_address_family_incorrect_instance(self):
+        set_module_args(
+            dict(
+                state="overridden",
+                config=dict(
+                    as_number=100,
+                    address_family=[
+                        dict(
+                            afi="ipv4",
+                            networks=[
+                                dict(
+                                    prefix="192.1.13.0/24", route_map="map01"
+                                ),
+                            ],
+                        ),
+                        dict(
+                            afi="ipv6",
+                            redistribute=[dict(protocol="ospfv3", metric=20)],
+                        ),
+                    ],
+                    neighbors=[
+                        dict(
+                            neighbor_address="192.10.21.25",
+                            address_family=[
+                                dict(
+                                    afi="ipv4",
+                                    route_map=[
+                                        dict(
+                                            action="import", route_map="map01"
+                                        )
+                                    ],
+                                ),
+                                dict(
+                                    afi="ipv6",
+                                    distribute_list=[
+                                        dict(action="export", acl=10)
+                                    ],
+                                    route_server_client=True,
+                                ),
+                            ],
+                        ),
+                    ],
+                ),
+            )
+        )
+        result = self.execute_module(failed=True)
+        self.assertIn(
+            "Only one bgp instance is allowed per device", result["msg"]
+        )
+
+    def test_vyos_bgp_address_family_rendered(self):
+        set_module_args(
+            dict(
+                state="rendered",
+                config=dict(
+                    as_number=65536,
+                    address_family=[
+                        dict(
+                            afi="ipv4",
+                            aggregate_address=[
+                                dict(prefix="192.0.2.0/24", as_set=True)
+                            ],
+                            networks=[
+                                dict(
+                                    prefix="192.1.13.0/24", route_map="map01"
+                                ),
+                                dict(prefix="192.2.13.0/24", backdoor=True),
+                            ],
+                        ),
+                        dict(
+                            afi="ipv6",
+                            redistribute=[dict(protocol="ripng", metric=20)],
+                        ),
+                    ],
+                    neighbors=[
+                        dict(
+                            neighbor_address="192.0.2.25",
+                            address_family=[
+                                dict(
+                                    afi="ipv4",
+                                    route_map=[
+                                        dict(
+                                            action="export", route_map="map01"
+                                        )
+                                    ],
+                                    soft_reconfiguration=True,
+                                ),
+                            ],
+                        ),
+                        dict(
+                            neighbor_address="203.0.113.5",
+                            address_family=[
+                                dict(
+                                    afi="ipv6",
+                                    attribute_unchanged=dict(next_hop=True),
+                                )
+                            ],
+                        ),
+                    ],
+                ),
+            )
+        )
+
+        rendered_cmds = [
+            "set protocols bgp 65536 address-family ipv4-unicast network 192.1.13.0/24 route-map map01",
+            "set protocols bgp 65536 address-family ipv4-unicast network 192.2.13.0/24 backdoor",
+            "set protocols bgp 65536 address-family ipv4-unicast aggregate-address 192.0.2.0/24 as-set",
+            "set protocols bgp 65536 address-family ipv6-unicast redistribute ripng metric 20",
+            "set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast route-map export map01",
+            "set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast soft-reconfiguration inbound",
+            "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged next-hop",
+        ]
+        result = self.execute_module(changed=False)
+        self.assertEqual(
+            sorted(result["rendered"]),
+            sorted(rendered_cmds),
+            result["rendered"],
+        )
+
+    def test_vyos_bgp_address_family_parsed(self):
+        commands = [
+            "set protocols bgp 65536 address-family ipv4-unicast network 192.1.13.0/24 route-map map01",
+            "set protocols bgp 65536 address-family ipv4-unicast network 192.2.13.0/24 backdoor",
+            "set protocols bgp 65536 address-family ipv4-unicast aggregate-address 192.0.2.0/24 as-set",
+            "set protocols bgp 65536 address-family ipv6-unicast redistribute ripng metric 20",
+            "set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast route-map export map01",
+            "set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast soft-reconfiguration inbound",
+            "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged next-hop",
+        ]
+
+        parsed_str = "\n".join(commands)
+        set_module_args(dict(running_config=parsed_str, state="parsed"))
+        result = self.execute_module(changed=False)
+        parsed_list = {
+            "as_number": 65536,
+            "address_family": [
+                {
+                    "afi": "ipv4",
+                    "networks": [
+                        {"prefix": "192.1.13.0/24", "route_map": "map01"},
+                        {"prefix": "192.2.13.0/24", "backdoor": True},
+                    ],
+                    "aggregate_address": [
+                        {"prefix": "192.0.2.0/24", "as_set": True}
+                    ],
+                },
+                {
+                    "afi": "ipv6",
+                    "redistribute": [{"protocol": "ripng", "metric": 20}],
+                },
+            ],
+            "neighbors": [
+                {
+                    "neighbor_address": "192.0.2.25",
+                    "address_family": [
+                        {"afi": "ipv4", "soft_reconfiguration": True},
+                    ],
+                },
+                {
+                    "neighbor_address": "203.0.113.5",
+                    "address_family": [
+                        {
+                            "afi": "ipv6",
+                            "attribute_unchanged": {"next_hop": True},
+                        }
+                    ],
+                },
+            ],
+        }
+        self.assertEqual(sorted(parsed_list), sorted(result["parsed"]))
+
+    def test_vyos_bgp_address_family_gathered(self):
+        set_module_args(dict(state="gathered"))
+        result = self.execute_module(changed=False)
+        gather_list = {
+            "as_number": 65536,
+            "address_family": [
+                {
+                    "afi": "ipv4",
+                    "networks": [
+                        {"prefix": "192.1.13.0/24", "route_map": "map01"},
+                        {"prefix": "192.2.13.0/24", "backdoor": True},
+                    ],
+                    "aggregate_address": [
+                        {"prefix": "192.0.2.0/24", "as_set": True}
+                    ],
+                },
+                {
+                    "afi": "ipv6",
+                    "redistribute": [{"protocol": "ripng", "metric": 20}],
+                },
+            ],
+            "neighbors": [
+                {
+                    "neighbor_address": "192.0.2.25",
+                    "address_family": [
+                        {"afi": "ipv4", "soft_reconfiguration": True},
+                    ],
+                },
+                {
+                    "neighbor_address": "203.0.113.5",
+                    "address_family": [
+                        {
+                            "afi": "ipv6",
+                            "attribute_unchanged": {"next_hop": True},
+                        }
+                    ],
+                },
+            ],
+        }
+        self.assertEqual(sorted(gather_list), sorted(result["gathered"]))
-- 
cgit v1.2.3