stackport 0.2.2__tar.gz → 0.2.4__tar.gz
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.
- {stackport-0.2.2/stackport.egg-info → stackport-0.2.4}/PKG-INFO +5 -5
- {stackport-0.2.2 → stackport-0.2.4}/README.md +4 -4
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/resources.py +30 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/stats.py +4 -1
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/tags.py +52 -0
- {stackport-0.2.2 → stackport-0.2.4}/pyproject.toml +1 -1
- {stackport-0.2.2 → stackport-0.2.4/stackport.egg-info}/PKG-INFO +5 -5
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_tags_routes.py +5 -2
- {stackport-0.2.2 → stackport-0.2.4}/LICENSE +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/MANIFEST.in +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/__init__.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/aws_client.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/cache.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/cli.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/config.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/main.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/__init__.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/common.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/dynamodb.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/ec2.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/endpoints.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/iam.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/lambda_svc.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/logs.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/s3.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/secretsmanager.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/routes/sqs.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/schemas/__init__.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/schemas/dynamodb.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/schemas/s3.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/schemas/sqs.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/schemas/tags.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/backend/websocket.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/setup.cfg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/stackport.egg-info/SOURCES.txt +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/stackport.egg-info/dependency_links.txt +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/stackport.egg-info/entry_points.txt +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/stackport.egg-info/requires.txt +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/stackport.egg-info/top_level.txt +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_cache.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_cli.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_client.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_config.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_dynamodb_routes.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_ec2_routes.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_endpoints.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_iam_routes.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_lambda_routes.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_logs_routes.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_multi_endpoint.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_readonly_middleware.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_registries.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_routes.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_s3_routes.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_s3_upload_limit_env.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_secretsmanager_routes.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_sqs_routes.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/tests/test_websocket.py +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/assets/index-B2xjVeE-.js +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/assets/index-D_vb_J84.css +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/acm.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/apigateway.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/appsync.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/athena.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/cloudformation.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/cloudfront.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/cognito-idp.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/dynamodb.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/ec2.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/ecr.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/ecs.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/elasticache.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/elasticfilesystem.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/elasticloadbalancing.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/elasticmapreduce.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/events.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/firehose.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/glue.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/iam.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/kinesis.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/kms.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/lambda.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/logs.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/monitoring.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/rds.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/route53.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/s3.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/secretsmanager.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/ses.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/sns.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/sqs.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/ssm.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/stepfunctions.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/aws-icons/wafv2.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/favicon.png +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/favicon.svg +0 -0
- {stackport-0.2.2 → stackport-0.2.4}/ui/dist/index.html +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stackport
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Universal AWS resource browser for local emulators
|
|
5
5
|
Author: Davi Reis Vieira
|
|
6
6
|
License: MIT
|
|
@@ -54,13 +54,13 @@ Dynamic: license-file
|
|
|
54
54
|
## Screenshots
|
|
55
55
|
|
|
56
56
|
**Dashboard** — Service overview with resource counts and health status
|
|
57
|
-

|
|
57
|
+

|
|
58
58
|
|
|
59
|
-
**
|
|
60
|
-

|
|
61
61
|
|
|
62
62
|
**S3 Browser** — File browser with upload, download, folder navigation, and tagging
|
|
63
|
-

|
|
63
|
+

|
|
64
64
|
|
|
65
65
|
## Features
|
|
66
66
|
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
## Screenshots
|
|
20
20
|
|
|
21
21
|
**Dashboard** — Service overview with resource counts and health status
|
|
22
|
-

|
|
22
|
+

|
|
23
23
|
|
|
24
|
-
**
|
|
25
|
-

|
|
26
26
|
|
|
27
27
|
**S3 Browser** — File browser with upload, download, folder navigation, and tagging
|
|
28
|
-

|
|
28
|
+

