Repository: aristanetworks/anta (python)

Issue:
feat(anta_tests): VerifyBGPAdvCommunities support a combination of communities
Extend `BgpPeer` model to support an optional list of communities and check against those instead of all.

```
advertised_communities: list[Community] = Field(default=["standard', "extended', "large"])
```

Pull request description:
feat(anta_tests): VerifyBGPAdvCommunities support a combination of communities
# Description

Extend BgpPeer model to support an optional list of communities and check against those instead of all.

advertised_communities: list[Community] = Field(default=["standard', "extended', "large"

Fixes #1173 

# Checklist:

- [X] My code follows the style guidelines of this project
- [X] I have performed a self-review of my code
- [X] I have run pre-commit for code linting and typing (`pre-commit run`)
- [ ] I have made corresponding changes to the documentation
- [X] I have added tests that prove my fix is effective or that my feature works
- [X] New and existing unit tests pass locally with my changes (`tox -e testenv`)


Patch:
diff --git a/anta/custom_types.py b/anta/custom_types.py
index bacb641d..9e5c085f 100644
--- a/anta/custom_types.py
+++ b/anta/custom_types.py
@@ -419,3 +419,4 @@ ReloadCause = Annotated[
     Literal["System reloaded due to Zero Touch Provisioning", "Reload requested by the user.", "Reload requested after FPGA upgrade", "USER", "FPGA", "ZTP"],
     BeforeValidator(convert_reload_cause),
 ]
+BgpCommunity = Literal["standard", "extended", "large"]
diff --git a/anta/input_models/routing/bgp.py b/anta/input_models/routing/bgp.py
index 09def7fe..840edfcd 100644
--- a/anta/input_models/routing/bgp.py
+++ b/anta/input_models/routing/bgp.py
@@ -12,7 +12,7 @@ from warnings import warn
 from pydantic import BaseModel, ConfigDict, Field, PositiveInt, model_validator
 from pydantic_extra_types.mac_address import MacAddress
 
-from anta.custom_types import Afi, BgpDropStats, BgpUpdateError, MultiProtocolCaps, RedistributedAfiSafi, RedistributedProtocol, Safi, Vni
+from anta.custom_types import Afi, BgpCommunity, BgpDropStats, BgpUpdateError, MultiProtocolCaps, RedistributedAfiSafi, RedistributedProtocol, Safi, Vni
 
 if TYPE_CHECKING:
     import sys
@@ -196,6 +196,10 @@ class BgpPeer(BaseModel):
     """The Time-To-Live (TTL). Required field in the `VerifyBGPPeerTtlMultiHops` test."""
     max_ttl_hops: int | None = Field(default=None, ge=1, le=255)
     """The Max TTL hops. Required field in the `VerifyBGPPeerTtlMultiHops` test."""
+    advertised_communities: list[BgpCommunity] = Field(default=["standard", "extended", "large"])
+    """List of advertised communities to be verified.
+
+    Optional field in the `VerifyBGPAdvCommunities` test. If not provided, the test will verify that all communities are advertised."""
 
     def __str__(self) -> str:
         """Return a human-readable string representation of the BgpPeer for reporting."""


Test patch:
diff --git a/anta/tests/routing/bgp.py b/anta/tests/routing/bgp.py
index da4d757c..1398fac2 100644
--- a/anta/tests/routing/bgp.py
+++ b/anta/tests/routing/bgp.py
@@ -923,24 +923,21 @@ class VerifyEVPNType2Route(AntaTest):
 
 
 class VerifyBGPAdvCommunities(AntaTest):
-    """Verifies that advertised communities are standard, extended and large for BGP IPv4 peer(s).
+    """Verifies the advertised communities for BGP IPv4 peer(s).
 
     This test performs the following checks for each specified peer:
 
       1. Verifies that the peer is found in its VRF in the BGP configuration.
-      2. Validates that all required community types are advertised:
-        - Standard communities
-        - Extended communities
-        - Large communities
+      2. Validates that given community types are advertised. If not provided, validates that all communities (standard, extended, large) are advertised.
 
     Expected Results
     ----------------
     * Success: If all of the following conditions are met:
         - All specified peers are found in the BGP configuration.
-        - Each peer advertises standard, extended and large communities.
+        - Each peer advertises the given community types.
     * Failure: If any of the following occur:
         - A specified peer is not found in the BGP configuration.
-        - A peer does not advertise standard, extended or large communities.
+        - A peer does not advertise any of the given community types.
 
     Examples
     --------
@@ -953,6 +950,7 @@ class VerifyBGPAdvCommunities(AntaTest):
                 vrf: default
               - peer_address: 172.30.11.21
                 vrf: default
+                advertised_communities: ["standard", "extended"]
     ```
     """
 
@@ -983,7 +981,7 @@ class VerifyBGPAdvCommunities(AntaTest):
                 continue
 
             # Check BGP peer advertised communities
-            if not all(get_value(peer_data, f"advertisedCommunities.{community}") is True for community in ["standard", "extended", "large"]):
+            if not all(get_value(peer_data, f"advertisedCommunities.{community}") is True for community in peer.advertised_communities):
                 self.result.is_failure(f"{peer} - {format_data(peer_data['advertisedCommunities'])}")
 
 
diff --git a/examples/tests.yaml b/examples/tests.yaml
index a0cb8c0e..68eae415 100644
--- a/examples/tests.yaml
+++ b/examples/tests.yaml
@@ -387,12 +387,13 @@ anta.tests.ptp:
       # Verifies the PTP interfaces state.
 anta.tests.routing.bgp:
   - VerifyBGPAdvCommunities:
-      # Verifies that advertised communities are standard, extended and large for BGP IPv4 peer(s).
+      # Verifies the advertised communities for BGP IPv4 peer(s).
       bgp_peers:
         - peer_address: 172.30.11.17
           vrf: default
         - peer_address: 172.30.11.21
           vrf: default
+          advertised_communities: ["standard", "extended"]
   - VerifyBGPExchangedRoutes:
       # Verifies the advertised and received routes of BGP IPv4 peer(s).
       bgp_peers:
diff --git a/tests/units/anta_tests/routing/test_bgp.py b/tests/units/anta_tests/routing/test_bgp.py
index e26d452a..10624467 100644
--- a/tests/units/anta_tests/routing/test_bgp.py
+++ b/tests/units/anta_tests/routing/test_bgp.py
@@ -3231,6 +3231,47 @@ DATA: list[dict[str, Any]] = [
         },
         "expected": {"result": "success"},
     },
+    {
+        "name": "success-specified-communities",
+        "test": VerifyBGPAdvCommunities,
+        "eos_data": [
+            {
+                "vrfs": {
+                    "default": {
+                        "peerList": [
+                            {
+                                "peerAddress": "172.30.11.1",
+                                "advertisedCommunities": {
+                                    "standard": True,
+                                    "extended": True,
+                                    "large": False,
+                                },
+                            }
+                        ]
+                    },
+                    "MGMT": {
+                        "peerList": [
+                            {
+                                "peerAddress": "172.30.11.10",
+                                "advertisedCommunities": {
+                                    "standard": False,
+                                    "extended": True,
+                                    "large": False,
+                                },
+                            }
+                        ]
+                    },
+                }
+            }
+        ],
+        "inputs": {
+            "bgp_peers": [
+                {"peer_address": "172.30.11.1", "advertised_communities": ["standard", "extended"]},
+                {"peer_address": "172.30.11.10", "vrf": "MGMT", "advertised_communities": ["extended"]},
+            ]
+        },
+        "expected": {"result": "success"},
+    },
     {
         "name": "failure-no-peer",
         "test": VerifyBGPAdvCommunities,
@@ -3337,6 +3378,52 @@ DATA: list[dict[str, Any]] = [
             ],
         },
     },
+    {
+        "name": "failure-specified-communities",
+        "test": VerifyBGPAdvCommunities,
+        "eos_data": [
+            {
+                "vrfs": {
+                    "default": {
+                        "peerList": [
+                            {
+                                "peerAddress": "172.30.11.1",
+                                "advertisedCommunities": {
+                                    "standard": False,
+                                    "extended": False,
+                                    "large": False,
+                                },
+                            }
+                        ]
+                    },
+                    "MGMT": {
+                        "peerList": [
+                            {
+                                "peerAddress": "172.30.11.10",
+                                "advertisedCommunities": {
+                                    "standard": False,
+                                    "extended": True,
+                                    "large": False,
+                                },
+                            }
+                        ]
+                    },
+                }
+            }
+        ],
+        "inputs": {
+            "bgp_peers": [
+                {"peer_address": "172.30.11.1", "advertised_communities": ["standard", "extended"]},
+                {"peer_address": "172.30.11.10", "vrf": "MGMT", "advertised_communities": ["extended"]},
+            ]
+        },
+        "expected": {
+            "result": "failure",
+            "messages": [
+                "Peer: 172.30.11.1 VRF: default - Standard: False, Extended: False, Large: False",
+            ],
+        },
+    },
     {
         "name": "success",
         "test": VerifyBGPTimers,