Skip to content

Commit 39c2968

Browse files
authored
Fixed pagination when retrieving locations from DNA Center (#1161)
1 parent 0d9ded0 commit 39c2968

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

changes/1160.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed a bug in the DNA Center integration where the get_locations method was not correctly paginating the results.

nautobot_ssot/integrations/dna_center/utils/dna_center.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@ def get_locations(self):
4545
try:
4646
total_num_sites = self.conn.sites.get_site_count()["response"]
4747
offset = 1
48+
# Default page size is 50, max is 500, so we'll use a comfortable middle ground.
49+
limit = 200
4850
while len(loc_data) < total_num_sites:
49-
loc_data.extend(self.conn.sites.get_site(offset=offset)["response"])
50-
offset = len(loc_data)
51+
loc_data.extend(self.conn.sites.get_site(offset=offset, limit=limit)["response"])
52+
offset += limit
5153
for _, item in enumerate(loc_data):
5254
if item["siteNameHierarchy"] not in loc_names:
5355
loc_names.append(item["siteNameHierarchy"])

nautobot_ssot/tests/dna_center/test_utils_dna_center.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def setUp(self):
3333
self.verify = False
3434
self.dnac = DnaCenterClient(self.url, self.username, self.password, verify=self.verify)
3535
self.dnac.conn = MagicMock()
36-
self.dnac.conn.sites.get_site_count.return_value = {"response": 4}
36+
self.dnac.conn.sites.get_site_count.return_value = {"response": 31}
3737
self.dnac.conn.devices.get_device_count.return_value = {"response": 3}
3838

3939
self.mock_response = create_autospec(Response)
@@ -70,6 +70,26 @@ def test_get_locations(self):
7070
actual = self.dnac.get_locations()
7171
self.assertEqual(actual, LOCATION_FIXTURE)
7272

73+
def test_get_locations_pagination(self):
74+
"""Test the get_locations method correctly paginates without skipping items.
75+
76+
Simulates a 1-based offset API returning a fixed page size. With N total items
77+
and page_size P, an off-by-one in offset causes one duplicate per page. When the
78+
accumulated duplicates inflate loc_data to >= total before all unique items are
79+
fetched, the loop exits early and items are silently skipped.
80+
"""
81+
all_locations = RECV_LOCATION_FIXTURE["response"][:30]
82+
83+
def fake_get_site(offset=1, limit=10, **kwargs):
84+
"""Simulate 1-based offset API returning up to limit items."""
85+
start = offset - 1
86+
return {"response": all_locations[start : start + limit]}
87+
88+
self.dnac.conn.sites.get_site.side_effect = fake_get_site
89+
self.dnac.conn.sites.get_site_count.return_value = {"response": len(all_locations)}
90+
actual = self.dnac.get_locations()
91+
self.assertEqual(len(actual), len(all_locations))
92+
7393
def test_get_locations_catches_api_error(self):
7494
"""Test the get_locations method in DnaCenterClient catches dnacentersdkException."""
7595
self.dnac.conn.sites.get_site.side_effect = dnacentersdkException(self.mock_response)

0 commit comments

Comments
 (0)