locust-cloud 1.2.11__py3-none-any.whl → 1.3.1__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 +4 -2
- locust_cloud/cloud.py +66 -40
- locust_cloud/webui/dist/assets/{index-viQieTyS.js → index-BzflLAyP.js} +83 -83
- locust_cloud/webui/dist/index.html +1 -1
- {locust_cloud-1.2.11.dist-info → locust_cloud-1.3.1.dist-info}/METADATA +1 -1
- {locust_cloud-1.2.11.dist-info → locust_cloud-1.3.1.dist-info}/RECORD +8 -8
- {locust_cloud-1.2.11.dist-info → locust_cloud-1.3.1.dist-info}/WHEEL +0 -0
- {locust_cloud-1.2.11.dist-info → locust_cloud-1.3.1.dist-info}/entry_points.txt +0 -0
locust_cloud/__init__.py
CHANGED
@@ -2,6 +2,8 @@ import os
|
|
2
2
|
|
3
3
|
os.environ["LOCUST_SKIP_MONKEY_PATCH"] = "1"
|
4
4
|
|
5
|
+
import argparse
|
6
|
+
|
5
7
|
from locust import events
|
6
8
|
from locust.argument_parser import LocustArgumentParser
|
7
9
|
from locust_cloud.auth import register_auth
|
@@ -17,7 +19,7 @@ GRAPH_VIEWER = os.environ.get("GRAPH_VIEWER")
|
|
17
19
|
|
18
20
|
@events.init_command_line_parser.add_listener
|
19
21
|
def add_arguments(parser: LocustArgumentParser):
|
20
|
-
if not PG_HOST:
|
22
|
+
if not (PG_HOST or GRAPH_VIEWER):
|
21
23
|
parser.add_argument_group(
|
22
24
|
"locust-cloud",
|
23
25
|
"locust-cloud disabled, because PG_HOST was not set - this is normal for local runs",
|
@@ -32,7 +34,7 @@ def add_arguments(parser: LocustArgumentParser):
|
|
32
34
|
locust_cloud.add_argument(
|
33
35
|
"--exporter",
|
34
36
|
default=True,
|
35
|
-
action=
|
37
|
+
action=argparse.BooleanOptionalAction,
|
36
38
|
env_var="LOCUST_EXPORTER",
|
37
39
|
help="Exports Locust stats to Timescale",
|
38
40
|
)
|
locust_cloud/cloud.py
CHANGED
@@ -92,7 +92,6 @@ parser.add_argument(
|
|
92
92
|
env_var="LOCUST_USERS",
|
93
93
|
)
|
94
94
|
parser.add_argument(
|
95
|
-
"-r",
|
96
95
|
"--requirements",
|
97
96
|
type=str,
|
98
97
|
help="Optional requirements.txt file that contains your external libraries.",
|
@@ -169,6 +168,11 @@ parser.add_argument(
|
|
169
168
|
env_var="LOCUST_CLOUD_WORKERS",
|
170
169
|
default=None,
|
171
170
|
)
|
171
|
+
parser.add_argument(
|
172
|
+
"--delete",
|
173
|
+
action="store_true",
|
174
|
+
help="Delete a running cluster. Useful if locust-cloud was killed/disconnected or if there was an error.",
|
175
|
+
)
|
172
176
|
|
173
177
|
options, locust_options = parser.parse_known_args()
|
174
178
|
options: Namespace
|
@@ -218,6 +222,10 @@ def main() -> None:
|
|
218
222
|
aws_secret_access_key = credentials.get("secret_key")
|
219
223
|
aws_session_token = credentials.get("token", "")
|
220
224
|
|
225
|
+
if options.delete:
|
226
|
+
delete(s3_bucket, credential_manager)
|
227
|
+
return
|
228
|
+
|
221
229
|
logger.info(f"Uploading {options.locustfile}")
|
222
230
|
s3 = credential_manager.session.client("s3")
|
223
231
|
try:
|
@@ -257,7 +265,18 @@ def main() -> None:
|
|
257
265
|
locust_env_variables = [
|
258
266
|
{"name": env_variable, "value": str(os.environ[env_variable])}
|
259
267
|
for env_variable in os.environ
|
260
|
-
if env_variable.startswith("LOCUST_")
|
268
|
+
if env_variable.startswith("LOCUST_")
|
269
|
+
and not env_variable.startswith("LOCUST_CLOUD")
|
270
|
+
and not env_variable
|
271
|
+
in [
|
272
|
+
"LOCUST_LOCUSTFILE",
|
273
|
+
"LOCUST_USERS",
|
274
|
+
"LOCUST_WEB_HOST_DISPLAY_NAME",
|
275
|
+
"LOCUST_API_BASE_URL",
|
276
|
+
"LOCUST_SKIP_MONKEY_PATCH",
|
277
|
+
"LOCUST_REQUIREMENTS_URL",
|
278
|
+
]
|
279
|
+
and os.environ[env_variable]
|
261
280
|
]
|
262
281
|
deploy_endpoint = f"{options.lambda_url}/{options.kube_cluster_name}"
|
263
282
|
payload = {
|
@@ -289,9 +308,12 @@ def main() -> None:
|
|
289
308
|
if response.status_code == 200:
|
290
309
|
deployed_pods = response.json().get("pods", [])
|
291
310
|
else:
|
292
|
-
|
293
|
-
f"
|
294
|
-
|
311
|
+
try:
|
312
|
+
logger.error(f"Error when deploying: {response.json()['Message']}")
|
313
|
+
except Exception:
|
314
|
+
logger.error(
|
315
|
+
f"HTTP {response.status_code}/{response.reason} - Response: {response.text} - URL: {response.request.url}"
|
316
|
+
)
|
295
317
|
sys.exit(1)
|
296
318
|
except CredentialError as ce:
|
297
319
|
logger.error(f"Credential error: {ce}")
|
@@ -362,43 +384,47 @@ def main() -> None:
|
|
362
384
|
logger.exception(e)
|
363
385
|
sys.exit(1)
|
364
386
|
finally:
|
365
|
-
|
366
|
-
logger.info("Tearing down Locust cloud...")
|
367
|
-
credential_manager.refresh_credentials()
|
368
|
-
refreshed_credentials = credential_manager.get_current_credentials()
|
369
|
-
|
370
|
-
headers = {
|
371
|
-
"AWS_ACCESS_KEY_ID": refreshed_credentials.get("access_key", ""),
|
372
|
-
"AWS_SECRET_ACCESS_KEY": refreshed_credentials.get("secret_key", ""),
|
373
|
-
"Authorization": f"Bearer {refreshed_credentials.get('cognito_client_id_token', '')}",
|
374
|
-
}
|
375
|
-
|
376
|
-
token = refreshed_credentials.get("token")
|
377
|
-
if token:
|
378
|
-
headers["AWS_SESSION_TOKEN"] = token
|
379
|
-
|
380
|
-
response = requests.delete(
|
381
|
-
f"{options.lambda_url}/{options.kube_cluster_name}",
|
382
|
-
headers=headers,
|
383
|
-
params={"namespace": options.kube_namespace} if options.kube_namespace else {},
|
384
|
-
)
|
387
|
+
delete(s3_bucket, credential_manager)
|
385
388
|
|
386
|
-
if response.status_code != 200:
|
387
|
-
logger.error(
|
388
|
-
f"Could not automatically tear down Locust Cloud: HTTP {response.status_code}/{response.reason} - Response: {response.text} - URL: {response.request.url}"
|
389
|
-
)
|
390
|
-
except Exception as e:
|
391
|
-
logger.error(f"Could not automatically tear down Locust Cloud: {e}")
|
392
389
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
390
|
+
def delete(s3_bucket, credential_manager):
|
391
|
+
try:
|
392
|
+
logger.info("Tearing down Locust cloud...")
|
393
|
+
credential_manager.refresh_credentials()
|
394
|
+
refreshed_credentials = credential_manager.get_current_credentials()
|
395
|
+
|
396
|
+
headers = {
|
397
|
+
"AWS_ACCESS_KEY_ID": refreshed_credentials.get("access_key", ""),
|
398
|
+
"AWS_SECRET_ACCESS_KEY": refreshed_credentials.get("secret_key", ""),
|
399
|
+
"Authorization": f"Bearer {refreshed_credentials.get('cognito_client_id_token', '')}",
|
400
|
+
}
|
401
|
+
|
402
|
+
token = refreshed_credentials.get("token")
|
403
|
+
if token:
|
404
|
+
headers["AWS_SESSION_TOKEN"] = token
|
405
|
+
|
406
|
+
response = requests.delete(
|
407
|
+
f"{options.lambda_url}/{options.kube_cluster_name}",
|
408
|
+
headers=headers,
|
409
|
+
params={"namespace": options.kube_namespace} if options.kube_namespace else {},
|
410
|
+
)
|
411
|
+
|
412
|
+
if response.status_code != 200:
|
413
|
+
logger.error(
|
414
|
+
f"Could not automatically tear down Locust Cloud: HTTP {response.status_code}/{response.reason} - Response: {response.text} - URL: {response.request.url}"
|
415
|
+
)
|
416
|
+
except Exception as e:
|
417
|
+
logger.error(f"Could not automatically tear down Locust Cloud: {e}")
|
418
|
+
|
419
|
+
try:
|
420
|
+
logger.debug("Cleaning up locustfiles")
|
421
|
+
s3 = credential_manager.session.resource("s3")
|
422
|
+
bucket = s3.Bucket(s3_bucket)
|
423
|
+
bucket.objects.all().delete()
|
424
|
+
logger.info("Done! ✨")
|
425
|
+
except ClientError as e:
|
426
|
+
logger.error(f"Failed to clean up locust files: {e}")
|
427
|
+
sys.exit(1)
|
402
428
|
|
403
429
|
|
404
430
|
if __name__ == "__main__":
|