|
|
29
29
|
|
|
30
30
|
## Features
|
|
31
31
|
|
|
@@ -66,6 +66,7 @@ DESCRIBE_REGISTRY: dict[tuple[str, str], tuple[str, str, str, str | None]] = {
|
|
|
66
66
|
("glue", "crawlers"): ("glue", "get_crawler", "Name", "Crawler"),
|
|
67
67
|
("athena", "workgroups"): ("athena", "get_work_group", "WorkGroup", "WorkGroup"),
|
|
68
68
|
# API
|
|
69
|
+
("apigateway", "rest_apis"): ("apigateway", "get_rest_api", "restApiId", None),
|
|
69
70
|
("apigateway", "apis"): ("apigatewayv2", "get_api", "ApiId", None),
|
|
70
71
|
("appsync", "graphql_apis"): ("appsync", "get_graphql_api", "apiId", "graphqlApi"),
|
|
71
72
|
# EMR
|
|
@@ -79,6 +80,10 @@ _PREFERRED_ID_FIELD: dict[tuple[str, str], str] = {
|
|
|
79
80
|
("events", "rules"): "Name",
|
|
80
81
|
("events", "event_buses"): "Name",
|
|
81
82
|
("wafv2", "web_acls"): "Name",
|
|
83
|
+
("appsync", "graphql_apis"): "apiId",
|
|
84
|
+
("elasticmapreduce", "clusters"): "Id",
|
|
85
|
+
("cognito-idp", "user_pools"): "Id",
|
|
86
|
+
("apigateway", "rest_apis"): "id",
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
# Known ID field names for extracting a resource identifier from list results
|
|
@@ -126,6 +131,8 @@ _ID_FIELDS = [
|
|
|
126
131
|
"CrawlerName",
|
|
127
132
|
"DatabaseName",
|
|
128
133
|
"DistributionId",
|
|
134
|
+
"apiId",
|
|
135
|
+
"ClusterId",
|
|
129
136
|
]
|
|
130
137
|
|
|
131
138
|
|
|
@@ -201,6 +208,29 @@ def get_resource_detail(service: str, res_type: str, res_id: str, endpoint_url:
|
|
|
201
208
|
if cached is not None:
|
|
202
209
|
return cached
|
|
203
210
|
|
|
211
|
+
# SES identities are plain strings — aggregate detail from multiple APIs
|
|
212
|
+
if (service, res_type) == ("ses", "identities"):
|
|
213
|
+
try:
|
|
214
|
+
client = get_client("ses", endpoint_url)
|
|
215
|
+
verif = client.get_identity_verification_attributes(Identities=[res_id])
|
|
216
|
+
attrs = verif.get("VerificationAttributes", {}).get(res_id, {})
|
|
217
|
+
dkim = client.get_identity_dkim_attributes(Identities=[res_id])
|
|
218
|
+
dkim_attrs = dkim.get("DkimAttributes", {}).get(res_id, {})
|
|
219
|
+
detail = _serialize({
|
|
220
|
+
"Identity": res_id,
|
|
221
|
+
"VerificationStatus": attrs.get("VerificationStatus", "Unknown"),
|
|
222
|
+
"VerificationToken": attrs.get("VerificationToken"),
|
|
223
|
+
"DkimEnabled": dkim_attrs.get("DkimEnabled", False),
|
|
224
|
+
"DkimVerificationStatus": dkim_attrs.get("DkimVerificationStatus", "Unknown"),
|
|
225
|
+
"DkimTokens": dkim_attrs.get("DkimTokens", []),
|
|
226
|
+
})
|
|
227
|
+
result = {"service": service, "type": res_type, "id": res_id, "detail": detail}
|
|
228
|
+
cache.set(cache_key, result, ttl=5)
|
|
229
|
+
return result
|
|
230
|
+
except Exception as exc:
|
|
231
|
+
logger.warning("Failed to get detail for %s/%s/%s", service, res_type, res_id, exc_info=True)
|
|
232
|
+
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
|
233
|
+
|
|
204
234
|
# WAFv2 get_web_acl requires Name, Scope, AND Id — resolve Id from list first
|
|
205
235
|
if (service, res_type) == ("wafv2", "web_acls"):
|
|
206
236
|
try:
|
|
@@ -75,7 +75,10 @@ SERVICE_REGISTRY: dict[str, list[tuple[str, str, str, str]]] = {
|
|
|
75
75
|
("crawlers", "glue", "get_crawlers", "Crawlers"),
|
|
76
76
|
],
|
|
77
77
|
"athena": [("workgroups", "athena", "list_work_groups", "WorkGroups")],
|
|
78
|
-
"apigateway": [
|
|
78
|
+
"apigateway": [
|
|
79
|
+
("rest_apis", "apigateway", "get_rest_apis", "items"),
|
|
80
|
+
("apis", "apigatewayv2", "get_apis", "Items"),
|
|
81
|
+
],
|
|
79
82
|
"firehose": [("delivery_streams", "firehose", "list_delivery_streams", "DeliveryStreamNames")],
|
|
80
83
|
"cognito-idp": [("user_pools", "cognito-idp", "list_user_pools", "UserPools")],
|
|
81
84
|
"cognito-identity": [("identity_pools", "cognito-identity", "list_identity_pools", "IdentityPools")],
|
|
@@ -356,6 +356,52 @@ def _set_tags_elasticache_cluster(client: Any, resource_id: str, tags: dict[str,
|
|
|
356
356
|
client.add_tags_to_resource(ResourceName=arn, Tags=tag_list)
|
|
357
357
|
|
|
358
358
|
|
|
359
|
+
def _get_tags_cognito_idp_user_pool(client: Any, resource_id: str) -> dict[str, str]:
|
|
360
|
+
pool = client.describe_user_pool(UserPoolId=resource_id)
|
|
361
|
+
arn = pool["UserPool"]["Arn"]
|
|
362
|
+
resp = client.list_tags_for_resource(ResourceArn=arn)
|
|
363
|
+
return resp.get("Tags", {})
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def _get_tags_emr_cluster(client: Any, resource_id: str) -> dict[str, str]:
|
|
367
|
+
resp = client.describe_cluster(ClusterId=resource_id)
|
|
368
|
+
return {t["Key"]: t["Value"] for t in resp["Cluster"].get("Tags", [])}
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def _get_tags_apigateway_rest_api(client: Any, resource_id: str) -> dict[str, str]:
|
|
372
|
+
arn = f"arn:aws:apigateway:{client.meta.region_name}::/restapis/{resource_id}"
|
|
373
|
+
resp = client.get_tags(resourceArn=arn)
|
|
374
|
+
return resp.get("tags", {})
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def _set_tags_cognito_idp_user_pool(client: Any, resource_id: str, tags: dict[str, str]) -> None:
|
|
378
|
+
pool = client.describe_user_pool(UserPoolId=resource_id)
|
|
379
|
+
arn = pool["UserPool"]["Arn"]
|
|
380
|
+
existing = client.list_tags_for_resource(ResourceArn=arn).get("Tags", {})
|
|
381
|
+
if existing:
|
|
382
|
+
client.untag_resource(ResourceArn=arn, TagKeys=list(existing.keys()))
|
|
383
|
+
if tags:
|
|
384
|
+
client.tag_resource(ResourceArn=arn, Tags=tags)
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def _set_tags_emr_cluster(client: Any, resource_id: str, tags: dict[str, str]) -> None:
|
|
388
|
+
existing = _get_tags_emr_cluster(client, resource_id)
|
|
389
|
+
if existing:
|
|
390
|
+
client.remove_tags(ResourceId=resource_id, TagKeys=list(existing.keys()))
|
|
391
|
+
if tags:
|
|
392
|
+
tag_list = [{"Key": k, "Value": v} for k, v in tags.items()]
|
|
393
|
+
client.add_tags(ResourceId=resource_id, Tags=tag_list)
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def _set_tags_apigateway_rest_api(client: Any, resource_id: str, tags: dict[str, str]) -> None:
|
|
397
|
+
arn = f"arn:aws:apigateway:{client.meta.region_name}::/restapis/{resource_id}"
|
|
398
|
+
existing = client.get_tags(resourceArn=arn).get("tags", {})
|
|
399
|
+
if existing:
|
|
400
|
+
client.untag_resource(resourceArn=arn, tagKeys=list(existing.keys()))
|
|
401
|
+
if tags:
|
|
402
|
+
client.tag_resource(resourceArn=arn, tags=tags)
|
|
403
|
+
|
|
404
|
+
|
|
359
405
|
# --- Registries ---
|
|
360
406
|
|
|
361
407
|
TAG_GETTER_REGISTRY: dict[tuple[str, str], tuple[str, Any]] = {
|
|
@@ -380,6 +426,9 @@ TAG_GETTER_REGISTRY: dict[tuple[str, str], tuple[str, Any]] = {
|
|
|
380
426
|
("ssm", "parameters"): ("ssm", _get_tags_ssm_parameter),
|
|
381
427
|
("elasticloadbalancing", "load_balancers"): ("elbv2", _get_tags_elbv2_load_balancer),
|
|
382
428
|
("elasticache", "cache_clusters"): ("elasticache", _get_tags_elasticache_cluster),
|
|
429
|
+
("cognito-idp", "user_pools"): ("cognito-idp", _get_tags_cognito_idp_user_pool),
|
|
430
|
+
("elasticmapreduce", "clusters"): ("emr", _get_tags_emr_cluster),
|
|
431
|
+
("apigateway", "rest_apis"): ("apigateway", _get_tags_apigateway_rest_api),
|
|
383
432
|
}
|
|
384
433
|
|
|
385
434
|
TAG_SETTER_REGISTRY: dict[tuple[str, str], tuple[str, Any]] = {
|
|
@@ -403,6 +452,9 @@ TAG_SETTER_REGISTRY: dict[tuple[str, str], tuple[str, Any]] = {
|
|
|
403
452
|
("ssm", "parameters"): ("ssm", _set_tags_ssm_parameter),
|
|
404
453
|
("elasticloadbalancing", "load_balancers"): ("elbv2", _set_tags_elbv2_load_balancer),
|
|
405
454
|
("elasticache", "cache_clusters"): ("elasticache", _set_tags_elasticache_cluster),
|
|
455
|
+
("cognito-idp", "user_pools"): ("cognito-idp", _set_tags_cognito_idp_user_pool),
|
|
456
|
+
("elasticmapreduce", "clusters"): ("emr", _set_tags_emr_cluster),
|
|
457
|
+
("apigateway", "rest_apis"): ("apigateway", _set_tags_apigateway_rest_api),
|
|
406
458
|
}
|
|
407
459
|
|
|
408
460
|
# Delete registry: (service, type) -> (boto3_service, callable(client, resource_id))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stackport
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Universal AWS resource browser for local emulators
|
|
5
5
|
Author: Davi Reis Vieira
|
|
6
6
|
License: MIT
|
|
@@ -54,13 +54,13 @@ Dynamic: license-file
|
|
|
54
54
|
## Screenshots
|
|
55
55
|
|
|
56
56
|
**Dashboard** — Service overview with resource counts and health status
|
|
57
|
-

|
|
57
|
+

|
|
58
58
|
|
|
59
|
-
**
|
|
60
|
-

|
|
61
61
|
|
|
62
62
|
**S3 Browser** — File browser with upload, download, folder navigation, and tagging
|
|
63
|
-

|
|
63
|
+

|
|
64
64
|
|
|
65
65
|
## Features
|
|
66
66
|
|
|
@@ -336,7 +336,7 @@ class TestTagsSupported:
|
|
|
336
336
|
assert resp.status_code == 200
|
|
337
337
|
data = resp.json()
|
|
338
338
|
supported = data["supported"]
|
|
339
|
-
assert len(supported) ==
|
|
339
|
+
assert len(supported) == 24
|
|
340
340
|
|
|
341
341
|
keys = {(s["service"], s["type"]) for s in supported}
|
|
342
342
|
assert ("s3", "buckets") in keys
|
|
@@ -360,6 +360,9 @@ class TestTagsSupported:
|
|
|
360
360
|
assert ("ssm", "parameters") in keys
|
|
361
361
|
assert ("elasticloadbalancing", "load_balancers") in keys
|
|
362
362
|
assert ("elasticache", "cache_clusters") in keys
|
|
363
|
+
assert ("cognito-idp", "user_pools") in keys
|
|
364
|
+
assert ("elasticmapreduce", "clusters") in keys
|
|
365
|
+
assert ("apigateway", "rest_apis") in keys
|
|
363
366
|
|
|
364
367
|
def test_writable_flag(self):
|
|
365
368
|
resp = client.get("/api/tags/supported")
|
|
@@ -367,7 +370,7 @@ class TestTagsSupported:
|
|
|
367
370
|
writable_lookup = {(e["service"], e["type"]): e["writable"] for e in supported}
|
|
368
371
|
assert writable_lookup[("cloudformation", "stacks")] is False
|
|
369
372
|
writable_count = sum(1 for e in supported if e["writable"])
|
|
370
|
-
assert writable_count ==
|
|
373
|
+
assert writable_count == 23
|
|
371
374
|
|
|
372
375
|
|
|
373
376
|
# --- PUT tags ---
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|