From 55ccf0abdb985c61954508677c024a164338f839 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:13:08 -0600 Subject: [PATCH 01/29] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20ability=20to=20?= =?UTF-8?q?rename=20Area=20if=20name=20key=20found=20and=20Building=20key?= =?UTF-8?q?=20not=20found=20in=20Location=20Map.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integrations/dna_center/diffsync/adapters/dna_center.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 8e763937..9d001e0c 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -179,9 +179,11 @@ def load_buildings(self, buildings: List[dict]): _area = self.dnac_location_map[location["parentId"]]["name"] _area_parent = self.dnac_location_map[location["parentId"]]["parent"] if _area in self.job.location_map and ( - "parent" in self.job.location_map[_area] and bldg_name not in self.job.location_map + self.job.location_map[_area].get("parent") and bldg_name not in self.job.location_map ): _area_parent = self.job.location_map[_area]["parent"] + if self.job.location_map[_area].get("name"): + _area = self.job.location_map[_area]["name"] if not settings.PLUGINS_CONFIG["nautobot_ssot"].get("dna_center_import_global"): if _area == "Global": _area = None From 6bc3b281be73d6414fb78f5abdc98418b9b7c9cc Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 13 Dec 2024 11:49:57 -0600 Subject: [PATCH 02/29] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Extract?= =?UTF-8?q?=20determination=20of=20device=20role=20into=20own=20function.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../diffsync/adapters/dna_center.py | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 9d001e0c..3edc0f51 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -312,12 +312,7 @@ def load_devices(self): } self.failed_import_devices.append(dev) continue - if self.job.hostname_map: - dev_role = parse_hostname_for_role( - hostname_map=self.job.hostname_map, device_hostname=dev["hostname"], default_role="Unknown" - ) - if dev_role == "Unknown": - dev_role = dev["role"] + dev_role = self.get_device_role(dev) if dev["softwareType"] in DNA_CENTER_LIB_MAPPER: platform = DNA_CENTER_LIB_MAPPER[dev["softwareType"]] else: @@ -401,6 +396,23 @@ def load_devices(self): } self.failed_import_devices.append(dev) + def get_device_role(self, dev): + """Get Device Role from Job Hostname map or DNA Center 'role'. + + Args: + dev (dict): Dictionary of information about Device from DNA Center. + + Returns: + str: Device role that has been determined from Hostname map or DNA Center information. + """ + if self.job.hostname_map: + dev_role = parse_hostname_for_role( + hostname_map=self.job.hostname_map, device_hostname=dev["hostname"], default_role="Unknown" + ) + if dev_role == "Unknown": + dev_role = dev["role"] + return dev_role + def load_ports(self, device_id: str, dev: DnaCenterDevice, mgmt_addr: str = ""): """Load port info from DNAC into Port DiffSyncModel. From d7f3c4feb198b66ad5a4f2fd335d0e446829f388 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Mon, 16 Dec 2024 20:31:27 -0600 Subject: [PATCH 03/29] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Refactor?= =?UTF-8?q?=20build=5Fdnac=5Flocation=5Fmap=20to=20integrate=20Job=20locat?= =?UTF-8?q?ion=5Fmap.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../diffsync/adapters/dna_center.py | 113 +++++++++--------- 1 file changed, 58 insertions(+), 55 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 3edc0f51..a79f45e6 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -55,6 +55,7 @@ def __init__(self, *args, job, sync=None, client: DnaCenterClient, tenant: Tenan self.conn = client self.failed_import_devices = [] self.dnac_location_map = {} + self.floors = [] self.tenant = tenant def load_locations(self): @@ -62,13 +63,64 @@ def load_locations(self): self.load_controller_locations() locations = self.conn.get_locations() if locations: - # to ensure we process locations in the appropriate order we need to split them into their own list of locations - self.dnac_location_map = self.build_dnac_location_map(locations) - _, buildings, floors = self.parse_and_sort_locations(locations) - self.load_buildings(buildings) - self.load_floors(floors) + self.floors = self.build_dnac_location_map(locations) else: - self.job.logger.error("No location data was returned from DNAC. Unable to proceed.") + self.job.logger.error("No location data was returned from DNA Center. Unable to proceed.") + + def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too-many-branches + """Build out the DNA Center location structure based off DNAC information or Job location_map field. + + Args: + locations (List[dict]): List of Locations from DNA Center to be separated. + """ + floors = [] + for location in locations: + if ( + not settings.PLUGINS_CONFIG["nautobot_ssot"].get("dna_center_import_global") + and location["name"] == "Global" + ): + continue + if location["name"] in self.job.location_map and self.job.location_map[location["name"]].get("name"): + loc_name = self.job.location_map[location["name"]]["name"] + else: + loc_name = location["name"] + self.dnac_location_map[location["id"]] = { + "name": loc_name, + "parent": None, + "parent_of_parent": None, + } + for location in locations: # pylint: disable=too-many-nested-blocks + loc_id = location["id"] + loc_name = location["name"] + parent_id, parent_name = None, None + if location.get("parentId"): + parent_id = location["parentId"] + if self.dnac_location_map.get(parent_id): + parent_name = self.dnac_location_map[parent_id]["name"] + if not settings.PLUGINS_CONFIG["nautobot_ssot"].get("dna_center_import_global"): + if loc_name == "Global": + continue + if parent_name == "Global": + parent_name = None + self.dnac_location_map[loc_id]["parent"] = parent_name + for info in location["additionalInfo"]: + if info["attributes"].get("type"): + self.dnac_location_map[loc_id]["loc_type"] = info["attributes"]["type"] + if info["attributes"]["type"] in ["area", "building"]: + if info["attributes"]["type"] == "building" and loc_name in self.job.location_map: + if self.job.location_map[loc_name].get("parent"): + self.dnac_location_map[loc_id]["parent"] = self.job.location_map[loc_name]["parent"] + if self.job.location_map[loc_name].get("area_parent"): + self.dnac_location_map[loc_id]["parent_of_parent"] = self.job.location_map[loc_name][ + "area_parent" + ] + else: + self.dnac_location_map[loc_id]["parent_of_parent"] = parent_name + if info["attributes"]["type"] == "floor": + floors.append(location) + if parent_name in self.job.location_map and self.dnac_location_map[parent_id].get("name"): + self.dnac_location_map[loc_id]["parent"] = self.dnac_location_map[parent_id]["name"] + return floors def load_controller_locations(self): """Load location data for Controller specified in Job form.""" @@ -243,55 +295,6 @@ def load_floors(self, floors: List[dict]): f"Unable to find {self.job.building_loctype.name} {bldg_name} for {self.job.floor_loctype.name} {floor_name}. {err}" ) - def parse_and_sort_locations(self, locations: List[dict]): - """Separate locations into areas, buildings, and floors for processing. Also sort by siteHierarchy. - - Args: - locations (List[dict]): List of Locations (Sites) from DNAC to be separated. - - Returns: - tuple (List[dict], List[dict], List[dict]): Tuple containing lists of areas, buildings, and floors in DNAC to be processed. - """ - areas, buildings, floors = [], [], [] - for location in locations: - self.dnac_location_map[location["id"]] = {"name": location["name"], "loc_type": "area"} - for location in locations: - for info in location["additionalInfo"]: - if info["attributes"].get("type") == "building": - buildings.append(location) - self.dnac_location_map[location["id"]]["loc_type"] = "building" - break - if info["attributes"].get("type") == "floor": - floors.append(location) - self.dnac_location_map[location["id"]]["loc_type"] = "floor" - break - else: - areas.append(location) - if location.get("parentId") and location["parentId"] in self.dnac_location_map: - self.dnac_location_map[location["id"]]["parent"] = self.dnac_location_map[location["parentId"]]["name"] - else: - self.dnac_location_map[location["id"]]["parent"] = None - # sort areas by length of siteHierarchy so that parent areas loaded before child areas. - areas = sorted(areas, key=lambda x: len(x["siteHierarchy"].split("/"))) - return areas, buildings, floors - - def build_dnac_location_map(self, locations: List[dict]): - """Build out the initial DNAC location map for Location ID to name and type. - - Args: - locations (List[dict]): List of Locations (Sites) from DNAC. - - Returns: - dict: Dictionary of Locations mapped with ID to their name and location type. - """ - location_map = {} - for loc in locations: - if not settings.PLUGINS_CONFIG["nautobot_ssot"].get("dna_center_import_global"): - if loc["name"] == "Global": - continue - location_map[loc["id"]] = {"name": loc["name"], "parent": None, "loc_type": "area"} - return location_map - def load_devices(self): """Load Device data from DNA Center info DiffSync models.""" devices = self.conn.get_devices() From da5a089c5aba69036011f42e669dc582d2b0c7d2 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Mon, 16 Dec 2024 20:53:43 -0600 Subject: [PATCH 04/29] =?UTF-8?q?test:=20=E2=9C=85=20Update=20tests=20to?= =?UTF-8?q?=20adjust=20for=20refactor=20of=20build=5Fdnac=5Flocation=5Fmap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nautobot_ssot/tests/dna_center/fixtures.py | 6 +- .../dna_center/fixtures/expected_areas.json | 299 ------------------ .../fixtures/expected_areas_wo_global.json | 291 ----------------- .../fixtures/expected_buildings.json | 169 ---------- .../fixtures/expected_dnac_location_map.json | 93 ++++-- ..._dnac_location_map_w_job_location_map.json | 157 +++++++++ .../expected_dnac_location_map_wo_global.json | 90 ++++-- .../dna_center/test_adapters_dna_center.py | 209 ++---------- 8 files changed, 300 insertions(+), 1014 deletions(-) delete mode 100644 nautobot_ssot/tests/dna_center/fixtures/expected_areas.json delete mode 100644 nautobot_ssot/tests/dna_center/fixtures/expected_areas_wo_global.json delete mode 100644 nautobot_ssot/tests/dna_center/fixtures/expected_buildings.json create mode 100644 nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_w_job_location_map.json diff --git a/nautobot_ssot/tests/dna_center/fixtures.py b/nautobot_ssot/tests/dna_center/fixtures.py index 3aefc978..720877ce 100644 --- a/nautobot_ssot/tests/dna_center/fixtures.py +++ b/nautobot_ssot/tests/dna_center/fixtures.py @@ -14,6 +14,9 @@ def load_json(path): EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL = load_json( path="./nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_wo_global.json" ) +EXPECTED_DNAC_LOCATION_MAP_W_JOB_LOCATION_MAP = load_json( + path="./nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_w_job_location_map.json" +) RECV_LOCATION_FIXTURE = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/get_locations_recv.json") DEVICE_FIXTURE = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/get_devices.json") RECV_DEVICE_FIXTURE = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/get_devices_recv.json") @@ -22,7 +25,4 @@ def load_json(path): PORT_FIXTURE = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/get_port_info.json") RECV_PORT_FIXTURE = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/get_port_info_recv.json") -EXPECTED_AREAS = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/expected_areas.json") -EXPECTED_AREAS_WO_GLOBAL = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/expected_areas_wo_global.json") -EXPECTED_BUILDINGS = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/expected_buildings.json") EXPECTED_FLOORS = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/expected_floors.json") diff --git a/nautobot_ssot/tests/dna_center/fixtures/expected_areas.json b/nautobot_ssot/tests/dna_center/fixtures/expected_areas.json deleted file mode 100644 index f607c6e6..00000000 --- a/nautobot_ssot/tests/dna_center/fixtures/expected_areas.json +++ /dev/null @@ -1,299 +0,0 @@ -[ - { - "additionalInfo": [], - "name": "Global", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "siteNameHierarchy": "Global" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "eed5ccc3-d76f-46e2-9d8d-97624f5418ac", - "type": "area" - } - } - ], - "name": "SanJose", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "eed5ccc3-d76f-46e2-9d8d-97624f5418ac", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/eed5ccc3-d76f-46e2-9d8d-97624f5418ac", - "siteNameHierarchy": "Global/SanJose" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "cf1746d3-4de0-4ef5-bd3a-a5e51191eee1", - "type": "area" - } - } - ], - "name": "OZ", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "cf1746d3-4de0-4ef5-bd3a-a5e51191eee1", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/cf1746d3-4de0-4ef5-bd3a-a5e51191eee1", - "siteNameHierarchy": "Global/OZ" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "04509ce4-6c88-40a3-b444-9e00f2cd97f2", - "type": "area" - } - } - ], - "name": "SanDiego", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "04509ce4-6c88-40a3-b444-9e00f2cd97f2", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/04509ce4-6c88-40a3-b444-9e00f2cd97f2", - "siteNameHierarchy": "Global/SanDiego" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "73b2f82c-413e-439e-a614-0ab0d0378114", - "type": "area" - } - } - ], - "name": "Antartica2", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "73b2f82c-413e-439e-a614-0ab0d0378114", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/73b2f82c-413e-439e-a614-0ab0d0378114", - "siteNameHierarchy": "Global/Antartica2" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "4e84a340-efdb-4f06-878f-3235173036ef", - "type": "area" - } - } - ], - "name": "Antartica3", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "4e84a340-efdb-4f06-878f-3235173036ef", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/4e84a340-efdb-4f06-878f-3235173036ef", - "siteNameHierarchy": "Global/Antartica3" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "20d34f71-f4db-4833-90f7-4208a349f876", - "type": "area" - } - } - ], - "name": "Antartica", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "20d34f71-f4db-4833-90f7-4208a349f876", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/20d34f71-f4db-4833-90f7-4208a349f876", - "siteNameHierarchy": "Global/Antartica" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "262696b1-aa87-432b-8a21-db9a77c51f23", - "type": "area" - } - } - ], - "name": "Australia", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "262696b1-aa87-432b-8a21-db9a77c51f23", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/262696b1-aa87-432b-8a21-db9a77c51f23", - "siteNameHierarchy": "Global/Australia" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "63a7fb03-d4b2-408e-a6ab-b4df0a198643", - "type": "area" - } - } - ], - "name": "Sydney", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "63a7fb03-d4b2-408e-a6ab-b4df0a198643", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/63a7fb03-d4b2-408e-a6ab-b4df0a198643", - "siteNameHierarchy": "Global/Sydney" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "f5a19514-3c1e-4127-a2b5-2a64a963c934", - "type": "area" - } - } - ], - "name": "Area_52", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "f5a19514-3c1e-4127-a2b5-2a64a963c934", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f5a19514-3c1e-4127-a2b5-2a64a963c934", - "siteNameHierarchy": "Global/Area_52" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "fa22b4e1-ee80-4aa8-8d76-83c4126d16ee", - "type": "area" - } - } - ], - "name": "Area_51", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "fa22b4e1-ee80-4aa8-8d76-83c4126d16ee", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/fa22b4e1-ee80-4aa8-8d76-83c4126d16ee", - "siteNameHierarchy": "Global/Area_51" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661", - "type": "area" - } - } - ], - "name": "Area_51a", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661", - "siteNameHierarchy": "Global/Area_51a" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "7760b82a-b07e-4fa7-8cad-91adfa12dd43", - "type": "area" - } - } - ], - "name": "Area 51", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "7760b82a-b07e-4fa7-8cad-91adfa12dd43", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/7760b82a-b07e-4fa7-8cad-91adfa12dd43", - "siteNameHierarchy": "Global/Area 51" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "5c882916-4f65-45b5-a5cc-ca5fa927cba6", - "type": "area" - } - } - ], - "name": "Forschungszentrum", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "5c882916-4f65-45b5-a5cc-ca5fa927cba6", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/5c882916-4f65-45b5-a5cc-ca5fa927cba6", - "siteNameHierarchy": "Global/Forschungszentrum" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "257c51d3-971d-49f4-83f7-c9baf334865a", - "type": "area" - } - } - ], - "name": "Texas", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "257c51d3-971d-49f4-83f7-c9baf334865a", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/257c51d3-971d-49f4-83f7-c9baf334865a", - "siteNameHierarchy": "Global/Texas" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "f372dbbb-d689-4d9a-9a5e-887de33fbce5", - "type": "area" - } - } - ], - "name": "Maryland", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "f372dbbb-d689-4d9a-9a5e-887de33fbce5", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f372dbbb-d689-4d9a-9a5e-887de33fbce5", - "siteNameHierarchy": "Global/Maryland" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "8004668a-eb96-47cc-b659-bcc9c04669ba", - "type": "area" - } - } - ], - "name": "Treton", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "8004668a-eb96-47cc-b659-bcc9c04669ba", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/8004668a-eb96-47cc-b659-bcc9c04669ba", - "siteNameHierarchy": "Global/Treton" - }, - { - "parentId": "262696b1-aa87-432b-8a21-db9a77c51f23", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "262696b1-aa87-432b-8a21-db9a77c51f23", - "type": "area" - } - } - ], - "name": "Sydney", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "6e404051-4c06-4dab-adaa-72c5eeac577b", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/262696b1-aa87-432b-8a21-db9a77c51f23/6e404051-4c06-4dab-adaa-72c5eeac577b", - "siteNameHierarchy": "Global/Australia/Sydney" - } -] \ No newline at end of file diff --git a/nautobot_ssot/tests/dna_center/fixtures/expected_areas_wo_global.json b/nautobot_ssot/tests/dna_center/fixtures/expected_areas_wo_global.json deleted file mode 100644 index 996a7368..00000000 --- a/nautobot_ssot/tests/dna_center/fixtures/expected_areas_wo_global.json +++ /dev/null @@ -1,291 +0,0 @@ -[ - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "eed5ccc3-d76f-46e2-9d8d-97624f5418ac", - "type": "area" - } - } - ], - "name": "SanJose", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "eed5ccc3-d76f-46e2-9d8d-97624f5418ac", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/eed5ccc3-d76f-46e2-9d8d-97624f5418ac", - "siteNameHierarchy": "Global/SanJose" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "cf1746d3-4de0-4ef5-bd3a-a5e51191eee1", - "type": "area" - } - } - ], - "name": "OZ", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "cf1746d3-4de0-4ef5-bd3a-a5e51191eee1", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/cf1746d3-4de0-4ef5-bd3a-a5e51191eee1", - "siteNameHierarchy": "Global/OZ" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "04509ce4-6c88-40a3-b444-9e00f2cd97f2", - "type": "area" - } - } - ], - "name": "SanDiego", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "04509ce4-6c88-40a3-b444-9e00f2cd97f2", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/04509ce4-6c88-40a3-b444-9e00f2cd97f2", - "siteNameHierarchy": "Global/SanDiego" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "73b2f82c-413e-439e-a614-0ab0d0378114", - "type": "area" - } - } - ], - "name": "Antartica2", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "73b2f82c-413e-439e-a614-0ab0d0378114", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/73b2f82c-413e-439e-a614-0ab0d0378114", - "siteNameHierarchy": "Global/Antartica2" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "4e84a340-efdb-4f06-878f-3235173036ef", - "type": "area" - } - } - ], - "name": "Antartica3", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "4e84a340-efdb-4f06-878f-3235173036ef", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/4e84a340-efdb-4f06-878f-3235173036ef", - "siteNameHierarchy": "Global/Antartica3" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "20d34f71-f4db-4833-90f7-4208a349f876", - "type": "area" - } - } - ], - "name": "Antartica", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "20d34f71-f4db-4833-90f7-4208a349f876", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/20d34f71-f4db-4833-90f7-4208a349f876", - "siteNameHierarchy": "Global/Antartica" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "262696b1-aa87-432b-8a21-db9a77c51f23", - "type": "area" - } - } - ], - "name": "Australia", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "262696b1-aa87-432b-8a21-db9a77c51f23", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/262696b1-aa87-432b-8a21-db9a77c51f23", - "siteNameHierarchy": "Global/Australia" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "63a7fb03-d4b2-408e-a6ab-b4df0a198643", - "type": "area" - } - } - ], - "name": "Sydney", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "63a7fb03-d4b2-408e-a6ab-b4df0a198643", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/63a7fb03-d4b2-408e-a6ab-b4df0a198643", - "siteNameHierarchy": "Global/Sydney" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "f5a19514-3c1e-4127-a2b5-2a64a963c934", - "type": "area" - } - } - ], - "name": "Area_52", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "f5a19514-3c1e-4127-a2b5-2a64a963c934", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f5a19514-3c1e-4127-a2b5-2a64a963c934", - "siteNameHierarchy": "Global/Area_52" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "fa22b4e1-ee80-4aa8-8d76-83c4126d16ee", - "type": "area" - } - } - ], - "name": "Area_51", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "fa22b4e1-ee80-4aa8-8d76-83c4126d16ee", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/fa22b4e1-ee80-4aa8-8d76-83c4126d16ee", - "siteNameHierarchy": "Global/Area_51" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661", - "type": "area" - } - } - ], - "name": "Area_51a", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661", - "siteNameHierarchy": "Global/Area_51a" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "7760b82a-b07e-4fa7-8cad-91adfa12dd43", - "type": "area" - } - } - ], - "name": "Area 51", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "7760b82a-b07e-4fa7-8cad-91adfa12dd43", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/7760b82a-b07e-4fa7-8cad-91adfa12dd43", - "siteNameHierarchy": "Global/Area 51" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "5c882916-4f65-45b5-a5cc-ca5fa927cba6", - "type": "area" - } - } - ], - "name": "Forschungszentrum", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "5c882916-4f65-45b5-a5cc-ca5fa927cba6", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/5c882916-4f65-45b5-a5cc-ca5fa927cba6", - "siteNameHierarchy": "Global/Forschungszentrum" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "257c51d3-971d-49f4-83f7-c9baf334865a", - "type": "area" - } - } - ], - "name": "Texas", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "257c51d3-971d-49f4-83f7-c9baf334865a", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/257c51d3-971d-49f4-83f7-c9baf334865a", - "siteNameHierarchy": "Global/Texas" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "f372dbbb-d689-4d9a-9a5e-887de33fbce5", - "type": "area" - } - } - ], - "name": "Maryland", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "f372dbbb-d689-4d9a-9a5e-887de33fbce5", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f372dbbb-d689-4d9a-9a5e-887de33fbce5", - "siteNameHierarchy": "Global/Maryland" - }, - { - "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "8004668a-eb96-47cc-b659-bcc9c04669ba", - "type": "area" - } - } - ], - "name": "Treton", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "8004668a-eb96-47cc-b659-bcc9c04669ba", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/8004668a-eb96-47cc-b659-bcc9c04669ba", - "siteNameHierarchy": "Global/Treton" - }, - { - "parentId": "262696b1-aa87-432b-8a21-db9a77c51f23", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "addressInheritedFrom": "262696b1-aa87-432b-8a21-db9a77c51f23", - "type": "area" - } - } - ], - "name": "Sydney", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "6e404051-4c06-4dab-adaa-72c5eeac577b", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/262696b1-aa87-432b-8a21-db9a77c51f23/6e404051-4c06-4dab-adaa-72c5eeac577b", - "siteNameHierarchy": "Global/Australia/Sydney" - } -] \ No newline at end of file diff --git a/nautobot_ssot/tests/dna_center/fixtures/expected_buildings.json b/nautobot_ssot/tests/dna_center/fixtures/expected_buildings.json deleted file mode 100644 index fb3910f7..00000000 --- a/nautobot_ssot/tests/dna_center/fixtures/expected_buildings.json +++ /dev/null @@ -1,169 +0,0 @@ -[ - { - "parentId": "eed5ccc3-d76f-46e2-9d8d-97624f5418ac", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "country": "United States", - "address": "1000 I Street, Sacramento, California 95814, United States", - "latitude": "38.581405819248886", - "addressInheritedFrom": "5c59e37a-f12d-4e84-a085-ac5c02f240d4", - "type": "building", - "longitude": "-121.49309067224416" - } - } - ], - "name": "Building1", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "5c59e37a-f12d-4e84-a085-ac5c02f240d4", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/eed5ccc3-d76f-46e2-9d8d-97624f5418ac/5c59e37a-f12d-4e84-a085-ac5c02f240d4", - "siteNameHierarchy": "Global/SanJose/Building1" - }, - { - "parentId": "257c51d3-971d-49f4-83f7-c9baf334865a", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "country": "Vietnam", - "latitude": "38.10344327099361", - "addressInheritedFrom": "257c51d3-971d-49f4-83f7-c9baf334865a", - "type": "building", - "longitude": "-70.53258776522935" - } - } - ], - "name": "VN_1", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "6e1ebb51-62cd-400f-b130-a6959d81e775", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/257c51d3-971d-49f4-83f7-c9baf334865a/6e1ebb51-62cd-400f-b130-a6959d81e775", - "siteNameHierarchy": "Global/Texas/VN_1" - }, - { - "parentId": "7760b82a-b07e-4fa7-8cad-91adfa12dd43", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "country": "United States", - "address": "Mercury, NV 89023", - "latitude": "36.632621", - "addressInheritedFrom": "331f7e36-1a45-4c9f-bfa9-3425a053f81a", - "type": "building", - "longitude": "-115.934912" - } - } - ], - "name": "Deep Space", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "331f7e36-1a45-4c9f-bfa9-3425a053f81a", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/7760b82a-b07e-4fa7-8cad-91adfa12dd43/331f7e36-1a45-4c9f-bfa9-3425a053f81a", - "siteNameHierarchy": "Global/Area 51/Deep Space" - }, - { - "parentId": "257c51d3-971d-49f4-83f7-c9baf334865a", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "country": "United States", - "address": "County Road 186, Brookesmith, Texas 76827, United States", - "latitude": "31.559432441659325", - "addressInheritedFrom": "398de1d9-d595-429d-8239-64b51d24f230", - "type": "building", - "longitude": "-99.19356001285279" - } - } - ], - "name": "Texas_building", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "398de1d9-d595-429d-8239-64b51d24f230", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/257c51d3-971d-49f4-83f7-c9baf334865a/398de1d9-d595-429d-8239-64b51d24f230", - "siteNameHierarchy": "Global/Texas/Texas_building" - }, - { - "parentId": "5c882916-4f65-45b5-a5cc-ca5fa927cba6", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "country": "Germany", - "address": "Wallstadter Straße 59, 68526 Ladenburg", - "latitude": "49.479617", - "addressInheritedFrom": "1c3bb089-2a74-4fdf-96e3-d1815ac67e38", - "type": "building", - "longitude": "8.602459" - } - } - ], - "name": "Building 1", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "1c3bb089-2a74-4fdf-96e3-d1815ac67e38", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/5c882916-4f65-45b5-a5cc-ca5fa927cba6/1c3bb089-2a74-4fdf-96e3-d1815ac67e38", - "siteNameHierarchy": "Global/Forschungszentrum/Building 1" - }, - { - "parentId": "04509ce4-6c88-40a3-b444-9e00f2cd97f2", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "country": "United States", - "address": "Ocean Drive Bar & Restaurant, 3915 Landis Ave, Sea Isle City, New Jersey 08243, United States", - "latitude": "39.156233", - "addressInheritedFrom": "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738", - "type": "building", - "longitude": "-74.690192" - } - } - ], - "name": "1", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/04509ce4-6c88-40a3-b444-9e00f2cd97f2/2d0d8545-b6de-4dda-a0f7-93bcd7d0e738", - "siteNameHierarchy": "Global/SanDiego/1" - }, - { - "parentId": "f372dbbb-d689-4d9a-9a5e-887de33fbce5", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "country": "United States", - "address": "123 Main Street", - "latitude": "39.0458", - "addressInheritedFrom": "755faf69-0d07-48f7-b130-4806c32eb13e", - "type": "building", - "longitude": "-76.6413" - } - } - ], - "name": "secretlab", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "755faf69-0d07-48f7-b130-4806c32eb13e", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f372dbbb-d689-4d9a-9a5e-887de33fbce5/755faf69-0d07-48f7-b130-4806c32eb13e", - "siteNameHierarchy": "Global/Maryland/secretlab" - }, - { - "parentId": "8004668a-eb96-47cc-b659-bcc9c04669ba", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "country": "United States", - "address": "51 West Center Road Southeast, Rome, Georgia 30161, United States", - "latitude": "34.237896413975506", - "addressInheritedFrom": "fedd8d33-5334-413f-8a49-fb2459d7e337", - "type": "building", - "longitude": "-85.13241190760431" - } - } - ], - "name": "Rome", - "instanceTenantId": "623f029857259506a56ad9bd", - "id": "fedd8d33-5334-413f-8a49-fb2459d7e337", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/8004668a-eb96-47cc-b659-bcc9c04669ba/fedd8d33-5334-413f-8a49-fb2459d7e337", - "siteNameHierarchy": "Global/Treton/Rome" - } -] \ No newline at end of file diff --git a/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map.json b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map.json index cf93cadd..9595c483 100644 --- a/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map.json +++ b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map.json @@ -2,156 +2,187 @@ "9e5f9fc2-032e-45e8-994c-4a00629648e8": { "name": "Global", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "eed5ccc3-d76f-46e2-9d8d-97624f5418ac": { "name": "SanJose", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "5c59e37a-f12d-4e84-a085-ac5c02f240d4": { "name": "Building1", "loc_type": "building", - "parent": "SanJose" + "parent": "SanJose", + "parent_of_parent": null }, "49aa97a7-5d45-4303-89dd-f76dfbfc624a": { "name": "Floor1", "loc_type": "floor", - "parent": "Building1" + "parent": "Building1", + "parent_of_parent": null }, "925f1a03-05df-4d9a-b2e0-db1989367138": { "name": "1", "loc_type": "floor", - "parent": "1" + "parent": "1", + "parent_of_parent": null }, "cf1746d3-4de0-4ef5-bd3a-a5e51191eee1": { "name": "OZ", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "04509ce4-6c88-40a3-b444-9e00f2cd97f2": { "name": "SanDiego", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "73b2f82c-413e-439e-a614-0ab0d0378114": { "name": "Antartica2", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "4e84a340-efdb-4f06-878f-3235173036ef": { "name": "Antartica3", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "6e1ebb51-62cd-400f-b130-a6959d81e775": { "name": "VN_1", "loc_type": "building", - "parent": "Texas" + "parent": "Texas", + "parent_of_parent": null }, "20d34f71-f4db-4833-90f7-4208a349f876": { "name": "Antartica", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "262696b1-aa87-432b-8a21-db9a77c51f23": { "name": "Australia", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "6e404051-4c06-4dab-adaa-72c5eeac577b": { "name": "Sydney", "loc_type": "area", - "parent": "Australia" + "parent": "Australia", + "parent_of_parent": null }, "63a7fb03-d4b2-408e-a6ab-b4df0a198643": { "name": "Sydney", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "f5a19514-3c1e-4127-a2b5-2a64a963c934": { "name": "Area_52", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "fa22b4e1-ee80-4aa8-8d76-83c4126d16ee": { "name": "Area_51", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661": { "name": "Area_51a", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "7760b82a-b07e-4fa7-8cad-91adfa12dd43": { "name": "Area 51", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "331f7e36-1a45-4c9f-bfa9-3425a053f81a": { "name": "Deep Space", "loc_type": "building", - "parent": "Area 51" + "parent": "Area 51", + "parent_of_parent": null }, "42a47e36-01ea-4189-8e54-16a2fd063648": { "name": "1st Floor", "loc_type": "floor", - "parent": "Deep Space" + "parent": "Deep Space", + "parent_of_parent": null }, "398de1d9-d595-429d-8239-64b51d24f230": { "name": "Texas_building", "loc_type": "building", - "parent": "Texas" + "parent": "Texas", + "parent_of_parent": null }, "5c882916-4f65-45b5-a5cc-ca5fa927cba6": { "name": "Forschungszentrum", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "1c3bb089-2a74-4fdf-96e3-d1815ac67e38": { "name": "Building 1", "loc_type": "building", - "parent": "Forschungszentrum" + "parent": "Forschungszentrum", + "parent_of_parent": null }, "0b1f8f7f-f0be-4d14-974d-69b1693d39ec": { "name": "Lab", "loc_type": "floor", - "parent": "Building 1" + "parent": "Building 1", + "parent_of_parent": null }, "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738": { "name": "1", "loc_type": "building", - "parent": "SanDiego" + "parent": "SanDiego", + "parent_of_parent": null }, "257c51d3-971d-49f4-83f7-c9baf334865a": { "name": "Texas", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "f372dbbb-d689-4d9a-9a5e-887de33fbce5": { "name": "Maryland", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "8004668a-eb96-47cc-b659-bcc9c04669ba": { "name": "Treton", "loc_type": "area", - "parent": "Global" + "parent": "Global", + "parent_of_parent": null }, "755faf69-0d07-48f7-b130-4806c32eb13e": { "name": "secretlab", "loc_type": "building", - "parent": "Maryland" + "parent": "Maryland", + "parent_of_parent": null }, "fedd8d33-5334-413f-8a49-fb2459d7e337": { "name": "Rome", "loc_type": "building", - "parent": "Treton" + "parent": "Treton", + "parent_of_parent": null }, "f4ff8ca1-c062-4228-868a-d6cd0bc53852": { "name": "Floor 2", "loc_type": "floor", - "parent": "secretlab" + "parent": "secretlab", + "parent_of_parent": null } } \ No newline at end of file diff --git a/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_w_job_location_map.json b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_w_job_location_map.json new file mode 100644 index 00000000..46ea33e7 --- /dev/null +++ b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_w_job_location_map.json @@ -0,0 +1,157 @@ +{ + "9e5f9fc2-032e-45e8-994c-4a00629648e8": { + "name": "Global", + "parent": null, + "parent_of_parent": null + }, + "eed5ccc3-d76f-46e2-9d8d-97624f5418ac": { + "name": "San Jose", + "parent": "California", + "parent_of_parent": "USA" + }, + "5c59e37a-f12d-4e84-a085-ac5c02f240d4": { + "name": "Building1", + "parent": "San Jose", + "parent_of_parent": null + }, + "49aa97a7-5d45-4303-89dd-f76dfbfc624a": { + "name": "Floor1", + "parent": "Building1", + "parent_of_parent": null + }, + "925f1a03-05df-4d9a-b2e0-db1989367138": { + "name": "1", + "parent": "1", + "parent_of_parent": null + }, + "cf1746d3-4de0-4ef5-bd3a-a5e51191eee1": { + "name": "OZ", + "parent": "Global", + "parent_of_parent": null + }, + "04509ce4-6c88-40a3-b444-9e00f2cd97f2": { + "name": "SanDiego", + "parent": "Global", + "parent_of_parent": null + }, + "73b2f82c-413e-439e-a614-0ab0d0378114": { + "name": "South Pole", + "parent": "Global", + "parent_of_parent": null + }, + "4e84a340-efdb-4f06-878f-3235173036ef": { + "name": "Antartica3", + "parent": "Global", + "parent_of_parent": null + }, + "6e1ebb51-62cd-400f-b130-a6959d81e775": { + "name": "VN_1", + "parent": "Texas", + "parent_of_parent": null + }, + "20d34f71-f4db-4833-90f7-4208a349f876": { + "name": "Antartica", + "parent": "Global", + "parent_of_parent": null + }, + "262696b1-aa87-432b-8a21-db9a77c51f23": { + "name": "Australia", + "parent": "Global", + "parent_of_parent": null + }, + "6e404051-4c06-4dab-adaa-72c5eeac577b": { + "name": "Sydney", + "parent": "Australia", + "parent_of_parent": null + }, + "63a7fb03-d4b2-408e-a6ab-b4df0a198643": { + "name": "Sydney", + "parent": "Global", + "parent_of_parent": null + }, + "f5a19514-3c1e-4127-a2b5-2a64a963c934": { + "name": "Area_52", + "parent": "Global", + "parent_of_parent": null + }, + "fa22b4e1-ee80-4aa8-8d76-83c4126d16ee": { + "name": "Area_51", + "parent": "Global", + "parent_of_parent": null + }, + "f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661": { + "name": "Area_51a", + "parent": "Global", + "parent_of_parent": null + }, + "7760b82a-b07e-4fa7-8cad-91adfa12dd43": { + "name": "Area 51", + "parent": "Global", + "parent_of_parent": null + }, + "331f7e36-1a45-4c9f-bfa9-3425a053f81a": { + "name": "Deep Space", + "parent": "Area 51", + "parent_of_parent": null + }, + "42a47e36-01ea-4189-8e54-16a2fd063648": { + "name": "1st Floor", + "parent": "Deep Space", + "parent_of_parent": null + }, + "398de1d9-d595-429d-8239-64b51d24f230": { + "name": "Texas_building", + "parent": "Texas", + "parent_of_parent": null + }, + "5c882916-4f65-45b5-a5cc-ca5fa927cba6": { + "name": "Forschungszentrum", + "parent": "Global", + "parent_of_parent": null + }, + "1c3bb089-2a74-4fdf-96e3-d1815ac67e38": { + "name": "Building 1", + "parent": "Forschungszentrum", + "parent_of_parent": null + }, + "0b1f8f7f-f0be-4d14-974d-69b1693d39ec": { + "name": "Lab", + "parent": "Building 1", + "parent_of_parent": null + }, + "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738": { + "name": "1", + "parent": "SanDiego", + "parent_of_parent": null + }, + "257c51d3-971d-49f4-83f7-c9baf334865a": { + "name": "Texas", + "parent": "Global", + "parent_of_parent": null + }, + "f372dbbb-d689-4d9a-9a5e-887de33fbce5": { + "name": "Maryland", + "parent": "Global", + "parent_of_parent": null + }, + "8004668a-eb96-47cc-b659-bcc9c04669ba": { + "name": "Treton", + "parent": "Global", + "parent_of_parent": null + }, + "755faf69-0d07-48f7-b130-4806c32eb13e": { + "name": "secretlab", + "parent": "Maryland", + "parent_of_parent": null + }, + "fedd8d33-5334-413f-8a49-fb2459d7e337": { + "name": "Rome", + "parent": "Treton", + "parent_of_parent": null + }, + "f4ff8ca1-c062-4228-868a-d6cd0bc53852": { + "name": "Floor 2", + "parent": "secretlab", + "parent_of_parent": null + } +} \ No newline at end of file diff --git a/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_wo_global.json b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_wo_global.json index 235936b1..f46f3e32 100644 --- a/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_wo_global.json +++ b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_wo_global.json @@ -2,151 +2,181 @@ "eed5ccc3-d76f-46e2-9d8d-97624f5418ac": { "name": "SanJose", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "5c59e37a-f12d-4e84-a085-ac5c02f240d4": { "name": "Building1", "loc_type": "building", - "parent": "SanJose" + "parent": "SanJose", + "parent_of_parent": null }, "49aa97a7-5d45-4303-89dd-f76dfbfc624a": { "name": "Floor1", "loc_type": "floor", - "parent": "Building1" + "parent": "Building1", + "parent_of_parent": null }, "925f1a03-05df-4d9a-b2e0-db1989367138": { "name": "1", "loc_type": "floor", - "parent": "1" + "parent": "1", + "parent_of_parent": null }, "cf1746d3-4de0-4ef5-bd3a-a5e51191eee1": { "name": "OZ", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "04509ce4-6c88-40a3-b444-9e00f2cd97f2": { "name": "SanDiego", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "73b2f82c-413e-439e-a614-0ab0d0378114": { "name": "Antartica2", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "4e84a340-efdb-4f06-878f-3235173036ef": { "name": "Antartica3", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "6e1ebb51-62cd-400f-b130-a6959d81e775": { "name": "VN_1", "loc_type": "building", - "parent": "Texas" + "parent": "Texas", + "parent_of_parent": null }, "20d34f71-f4db-4833-90f7-4208a349f876": { "name": "Antartica", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "262696b1-aa87-432b-8a21-db9a77c51f23": { "name": "Australia", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "6e404051-4c06-4dab-adaa-72c5eeac577b": { "name": "Sydney", "loc_type": "area", - "parent": "Australia" + "parent": "Australia", + "parent_of_parent": null }, "63a7fb03-d4b2-408e-a6ab-b4df0a198643": { "name": "Sydney", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "f5a19514-3c1e-4127-a2b5-2a64a963c934": { "name": "Area_52", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "fa22b4e1-ee80-4aa8-8d76-83c4126d16ee": { "name": "Area_51", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661": { "name": "Area_51a", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "7760b82a-b07e-4fa7-8cad-91adfa12dd43": { "name": "Area 51", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "331f7e36-1a45-4c9f-bfa9-3425a053f81a": { "name": "Deep Space", "loc_type": "building", - "parent": "Area 51" + "parent": "Area 51", + "parent_of_parent": null }, "42a47e36-01ea-4189-8e54-16a2fd063648": { "name": "1st Floor", "loc_type": "floor", - "parent": "Deep Space" + "parent": "Deep Space", + "parent_of_parent": null }, "398de1d9-d595-429d-8239-64b51d24f230": { "name": "Texas_building", "loc_type": "building", - "parent": "Texas" + "parent": "Texas", + "parent_of_parent": null }, "5c882916-4f65-45b5-a5cc-ca5fa927cba6": { "name": "Forschungszentrum", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "1c3bb089-2a74-4fdf-96e3-d1815ac67e38": { "name": "Building 1", "loc_type": "building", - "parent": "Forschungszentrum" + "parent": "Forschungszentrum", + "parent_of_parent": null }, "0b1f8f7f-f0be-4d14-974d-69b1693d39ec": { "name": "Lab", "loc_type": "floor", - "parent": "Building 1" + "parent": "Building 1", + "parent_of_parent": null }, "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738": { "name": "1", "loc_type": "building", - "parent": "SanDiego" + "parent": "SanDiego", + "parent_of_parent": null }, "257c51d3-971d-49f4-83f7-c9baf334865a": { "name": "Texas", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "f372dbbb-d689-4d9a-9a5e-887de33fbce5": { "name": "Maryland", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "8004668a-eb96-47cc-b659-bcc9c04669ba": { "name": "Treton", "loc_type": "area", - "parent": null + "parent": null, + "parent_of_parent": null }, "755faf69-0d07-48f7-b130-4806c32eb13e": { "name": "secretlab", "loc_type": "building", - "parent": "Maryland" + "parent": "Maryland", + "parent_of_parent": null }, "fedd8d33-5334-413f-8a49-fb2459d7e337": { "name": "Rome", "loc_type": "building", - "parent": "Treton" + "parent": "Treton", + "parent_of_parent": null }, "f4ff8ca1-c062-4228-868a-d6cd0bc53852": { "name": "Floor 2", "loc_type": "floor", - "parent": "secretlab" + "parent": "secretlab", + "parent_of_parent": null } } \ No newline at end of file diff --git a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py index 22e859ca..803c386e 100644 --- a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py +++ b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py @@ -26,12 +26,9 @@ from nautobot_ssot.tests.dna_center.fixtures import ( DEVICE_DETAIL_FIXTURE, DEVICE_FIXTURE, - EXPECTED_AREAS, - EXPECTED_AREAS_WO_GLOBAL, - EXPECTED_BUILDINGS, EXPECTED_DNAC_LOCATION_MAP, + EXPECTED_DNAC_LOCATION_MAP_W_JOB_LOCATION_MAP, EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL, - EXPECTED_FLOORS, LOCATION_FIXTURE, PORT_FIXTURE, ) @@ -145,216 +142,46 @@ def setUp(self): # pylint: disable=too-many-statements def test_build_dnac_location_map(self): """Test Nautobot adapter build_dnac_location_map method.""" self.dna_center.dnac_location_map = {} - actual = self.dna_center.build_dnac_location_map(locations=LOCATION_FIXTURE) + self.dna_center.build_dnac_location_map(locations=LOCATION_FIXTURE) expected = EXPECTED_DNAC_LOCATION_MAP - self.assertEqual(sorted(actual), sorted(expected)) + self.assertEqual(sorted(self.dna_center.dnac_location_map), sorted(expected)) @override_settings(PLUGINS_CONFIG={"nautobot_ssot": {"dna_center_import_global": False}}) def test_build_dnac_location_map_wo_global(self): """Test Nautobot adapter build_dnac_location_map method without global.""" self.dna_center.dnac_location_map = {} - actual = self.dna_center.build_dnac_location_map(locations=LOCATION_FIXTURE) + self.dna_center.build_dnac_location_map(locations=LOCATION_FIXTURE) expected = EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL - self.assertEqual(sorted(actual), sorted(expected)) + self.assertEqual(sorted(self.dna_center.dnac_location_map), sorted(expected)) - def test_parse_and_sort_locations(self): - """Test Nautobot adapter parse_and_sort_locations method.""" - actual_areas, actual_buildings, actual_floors = self.dna_center.parse_and_sort_locations( - locations=LOCATION_FIXTURE + def test_build_dnac_location_map_w_job_location_map(self): + """Test Nautobot adapter build_dnac_location_map method when used with the Job location map.""" + self.dna_center.dnac_location_map = {} + self.job.location_map = { + "SanJose": {"name": "San Jose", "parent": "Califonia", "area_parent": "USA"}, + "Antartica2": {"name": "South Pole"}, + } + self.dna_center.build_dnac_location_map(locations=LOCATION_FIXTURE) + self.assertEqual( + sorted(self.dna_center.dnac_location_map), sorted(EXPECTED_DNAC_LOCATION_MAP_W_JOB_LOCATION_MAP) ) - self.assertEqual(actual_areas, EXPECTED_AREAS) - self.assertEqual(actual_buildings, EXPECTED_BUILDINGS) - self.assertEqual(actual_floors, EXPECTED_FLOORS) def test_load_locations_success(self): """Test Nautobot SSoT for Cisco DNA Center load_locations() function successfully.""" - self.dna_center.load_buildings = MagicMock() - self.dna_center.load_floors = MagicMock() + self.dna_center.build_dnac_location_map = MagicMock() self.dna_center_client.get_location.return_value = [{"name": "NY"}] self.dna_center.load_locations() self.dna_center_client.get_locations.assert_called() - self.dna_center.load_buildings.assert_called_once() - self.dna_center.load_floors.assert_called_once() + self.dna_center.build_dnac_location_map.assert_called_once() def test_load_locations_failure(self): """Test Nautobot SSoT for Cisco DNA Center load_locations() function fails.""" self.dna_center_client.get_locations.return_value = [] self.dna_center.load_locations() self.dna_center.job.logger.error.assert_called_once_with( - "No location data was returned from DNAC. Unable to proceed." + "No location data was returned from DNA Center. Unable to proceed." ) - def test_load_area_w_global(self): - """Test Nautobot SSoT for Cisco DNA Center load_area() function with Global area.""" - for area in EXPECTED_AREAS: - hierarchy = area["siteNameHierarchy"].split("/") - if isinstance(hierarchy, list) and len(hierarchy) > 1: - self.dna_center.load_area(area=hierarchy[-1], area_parent=hierarchy[-2]) - else: - self.dna_center.load_area(area=hierarchy[0]) - area_expected = sorted( - [f"{x['name']}__{x['parent']}" for x in EXPECTED_DNAC_LOCATION_MAP.values() if x["loc_type"] == "area"] - ) - area_actual = sorted([area.get_unique_id() for area in self.dna_center.get_all("area")]) - self.assertEqual(area_actual, area_expected) - - @override_settings(PLUGINS_CONFIG={"nautobot_ssot": {"dna_center_import_global": False}}) - def test_load_area_wo_global(self): - """Test Nautobot SSoT for Cisco DNA Center load_area() function without Global area.""" - self.dna_center.dnac_location_map = EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL - for area in EXPECTED_AREAS_WO_GLOBAL: - hierarchy = area["siteNameHierarchy"].split("/") - if hierarchy[-2] == "Global": - area_parent = None - else: - area_parent = hierarchy[-2] - self.dna_center.load_area(area=hierarchy[-1], area_parent=area_parent) - area_expected = [ - f"{x['name']}__{x['parent']}" - for x in EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL.values() - if x["loc_type"] == "area" - ] - area_actual = [area.get_unique_id() for area in self.dna_center.get_all("area")] - self.assertEqual(sorted(area_actual), sorted(area_expected)) - - def test_load_buildings_w_global(self): - """Test Nautobot SSoT for Cisco DNA Center load_buildings() function with Global area.""" - self.dna_center_client.find_address_and_type.side_effect = [ - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ] - self.dna_center.load_buildings(buildings=EXPECTED_BUILDINGS) - building_expected = [ - f"{x['name']}__{x['parent']}" for x in EXPECTED_DNAC_LOCATION_MAP.values() if x["loc_type"] == "building" - ] - building_actual = [building.get_unique_id() for building in self.dna_center.get_all("building")] - self.assertEqual(building_actual, building_expected) - - def test_load_buildings_wo_global(self): - """Test Nautobot SSoT for Cisco DNA Center load_buildings() function without Global area.""" - self.dna_center_client.find_address_and_type.side_effect = [ - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ] - self.dna_center.dnac_location_map = EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL - self.dna_center.load_buildings(buildings=EXPECTED_BUILDINGS) - building_expected = [ - f"{x['name']}__{x['parent']}" - for x in EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL.values() - if x["loc_type"] == "building" - ] - building_actual = [building.get_unique_id() for building in self.dna_center.get_all("building")] - self.assertEqual(sorted(building_actual), sorted(building_expected)) - - def test_load_buildings_duplicate(self): - """Test Nautobot SSoT for Cisco DNA Center load_buildings() function with duplicate building.""" - self.dna_center.load_area = MagicMock() - self.dna_center_client.find_address_and_type.side_effect = [ - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ("", "building"), - ] - self.dna_center.load_buildings(buildings=EXPECTED_BUILDINGS) - self.dna_center.load_buildings(buildings=[EXPECTED_BUILDINGS[0]]) - self.dna_center.job.logger.warning.assert_called_with("Site Building1 already loaded so skipping.") - - def test_load_buildings_w_location_map_building_change(self): - """Test Nautobot SSoT for Cisco DNA Center load_buildings() function with Job location_map and building data.""" - self.job.location_map = {"Rome": {"parent": "Italy", "area_parent": "Europe"}} - self.dna_center_client.find_address_and_type.side_effect = [("", "building")] - - self.dna_center.load_area = MagicMock() - self.dna_center.load_buildings(buildings=[EXPECTED_BUILDINGS[7]]) - self.dna_center.load_area.assert_called_with(area="Italy", area_parent="Europe") - loaded_bldg = self.dna_center.get("building", {"name": "Rome", "area": "Italy"}) - self.assertEqual(loaded_bldg.name, "Rome") - self.assertEqual(loaded_bldg.area, "Italy") - self.assertEqual(loaded_bldg.area_parent, "Europe") - - def test_load_buildings_w_location_map_area_change(self): - """Test Nautobot SSoT for Cisco DNA Center load_buildings() function with Job location_map and area data.""" - self.job.location_map = {"SanDiego": {"parent": "California"}} - self.dna_center_client.find_address_and_type.side_effect = [("", "building")] - - self.dna_center.load_area = MagicMock() - self.dna_center.load_buildings(buildings=[EXPECTED_BUILDINGS[5]]) - self.dna_center.load_area.assert_called_with(area="SanDiego", area_parent="California") - loaded_bldg = self.dna_center.get("building", {"name": "1", "area": "SanDiego"}) - self.assertEqual(loaded_bldg.name, "1") - self.assertEqual(loaded_bldg.area, "SanDiego") - self.assertEqual(loaded_bldg.area_parent, "California") - - def test_load_buildings_w_location_map_area_and_bldg_change(self): - """Test Nautobot SSoT for Cisco DNA Center load_buildings() function with Job location_map and area and building data.""" - self.job.location_map = {"HQ": {"parent": "New York", "area_parent": "USA"}, "New York": {"parent": "New York"}} - self.dna_center_client.find_address_and_type.side_effect = [("", "building")] - - self.dna_center.load_area = MagicMock() - test_bldg = [ - { - "parentId": "04509ce4-6c88-40a3-b444-9e00f2cd97f2", - "additionalInfo": [ - { - "nameSpace": "Location", - "attributes": { - "latitude": "39.156233", - "type": "building", - "longitude": "-74.690192", - }, - } - ], - "name": "HQ", - "id": "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738", - "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/04509ce4-6c88-40a3-b444-9e00f2cd97f2/2d0d8545-b6de-4dda-a0f7-93bcd7d0e738", - "siteNameHierarchy": "Global/SanDiego/HQ", - } - ] - self.dna_center.load_buildings(buildings=test_bldg) - self.dna_center.load_area.assert_called_with(area="New York", area_parent="USA") - loaded_bldg = self.dna_center.get("building", {"name": "HQ", "area": "New York"}) - self.assertEqual(loaded_bldg.name, "HQ") - self.assertEqual(loaded_bldg.area, "New York") - self.assertEqual(loaded_bldg.area_parent, "USA") - - def test_load_floors(self): - """Test Nautobot SSoT for Cisco DNA Center load_floors() function.""" - self.job.location_map = {} - self.dna_center.get = MagicMock() - self.dna_center.load_floors(floors=EXPECTED_FLOORS) - floor_expected = [ - "Building1 - Floor1__Building1", - "1 - 1__1", - "Deep Space - 1st Floor__Deep Space", - "Building 1 - Lab__Building 1", - "secretlab - Floor 2__secretlab", - ] - floor_actual = [floor.get_unique_id() for floor in self.dna_center.get_all("floor")] - self.assertEqual(floor_actual, floor_expected) - - def test_load_floors_missing_parent(self): - """Test Nautobot SSoT for Cisco DNA Center load_floors() function with missing parent.""" - self.dna_center.dnac_location_map = {} - self.dna_center.load_floors(floors=EXPECTED_FLOORS) - self.dna_center.job.logger.warning.assert_called_with("Parent to Floor 2 can't be found so will be skipped.") - def test_load_devices(self): """Test Nautobot SSoT for Cisco DNA Center load_devices() function.""" self.dna_center.load_ports = MagicMock() From 040db065c4cea1b0cb4cb0599d207fe725646fde Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:55:13 -0600 Subject: [PATCH 05/29] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Refactor?= =?UTF-8?q?=20Device=20platform=20determination=20into=20own=20function.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../diffsync/adapters/dna_center.py | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index a79f45e6..82aba96c 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -304,7 +304,6 @@ def load_devices(self): or (dev.get("errorDescription") and "Meraki" in dev["errorDescription"]) ): continue - platform = "unknown" dev_role = "Unknown" vendor = "Cisco" if not dev.get("hostname"): @@ -316,13 +315,7 @@ def load_devices(self): self.failed_import_devices.append(dev) continue dev_role = self.get_device_role(dev) - if dev["softwareType"] in DNA_CENTER_LIB_MAPPER: - platform = DNA_CENTER_LIB_MAPPER[dev["softwareType"]] - else: - if not dev.get("softwareType") and dev.get("type") and ("3800" in dev["type"] or "9130" in dev["type"]): - platform = "cisco_ios" - if not dev.get("softwareType") and dev.get("family") and "Meraki" in dev["family"]: - platform = "cisco_meraki" + platform = self.get_device_platform(dev) if platform == "unknown": self.job.logger.warning(f"Device {dev['hostname']} is missing Platform so will be skipped.") dev["field_validation"] = { @@ -416,6 +409,25 @@ def get_device_role(self, dev): dev_role = dev["role"] return dev_role + def get_device_platform(self, dev): + """Get Device Platform from Job information. + + Args: + dev (dict): Dictionary of information about Device from DNA Center. + + Returns: + str: Device platform that has been determined from DNA Center information. + """ + platform = "unknown" + if dev["softwareType"] in DNA_CENTER_LIB_MAPPER: + platform = DNA_CENTER_LIB_MAPPER[dev["softwareType"]] + else: + if not dev.get("softwareType") and dev.get("type") and ("3800" in dev["type"] or "9130" in dev["type"]): + platform = "cisco_ios" + if not dev.get("softwareType") and dev.get("family") and "Meraki" in dev["family"]: + platform = "cisco_meraki" + return platform + def load_ports(self, device_id: str, dev: DnaCenterDevice, mgmt_addr: str = ""): """Load port info from DNAC into Port DiffSyncModel. From 738fcf68200b6c39891322de00ecb1079eff58c7 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Tue, 17 Dec 2024 16:07:12 -0600 Subject: [PATCH 06/29] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Update?= =?UTF-8?q?=20loading=20of=20areas,=20buildings,=20and=20floors=20to=20be?= =?UTF-8?q?=20done=20from=20Device=20POV=20instead=20of=20loading=20all.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should ensure that only Locations that have a Device associated will be imported. --- .../diffsync/adapters/dna_center.py | 148 +++++++++--------- 1 file changed, 70 insertions(+), 78 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 82aba96c..726c3cf0 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -55,6 +55,7 @@ def __init__(self, *args, job, sync=None, client: DnaCenterClient, tenant: Tenan self.conn = client self.failed_import_devices = [] self.dnac_location_map = {} + self.building_map = {} self.floors = [] self.tenant = tenant @@ -107,6 +108,8 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too if info["attributes"].get("type"): self.dnac_location_map[loc_id]["loc_type"] = info["attributes"]["type"] if info["attributes"]["type"] in ["area", "building"]: + if info["attributes"]["type"] == "building": + self.building_map[loc_id] = location if info["attributes"]["type"] == "building" and loc_name in self.job.location_map: if self.job.location_map[loc_name].get("parent"): self.dnac_location_map[loc_id]["parent"] = self.job.location_map[loc_name]["parent"] @@ -210,90 +213,54 @@ def load_area(self, area: str, area_parent: Optional[str] = None): """ self.get_or_instantiate(self.area, ids={"name": area, "parent": area_parent}, attrs={"uuid": None}) - def load_buildings(self, buildings: List[dict]): + def load_building(self, building: dict, area_name: Optional[str] = None, area_parent_name: Optional[str] = None): """Load building data from DNAC into DiffSync model. Args: - buildings (List[dict]): List of dictionaries containing location information about a building. + building (dict): Dictionary containing location information about a building. """ - for location in buildings: - if self.job.debug: - self.job.logger.info(f"Loading {self.job.building_loctype.name} {location['name']}. {location}") - bldg_name = location["name"] - _area, _area_parent = None, None - if bldg_name in self.job.location_map and "parent" in self.job.location_map[bldg_name]: - _area = self.job.location_map[bldg_name]["parent"] - if self.job.location_map[bldg_name].get("area_parent"): - _area_parent = self.job.location_map[bldg_name]["area_parent"] - if self.job.location_map[bldg_name].get("name"): - bldg_name = self.job.location_map[bldg_name]["name"] - elif location["parentId"] in self.dnac_location_map: - _area = self.dnac_location_map[location["parentId"]]["name"] - _area_parent = self.dnac_location_map[location["parentId"]]["parent"] - if _area in self.job.location_map and ( - self.job.location_map[_area].get("parent") and bldg_name not in self.job.location_map - ): - _area_parent = self.job.location_map[_area]["parent"] - if self.job.location_map[_area].get("name"): - _area = self.job.location_map[_area]["name"] - if not settings.PLUGINS_CONFIG["nautobot_ssot"].get("dna_center_import_global"): - if _area == "Global": - _area = None - if _area_parent == "Global": - _area_parent = None - if _area: - self.load_area(area=_area, area_parent=_area_parent) - address, _ = self.conn.find_address_and_type(info=location["additionalInfo"]) - latitude, longitude = self.conn.find_latitude_and_longitude(info=location["additionalInfo"]) - _, loaded = self.get_or_instantiate( - self.building, - ids={"name": bldg_name, "area": _area}, - attrs={ - "address": address if address else "", - "area_parent": _area_parent, - "latitude": latitude[:9].rstrip("0"), - "longitude": longitude[:7].rstrip("0"), - "tenant": self.tenant.name if self.tenant else None, - "uuid": None, - }, - ) - if not loaded: - self.job.logger.warning(f"{self.job.building_loctype.name} {bldg_name} already loaded so skipping.") + if self.job.debug: + self.job.logger.info(f"Loading {self.job.building_loctype.name} {building['name']}. {building}") + bldg_name = building["name"] + address, _ = self.conn.find_address_and_type(info=building["additionalInfo"]) + latitude, longitude = self.conn.find_latitude_and_longitude(info=building["additionalInfo"]) + self.get_or_instantiate( + self.building, + ids={"name": bldg_name, "area": area_name}, + attrs={ + "address": address if address else "", + "area_parent": area_parent_name, + "latitude": latitude[:9].rstrip("0"), + "longitude": longitude[:7].rstrip("0"), + "tenant": self.tenant.name if self.tenant else None, + "uuid": None, + }, + ) - def load_floors(self, floors: List[dict]): + def load_floor(self, floor_name: str, bldg_name: str, area_name: str): """Load floor data from DNAC into DiffSync model. Args: - floors (List[dict]): List of dictionaries containing location information about a floor. + floor_name (str): Name of Floor location to be loaded. + bldg_name (str): Name of Building location that Floor is a part of. + area_name (str): Name of Area that Building location resides in. """ - for location in floors: - if self.job.debug: - self.job.logger.info(f"Loading floor {location['name']}. {location}") - area_name = None - if location["parentId"] in self.dnac_location_map: - bldg_name = self.dnac_location_map[location["parentId"]]["name"] - area_name = self.dnac_location_map[location["parentId"]]["parent"] - else: - self.job.logger.warning(f"Parent to {location['name']} can't be found so will be skipped.") - continue - if self.job.location_map.get(bldg_name): - area_name = self.job.location_map[bldg_name]["parent"] - if self.job.location_map[bldg_name].get("name"): - bldg_name = self.job.location_map[bldg_name]["name"] - floor_name = f"{bldg_name} - {location['name']}" - try: - parent = self.get(self.building, {"name": bldg_name, "area": area_name}) - new_floor, loaded = self.get_or_instantiate( - self.floor, - ids={"name": floor_name, "building": bldg_name}, - attrs={"tenant": self.tenant.name if self.tenant else None, "uuid": None}, - ) - if loaded: - parent.add_child(new_floor) - except ObjectNotFound as err: - self.job.logger.warning( - f"Unable to find {self.job.building_loctype.name} {bldg_name} for {self.job.floor_loctype.name} {floor_name}. {err}" - ) + if self.job.debug: + self.job.logger.info(f"Loading floor {floor_name} in {bldg_name} building in {area_name} area.") + floor_name = f"{bldg_name} - {floor_name}" + try: + parent = self.get(self.building, {"name": bldg_name, "area": area_name}) + new_floor, loaded = self.get_or_instantiate( + self.floor, + ids={"name": floor_name, "building": bldg_name}, + attrs={"tenant": self.tenant.name if self.tenant else None, "uuid": None}, + ) + if loaded: + parent.add_child(new_floor) + except ObjectNotFound as err: + self.job.logger.warning( + f"Unable to find {self.job.building_loctype.name} {bldg_name} for {self.job.floor_loctype.name} {floor_name}. {err}" + ) def load_devices(self): """Load Device data from DNA Center info DiffSync models.""" @@ -345,6 +312,7 @@ def load_devices(self): } self.failed_import_devices.append(dev) continue + self.load_device_location_tree(dev_details, loc_data) try: if self.job.debug: self.job.logger.info( @@ -392,6 +360,30 @@ def load_devices(self): } self.failed_import_devices.append(dev) + def load_device_location_tree(self, dev_details: dict, loc_data: dict): + """Load Device locations into DiffSync models for Floor, Building, and Areas. + + Args: + dev_details (dict): Dictionary of Device information. + loc_data (dict): Location data for the Device. + """ + reversed_areas = loc_data["areas"][::-1] + for area in reversed_areas: + item_index = reversed_areas.index(area) + if item_index + 2 <= len(loc_data["areas"]): + self.load_area(area=area, area_parent=reversed_areas[item_index + 1]) + else: + self.load_area(area=area, area_parent=None) + if loc_data.get("floor"): + building_id = dev_details["siteHierarchyGraphId"].lstrip("/").rstrip("/").split("/")[-2] + self.load_building(building=self.building_map[building_id], area_name=loc_data["areas"][-1]) + self.load_floor( + floor_name=loc_data["floor"], bldg_name=loc_data["building"], area_name=loc_data["areas"][-1] + ) + else: + building_id = dev_details["siteHierarchyGraphId"].lstrip("/").rstrip("/").split("/")[-1] + self.load_building(building=self.building_map[building_id], area_name=loc_data["areas"][-1]) + def get_device_role(self, dev): """Get Device Role from Job Hostname map or DNA Center 'role'. @@ -403,9 +395,9 @@ def get_device_role(self, dev): """ if self.job.hostname_map: dev_role = parse_hostname_for_role( - hostname_map=self.job.hostname_map, device_hostname=dev["hostname"], default_role="Unknown" - ) - if dev_role == "Unknown": + hostname_map=self.job.hostname_map, device_hostname=dev["hostname"], default_role="Unknown" + ) + else: dev_role = dev["role"] return dev_role From 759606749b1a3abc726b48cc5089010f8f4257f5 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Tue, 17 Dec 2024 16:07:51 -0600 Subject: [PATCH 07/29] =?UTF-8?q?test:=20=E2=9C=85=20Add=20a=20test=20vali?= =?UTF-8?q?dating=20load=5Fdevice=5Flocation=5Ftree()=20when=20a=20floor?= =?UTF-8?q?=20is=20found.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dna_center/test_adapters_dna_center.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py index 803c386e..2cee8b0c 100644 --- a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py +++ b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py @@ -182,6 +182,42 @@ def test_load_locations_failure(self): "No location data was returned from DNA Center. Unable to proceed." ) + def test_load_device_location_tree_w_floor(self): + """Test Nautobot SSoT for Cisco DNA Center load_device_location_tree() function with Device that has floor Location.""" + self.dna_center.building_map = { + "3": { + "name": "HQ", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "country": "United States", + "address": "123 Broadway, New York City, New York 12345, United States", + "latitude": "40.758746", + "addressInheritedFrom": "2", + "type": "building", + "longitude": "-73.978660", + }, + } + ], + } + } + mock_loc_data = {"areas": ["Global", "USA", "New York", "NYC"], "building": "HQ", "floor": "1st Floor"} + mock_dev_details = {"siteHierarchyGraphId": "/1/2/3/4/"} + self.dna_center.load_device_location_tree(dev_details=mock_dev_details, loc_data=mock_loc_data) + self.assertEqual( + {"HQ - 1st Floor__HQ"}, + {dev.get_unique_id() for dev in self.dna_center.get_all("floor")}, + ) + self.assertEqual( + {"HQ__NYC"}, + {dev.get_unique_id() for dev in self.dna_center.get_all("building")}, + ) + self.assertEqual( + {"Global__None", "USA__Global", "New York__USA", "NYC__New York"}, + {dev.get_unique_id() for dev in self.dna_center.get_all("area")}, + ) + def test_load_devices(self): """Test Nautobot SSoT for Cisco DNA Center load_devices() function.""" self.dna_center.load_ports = MagicMock() From 1dd3c51db20370bb71bd1052cc3934aba5ce8630 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Tue, 17 Dec 2024 16:08:34 -0600 Subject: [PATCH 08/29] =?UTF-8?q?test:=20=E2=9C=85=20Add=20a=20test=20fixt?= =?UTF-8?q?ure=20for=20the=20expected=20building=5Fmap=20to=20use=20with?= =?UTF-8?q?=20adapter=20tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nautobot_ssot/tests/dna_center/fixtures.py | 1 + .../fixtures/expected_building_map.json | 50 +++++++++++++++++++ .../dna_center/test_adapters_dna_center.py | 2 + 3 files changed, 53 insertions(+) create mode 100644 nautobot_ssot/tests/dna_center/fixtures/expected_building_map.json diff --git a/nautobot_ssot/tests/dna_center/fixtures.py b/nautobot_ssot/tests/dna_center/fixtures.py index 720877ce..bd271eb5 100644 --- a/nautobot_ssot/tests/dna_center/fixtures.py +++ b/nautobot_ssot/tests/dna_center/fixtures.py @@ -10,6 +10,7 @@ def load_json(path): LOCATION_FIXTURE = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/get_locations.json") +EXPECTED_BUILDING_MAP = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/expected_building_map.json") EXPECTED_DNAC_LOCATION_MAP = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map.json") EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL = load_json( path="./nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_wo_global.json" diff --git a/nautobot_ssot/tests/dna_center/fixtures/expected_building_map.json b/nautobot_ssot/tests/dna_center/fixtures/expected_building_map.json new file mode 100644 index 00000000..d85ca2f7 --- /dev/null +++ b/nautobot_ssot/tests/dna_center/fixtures/expected_building_map.json @@ -0,0 +1,50 @@ +{ + "5c59e37a-f12d-4e84-a085-ac5c02f240d4": { + "name": "Building1", + "loc_type": "building", + "parent": "SanJose", + "parent_of_parent": null + }, + "6e1ebb51-62cd-400f-b130-a6959d81e775": { + "name": "VN_1", + "loc_type": "building", + "parent": "Texas", + "parent_of_parent": null + }, + "331f7e36-1a45-4c9f-bfa9-3425a053f81a": { + "name": "Deep Space", + "loc_type": "building", + "parent": "Area 51", + "parent_of_parent": null + }, + "398de1d9-d595-429d-8239-64b51d24f230": { + "name": "Texas_building", + "loc_type": "building", + "parent": "Texas", + "parent_of_parent": null + }, + "1c3bb089-2a74-4fdf-96e3-d1815ac67e38": { + "name": "Building 1", + "loc_type": "building", + "parent": "Forschungszentrum", + "parent_of_parent": null + }, + "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738": { + "name": "1", + "loc_type": "building", + "parent": "SanDiego", + "parent_of_parent": null + }, + "755faf69-0d07-48f7-b130-4806c32eb13e": { + "name": "secretlab", + "loc_type": "building", + "parent": "Maryland", + "parent_of_parent": null + }, + "fedd8d33-5334-413f-8a49-fb2459d7e337": { + "name": "Rome", + "loc_type": "building", + "parent": "Treton", + "parent_of_parent": null + } +} \ No newline at end of file diff --git a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py index 2cee8b0c..fc96fb38 100644 --- a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py +++ b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py @@ -26,6 +26,7 @@ from nautobot_ssot.tests.dna_center.fixtures import ( DEVICE_DETAIL_FIXTURE, DEVICE_FIXTURE, + EXPECTED_BUILDING_MAP, EXPECTED_DNAC_LOCATION_MAP, EXPECTED_DNAC_LOCATION_MAP_W_JOB_LOCATION_MAP, EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL, @@ -138,6 +139,7 @@ def setUp(self): # pylint: disable=too-many-statements ) self.dna_center = DnaCenterAdapter(job=self.job, sync=None, client=self.dna_center_client, tenant=None) self.dna_center.dnac_location_map = EXPECTED_DNAC_LOCATION_MAP + self.dna_center.building_map = EXPECTED_BUILDING_MAP def test_build_dnac_location_map(self): """Test Nautobot adapter build_dnac_location_map method.""" From e3eba4aa2213455643372197c430e5e418799c56 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Tue, 17 Dec 2024 21:35:02 -0600 Subject: [PATCH 09/29] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Have=20parent=5Fof?= =?UTF-8?q?=5Fparent=20for=20a=20Building=20passed=20to=20the=20function?= =?UTF-8?q?=20to=20have=20it=20used=20in=20loading.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dna_center/diffsync/adapters/dna_center.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 726c3cf0..32c42475 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -376,13 +376,21 @@ def load_device_location_tree(self, dev_details: dict, loc_data: dict): self.load_area(area=area, area_parent=None) if loc_data.get("floor"): building_id = dev_details["siteHierarchyGraphId"].lstrip("/").rstrip("/").split("/")[-2] - self.load_building(building=self.building_map[building_id], area_name=loc_data["areas"][-1]) + self.load_building( + building=self.building_map[building_id], + area_name=self.dnac_location_map[building_id]["parent"], + area_parent_name=self.dnac_location_map[building_id]["parent_of_parent"], + ) self.load_floor( floor_name=loc_data["floor"], bldg_name=loc_data["building"], area_name=loc_data["areas"][-1] ) else: building_id = dev_details["siteHierarchyGraphId"].lstrip("/").rstrip("/").split("/")[-1] - self.load_building(building=self.building_map[building_id], area_name=loc_data["areas"][-1]) + self.load_building( + building=self.building_map[building_id], + area_name=self.dnac_location_map[building_id]["parent"], + area_parent_name=self.dnac_location_map[building_id]["parent_of_parent"], + ) def get_device_role(self, dev): """Get Device Role from Job Hostname map or DNA Center 'role'. From 8c896a5931e9e909602df99bb9f1ce0f26abdbac Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Tue, 17 Dec 2024 21:40:17 -0600 Subject: [PATCH 10/29] =?UTF-8?q?style:=20=F0=9F=A7=91=E2=80=8D?= =?UTF-8?q?=F0=9F=92=BB=20Add=20debug=20logging=20for=20DNAC=20location=20?= =?UTF-8?q?map?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integrations/dna_center/diffsync/adapters/dna_center.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 32c42475..6b4114d4 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -123,6 +123,8 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too floors.append(location) if parent_name in self.job.location_map and self.dnac_location_map[parent_id].get("name"): self.dnac_location_map[loc_id]["parent"] = self.dnac_location_map[parent_id]["name"] + if self.job.debug: + self.job.logger.debug(f"Generated DNAC Location Map: {self.dnac_location_map}") return floors def load_controller_locations(self): From 5a4adbfbff516207d9e24e941380be8371f5c52d Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Tue, 17 Dec 2024 21:40:52 -0600 Subject: [PATCH 11/29] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Remove?= =?UTF-8?q?=20area=5Fparent=20None=20for=20load=5Farea=20as=20it's=20unnee?= =?UTF-8?q?ded.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integrations/dna_center/diffsync/adapters/dna_center.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 6b4114d4..2ca7fa06 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -375,7 +375,7 @@ def load_device_location_tree(self, dev_details: dict, loc_data: dict): if item_index + 2 <= len(loc_data["areas"]): self.load_area(area=area, area_parent=reversed_areas[item_index + 1]) else: - self.load_area(area=area, area_parent=None) + self.load_area(area=area) if loc_data.get("floor"): building_id = dev_details["siteHierarchyGraphId"].lstrip("/").rstrip("/").split("/")[-2] self.load_building( From e2a10aa5eb2e4c71ea8be68bed3816218e0d3875 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Tue, 17 Dec 2024 21:52:41 -0600 Subject: [PATCH 12/29] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Only=20update=20nam?= =?UTF-8?q?e=20for=20Floor=20to=20include=20Building=20name=20if=20it's=20?= =?UTF-8?q?not=20already=20in=20the=20Floor=20name.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integrations/dna_center/diffsync/adapters/dna_center.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 2ca7fa06..8c4f0654 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -247,9 +247,10 @@ def load_floor(self, floor_name: str, bldg_name: str, area_name: str): bldg_name (str): Name of Building location that Floor is a part of. area_name (str): Name of Area that Building location resides in. """ + if bldg_name not in floor_name: + floor_name = f"{bldg_name} - {floor_name}" if self.job.debug: - self.job.logger.info(f"Loading floor {floor_name} in {bldg_name} building in {area_name} area.") - floor_name = f"{bldg_name} - {floor_name}" + self.job.logger.info(f"Loading floor {floor_name} in {area_name} area.") try: parent = self.get(self.building, {"name": bldg_name, "area": area_name}) new_floor, loaded = self.get_or_instantiate( From 5049675ab781baae5e1fc0159d70c28cc53b7bc7 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Tue, 17 Dec 2024 21:53:41 -0600 Subject: [PATCH 13/29] =?UTF-8?q?test:=20=E2=9C=85=20Add=20tests=20validat?= =?UTF-8?q?ing=20load=5Fdevice=5Flocation=5Ftree()=20with=20and=20without?= =?UTF-8?q?=20a=20floor.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dna_center/test_adapters_dna_center.py | 79 ++++++++++++++++++- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py index fc96fb38..0a58c944 100644 --- a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py +++ b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py @@ -186,8 +186,31 @@ def test_load_locations_failure(self): def test_load_device_location_tree_w_floor(self): """Test Nautobot SSoT for Cisco DNA Center load_device_location_tree() function with Device that has floor Location.""" - self.dna_center.building_map = { + self.dna_center.dnac_location_map = { + "1": { + "name": "Global", + "parent": None, + "parent_of_parent": None, + }, + "2": { + "name": "USA", + "parent": "Global", + "parent_of_parent": None, + }, "3": { + "name": "New York", + "parent": "USA", + "parent_of_parent": "Global", + }, + "4": { + "name": "NYC", + "parent": "New York", + "parent_of_parent": "USA", + }, + "5": {"name": "HQ", "parent": "NYC", "parent_of_parent": "New York"}, + } + self.dna_center.building_map = { + "5": { "name": "HQ", "additionalInfo": [ { @@ -202,10 +225,10 @@ def test_load_device_location_tree_w_floor(self): }, } ], - } + }, } mock_loc_data = {"areas": ["Global", "USA", "New York", "NYC"], "building": "HQ", "floor": "1st Floor"} - mock_dev_details = {"siteHierarchyGraphId": "/1/2/3/4/"} + mock_dev_details = {"siteHierarchyGraphId": "/1/2/3/4/5/6/"} self.dna_center.load_device_location_tree(dev_details=mock_dev_details, loc_data=mock_loc_data) self.assertEqual( {"HQ - 1st Floor__HQ"}, @@ -215,11 +238,61 @@ def test_load_device_location_tree_w_floor(self): {"HQ__NYC"}, {dev.get_unique_id() for dev in self.dna_center.get_all("building")}, ) + loaded_bldgs = self.dna_center.get_all("building") + self.assertEqual(loaded_bldgs[0].area_parent, "New York") self.assertEqual( {"Global__None", "USA__Global", "New York__USA", "NYC__New York"}, {dev.get_unique_id() for dev in self.dna_center.get_all("area")}, ) + def test_load_device_location_tree_wo_floor(self): + """Test Nautobot SSoT for Cisco DNA Center load_device_location_tree() function with Device that doesn't have a floor Location.""" + self.dna_center.dnac_location_map = { + "1": { + "name": "Global", + "parent": None, + "parent_of_parent": None, + }, + "2": { + "name": "USA", + "parent": "Global", + "parent_of_parent": None, + }, + "3": { + "name": "New York", + "parent": "USA", + "parent_of_parent": "Global", + }, + "4": { + "name": "NYC", + "parent": "New York", + "parent_of_parent": "USA", + }, + "5": {"name": "HQ", "parent": "NYC", "parent_of_parent": "New York"}, + } + self.dna_center.building_map = { + "5": { + "name": "HQ", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "country": "United States", + "address": "123 Broadway, New York City, New York 12345, United States", + "latitude": "40.758746", + "addressInheritedFrom": "2", + "type": "building", + "longitude": "-73.978660", + }, + } + ], + }, + } + mock_loc_data = {"areas": ["Global", "USA", "New York", "NYC"], "building": "HQ"} + mock_dev_details = {"siteHierarchyGraphId": "/1/2/3/4/5/"} + self.dna_center.load_device_location_tree(dev_details=mock_dev_details, loc_data=mock_loc_data) + self.assertEqual(len(self.dna_center.get_all("floor")), 0) + def test_load_devices(self): """Test Nautobot SSoT for Cisco DNA Center load_devices() function.""" self.dna_center.load_ports = MagicMock() From f2a5e8dfa75ea326344888898f6defdfc40c0e09 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Tue, 17 Dec 2024 22:05:26 -0600 Subject: [PATCH 14/29] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Update=20floor=20na?= =?UTF-8?q?me=20when=20loading=20a=20Device=20to=20consider=20if=20Buildin?= =?UTF-8?q?g=20name=20is=20in=20the=20floor=20name.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dna_center/diffsync/adapters/dna_center.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 8c4f0654..add736d8 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -335,6 +335,12 @@ def load_devices(self): self.failed_import_devices.append(dev) continue except ObjectNotFound: + if loc_data.get("floor") and loc_data["building"] not in loc_data["floor"]: + floor_name = f"{loc_data['building']} - {loc_data['floor']}" + elif loc_data.get("floor"): + floor_name = f"{loc_data['building']} - {loc_data['floor']}" + else: + floor_name = None new_dev = self.device( name=dev["hostname"], status="Active" if dev.get("reachabilityStatus") != "Unreachable" else "Offline", @@ -342,7 +348,7 @@ def load_devices(self): vendor=vendor, model=self.conn.get_model_name(models=dev["platformId"]) if dev.get("platformId") else "Unknown", site=loc_data["building"], - floor=f"{loc_data['building']} - {loc_data['floor']}" if loc_data.get("floor") else None, + floor=floor_name, serial=dev["serialNumber"] if dev.get("serialNumber") else "", version=dev.get("softwareVersion"), platform=platform, From 5a3ba520106041760085d02437a892b68774089f Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Wed, 18 Dec 2024 12:10:29 -0600 Subject: [PATCH 15/29] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Use=20dnac=5Flocati?= =?UTF-8?q?on=5Fmap=20for=20Floor=20area=5Fname=20instead=20of=20name=20fr?= =?UTF-8?q?om=20query.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integrations/dna_center/diffsync/adapters/dna_center.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index add736d8..782f27cf 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -391,7 +391,9 @@ def load_device_location_tree(self, dev_details: dict, loc_data: dict): area_parent_name=self.dnac_location_map[building_id]["parent_of_parent"], ) self.load_floor( - floor_name=loc_data["floor"], bldg_name=loc_data["building"], area_name=loc_data["areas"][-1] + floor_name=loc_data["floor"], + bldg_name=loc_data["building"], + area_name=self.dnac_location_map[building_id]["parent"], ) else: building_id = dev_details["siteHierarchyGraphId"].lstrip("/").rstrip("/").split("/")[-1] From d30e2e756bd8d18c6007d8a459a4ab3eb8c84f7e Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Wed, 18 Dec 2024 12:11:35 -0600 Subject: [PATCH 16/29] =?UTF-8?q?style:=20=F0=9F=93=9D=20Tweak=20logging?= =?UTF-8?q?=20to=20include=20area=20and=20area=20parent=20names.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integrations/dna_center/diffsync/adapters/dna_center.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 782f27cf..1dbf5d96 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -222,7 +222,9 @@ def load_building(self, building: dict, area_name: Optional[str] = None, area_pa building (dict): Dictionary containing location information about a building. """ if self.job.debug: - self.job.logger.info(f"Loading {self.job.building_loctype.name} {building['name']}. {building}") + self.job.logger.info( + f"Loading {self.job.building_loctype.name} {building['name']} in {area_name} with parent {area_parent_name}. {building}" + ) bldg_name = building["name"] address, _ = self.conn.find_address_and_type(info=building["additionalInfo"]) latitude, longitude = self.conn.find_latitude_and_longitude(info=building["additionalInfo"]) From c522aa09f5e463837ede94b098253244ee1b40c6 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Wed, 18 Dec 2024 12:12:22 -0600 Subject: [PATCH 17/29] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Update?= =?UTF-8?q?=20floors=20in=20dnac=5Flocation=5Fmap=20to=20have=20parent=5Fo?= =?UTF-8?q?f=5Fparent=20if=20provided=20in=20Job=20location=5Fmap.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dna_center/diffsync/adapters/dna_center.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 1dbf5d96..edd15e63 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -72,7 +72,7 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too """Build out the DNA Center location structure based off DNAC information or Job location_map field. Args: - locations (List[dict]): List of Locations from DNA Center to be separated. + locations (List[dict]): List of Locations from DNA Center to be processed. """ floors = [] for location in locations: @@ -121,8 +121,14 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too self.dnac_location_map[loc_id]["parent_of_parent"] = parent_name if info["attributes"]["type"] == "floor": floors.append(location) - if parent_name in self.job.location_map and self.dnac_location_map[parent_id].get("name"): + if self.job.location_map.get(parent_name) and self.dnac_location_map[parent_id].get("name"): self.dnac_location_map[loc_id]["parent"] = self.dnac_location_map[parent_id]["name"] + if self.job.location_map.get(parent_name) and self.dnac_location_map[parent_id].get( + "parent" + ): + self.dnac_location_map[loc_id]["parent_of_parent"] = self.dnac_location_map[parent_id][ + "parent" + ] if self.job.debug: self.job.logger.debug(f"Generated DNAC Location Map: {self.dnac_location_map}") return floors From 023de5892bdcbb1e09d43879303f516ed898e84a Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Wed, 18 Dec 2024 18:55:51 -0600 Subject: [PATCH 18/29] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Change?= =?UTF-8?q?=20update=20of=20parent=20and=20parent=5Fof=5Fparent=20to=20hap?= =?UTF-8?q?pen=20for=20both=20building=20and=20area=20locations.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integrations/dna_center/diffsync/adapters/dna_center.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index edd15e63..e404d414 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -110,7 +110,7 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too if info["attributes"]["type"] in ["area", "building"]: if info["attributes"]["type"] == "building": self.building_map[loc_id] = location - if info["attributes"]["type"] == "building" and loc_name in self.job.location_map: + if self.job.location_map.get(loc_name): if self.job.location_map[loc_name].get("parent"): self.dnac_location_map[loc_id]["parent"] = self.job.location_map[loc_name]["parent"] if self.job.location_map[loc_name].get("area_parent"): From 8fce37078d18d85b8f3b083405701f52c7c66398 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Wed, 18 Dec 2024 20:24:46 -0600 Subject: [PATCH 19/29] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Update=20parent=5Fo?= =?UTF-8?q?f=5Fparent=20for=20building=20if=20parent=20on=20parent=20is=20?= =?UTF-8?q?found.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integrations/dna_center/diffsync/adapters/dna_center.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index e404d414..559a874c 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -110,6 +110,12 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too if info["attributes"]["type"] in ["area", "building"]: if info["attributes"]["type"] == "building": self.building_map[loc_id] = location + if self.job.location_map.get(parent_name) and self.job.location_map[parent_name].get( + "parent" + ): + self.dnac_location_map[loc_id]["parent_of_parent"] = self.job.location_map[parent_name][ + "parent" + ] if self.job.location_map.get(loc_name): if self.job.location_map[loc_name].get("parent"): self.dnac_location_map[loc_id]["parent"] = self.job.location_map[loc_name]["parent"] From 5992cfb5e16f918c2530db53820711d9d1c21363 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:49:22 -0600 Subject: [PATCH 20/29] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Refactor=20loading?= =?UTF-8?q?=20of=20DNAC=20location=5Fmap=20to=20set=20defaults=20and=20the?= =?UTF-8?q?n=20update=20with=20Job=20location=5Fmap.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../diffsync/adapters/dna_center.py | 92 ++++++++++++------- 1 file changed, 60 insertions(+), 32 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 559a874c..4f235584 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -68,13 +68,13 @@ def load_locations(self): else: self.job.logger.error("No location data was returned from DNA Center. Unable to proceed.") - def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too-many-branches + def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too-many-statements """Build out the DNA Center location structure based off DNAC information or Job location_map field. Args: locations (List[dict]): List of Locations from DNA Center to be processed. """ - floors = [] + # build initial mapping of IDs to location name for location in locations: if ( not settings.PLUGINS_CONFIG["nautobot_ssot"].get("dna_center_import_global") @@ -87,9 +87,12 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too loc_name = location["name"] self.dnac_location_map[location["id"]] = { "name": loc_name, + "loc_type": "area", "parent": None, "parent_of_parent": None, } + + # add parent name for each location for location in locations: # pylint: disable=too-many-nested-blocks loc_id = location["id"] loc_name = location["name"] @@ -104,6 +107,25 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too if parent_name == "Global": parent_name = None self.dnac_location_map[loc_id]["parent"] = parent_name + + # add parent of parent to the mapping + for location in locations: + if location.get("parentId") and self.dnac_location_map.get(location["parentId"]): + self.dnac_location_map[location["id"]]["parent_of_parent"] = self.dnac_location_map[ + location["parentId"] + ]["parent"] + + floors = [] + for location in locations: # pylint: disable=too-many-nested-blocks + if ( + not settings.PLUGINS_CONFIG["nautobot_ssot"].get("dna_center_import_global") + and location["name"] == "Global" + ): + continue + loc_id = location["id"] + loc_name = self.dnac_location_map[loc_id]["name"] + parent_id = location.get("parentId") + parent_name = self.dnac_location_map[loc_id]["parent"] for info in location["additionalInfo"]: if info["attributes"].get("type"): self.dnac_location_map[loc_id]["loc_type"] = info["attributes"]["type"] @@ -125,16 +147,16 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too ] else: self.dnac_location_map[loc_id]["parent_of_parent"] = parent_name - if info["attributes"]["type"] == "floor": - floors.append(location) - if self.job.location_map.get(parent_name) and self.dnac_location_map[parent_id].get("name"): - self.dnac_location_map[loc_id]["parent"] = self.dnac_location_map[parent_id]["name"] - if self.job.location_map.get(parent_name) and self.dnac_location_map[parent_id].get( + elif info["attributes"]["type"] == "floor": + floors.append(location) + self.dnac_location_map[loc_id]["parent"] = self.dnac_location_map[parent_id]["name"] + self.dnac_location_map[loc_id]["parent_of_parent"] = self.dnac_location_map[parent_id]["parent"] + if self.job.location_map.get(parent_name) and self.dnac_location_map[parent_id].get("name"): + self.dnac_location_map[loc_id]["parent"] = self.dnac_location_map[parent_id]["name"] + if self.job.location_map.get(parent_name) and self.dnac_location_map[parent_id].get("parent"): + self.dnac_location_map[loc_id]["parent_of_parent"] = self.dnac_location_map[parent_id][ "parent" - ): - self.dnac_location_map[loc_id]["parent_of_parent"] = self.dnac_location_map[parent_id][ - "parent" - ] + ] if self.job.debug: self.job.logger.debug(f"Generated DNAC Location Map: {self.dnac_location_map}") return floors @@ -390,31 +412,37 @@ def load_device_location_tree(self, dev_details: dict, loc_data: dict): dev_details (dict): Dictionary of Device information. loc_data (dict): Location data for the Device. """ - reversed_areas = loc_data["areas"][::-1] - for area in reversed_areas: - item_index = reversed_areas.index(area) - if item_index + 2 <= len(loc_data["areas"]): - self.load_area(area=area, area_parent=reversed_areas[item_index + 1]) - else: - self.load_area(area=area) + floor_id = "" + location_ids = dev_details["siteHierarchyGraphId"].lstrip("/").rstrip("/").split("/") if loc_data.get("floor"): - building_id = dev_details["siteHierarchyGraphId"].lstrip("/").rstrip("/").split("/")[-2] - self.load_building( - building=self.building_map[building_id], - area_name=self.dnac_location_map[building_id]["parent"], - area_parent_name=self.dnac_location_map[building_id]["parent_of_parent"], + floor_id = location_ids.pop() + building_id = location_ids.pop() + areas = location_ids + + for area_id in reversed(areas): + area_name = self.dnac_location_map[area_id]["name"] + area_parent = self.dnac_location_map[area_id]["parent"] + if self.job.debug: + self.job.logger.debug(f"Loading area {area_name} in {area_parent}.") + self.load_area(area=area_name, area_parent=area_parent) + if self.job.debug: + self.job.logger.debug( + f"Loading building {self.dnac_location_map[building_id]['name']} in {self.dnac_location_map[building_id]['parent']} which exists in {self.dnac_location_map[building_id]['parent_of_parent']} area parent." ) + self.load_building( + building=self.building_map[building_id], + area_name=self.dnac_location_map[building_id]["parent"], + area_parent_name=self.dnac_location_map[building_id]["parent_of_parent"], + ) + if loc_data.get("floor"): + if self.job.debug: + self.job.logger.debug( + f"Loading floor {self.dnac_location_map[floor_id]['name']} in {self.dnac_location_map[floor_id]['parent']} which exists in {self.dnac_location_map[building_id]['parent']} area." + ) self.load_floor( - floor_name=loc_data["floor"], - bldg_name=loc_data["building"], - area_name=self.dnac_location_map[building_id]["parent"], - ) - else: - building_id = dev_details["siteHierarchyGraphId"].lstrip("/").rstrip("/").split("/")[-1] - self.load_building( - building=self.building_map[building_id], + floor_name=self.dnac_location_map[floor_id]["name"], + bldg_name=self.dnac_location_map[floor_id]["parent"], area_name=self.dnac_location_map[building_id]["parent"], - area_parent_name=self.dnac_location_map[building_id]["parent_of_parent"], ) def get_device_role(self, dev): From 907124d3c0409467838438067fe60b08398abe57 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:50:11 -0600 Subject: [PATCH 21/29] =?UTF-8?q?test:=20=E2=9C=85=20Update=20test=20to=20?= =?UTF-8?q?account=20for=20change=20to=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fixtures/expected_dnac_location_map.json | 28 +++++++++---------- ..._dnac_location_map_w_job_location_map.json | 2 +- .../expected_dnac_location_map_wo_global.json | 10 +++---- .../dna_center/test_adapters_dna_center.py | 9 ++++-- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map.json b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map.json index 9595c483..90081b8a 100644 --- a/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map.json +++ b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map.json @@ -15,19 +15,19 @@ "name": "Building1", "loc_type": "building", "parent": "SanJose", - "parent_of_parent": null + "parent_of_parent": "Global" }, "49aa97a7-5d45-4303-89dd-f76dfbfc624a": { "name": "Floor1", "loc_type": "floor", "parent": "Building1", - "parent_of_parent": null + "parent_of_parent": "SanJose" }, "925f1a03-05df-4d9a-b2e0-db1989367138": { "name": "1", "loc_type": "floor", "parent": "1", - "parent_of_parent": null + "parent_of_parent": "SanDiego" }, "cf1746d3-4de0-4ef5-bd3a-a5e51191eee1": { "name": "OZ", @@ -57,7 +57,7 @@ "name": "VN_1", "loc_type": "building", "parent": "Texas", - "parent_of_parent": null + "parent_of_parent": "Global" }, "20d34f71-f4db-4833-90f7-4208a349f876": { "name": "Antartica", @@ -75,7 +75,7 @@ "name": "Sydney", "loc_type": "area", "parent": "Australia", - "parent_of_parent": null + "parent_of_parent": "Global" }, "63a7fb03-d4b2-408e-a6ab-b4df0a198643": { "name": "Sydney", @@ -111,19 +111,19 @@ "name": "Deep Space", "loc_type": "building", "parent": "Area 51", - "parent_of_parent": null + "parent_of_parent": "Global" }, "42a47e36-01ea-4189-8e54-16a2fd063648": { "name": "1st Floor", "loc_type": "floor", "parent": "Deep Space", - "parent_of_parent": null + "parent_of_parent": "Area 51" }, "398de1d9-d595-429d-8239-64b51d24f230": { "name": "Texas_building", "loc_type": "building", "parent": "Texas", - "parent_of_parent": null + "parent_of_parent": "Global" }, "5c882916-4f65-45b5-a5cc-ca5fa927cba6": { "name": "Forschungszentrum", @@ -135,19 +135,19 @@ "name": "Building 1", "loc_type": "building", "parent": "Forschungszentrum", - "parent_of_parent": null + "parent_of_parent": "Global" }, "0b1f8f7f-f0be-4d14-974d-69b1693d39ec": { "name": "Lab", "loc_type": "floor", "parent": "Building 1", - "parent_of_parent": null + "parent_of_parent": "Forschungszentrum" }, "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738": { "name": "1", "loc_type": "building", "parent": "SanDiego", - "parent_of_parent": null + "parent_of_parent": "Global" }, "257c51d3-971d-49f4-83f7-c9baf334865a": { "name": "Texas", @@ -171,18 +171,18 @@ "name": "secretlab", "loc_type": "building", "parent": "Maryland", - "parent_of_parent": null + "parent_of_parent": "Global" }, "fedd8d33-5334-413f-8a49-fb2459d7e337": { "name": "Rome", "loc_type": "building", "parent": "Treton", - "parent_of_parent": null + "parent_of_parent": "Global" }, "f4ff8ca1-c062-4228-868a-d6cd0bc53852": { "name": "Floor 2", "loc_type": "floor", "parent": "secretlab", - "parent_of_parent": null + "parent_of_parent": "Maryland" } } \ No newline at end of file diff --git a/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_w_job_location_map.json b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_w_job_location_map.json index 46ea33e7..416de315 100644 --- a/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_w_job_location_map.json +++ b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_w_job_location_map.json @@ -17,7 +17,7 @@ "49aa97a7-5d45-4303-89dd-f76dfbfc624a": { "name": "Floor1", "parent": "Building1", - "parent_of_parent": null + "parent_of_parent": "San Jose" }, "925f1a03-05df-4d9a-b2e0-db1989367138": { "name": "1", diff --git a/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_wo_global.json b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_wo_global.json index f46f3e32..40d8be33 100644 --- a/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_wo_global.json +++ b/nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map_wo_global.json @@ -15,13 +15,13 @@ "name": "Floor1", "loc_type": "floor", "parent": "Building1", - "parent_of_parent": null + "parent_of_parent": "SanJose" }, "925f1a03-05df-4d9a-b2e0-db1989367138": { "name": "1", "loc_type": "floor", "parent": "1", - "parent_of_parent": null + "parent_of_parent": "SanDiego" }, "cf1746d3-4de0-4ef5-bd3a-a5e51191eee1": { "name": "OZ", @@ -111,7 +111,7 @@ "name": "1st Floor", "loc_type": "floor", "parent": "Deep Space", - "parent_of_parent": null + "parent_of_parent": "Area 51" }, "398de1d9-d595-429d-8239-64b51d24f230": { "name": "Texas_building", @@ -135,7 +135,7 @@ "name": "Lab", "loc_type": "floor", "parent": "Building 1", - "parent_of_parent": null + "parent_of_parent": "Forschungszentrum" }, "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738": { "name": "1", @@ -177,6 +177,6 @@ "name": "Floor 2", "loc_type": "floor", "parent": "secretlab", - "parent_of_parent": null + "parent_of_parent": "Maryland" } } \ No newline at end of file diff --git a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py index 0a58c944..f0b97c25 100644 --- a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py +++ b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py @@ -30,6 +30,7 @@ EXPECTED_DNAC_LOCATION_MAP, EXPECTED_DNAC_LOCATION_MAP_W_JOB_LOCATION_MAP, EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL, + EXPECTED_FLOORS, LOCATION_FIXTURE, PORT_FIXTURE, ) @@ -144,9 +145,10 @@ def setUp(self): # pylint: disable=too-many-statements def test_build_dnac_location_map(self): """Test Nautobot adapter build_dnac_location_map method.""" self.dna_center.dnac_location_map = {} - self.dna_center.build_dnac_location_map(locations=LOCATION_FIXTURE) + actual_floors = self.dna_center.build_dnac_location_map(locations=LOCATION_FIXTURE) expected = EXPECTED_DNAC_LOCATION_MAP - self.assertEqual(sorted(self.dna_center.dnac_location_map), sorted(expected)) + self.assertEqual(self.dna_center.dnac_location_map, expected) + self.assertEqual(actual_floors, EXPECTED_FLOORS) @override_settings(PLUGINS_CONFIG={"nautobot_ssot": {"dna_center_import_global": False}}) def test_build_dnac_location_map_wo_global(self): @@ -154,7 +156,7 @@ def test_build_dnac_location_map_wo_global(self): self.dna_center.dnac_location_map = {} self.dna_center.build_dnac_location_map(locations=LOCATION_FIXTURE) expected = EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL - self.assertEqual(sorted(self.dna_center.dnac_location_map), sorted(expected)) + self.assertEqual(self.dna_center.dnac_location_map, expected) def test_build_dnac_location_map_w_job_location_map(self): """Test Nautobot adapter build_dnac_location_map method when used with the Job location map.""" @@ -208,6 +210,7 @@ def test_load_device_location_tree_w_floor(self): "parent_of_parent": "USA", }, "5": {"name": "HQ", "parent": "NYC", "parent_of_parent": "New York"}, + "6": {"name": "1st Floor", "parent": "HQ"}, } self.dna_center.building_map = { "5": { From 24814e45e6daee66b0417ad8bd23efd72378d066 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:52:15 -0600 Subject: [PATCH 22/29] =?UTF-8?q?test:=20=F0=9F=9A=A8=20Add=20ignore=20for?= =?UTF-8?q?=20pylint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integrations/dna_center/diffsync/adapters/dna_center.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 4f235584..0378be4a 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -68,7 +68,7 @@ def load_locations(self): else: self.job.logger.error("No location data was returned from DNA Center. Unable to proceed.") - def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too-many-statements + def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too-many-statements, too-many-branches """Build out the DNA Center location structure based off DNAC information or Job location_map field. Args: From df85eb7800ec077f85c2995ba7c654a45290bc82 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 20 Dec 2024 18:23:56 -0600 Subject: [PATCH 23/29] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Add=20check=20for?= =?UTF-8?q?=20parent=5Fid=20existing=20in=20dnac=5Flocation=5Fmap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dna_center/diffsync/adapters/dna_center.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 0378be4a..4f1e9fd4 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -149,8 +149,11 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too self.dnac_location_map[loc_id]["parent_of_parent"] = parent_name elif info["attributes"]["type"] == "floor": floors.append(location) - self.dnac_location_map[loc_id]["parent"] = self.dnac_location_map[parent_id]["name"] - self.dnac_location_map[loc_id]["parent_of_parent"] = self.dnac_location_map[parent_id]["parent"] + if self.dnac_location_map.get(parent_id): + self.dnac_location_map[loc_id]["parent"] = self.dnac_location_map[parent_id]["name"] + self.dnac_location_map[loc_id]["parent_of_parent"] = self.dnac_location_map[parent_id][ + "parent" + ] if self.job.location_map.get(parent_name) and self.dnac_location_map[parent_id].get("name"): self.dnac_location_map[loc_id]["parent"] = self.dnac_location_map[parent_id]["name"] if self.job.location_map.get(parent_name) and self.dnac_location_map[parent_id].get("parent"): From 77309af5d2c19db466d88c283ebc03ea07ce28aa Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 20 Dec 2024 18:38:47 -0600 Subject: [PATCH 24/29] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Check=20for=20area?= =?UTF-8?q?=5Fid=20in=20location=5Fmap=20before=20using?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dna_center/diffsync/adapters/dna_center.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 4f1e9fd4..67a71bf5 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -423,11 +423,12 @@ def load_device_location_tree(self, dev_details: dict, loc_data: dict): areas = location_ids for area_id in reversed(areas): - area_name = self.dnac_location_map[area_id]["name"] - area_parent = self.dnac_location_map[area_id]["parent"] - if self.job.debug: - self.job.logger.debug(f"Loading area {area_name} in {area_parent}.") - self.load_area(area=area_name, area_parent=area_parent) + if self.dnac_location_map.get(area_id): + area_name = self.dnac_location_map[area_id]["name"] + area_parent = self.dnac_location_map[area_id]["parent"] + if self.job.debug: + self.job.logger.debug(f"Loading area {area_name} in {area_parent}.") + self.load_area(area=area_name, area_parent=area_parent) if self.job.debug: self.job.logger.debug( f"Loading building {self.dnac_location_map[building_id]['name']} in {self.dnac_location_map[building_id]['parent']} which exists in {self.dnac_location_map[building_id]['parent_of_parent']} area parent." From 0659e077ceb757931a4326b3662f56f85c1d7fe8 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 20 Dec 2024 19:14:02 -0600 Subject: [PATCH 25/29] =?UTF-8?q?test:=20=E2=9C=85=20Add=20test=20fixture?= =?UTF-8?q?=20for=20expected=20locations=20without=20Global=20and=20update?= =?UTF-8?q?=20test=20to=20use=20it.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nautobot_ssot/tests/dna_center/fixtures.py | 1 + .../fixtures/get_locations_wo_global.json | 639 ++++++++++++++++++ .../dna_center/test_adapters_dna_center.py | 3 +- 3 files changed, 642 insertions(+), 1 deletion(-) create mode 100644 nautobot_ssot/tests/dna_center/fixtures/get_locations_wo_global.json diff --git a/nautobot_ssot/tests/dna_center/fixtures.py b/nautobot_ssot/tests/dna_center/fixtures.py index bd271eb5..4513e96f 100644 --- a/nautobot_ssot/tests/dna_center/fixtures.py +++ b/nautobot_ssot/tests/dna_center/fixtures.py @@ -10,6 +10,7 @@ def load_json(path): LOCATION_FIXTURE = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/get_locations.json") +LOCATION_WO_GLOBAL_FIXTURE = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/get_locations_wo_global.json") EXPECTED_BUILDING_MAP = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/expected_building_map.json") EXPECTED_DNAC_LOCATION_MAP = load_json(path="./nautobot_ssot/tests/dna_center/fixtures/expected_dnac_location_map.json") EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL = load_json( diff --git a/nautobot_ssot/tests/dna_center/fixtures/get_locations_wo_global.json b/nautobot_ssot/tests/dna_center/fixtures/get_locations_wo_global.json new file mode 100644 index 00000000..12a6a0bb --- /dev/null +++ b/nautobot_ssot/tests/dna_center/fixtures/get_locations_wo_global.json @@ -0,0 +1,639 @@ +[ + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "eed5ccc3-d76f-46e2-9d8d-97624f5418ac", + "type": "area" + } + } + ], + "name": "SanJose", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "eed5ccc3-d76f-46e2-9d8d-97624f5418ac", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/eed5ccc3-d76f-46e2-9d8d-97624f5418ac", + "siteNameHierarchy": "Global/SanJose" + }, + { + "parentId": "eed5ccc3-d76f-46e2-9d8d-97624f5418ac", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "country": "United States", + "address": "1000 I Street, Sacramento, California 95814, United States", + "latitude": "38.581405819248886", + "addressInheritedFrom": "5c59e37a-f12d-4e84-a085-ac5c02f240d4", + "type": "building", + "longitude": "-121.49309067224416" + } + } + ], + "name": "Building1", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "5c59e37a-f12d-4e84-a085-ac5c02f240d4", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/eed5ccc3-d76f-46e2-9d8d-97624f5418ac/5c59e37a-f12d-4e84-a085-ac5c02f240d4", + "siteNameHierarchy": "Global/SanJose/Building1" + }, + { + "parentId": "5c59e37a-f12d-4e84-a085-ac5c02f240d4", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "address": "1000 I Street, Sacramento, California 95814, United States", + "addressInheritedFrom": "5c59e37a-f12d-4e84-a085-ac5c02f240d4", + "type": "floor" + } + }, + { + "nameSpace": "mapsSummary", + "attributes": { + "rfModel": "95095", + "floorIndex": "1" + } + }, + { + "nameSpace": "mapGeometry", + "attributes": { + "offsetX": "0.0", + "offsetY": "0.0", + "length": "100.0", + "width": "100.0", + "height": "10.0" + } + } + ], + "name": "Floor1", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "49aa97a7-5d45-4303-89dd-f76dfbfc624a", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/eed5ccc3-d76f-46e2-9d8d-97624f5418ac/5c59e37a-f12d-4e84-a085-ac5c02f240d4/49aa97a7-5d45-4303-89dd-f76dfbfc624a", + "siteNameHierarchy": "Global/SanJose/Building1/Floor1" + }, + { + "parentId": "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "address": "Ocean Drive Bar & Restaurant, 3915 Landis Ave, Sea Isle City, New Jersey 08243, United States", + "addressInheritedFrom": "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738", + "type": "floor" + } + }, + { + "nameSpace": "mapsSummary", + "attributes": { + "rfModel": "95095", + "floorIndex": "1" + } + }, + { + "nameSpace": "mapGeometry", + "attributes": { + "offsetX": "0.0", + "offsetY": "0.0", + "length": "79.0", + "width": "100.0", + "height": "10.0" + } + } + ], + "name": "1", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "925f1a03-05df-4d9a-b2e0-db1989367138", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/04509ce4-6c88-40a3-b444-9e00f2cd97f2/2d0d8545-b6de-4dda-a0f7-93bcd7d0e738/925f1a03-05df-4d9a-b2e0-db1989367138", + "siteNameHierarchy": "Global/SanDiego/1/1" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "cf1746d3-4de0-4ef5-bd3a-a5e51191eee1", + "type": "area" + } + } + ], + "name": "OZ", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "cf1746d3-4de0-4ef5-bd3a-a5e51191eee1", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/cf1746d3-4de0-4ef5-bd3a-a5e51191eee1", + "siteNameHierarchy": "Global/OZ" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "04509ce4-6c88-40a3-b444-9e00f2cd97f2", + "type": "area" + } + } + ], + "name": "SanDiego", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "04509ce4-6c88-40a3-b444-9e00f2cd97f2", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/04509ce4-6c88-40a3-b444-9e00f2cd97f2", + "siteNameHierarchy": "Global/SanDiego" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "73b2f82c-413e-439e-a614-0ab0d0378114", + "type": "area" + } + } + ], + "name": "Antartica2", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "73b2f82c-413e-439e-a614-0ab0d0378114", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/73b2f82c-413e-439e-a614-0ab0d0378114", + "siteNameHierarchy": "Global/Antartica2" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "4e84a340-efdb-4f06-878f-3235173036ef", + "type": "area" + } + } + ], + "name": "Antartica3", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "4e84a340-efdb-4f06-878f-3235173036ef", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/4e84a340-efdb-4f06-878f-3235173036ef", + "siteNameHierarchy": "Global/Antartica3" + }, + { + "parentId": "257c51d3-971d-49f4-83f7-c9baf334865a", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "country": "Vietnam", + "latitude": "38.10344327099361", + "addressInheritedFrom": "257c51d3-971d-49f4-83f7-c9baf334865a", + "type": "building", + "longitude": "-70.53258776522935" + } + } + ], + "name": "VN_1", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "6e1ebb51-62cd-400f-b130-a6959d81e775", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/257c51d3-971d-49f4-83f7-c9baf334865a/6e1ebb51-62cd-400f-b130-a6959d81e775", + "siteNameHierarchy": "Global/Texas/VN_1" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "20d34f71-f4db-4833-90f7-4208a349f876", + "type": "area" + } + } + ], + "name": "Antartica", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "20d34f71-f4db-4833-90f7-4208a349f876", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/20d34f71-f4db-4833-90f7-4208a349f876", + "siteNameHierarchy": "Global/Antartica" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "262696b1-aa87-432b-8a21-db9a77c51f23", + "type": "area" + } + } + ], + "name": "Australia", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "262696b1-aa87-432b-8a21-db9a77c51f23", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/262696b1-aa87-432b-8a21-db9a77c51f23", + "siteNameHierarchy": "Global/Australia" + }, + { + "parentId": "262696b1-aa87-432b-8a21-db9a77c51f23", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "262696b1-aa87-432b-8a21-db9a77c51f23", + "type": "area" + } + } + ], + "name": "Sydney", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "6e404051-4c06-4dab-adaa-72c5eeac577b", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/262696b1-aa87-432b-8a21-db9a77c51f23/6e404051-4c06-4dab-adaa-72c5eeac577b", + "siteNameHierarchy": "Global/Australia/Sydney" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "63a7fb03-d4b2-408e-a6ab-b4df0a198643", + "type": "area" + } + } + ], + "name": "Sydney", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "63a7fb03-d4b2-408e-a6ab-b4df0a198643", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/63a7fb03-d4b2-408e-a6ab-b4df0a198643", + "siteNameHierarchy": "Global/Sydney" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "f5a19514-3c1e-4127-a2b5-2a64a963c934", + "type": "area" + } + } + ], + "name": "Area_52", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "f5a19514-3c1e-4127-a2b5-2a64a963c934", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f5a19514-3c1e-4127-a2b5-2a64a963c934", + "siteNameHierarchy": "Global/Area_52" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "fa22b4e1-ee80-4aa8-8d76-83c4126d16ee", + "type": "area" + } + } + ], + "name": "Area_51", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "fa22b4e1-ee80-4aa8-8d76-83c4126d16ee", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/fa22b4e1-ee80-4aa8-8d76-83c4126d16ee", + "siteNameHierarchy": "Global/Area_51" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661", + "type": "area" + } + } + ], + "name": "Area_51a", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f1c8b4ea-ccc1-4b26-9cfd-25c0eb4ca661", + "siteNameHierarchy": "Global/Area_51a" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "7760b82a-b07e-4fa7-8cad-91adfa12dd43", + "type": "area" + } + } + ], + "name": "Area 51", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "7760b82a-b07e-4fa7-8cad-91adfa12dd43", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/7760b82a-b07e-4fa7-8cad-91adfa12dd43", + "siteNameHierarchy": "Global/Area 51" + }, + { + "parentId": "7760b82a-b07e-4fa7-8cad-91adfa12dd43", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "country": "United States", + "address": "Mercury, NV 89023", + "latitude": "36.632621", + "addressInheritedFrom": "331f7e36-1a45-4c9f-bfa9-3425a053f81a", + "type": "building", + "longitude": "-115.934912" + } + } + ], + "name": "Deep Space", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "331f7e36-1a45-4c9f-bfa9-3425a053f81a", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/7760b82a-b07e-4fa7-8cad-91adfa12dd43/331f7e36-1a45-4c9f-bfa9-3425a053f81a", + "siteNameHierarchy": "Global/Area 51/Deep Space" + }, + { + "parentId": "331f7e36-1a45-4c9f-bfa9-3425a053f81a", + "additionalInfo": [ + { + "nameSpace": "mapGeometry", + "attributes": { + "offsetX": "0.0", + "offsetY": "0.0", + "length": "300.0", + "width": "1000.0", + "height": "30.0" + } + }, + { + "nameSpace": "mapsSummary", + "attributes": { + "rfModel": "95098", + "imageURL": "", + "isCadFile": "false", + "floorIndex": "1" + } + }, + { + "nameSpace": "Location", + "attributes": { + "address": "Mercury, NV 89023", + "addressInheritedFrom": "331f7e36-1a45-4c9f-bfa9-3425a053f81a", + "type": "floor" + } + } + ], + "name": "1st Floor", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "42a47e36-01ea-4189-8e54-16a2fd063648", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/7760b82a-b07e-4fa7-8cad-91adfa12dd43/331f7e36-1a45-4c9f-bfa9-3425a053f81a/42a47e36-01ea-4189-8e54-16a2fd063648", + "siteNameHierarchy": "Global/Area 51/Deep Space/1st Floor" + }, + { + "parentId": "257c51d3-971d-49f4-83f7-c9baf334865a", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "country": "United States", + "address": "County Road 186, Brookesmith, Texas 76827, United States", + "latitude": "31.559432441659325", + "addressInheritedFrom": "398de1d9-d595-429d-8239-64b51d24f230", + "type": "building", + "longitude": "-99.19356001285279" + } + } + ], + "name": "Texas_building", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "398de1d9-d595-429d-8239-64b51d24f230", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/257c51d3-971d-49f4-83f7-c9baf334865a/398de1d9-d595-429d-8239-64b51d24f230", + "siteNameHierarchy": "Global/Texas/Texas_building" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "5c882916-4f65-45b5-a5cc-ca5fa927cba6", + "type": "area" + } + } + ], + "name": "Forschungszentrum", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "5c882916-4f65-45b5-a5cc-ca5fa927cba6", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/5c882916-4f65-45b5-a5cc-ca5fa927cba6", + "siteNameHierarchy": "Global/Forschungszentrum" + }, + { + "parentId": "5c882916-4f65-45b5-a5cc-ca5fa927cba6", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "country": "Germany", + "address": "Wallstadter Straße 59, 68526 Ladenburg", + "latitude": "49.479617", + "addressInheritedFrom": "1c3bb089-2a74-4fdf-96e3-d1815ac67e38", + "type": "building", + "longitude": "8.602459" + } + } + ], + "name": "Building 1", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "1c3bb089-2a74-4fdf-96e3-d1815ac67e38", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/5c882916-4f65-45b5-a5cc-ca5fa927cba6/1c3bb089-2a74-4fdf-96e3-d1815ac67e38", + "siteNameHierarchy": "Global/Forschungszentrum/Building 1" + }, + { + "parentId": "1c3bb089-2a74-4fdf-96e3-d1815ac67e38", + "additionalInfo": [ + { + "nameSpace": "mapGeometry", + "attributes": { + "offsetX": "0.0", + "offsetY": "0.0", + "length": "100.0", + "width": "100.0", + "height": "10.0" + } + }, + { + "nameSpace": "mapsSummary", + "attributes": { + "rfModel": "95095", + "imageURL": "", + "isCadFile": "false", + "floorIndex": "0" + } + }, + { + "nameSpace": "Location", + "attributes": { + "address": "Wallstadter Straße 59, 68526 Ladenburg", + "addressInheritedFrom": "1c3bb089-2a74-4fdf-96e3-d1815ac67e38", + "type": "floor" + } + } + ], + "name": "Lab", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "0b1f8f7f-f0be-4d14-974d-69b1693d39ec", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/5c882916-4f65-45b5-a5cc-ca5fa927cba6/1c3bb089-2a74-4fdf-96e3-d1815ac67e38/0b1f8f7f-f0be-4d14-974d-69b1693d39ec", + "siteNameHierarchy": "Global/Forschungszentrum/Building 1/Lab" + }, + { + "parentId": "04509ce4-6c88-40a3-b444-9e00f2cd97f2", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "country": "United States", + "address": "Ocean Drive Bar & Restaurant, 3915 Landis Ave, Sea Isle City, New Jersey 08243, United States", + "latitude": "39.156233", + "addressInheritedFrom": "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738", + "type": "building", + "longitude": "-74.690192" + } + } + ], + "name": "1", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "2d0d8545-b6de-4dda-a0f7-93bcd7d0e738", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/04509ce4-6c88-40a3-b444-9e00f2cd97f2/2d0d8545-b6de-4dda-a0f7-93bcd7d0e738", + "siteNameHierarchy": "Global/SanDiego/1" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "257c51d3-971d-49f4-83f7-c9baf334865a", + "type": "area" + } + } + ], + "name": "Texas", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "257c51d3-971d-49f4-83f7-c9baf334865a", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/257c51d3-971d-49f4-83f7-c9baf334865a", + "siteNameHierarchy": "Global/Texas" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "f372dbbb-d689-4d9a-9a5e-887de33fbce5", + "type": "area" + } + } + ], + "name": "Maryland", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "f372dbbb-d689-4d9a-9a5e-887de33fbce5", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f372dbbb-d689-4d9a-9a5e-887de33fbce5", + "siteNameHierarchy": "Global/Maryland" + }, + { + "parentId": "9e5f9fc2-032e-45e8-994c-4a00629648e8", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "addressInheritedFrom": "8004668a-eb96-47cc-b659-bcc9c04669ba", + "type": "area" + } + } + ], + "name": "Treton", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "8004668a-eb96-47cc-b659-bcc9c04669ba", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/8004668a-eb96-47cc-b659-bcc9c04669ba", + "siteNameHierarchy": "Global/Treton" + }, + { + "parentId": "f372dbbb-d689-4d9a-9a5e-887de33fbce5", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "country": "United States", + "address": "123 Main Street", + "latitude": "39.0458", + "addressInheritedFrom": "755faf69-0d07-48f7-b130-4806c32eb13e", + "type": "building", + "longitude": "-76.6413" + } + } + ], + "name": "secretlab", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "755faf69-0d07-48f7-b130-4806c32eb13e", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f372dbbb-d689-4d9a-9a5e-887de33fbce5/755faf69-0d07-48f7-b130-4806c32eb13e", + "siteNameHierarchy": "Global/Maryland/secretlab" + }, + { + "parentId": "8004668a-eb96-47cc-b659-bcc9c04669ba", + "additionalInfo": [ + { + "nameSpace": "Location", + "attributes": { + "country": "United States", + "address": "51 West Center Road Southeast, Rome, Georgia 30161, United States", + "latitude": "34.237896413975506", + "addressInheritedFrom": "fedd8d33-5334-413f-8a49-fb2459d7e337", + "type": "building", + "longitude": "-85.13241190760431" + } + } + ], + "name": "Rome", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "fedd8d33-5334-413f-8a49-fb2459d7e337", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/8004668a-eb96-47cc-b659-bcc9c04669ba/fedd8d33-5334-413f-8a49-fb2459d7e337", + "siteNameHierarchy": "Global/Treton/Rome" + }, + { + "parentId": "755faf69-0d07-48f7-b130-4806c32eb13e", + "additionalInfo": [ + { + "nameSpace": "mapGeometry", + "attributes": { + "offsetX": "0.0", + "offsetY": "0.0", + "width": "50.0", + "length": "60.0", + "height": "10.0" + } + }, + { + "nameSpace": "mapsSummary", + "attributes": { + "rfModel": "95095", + "imageURL": "", + "isCadFile": "false", + "floorIndex": "1" + } + }, + { + "nameSpace": "Location", + "attributes": { + "address": "123 Main Street", + "addressInheritedFrom": "755faf69-0d07-48f7-b130-4806c32eb13e", + "type": "floor" + } + } + ], + "name": "Floor 2", + "instanceTenantId": "623f029857259506a56ad9bd", + "id": "f4ff8ca1-c062-4228-868a-d6cd0bc53852", + "siteHierarchy": "9e5f9fc2-032e-45e8-994c-4a00629648e8/f372dbbb-d689-4d9a-9a5e-887de33fbce5/755faf69-0d07-48f7-b130-4806c32eb13e/f4ff8ca1-c062-4228-868a-d6cd0bc53852", + "siteNameHierarchy": "Global/Maryland/secretlab/Floor 2" + } +] \ No newline at end of file diff --git a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py index f0b97c25..7dea21aa 100644 --- a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py +++ b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py @@ -32,6 +32,7 @@ EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL, EXPECTED_FLOORS, LOCATION_FIXTURE, + LOCATION_WO_GLOBAL_FIXTURE, PORT_FIXTURE, ) @@ -154,7 +155,7 @@ def test_build_dnac_location_map(self): def test_build_dnac_location_map_wo_global(self): """Test Nautobot adapter build_dnac_location_map method without global.""" self.dna_center.dnac_location_map = {} - self.dna_center.build_dnac_location_map(locations=LOCATION_FIXTURE) + self.dna_center.build_dnac_location_map(locations=LOCATION_WO_GLOBAL_FIXTURE) expected = EXPECTED_DNAC_LOCATION_MAP_WO_GLOBAL self.assertEqual(self.dna_center.dnac_location_map, expected) From 78d5d9804553d00216bb011f07816a76aa03509e Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 20 Dec 2024 20:52:53 -0600 Subject: [PATCH 26/29] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Update=20building?= =?UTF-8?q?=20name=20to=20pull=20from=20dnac=5Flocation=5Fmap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integrations/dna_center/diffsync/adapters/dna_center.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 67a71bf5..315e8fa1 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -257,12 +257,14 @@ def load_building(self, building: dict, area_name: Optional[str] = None, area_pa Args: building (dict): Dictionary containing location information about a building. + area_name (str): Parent area for building. + area_parent_name (str): Parent of parent area for building. """ + bldg_name = self.dnac_location_map[building["id"]]["name"] if self.job.debug: self.job.logger.info( - f"Loading {self.job.building_loctype.name} {building['name']} in {area_name} with parent {area_parent_name}. {building}" + f"Loading {self.job.building_loctype.name} {bldg_name} in {area_name} with parent {area_parent_name}. {building}" ) - bldg_name = building["name"] address, _ = self.conn.find_address_and_type(info=building["additionalInfo"]) latitude, longitude = self.conn.find_latitude_and_longitude(info=building["additionalInfo"]) self.get_or_instantiate( From cd4981eeb3b4397d52c06c856f2d36b7b454ece3 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 20 Dec 2024 20:53:16 -0600 Subject: [PATCH 27/29] =?UTF-8?q?test:=20=E2=9C=85=20Update=20tests=20to?= =?UTF-8?q?=20add=20missing=20pieces=20like=20id=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nautobot_ssot/tests/dna_center/test_adapters_dna_center.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py index 7dea21aa..3d3131bb 100644 --- a/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py +++ b/nautobot_ssot/tests/dna_center/test_adapters_dna_center.py @@ -216,6 +216,8 @@ def test_load_device_location_tree_w_floor(self): self.dna_center.building_map = { "5": { "name": "HQ", + "id": "5", + "parentId": "4", "additionalInfo": [ { "nameSpace": "Location", @@ -229,6 +231,7 @@ def test_load_device_location_tree_w_floor(self): }, } ], + "siteHierarchy": "/1/2/3/4/5/", }, } mock_loc_data = {"areas": ["Global", "USA", "New York", "NYC"], "building": "HQ", "floor": "1st Floor"} @@ -277,6 +280,8 @@ def test_load_device_location_tree_wo_floor(self): self.dna_center.building_map = { "5": { "name": "HQ", + "id": "5", + "parentId": "4", "additionalInfo": [ { "nameSpace": "Location", @@ -290,6 +295,7 @@ def test_load_device_location_tree_wo_floor(self): }, } ], + "siteHierarchy": "/1/2/3/4/5/", }, } mock_loc_data = {"areas": ["Global", "USA", "New York", "NYC"], "building": "HQ"} From 314f4798fa1df3da719897aaa1f44f0fea5c8259 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Sun, 22 Dec 2024 08:15:37 -0600 Subject: [PATCH 28/29] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Simplify?= =?UTF-8?q?=20building=20of=20dnac=5Flocation=5Fmap.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dna_center/diffsync/adapters/dna_center.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py index 315e8fa1..d6561983 100644 --- a/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py +++ b/nautobot_ssot/integrations/dna_center/diffsync/adapters/dna_center.py @@ -85,6 +85,7 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too loc_name = self.job.location_map[location["name"]]["name"] else: loc_name = location["name"] + self.dnac_location_map[location["id"]] = { "name": loc_name, "loc_type": "area", @@ -106,15 +107,11 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too continue if parent_name == "Global": parent_name = None + if location["name"] in self.job.location_map and self.job.location_map[location["name"]].get("parent"): + parent_name = self.job.location_map[location["name"]]["parent"] self.dnac_location_map[loc_id]["parent"] = parent_name # add parent of parent to the mapping - for location in locations: - if location.get("parentId") and self.dnac_location_map.get(location["parentId"]): - self.dnac_location_map[location["id"]]["parent_of_parent"] = self.dnac_location_map[ - location["parentId"] - ]["parent"] - floors = [] for location in locations: # pylint: disable=too-many-nested-blocks if ( @@ -123,8 +120,10 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too ): continue loc_id = location["id"] - loc_name = self.dnac_location_map[loc_id]["name"] + loc_name = location["name"] parent_id = location.get("parentId") + if self.dnac_location_map.get(parent_id): + self.dnac_location_map[loc_id]["parent_of_parent"] = self.dnac_location_map[parent_id]["parent"] parent_name = self.dnac_location_map[loc_id]["parent"] for info in location["additionalInfo"]: if info["attributes"].get("type"): @@ -145,8 +144,6 @@ def build_dnac_location_map(self, locations: List[dict]): # pylint: disable=too self.dnac_location_map[loc_id]["parent_of_parent"] = self.job.location_map[loc_name][ "area_parent" ] - else: - self.dnac_location_map[loc_id]["parent_of_parent"] = parent_name elif info["attributes"]["type"] == "floor": floors.append(location) if self.dnac_location_map.get(parent_id): From fa42e21474837e3ef09f243116f19990c632183f Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Tue, 7 Jan 2025 12:07:00 -0600 Subject: [PATCH 29/29] =?UTF-8?q?docs:=20=F0=9F=93=9D=20Add=20changelog=20?= =?UTF-8?q?snippet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changes/643.fixed | 1 + 1 file changed, 1 insertion(+) create mode 100644 changes/643.fixed diff --git a/changes/643.fixed b/changes/643.fixed new file mode 100644 index 00000000..c47fb3c6 --- /dev/null +++ b/changes/643.fixed @@ -0,0 +1 @@ +Fixed DNA Center bug where empty Locations were imported. \ No newline at end of file