4
4
# license information.
5
5
# --------------------------------------------------------------------------
6
6
import logging
7
- import requests
8
7
import six
9
8
import os
10
9
from typing import TYPE_CHECKING
18
17
19
18
# the trimming function to clean up incoming arguments to the test function we are wrapping
20
19
from azure_devtools .scenario_tests .utilities import trim_kwargs_from_test_function
20
+
21
21
from .config import PROXY_URL
22
22
from .helpers import get_test_id , is_live , is_live_and_not_recording , set_recording_id
23
23
from .proxy_startup import discovered_roots
24
+ from urllib3 import PoolManager , Retry
25
+ from urllib3 .exceptions import HTTPError
26
+ import json
24
27
25
28
if TYPE_CHECKING :
26
29
from typing import Callable , Dict , Tuple
29
32
# To learn about how to migrate SDK tests to the test proxy, please refer to the migration guide at
30
33
# https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/test_proxy_migration_guide.md
31
34
35
+ if os .getenv ("REQUESTS_CA_BUNDLE" ):
36
+ http_client = PoolManager (
37
+ retries = Retry (total = 3 , raise_on_status = False ),
38
+ cert_reqs = "CERT_REQUIRED" ,
39
+ ca_certs = os .getenv ("REQUESTS_CA_BUNDLE" ),
40
+ )
41
+ else :
42
+ http_client = PoolManager (retries = Retry (total = 3 , raise_on_status = False ))
32
43
33
44
# defaults
34
45
RECORDING_START_URL = "{}/record/start" .format (PROXY_URL )
35
46
RECORDING_STOP_URL = "{}/record/stop" .format (PROXY_URL )
36
47
PLAYBACK_START_URL = "{}/playback/start" .format (PROXY_URL )
37
48
PLAYBACK_STOP_URL = "{}/playback/stop" .format (PROXY_URL )
38
49
50
+
39
51
def get_recording_assets (test_id : str ) -> str :
40
52
"""
41
53
Used to retrieve the assets.json given a PYTEST_CURRENT_TEST test id.
@@ -58,45 +70,50 @@ def get_recording_assets(test_id: str) -> str:
58
70
59
71
return None
60
72
73
+
61
74
def start_record_or_playback (test_id : str ) -> "Tuple[str, Dict[str, str]]" :
62
75
"""Sends a request to begin recording or playing back the provided test.
63
76
64
77
This returns a tuple, (a, b), where a is the recording ID of the test and b is the `variables` dictionary that maps
65
78
test variables to values. If no variable dictionary was stored when the test was recorded, b is an empty dictionary.
66
79
"""
67
80
variables = {} # this stores a dictionary of test variable values that could have been stored with a recording
68
-
81
+
69
82
json_payload = {"x-recording-file" : test_id }
70
83
assets_json = get_recording_assets (test_id )
71
84
if assets_json :
72
- json_payload ["x-recording-assets-file" ] = assets_json
85
+ json_payload ["x-recording-assets-file" ] = assets_json
86
+
87
+ encoded_payload = json .dumps (json_payload ).encode ("utf-8" )
73
88
74
89
if is_live ():
75
- result = requests .post (
76
- RECORDING_START_URL ,
77
- json = json_payload ,
90
+ result = http_client .request (
91
+ method = "POST" ,
92
+ url = RECORDING_START_URL ,
93
+ body = encoded_payload ,
78
94
)
79
- if result .status_code != 200 :
80
- message = six .ensure_str (result ._content )
95
+ if result .status != 200 :
96
+ message = six .ensure_str (result .data )
81
97
raise HttpResponseError (message = message )
82
98
recording_id = result .headers ["x-recording-id" ]
83
99
84
100
else :
85
- result = requests .post (
86
- PLAYBACK_START_URL ,
87
- json = json_payload ,
101
+ result = http_client .request (
102
+ method = "POST" ,
103
+ url = PLAYBACK_START_URL ,
104
+ body = encoded_payload ,
88
105
)
89
- if result .status_code != 200 :
90
- message = six .ensure_str (result ._content )
106
+ if result .status != 200 :
107
+ message = six .ensure_str (result .data )
91
108
raise HttpResponseError (message = message )
92
109
93
110
try :
94
111
recording_id = result .headers ["x-recording-id" ]
95
112
except KeyError as ex :
96
113
six .raise_from (ValueError ("No recording file found for {}" .format (test_id )), ex )
97
- if result .text :
114
+ if result .data :
98
115
try :
99
- variables = result .json ( )
116
+ variables = json . loads ( result .data . decode ( "utf-8" ) )
100
117
except ValueError as ex : # would be a JSONDecodeError on Python 3, which subclasses ValueError
101
118
six .raise_from (
102
119
ValueError ("The response body returned from starting playback did not contain valid JSON" ),
@@ -109,25 +126,27 @@ def start_record_or_playback(test_id: str) -> "Tuple[str, Dict[str, str]]":
109
126
110
127
111
128
def stop_record_or_playback (test_id : str , recording_id : str , test_variables : "Dict[str, str]" ) -> None :
112
- if is_live ():
113
- response = requests .post (
114
- RECORDING_STOP_URL ,
115
- headers = {
116
- "x-recording-file" : test_id ,
117
- "x-recording-id" : recording_id ,
118
- "x-recording-save" : "true" ,
119
- "Content-Type" : "application/json" ,
120
- },
121
- json = test_variables or {}, # tests don't record successfully unless test_variables is a dictionary
122
- )
123
- else :
124
- response = requests .post (
125
- PLAYBACK_STOP_URL ,
126
- headers = {"x-recording-id" : recording_id },
127
- )
128
129
try :
129
- response .raise_for_status ()
130
- except requests .HTTPError as e :
130
+ if is_live ():
131
+ http_client .request (
132
+ method = "POST" ,
133
+ url = RECORDING_STOP_URL ,
134
+ headers = {
135
+ "x-recording-file" : test_id ,
136
+ "x-recording-id" : recording_id ,
137
+ "x-recording-save" : "true" ,
138
+ "Content-Type" : "application/json" ,
139
+ },
140
+ # tests don't record successfully unless test_variables is a dictionary
141
+ body = json .dumps (test_variables ).encode ("utf-8" ) if test_variables else "{}" ,
142
+ )
143
+ else :
144
+ http_client .request (
145
+ method = "POST" ,
146
+ url = PLAYBACK_STOP_URL ,
147
+ headers = {"x-recording-id" : recording_id },
148
+ )
149
+ except HTTPError as e :
131
150
raise HttpResponseError (
132
151
"The test proxy ran into an error while ending the session. Make sure any test variables you record have "
133
152
"string values."
0 commit comments