22This module is responsible for handling HTTP requests to the Linode API.
33"""
44
5+ import itertools
56import json
67import sys
78from sys import version_info
8- from typing import Optional
9+ from typing import Iterable , List , Optional
910
1011import requests
1112from packaging import version
1213from requests import Response
1314
1415from linodecli .helpers import API_CA_PATH
1516
17+ from .baked .operation import OpenAPIOperation
18+ from .helpers import handle_url_overrides
19+
20+
21+ def get_all_pages (ctx , operation : OpenAPIOperation , args : List [str ]):
22+ """
23+ Receive all pages of a resource from multiple
24+ API responses then merge into one page.
25+
26+ :param ctx: The main CLI object
27+ """
28+
29+ ctx .page_size = 500
30+ ctx .page = 1
31+ result = do_request (ctx , operation , args ).json ()
32+
33+ total_pages = result .get ("pages" )
34+
35+ if total_pages and total_pages > 1 :
36+ pages_needed = range (2 , total_pages + 1 )
37+
38+ result = _merge_results_data (
39+ itertools .chain (
40+ (result ,),
41+ _generate_all_pages_results (ctx , operation , args , pages_needed ),
42+ )
43+ )
44+ return result
45+
1646
1747def do_request (
1848 ctx ,
@@ -26,7 +56,10 @@ def do_request(
2656 """
2757 Makes a request to an operation's URL and returns the resulting JSON, or
2858 prints and error if a non-200 comes back
59+
60+ :param ctx: The main CLI object
2961 """
62+ # TODO: Revisit using pre-built calls from OpenAPI
3063 method = getattr (requests , operation .method )
3164 headers = {
3265 "Authorization" : f"Bearer { ctx .config .get_token ()} " ,
@@ -67,6 +100,39 @@ def do_request(
67100 return result
68101
69102
103+ def _merge_results_data (results : Iterable [dict ]):
104+ """Merge multiple json response into one"""
105+
106+ iterator = iter (results )
107+ merged_result = next (iterator , None )
108+ if not merged_result :
109+ return None
110+
111+ if "pages" in merged_result :
112+ merged_result ["pages" ] = 1
113+ if "page" in merged_result :
114+ merged_result ["page" ] = 1
115+ if "data" in merged_result :
116+ merged_result ["data" ] += list (
117+ itertools .chain .from_iterable (r ["data" ] for r in iterator )
118+ )
119+ return merged_result
120+
121+
122+ def _generate_all_pages_results (
123+ ctx ,
124+ operation : OpenAPIOperation ,
125+ args : List [str ],
126+ pages_needed : Iterable [int ],
127+ ):
128+ """
129+ :param ctx: The main CLI object
130+ """
131+ for p in pages_needed :
132+ ctx .page = p
133+ yield do_request (ctx , operation , args ).json ()
134+
135+
70136def _build_filter_header (
71137 operation , parsed_args , filter_header = None
72138) -> Optional [str ]:
@@ -102,7 +168,14 @@ def _build_filter_header(
102168
103169
104170def _build_request_url (ctx , operation , parsed_args ) -> str :
105- result = operation .url .format (** vars (parsed_args ))
171+ target_server = handle_url_overrides (
172+ operation .url_base ,
173+ host = ctx .config .get_value ("api_host" ),
174+ version = ctx .config .get_value ("api_version" ),
175+ scheme = ctx .config .get_value ("api_scheme" ),
176+ )
177+
178+ result = f"{ target_server } { operation .url_path } " .format (** vars (parsed_args ))
106179
107180 if operation .method == "get" :
108181 result += f"?page={ ctx .page } &page_size={ ctx .page_size } "
0 commit comments