locust-cloud 1.20.3__py3-none-any.whl → 1.20.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- locust_cloud/__init__.py +0 -23
- locust_cloud/apisession.py +11 -10
- locust_cloud/args.py +25 -0
- locust_cloud/cloud.py +8 -2
- locust_cloud/common.py +7 -0
- locust_cloud/web_login.py +7 -1
- {locust_cloud-1.20.3.dist-info → locust_cloud-1.20.4.dist-info}/METADATA +4 -3
- locust_cloud-1.20.4.dist-info/RECORD +18 -0
- locust_cloud-1.20.3.dist-info/RECORD +0 -18
- {locust_cloud-1.20.3.dist-info → locust_cloud-1.20.4.dist-info}/WHEEL +0 -0
- {locust_cloud-1.20.3.dist-info → locust_cloud-1.20.4.dist-info}/entry_points.txt +0 -0
- {locust_cloud-1.20.3.dist-info → locust_cloud-1.20.4.dist-info}/licenses/LICENSE +0 -0
locust_cloud/__init__.py
CHANGED
@@ -1,26 +1,3 @@
|
|
1
|
-
from locust import events
|
2
|
-
from locust_cloud.args import cloud_parser
|
3
1
|
from locust_cloud.cloud import main
|
4
2
|
|
5
3
|
__all__ = ["main"]
|
6
|
-
|
7
|
-
|
8
|
-
@events.init_command_line_parser.add_listener
|
9
|
-
def _(parser):
|
10
|
-
cloud_group = parser.add_argument_group(
|
11
|
-
"Locust Cloud",
|
12
|
-
"""Launches a distributed Locust run on locust.cloud infrastructure.
|
13
|
-
|
14
|
-
Example: locust --cloud -f my_locustfile.py --users 1000 ...""",
|
15
|
-
)
|
16
|
-
|
17
|
-
# This arguments is defined here because only makes sense when
|
18
|
-
# running from locust core
|
19
|
-
cloud_group.add_argument(
|
20
|
-
"--cloud",
|
21
|
-
action="store_true",
|
22
|
-
help="Run Locust in cloud mode.",
|
23
|
-
)
|
24
|
-
|
25
|
-
for action in cloud_parser._actions:
|
26
|
-
cloud_group._add_action(action)
|
locust_cloud/apisession.py
CHANGED
@@ -3,7 +3,6 @@ import os
|
|
3
3
|
import sys
|
4
4
|
import time
|
5
5
|
|
6
|
-
import jwt
|
7
6
|
import requests
|
8
7
|
from locust_cloud.common import VALID_REGIONS, __version__, get_api_url, read_cloud_config, write_cloud_config
|
9
8
|
|
@@ -42,7 +41,8 @@ class ApiSession(requests.Session):
|
|
42
41
|
|
43
42
|
self.__refresh_token = response.json()["refresh_token"]
|
44
43
|
id_token = response.json()["cognito_client_id_token"]
|
45
|
-
|
44
|
+
user_sub_id = response.json()["user_sub_id"]
|
45
|
+
id_token_expires = response.json()["id_token_expires"]
|
46
46
|
else:
|
47
47
|
config = read_cloud_config()
|
48
48
|
|
@@ -55,14 +55,14 @@ class ApiSession(requests.Session):
|
|
55
55
|
self.__configure_for_region(config.region)
|
56
56
|
self.__refresh_token = config.refresh_token
|
57
57
|
id_token = config.id_token
|
58
|
+
user_sub_id = config.user_sub_id
|
59
|
+
id_token_expires = config.id_token_expires
|
58
60
|
|
59
61
|
assert id_token
|
60
62
|
|
61
|
-
|
62
|
-
self.
|
63
|
+
self.__user_sub_id = user_sub_id
|
64
|
+
self.__id_token_expires = id_token_expires - 60 # Refresh 1 minute before expiry
|
63
65
|
self.headers["Authorization"] = f"Bearer {id_token}"
|
64
|
-
|
65
|
-
self.__sub = decoded["sub"]
|
66
66
|
self.headers["X-Client-Version"] = __version__
|
67
67
|
|
68
68
|
def __configure_for_region(self, region: str) -> None:
|
@@ -73,12 +73,12 @@ class ApiSession(requests.Session):
|
|
73
73
|
logger.debug(f"Lambda url: {self.api_url}")
|
74
74
|
|
75
75
|
def __ensure_valid_authorization_header(self) -> None:
|
76
|
-
if self.
|
76
|
+
if self.__id_token_expires > time.time():
|
77
77
|
return
|
78
78
|
|
79
79
|
response = requests.post(
|
80
80
|
self.__login_url,
|
81
|
-
json={"user_sub_id": self.
|
81
|
+
json={"user_sub_id": self.__user_sub_id, "refresh_token": self.__refresh_token},
|
82
82
|
headers={"X-Client-Version": __version__},
|
83
83
|
)
|
84
84
|
|
@@ -92,13 +92,14 @@ class ApiSession(requests.Session):
|
|
92
92
|
# do a locust-cloud --login if we get that.
|
93
93
|
|
94
94
|
id_token = response.json()["cognito_client_id_token"]
|
95
|
-
|
96
|
-
self.
|
95
|
+
id_token_expires = response.json()["id_token_expires"]
|
96
|
+
self.__id_token_expires = id_token_expires - 60 # Refresh 1 minute before expiry
|
97
97
|
self.headers["Authorization"] = f"Bearer {id_token}"
|
98
98
|
|
99
99
|
if not self.non_interactive:
|
100
100
|
config = read_cloud_config()
|
101
101
|
config.id_token = id_token
|
102
|
+
config.id_token_expires = id_token_expires
|
102
103
|
write_cloud_config(config)
|
103
104
|
|
104
105
|
def request(self, method, url, *args, **kwargs) -> requests.Response:
|
locust_cloud/args.py
CHANGED
@@ -115,6 +115,11 @@ cloud_parser.add_argument(
|
|
115
115
|
action="store_true",
|
116
116
|
help="Launch an interactive session to authenticate your user.\nOnce completed your credentials will be stored and automatically refreshed for quite a long time.\nOnce those expire you will be prompted to perform another login.",
|
117
117
|
)
|
118
|
+
cloud_parser.add_argument(
|
119
|
+
"--logout",
|
120
|
+
action="store_true",
|
121
|
+
help="Removes the authentication credentials",
|
122
|
+
)
|
118
123
|
cloud_parser.add_argument(
|
119
124
|
"--delete",
|
120
125
|
action="store_true",
|
@@ -213,3 +218,23 @@ combined_cloud_parser.add_argument(
|
|
213
218
|
choices=["DEBUG", "INFO", "WARNING", "ERROR"],
|
214
219
|
default="INFO",
|
215
220
|
)
|
221
|
+
|
222
|
+
|
223
|
+
def add_locust_cloud_argparse(parser):
|
224
|
+
cloud_group = parser.add_argument_group(
|
225
|
+
"Locust Cloud",
|
226
|
+
"""Launches a distributed Locust run on locust.cloud infrastructure.
|
227
|
+
|
228
|
+
Example: locust --cloud -f my_locustfile.py --users 1000 ...""",
|
229
|
+
)
|
230
|
+
|
231
|
+
# This arguments is defined here because only makes sense when
|
232
|
+
# running from locust core
|
233
|
+
cloud_group.add_argument(
|
234
|
+
"--cloud",
|
235
|
+
action="store_true",
|
236
|
+
help="Run Locust in cloud mode.",
|
237
|
+
)
|
238
|
+
|
239
|
+
for action in cloud_parser._actions:
|
240
|
+
cloud_group._add_action(action)
|
locust_cloud/cloud.py
CHANGED
@@ -9,7 +9,7 @@ from locust_cloud.apisession import ApiSession
|
|
9
9
|
from locust_cloud.args import combined_cloud_parser
|
10
10
|
from locust_cloud.common import __version__
|
11
11
|
from locust_cloud.input_events import input_listener
|
12
|
-
from locust_cloud.web_login import web_login
|
12
|
+
from locust_cloud.web_login import logout, web_login
|
13
13
|
from locust_cloud.websocket import SessionMismatchError, Websocket, WebsocketTimeout
|
14
14
|
|
15
15
|
logger = logging.getLogger(__name__)
|
@@ -39,7 +39,13 @@ def main():
|
|
39
39
|
if options.login:
|
40
40
|
try:
|
41
41
|
web_login()
|
42
|
-
except
|
42
|
+
except Exception:
|
43
|
+
pass
|
44
|
+
return
|
45
|
+
if options.logout:
|
46
|
+
try:
|
47
|
+
logout()
|
48
|
+
except Exception:
|
43
49
|
pass
|
44
50
|
return
|
45
51
|
|
locust_cloud/common.py
CHANGED
@@ -16,9 +16,11 @@ CLOUD_CONF_FILE = pathlib.Path(platformdirs.user_config_dir(appname="locust-clou
|
|
16
16
|
@dataclass
|
17
17
|
class CloudConfig:
|
18
18
|
id_token: str | None = None
|
19
|
+
user_sub_id: str | None = None
|
19
20
|
refresh_token: str | None = None
|
20
21
|
refresh_token_expires: int = 0
|
21
22
|
region: str | None = None
|
23
|
+
id_token_expires: int = 0
|
22
24
|
|
23
25
|
|
24
26
|
def get_api_url(region):
|
@@ -38,3 +40,8 @@ def write_cloud_config(config: CloudConfig) -> None:
|
|
38
40
|
|
39
41
|
with open(CLOUD_CONF_FILE, "w") as f:
|
40
42
|
json.dump(config.__dict__, f)
|
43
|
+
|
44
|
+
|
45
|
+
def delete_cloud_config() -> None:
|
46
|
+
if CLOUD_CONF_FILE.exists():
|
47
|
+
CLOUD_CONF_FILE.unlink()
|
locust_cloud/web_login.py
CHANGED
@@ -3,7 +3,7 @@ import time
|
|
3
3
|
import webbrowser
|
4
4
|
|
5
5
|
import requests
|
6
|
-
from locust_cloud.common import VALID_REGIONS, CloudConfig, get_api_url, write_cloud_config
|
6
|
+
from locust_cloud.common import VALID_REGIONS, CloudConfig, delete_cloud_config, get_api_url, write_cloud_config
|
7
7
|
|
8
8
|
POLLING_FREQUENCY = 1
|
9
9
|
|
@@ -71,7 +71,13 @@ If the browser does not open or you wish to use a different device to authorize
|
|
71
71
|
config = CloudConfig(
|
72
72
|
id_token=data["id_token"],
|
73
73
|
refresh_token=data["refresh_token"],
|
74
|
+
user_sub_id=data["user_sub_id"],
|
74
75
|
refresh_token_expires=data["refresh_token_expires"],
|
76
|
+
id_token_expires=data["id_token_expires"],
|
75
77
|
region=region,
|
76
78
|
)
|
77
79
|
write_cloud_config(config)
|
80
|
+
|
81
|
+
|
82
|
+
def logout():
|
83
|
+
delete_cloud_config()
|
@@ -1,16 +1,17 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: locust-cloud
|
3
|
-
Version: 1.20.
|
3
|
+
Version: 1.20.4
|
4
4
|
Summary: Locust Cloud
|
5
5
|
Project-URL: homepage, https://locust.cloud
|
6
6
|
Project-URL: repository, https://github.com/locustcloud/locust-cloud
|
7
7
|
License: MIT
|
8
8
|
License-File: LICENSE
|
9
9
|
Requires-Python: >=3.10
|
10
|
-
Requires-Dist:
|
10
|
+
Requires-Dist: configargparse>=1.5.5
|
11
|
+
Requires-Dist: gevent<25.0.0,>=24.10.1
|
11
12
|
Requires-Dist: platformdirs<5.0.0,>=4.3.6
|
12
|
-
Requires-Dist: pyjwt<3.0,>=2.0
|
13
13
|
Requires-Dist: python-socketio[client]==5.13.0
|
14
|
+
Requires-Dist: tomli>=1.1.0; python_version < '3.11'
|
14
15
|
Description-Content-Type: text/markdown
|
15
16
|
|
16
17
|
# Locust Cloud
|
@@ -0,0 +1,18 @@
|
|
1
|
+
locust_cloud/__init__.py,sha256=6z2hE5rUP9WJyYgr-7XC2GhIV-05m8XxjOsnb8ae1WY,56
|
2
|
+
locust_cloud/apisession.py,sha256=gWqNADGL3H745fefm_tE1O1516OBfOhqZRlc-BgIudM,4224
|
3
|
+
locust_cloud/args.py,sha256=warMJQvUg_liowJWHS0XF400rQQ0PUigPSutfwG9BLY,7661
|
4
|
+
locust_cloud/cloud.py,sha256=LFO_Ykst0bOBYPqfxS6ll7abAvCCqyUpD3ql4nem9ys,6264
|
5
|
+
locust_cloud/common.py,sha256=GVKkWcbbqd9n8oU-fHZRVZw3jGtuIVGSCLD2ZizeEo0,1160
|
6
|
+
locust_cloud/input_events.py,sha256=MyxccgboHByICuK6VpQCCJhZQqTZAacNmkSpw-gxBEw,3420
|
7
|
+
locust_cloud/web_login.py,sha256=Byu62DKyf8NSbPdP9I2Q3lJh_lZgxjn0OZcRgnMIlXg,2555
|
8
|
+
locust_cloud/websocket.py,sha256=9Q7nTFuAwVhgW74DlJNcHTZXOQ1drsXi8hX9ciZhWlQ,8998
|
9
|
+
locust_cloud/docs/.gitignore,sha256=ghNPcjYkjQXNS_eVmu2hQFhq6FIUliAD1O2CJhulS2o,10
|
10
|
+
locust_cloud/docs/1-first-run.rst,sha256=dYYVxVb1RlWPNvhE98H1D_mzTJ1H2NWNn435nag3_jA,691
|
11
|
+
locust_cloud/docs/2-examples.rst,sha256=RublnAK3jHRsEtbJAr1y2NEEoN0YAjkzP1np-7tJ3aE,9565
|
12
|
+
locust_cloud/docs/locust-cloud.rst,sha256=NMfWGZdT0YPa0gPPuOcKplzBcqiEK7buPzXHOlzY5T0,98
|
13
|
+
locust_cloud/docs/images/locust-cloud-screenshot.png,sha256=ag0IxBi-40VexC84MApol1GCgRCL2h-l8NQDTMaeTyE,477350
|
14
|
+
locust_cloud-1.20.4.dist-info/METADATA,sha256=dEwbv0pE4L1vUKIfC9yoMFAGLuqafCiODj_HUW3-HlU,644
|
15
|
+
locust_cloud-1.20.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
16
|
+
locust_cloud-1.20.4.dist-info/entry_points.txt,sha256=PGyAb4e3aTsGS3N3VGShDl6VzJaXy7QwsEgsLOC7V00,57
|
17
|
+
locust_cloud-1.20.4.dist-info/licenses/LICENSE,sha256=Ow6fY6ta4KIjdlWalmxGvRP8yLmetvkbkl-SdHMjPIs,1093
|
18
|
+
locust_cloud-1.20.4.dist-info/RECORD,,
|
@@ -1,18 +0,0 @@
|
|
1
|
-
locust_cloud/__init__.py,sha256=9USe4yHuvpP5xrXm0dVsi08pu2l5TcjxQl6Pei8w3lk,713
|
2
|
-
locust_cloud/apisession.py,sha256=kCr271_l0IeMGw0L563mOecqPJj4OD9h2J3vxCM5zYQ,4015
|
3
|
-
locust_cloud/args.py,sha256=jBAKDNckEfP5v_2rKEMWWiWK_sjW6kX3sNgzgQkGk0Q,6974
|
4
|
-
locust_cloud/cloud.py,sha256=esKhV4BXIkn2-1kPyUkW-o8k7GpevgaJz8CrA0S89VE,6149
|
5
|
-
locust_cloud/common.py,sha256=cFrDVKpi9OEmH6giOuj9HoIUFSBArixNtNHzZIgDvPE,992
|
6
|
-
locust_cloud/input_events.py,sha256=MyxccgboHByICuK6VpQCCJhZQqTZAacNmkSpw-gxBEw,3420
|
7
|
-
locust_cloud/web_login.py,sha256=1j2AQoEM6XVSDtE1q0Ryrs4jFEx07r9IQfZCoFAQXJg,2400
|
8
|
-
locust_cloud/websocket.py,sha256=9Q7nTFuAwVhgW74DlJNcHTZXOQ1drsXi8hX9ciZhWlQ,8998
|
9
|
-
locust_cloud/docs/.gitignore,sha256=ghNPcjYkjQXNS_eVmu2hQFhq6FIUliAD1O2CJhulS2o,10
|
10
|
-
locust_cloud/docs/1-first-run.rst,sha256=dYYVxVb1RlWPNvhE98H1D_mzTJ1H2NWNn435nag3_jA,691
|
11
|
-
locust_cloud/docs/2-examples.rst,sha256=RublnAK3jHRsEtbJAr1y2NEEoN0YAjkzP1np-7tJ3aE,9565
|
12
|
-
locust_cloud/docs/locust-cloud.rst,sha256=NMfWGZdT0YPa0gPPuOcKplzBcqiEK7buPzXHOlzY5T0,98
|
13
|
-
locust_cloud/docs/images/locust-cloud-screenshot.png,sha256=ag0IxBi-40VexC84MApol1GCgRCL2h-l8NQDTMaeTyE,477350
|
14
|
-
locust_cloud-1.20.3.dist-info/METADATA,sha256=ifRrqs3KTmgT6Rt230IXc_5Clb6xwRL7jJPV-lfQ5wk,576
|
15
|
-
locust_cloud-1.20.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
16
|
-
locust_cloud-1.20.3.dist-info/entry_points.txt,sha256=PGyAb4e3aTsGS3N3VGShDl6VzJaXy7QwsEgsLOC7V00,57
|
17
|
-
locust_cloud-1.20.3.dist-info/licenses/LICENSE,sha256=Ow6fY6ta4KIjdlWalmxGvRP8yLmetvkbkl-SdHMjPIs,1093
|
18
|
-
locust_cloud-1.20.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|