From bb7f4c79e03883b05550e4d4c9ab11ec5ba4b08a Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Tue, 2 Jul 2024 15:47:00 +0200
Subject: [PATCH] Added pagination support.

---
 inventory_provider/gap.py | 71 ++++++++++++++++++++++++---------------
 test/test_gap.py          |  9 ++++-
 2 files changed, 51 insertions(+), 29 deletions(-)

diff --git a/inventory_provider/gap.py b/inventory_provider/gap.py
index 35ecd020..31816ea5 100644
--- a/inventory_provider/gap.py
+++ b/inventory_provider/gap.py
@@ -125,33 +125,48 @@ def extract_router_info(device: dict, token: str, app_config: dict) -> dict or N
 def load_routers_from_orchestrator(app_config: dict) -> dict:
     """Gets devices from the orchestrator and returns a dictionary of FQDNs and vendors."""
     token = get_token(app_config['aai'])
-    query = """
-    {
-        subscriptions(
-            filterBy: {field: "status", value: "PROVISIONING|ACTIVE"},
-            first: 500,
-            query: "tag:(RTR|OFFICE_ROUTER|Super_POP_SWITCH)"
-        ) {
-            page {
-                subscriptionId
-                product {
-                    tag
-                }
-            }
-        }
-    }
-    """
     routers = {}
-    response = make_request(body={'query': query}, token=token, app_config=app_config)
-    try:
-        devices = response['data']['subscriptions']['page']
-    except (TypeError, KeyError):
-        devices = []
-
-    with concurrent.futures.ThreadPoolExecutor() as executor:
-        futures = [executor.submit(extract_router_info, device, token, app_config) for device in devices]
-        for future in concurrent.futures.as_completed(futures):
-            router_info = future.result()
-            if router_info is not None:
-                routers[router_info['fqdn']] = router_info['vendor']
+    end_cursor = 0
+    has_next_page = True
+
+    while has_next_page:
+        query = f"""
+        {{
+            subscriptions(
+                filterBy: {{field: "status", value: "PROVISIONING|ACTIVE"}},
+                first: 100,
+                after: {end_cursor},
+                query: "tag:(RTR|OFFICE_ROUTER|Super_POP_SWITCH)"
+            ) {{
+                pageInfo {{
+                    hasNextPage
+                    endCursor
+                }}
+                page {{
+                    subscriptionId
+                    product {{
+                        tag
+                    }}
+                }}
+            }}
+        }}
+        """
+
+        response = make_request(body={'query': query}, token=token, app_config=app_config)
+        try:
+            devices = response['data']['subscriptions']['page']
+            page_info = response['data']['subscriptions']['pageInfo']
+            end_cursor = page_info['endCursor']
+            has_next_page = page_info['hasNextPage']
+        except (TypeError, KeyError):
+            devices = []
+            has_next_page = False
+
+        with concurrent.futures.ThreadPoolExecutor() as executor:
+            futures = [executor.submit(extract_router_info, device, token, app_config) for device in devices]
+            for future in concurrent.futures.as_completed(futures):
+                router_info = future.result()
+                if router_info is not None:
+                    routers[router_info['fqdn']] = router_info['vendor']
+
     return routers
diff --git a/test/test_gap.py b/test/test_gap.py
index 3bb88330..27b5a60a 100644
--- a/test/test_gap.py
+++ b/test/test_gap.py
@@ -71,7 +71,14 @@ def test_load_routers_from_orchestrator(mocker):
                 'page': [
                     {'subscriptionId': '1', 'product': {'tag': 'RTR'}},
                     {'subscriptionId': '2', 'product': {'tag': 'OFFICE_ROUTER'}}
-                ]
+                ],
+                "pageInfo": {
+                    "totalItems": 2,
+                    "startCursor": 0,
+                    "hasPreviousPage": False,
+                    "hasNextPage": False,
+                    "endCursor": 2
+                }
             }
         }
     })
-- 
GitLab