Python Declarative¶
If you were tasked to manage a set of VLANs, you may use an idempotent design to ensure that the VLAN existed. That would helpful in deploying new VLANs, but how would you ensure that only VLANs [10, 20, 30] existed and not any other? Using a traditional Cisco IOS cli, you would have to first understand which VLANs are on the configuration, e.g. [10, 15, 20] and VLANs that should not be present, and understand ones that need to be added.
Python Declarative Example¶
In the imperative approach, you must define how you add and remove VLANs, and that will be up for each developer to determine how to do so. This could result in various different mechanisms deployed, with various results expected.
>>> def add_vlan(add_vlans):
... for vlan in add_vlans:
... print("vlan {}".format(vlan))
... print(" name VLAN{}".format(vlan))
...
>>> def remove_vlan(removed_vlans):
... for vlan in remove_vlans:
... print("no vlan {}".format(vlan))
...
>>> expected_vlans = [30]
>>> remove_vlans = [15]
>>>
>>> add_vlan(expected_vlans)
vlan 30
name VLAN30
>>> remove_vlan(remove_vlans)
no vlan 15
>>>
However, in the declarative approach, you simply need to provide the end state:
>>> def declarative_vlan(existing_vlans, expected_vlans):
... persisted_vlans = list(set(expected_vlans).intersection(set(existing_vlans)))
... # shown for completeness, no functional value here
... add_vlans = list(set(expected_vlans).difference(set(existing_vlans)))
... remove_vlans = list(set(existing_vlans).difference(set(expected_vlans)))
... for vlan in add_vlans:
... print("vlan {}".format(vlan))
... print(" name VLAN{}".format(vlan))
... for vlan in remove_vlans:
... print("no vlan {}".format(vlan))
...
>>> existing_vlans = [10, 15, 20]
>>> expected_vlans = [10, 20, 30]
>>> declarative_vlan(existing_vlans, expected_vlans)
vlan 30
name VLAN30
no vlan 15
>>>
Info
The expected VLANs are given in this example for simplistic purposes only, in a real life example, you would expect to give a device or configuration, and the function to parse that out for you.
As you can see, the "steps" were still needed, e.g. the function had to determine which VLANs to add, and which VLANs to remove and build out that configuration. However, it is done one time for all occurrences afterwards, and each developer does not have to come up with their own solution.
Using declarative functions is far simpler to consume than to build, especially in the network space, but it is helpful to know how strategies on how to build them.
Python Declarative Example - LAB¶
In this short lab, take the existing function and work with different combinations of VLANS.
Python Declarative using Set Theory¶
Set theory can help you figure out how to build declarative functions. Let's say we have a large list of devices in our inventory and we need to compare which devices in our discovery engine that need to be added declaratively.
current_devices = ["nyc-rt01", "nyc-rt02", "nyc-rt03", "sfo-rt01", "sfo-rt02", "sfo-rt03", "lon-rt01", "lon-rt02", "lon-rt03"]
discovered_devices = ["nyc-rt01", "nyc-rt02", "nyc-rt03", "sfo-rt01", "sfo-rt02", "lon-rt01", "lon-rt02", "lon-rt03", "dal-rt01", "dal-rt02", "dal-rt03"]
pushed_devices = set(discovered_devices).difference(set(current_devices))
removed_devices = set(current_devices).difference(set(discovered_devices))
print(f"Update Devices {pushed_devices}")
print(f"Remove Devices {removed_devices}")
Python Declarative using Set Theory - LAB¶
Given the following vlan structure, build an declarative function using set theory with the provided starting code. The primary code should go in the generic function symmetric_difference_tuple. The symmetric_difference_tuple should be usable in other similar situations.
current_vlans = {
"200": "server",
"300": "desktop",
"400": "voice"
}
intended_vlans = {
"200": "server",
"350": "desktop",
"500": "video"
}
def symmetric_difference_tuple(current_set, wanted_set):
# Fill in here
# return (set, set)
pass
def create_vlan_declarative(current_vlans, intended_vlans):
return symmetric_difference_tuple(current_vlans, intended_vlans)
pushed_vlans, removed_vlans = create_vlan_declarative(current_vlans, intended_vlans)
print(f"Update VLANS {pushed_vlans}")
print(f"Remove VLANS {removed_vlans}")
Info
Hint: you send dict_items and receive a tuple of set's.