Skip to content

Commit 6fef539

Browse files
authored
Create script to contribute data gathered using benchmarks-monthly.py (dotnet#2422)
* Initial perfcontrib auth script * End to end implementation of auth + uploads complete * Fix type check errors * Minor clean-up * Improve error handling in perfcontrib
1 parent 9040d2b commit 6fef539

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

scripts/perfcontrib.py

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
from json import loads, dumps
2+
from urllib.request import urlopen, Request
3+
from urllib.parse import urlencode
4+
from urllib.error import HTTPError
5+
import time
6+
import sys
7+
import os
8+
9+
tenantId = "72f988bf-86f1-41af-91ab-2d7cd011db47"
10+
appId = "c2fe4cd0-be4a-468b-aa4f-078c67dcab6e"
11+
12+
uploadService = "https://perfcontrib.azurewebsites.net"
13+
uploadEndpoint = f"{uploadService}/api/UploadPerfData"
14+
authEndpoint = f"{uploadService}/.auth/login/aad"
15+
authDetailsEndpoint = f"{uploadService}/.auth/me"
16+
17+
aadUrl = f"https://login.microsoftonline.com/{tenantId}"
18+
19+
def get_token() -> str:
20+
path = os.path.expanduser("~/.perfcontrib")
21+
22+
token: str | None = None
23+
24+
try:
25+
if not os.path.exists(path):
26+
os.makedirs(path)
27+
with open(os.path.expanduser("~/.perfcontrib/token")) as tokenfile:
28+
token = tokenfile.readline()
29+
except FileNotFoundError:
30+
pass
31+
32+
if token:
33+
try:
34+
with urlopen(Request(authDetailsEndpoint,
35+
headers = { "X-ZUMO-AUTH": token })) as response:
36+
print("Using cached credentials.")
37+
except HTTPError as error:
38+
token = None
39+
40+
if not token:
41+
token = authenticate()
42+
43+
if token:
44+
with open(os.path.expanduser("~/.perfcontrib/token"), "w") as tokenfile:
45+
tokenfile.write(token)
46+
47+
return token
48+
49+
def authenticate() -> str:
50+
authBody = {
51+
"tenant": tenantId,
52+
"client_id": appId,
53+
"scope": "User.Read openid profile",
54+
}
55+
56+
authBodyEncoded = urlencode(authBody).encode()
57+
58+
with urlopen(Request(f"{aadUrl}/oauth2/v2.0/devicecode", data = authBodyEncoded)) as response:
59+
devicecodeResponse = loads(response.read().decode('utf-8'))
60+
61+
print(devicecodeResponse["message"])
62+
63+
authBody2 = {
64+
"tenant": tenantId,
65+
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
66+
"client_id": appId,
67+
"device_code": devicecodeResponse["device_code"]
68+
}
69+
70+
authBody2Encoded = urlencode(authBody2).encode()
71+
72+
authStatus = "waiting"
73+
print("waiting", end="", flush=True)
74+
while (authStatus == "waiting"):
75+
# Try to get the access token. if we encounter an error check the reason.
76+
# If the reason is we are waiting then sleep for some time.
77+
# If the reason is the user has declined or we timed out then quit.
78+
try:
79+
with urlopen(Request(f"{aadUrl}/oauth2/v2.0/token", data = authBody2Encoded)) as response:
80+
tokenResponse = loads(response.read().decode('utf-8'))
81+
authStatus = "done"
82+
except Exception as ex:
83+
reason = loads(ex.read().decode('utf-8'))["error"]
84+
if reason == "authorization_pending":
85+
print(".", end="", flush=True)
86+
time.sleep(5)
87+
elif reason == "authorization_declined":
88+
authStatus = "failed"
89+
elif reason == "expired_token":
90+
authStatus = "failed"
91+
92+
print()
93+
94+
if authStatus == "failed": raise "Authentication failed"
95+
96+
idToken = tokenResponse["id_token"]
97+
98+
print("Thanks.")
99+
authBody3 = {
100+
"access_token": idToken
101+
}
102+
103+
authBody3Json = dumps(authBody3).encode()
104+
105+
with urlopen(Request(authEndpoint,
106+
data = authBody3Json,
107+
headers = {"Content-Type": "application/json"})) as response:
108+
aadLoginResponse = loads(response.read().decode('utf-8'))
109+
110+
token = aadLoginResponse["authenticationToken"]
111+
112+
return token
113+
114+
def upload(filename: str) -> None:
115+
token = get_token()
116+
117+
print("Uploading.")
118+
119+
with urlopen(Request(uploadEndpoint,
120+
headers = { "X-ZUMO-AUTH": token, "Content-Type": "application/octet-stream", "X-Filename": filename },
121+
data = open(filename,"rb"))) as response:
122+
print(response.read().decode('utf-8'))
123+
124+
if __name__ == "__main__":
125+
upload(sys.argv[1])

0 commit comments

Comments
 (0)