Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix(eos_designs): Avoid in-place updates of network services impacting PyAVD #3544

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@ def _filtered_tenants(self) -> list[dict]:
tenants = convert_dicts(get(self._hostvars, network_services_key["name"]), "name")
for tenant in tenants:
if tenant["name"] in filter_tenants or "all" in filter_tenants:
tenant["l2vlans"] = self._filtered_l2vlans(tenant)
tenant["vrfs"] = self._filtered_vrfs(tenant)
filtered_tenants.append(tenant)
filtered_tenants.append(
{
**tenant,
"l2vlans": self._filtered_l2vlans(tenant),
"vrfs": self._filtered_vrfs(tenant),
}
)

no_vrf_default = all(vrf["name"] != "default" for tenant in filtered_tenants for vrf in tenant["vrfs"])
if self.shared_utils.wan_role is not None and no_vrf_default:
Expand Down Expand Up @@ -91,14 +95,12 @@ def _filtered_l2vlans(self, tenant: dict) -> list[dict]:

l2vlans: list[dict] = natural_sort(convert_dicts(tenant["l2vlans"], "id"), "id")
l2vlans = [
l2vlan
# Copy and set tenant key on all l2vlans
{**l2vlan, "tenant": tenant["name"]}
for l2vlan in l2vlans
if self._is_accepted_vlan(l2vlan)
and ("all" in self.shared_utils.filter_tags or set(l2vlan.get("tags", ["all"])).intersection(self.shared_utils.filter_tags))
]
# Set tenant key on all l2vlans
for l2vlan in l2vlans:
l2vlan.update({"tenant": tenant["name"]})

return l2vlans

Expand Down Expand Up @@ -161,9 +163,10 @@ def _filtered_vrfs(self, tenant: dict) -> list[dict]:
always_include_vrfs_in_tenants = get(self.shared_utils.switch_data_combined, "filter.always_include_vrfs_in_tenants", default=[])

vrfs: list[dict] = natural_sort(convert_dicts(tenant.get("vrfs", []), "name"), "name")
for vrf in vrfs:
# Storing tenant on VRF for use by child objects like SVIs
vrf["tenant"] = tenant["name"]
for original_vrf in vrfs:
# Copying original_vrf and setting "tenant" for use by child objects like SVIs
vrf = {**original_vrf, "tenant": tenant["name"]}

bgp_peers = natural_sort(convert_dicts(vrf.get("bgp_peers"), "ip_address"), "ip_address")
vrf["bgp_peers"] = [bgp_peer for bgp_peer in bgp_peers if self.shared_utils.hostname in bgp_peer.get("nodes", [])]
vrf["static_routes"] = [
Expand Down Expand Up @@ -224,15 +227,6 @@ def _filtered_vrfs(self, tenant: dict) -> list[dict]:
vrf["_evpn_l3_multicast_evpn_peg_transit"] = evpn_peg.get("transit")
break

if (
vrf["svis"]
or vrf["l3_interfaces"]
or vrf["loopbacks"]
or "all" in always_include_vrfs_in_tenants
or tenant["name"] in always_include_vrfs_in_tenants
):
filtered_vrfs.append(vrf)

vrf["additional_route_targets"] = [
rt
for rt in get(vrf, "additional_route_targets", default=[])
Expand All @@ -244,6 +238,15 @@ def _filtered_vrfs(self, tenant: dict) -> list[dict]:
)
]

if (
vrf["svis"]
or vrf["l3_interfaces"]
or vrf["loopbacks"]
or "all" in always_include_vrfs_in_tenants
or tenant["name"] in always_include_vrfs_in_tenants
):
filtered_vrfs.append(vrf)

return filtered_vrfs

@cached_property
Expand All @@ -254,11 +257,13 @@ def _svi_profiles(self) -> list[dict]:
The key "nodes" is filtered to only contain one item with the relevant dict from "nodes" or {}
"""
svi_profiles = convert_dicts(get(self._hostvars, "svi_profiles", default=[]), "profile")
for svi_profile in svi_profiles:
svi_profile["nodes"] = convert_dicts(svi_profile.get("nodes", []), "node")
svi_profile["nodes"] = [get_item(svi_profile["nodes"], "node", self.shared_utils.hostname, default={})]

return svi_profiles
return [
{
**svi_profile,
"nodes": [get_item(convert_dicts(svi_profile.get("nodes", []), "node"), "node", self.shared_utils.hostname, default={})],
}
for svi_profile in svi_profiles
]

def _get_merged_svi_config(self, svi: dict) -> list[dict]:
"""
Expand All @@ -277,10 +282,12 @@ def _get_merged_svi_config(self, svi: dict) -> list[dict]:
svi_profile = {"nodes": [{}]}
svi_parent_profile = {"nodes": [{}]}

svi["nodes"] = convert_dicts(svi.get("nodes", []), "node")
svi["nodes"] = [get_item(svi["nodes"], "node", self.shared_utils.hostname, default={})]
filtered_svi = {
**svi,
"nodes": [get_item(convert_dicts(svi.get("nodes", []), "node"), "node", self.shared_utils.hostname, default={})],
}

if (svi_profile_name := svi.get("profile")) is not None:
if (svi_profile_name := filtered_svi.get("profile")) is not None:
svi_profile = get_item(self._svi_profiles, "profile", svi_profile_name, default={})

if (svi_parent_profile_name := svi_profile.get("parent_profile")) is not None:
Expand All @@ -292,30 +299,30 @@ def _get_merged_svi_config(self, svi: dict) -> list[dict]:
merged_svi = merge(
svi_parent_profile,
svi_profile,
svi,
filtered_svi,
svi_parent_profile["nodes"][0],
svi_profile["nodes"][0],
svi["nodes"][0],
filtered_svi["nodes"][0],
list_merge="replace",
destructive_merge=False,
)

# Override structured configs since we don't want to deep-merge those
merged_svi["structured_config"] = default(
svi["nodes"][0].get("structured_config"),
filtered_svi["nodes"][0].get("structured_config"),
svi_profile["nodes"][0].get("structured_config"),
svi_parent_profile["nodes"][0].get("structured_config"),
svi.get("structured_config"),
filtered_svi.get("structured_config"),
svi_profile.get("structured_config"),
svi_parent_profile.get("structured_config"),
)

# Override bgp.structured configs since we don't want to deep-merge those
merged_svi.setdefault("bgp", {})["structured_config"] = default(
get(svi["nodes"][0], "bgp.structured_config"),
get(filtered_svi["nodes"][0], "bgp.structured_config"),
get(svi_profile["nodes"][0], "bgp.structured_config"),
get(svi_parent_profile["nodes"][0], "bgp.structured_config"),
get(svi, "bgp.structured_config"),
get(filtered_svi, "bgp.structured_config"),
get(svi_profile, "bgp.structured_config"),
get(svi_parent_profile, "bgp.structured_config"),
)
Expand Down
Loading