-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathmigrate_v1_perms_by_app.py
More file actions
executable file
·114 lines (84 loc) · 3.75 KB
/
migrate_v1_perms_by_app.py
File metadata and controls
executable file
·114 lines (84 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env python3
"""
Reads JSON files from a given source folder in the environment's S3 authorization
bucket, transforms each from a flat array into {"types": [...]} format, and
writes the results to both the consumer and producer folders in the same bucket
under a sub-folder matching the source folder name.
Usage:
python scripts/migrate_v1_perms_by_app.py <env> <folder>
Arguments:
env - NRLF environment name (e.g. dev, qa, int, prod)
folder - Source folder name within the authorization bucket
(e.g. an app identifier)
Example:
python scripts/migrate_v1_perms_by_app.py dev my-app-folder
The script reads from:
s3://nhsd-nrlf--<env>-authorization-store/<folder>/*.json
And writes to:
s3://nhsd-nrlf--<env>-authorization-store/consumer/<folder>/<filename>.json
s3://nhsd-nrlf--<env>-authorization-store/producer/<folder>/<filename>.json
The bucket name defaults to nhsd-nrlf--<env>-authorization-store and can be
overridden via the NRL_AUTH_BUCKET_NAME environment variable.
"""
import json
import os
import sys
from aws_session_assume import get_boto_session
from botocore.exceptions import ClientError
CONSUMER_OR_PRODUCER = ("consumer", "producer")
def _get_bucket_name(env: str) -> str:
return os.getenv("NRL_AUTH_BUCKET_NAME", f"nhsd-nrlf--{env}-authorization-store")
def _get_s3_client(env: str):
return get_boto_session(env).client("s3")
def _list_json_files(s3, bucket: str, folder: str) -> list[str]:
paginator = s3.get_paginator("list_objects_v2")
return sorted(
item["Key"]
for page in paginator.paginate(Bucket=bucket, Prefix=f"{folder}/")
for item in page.get("Contents", [])
if item["Key"].endswith(".json")
)
def _read_and_transform(s3, bucket: str, file_path: str) -> tuple[str, int]:
try:
response = s3.get_object(Bucket=bucket, Key=file_path)
except ClientError as e:
raise RuntimeError(
f"Failed to read s3://{bucket}/{file_path}: {e.response['Error']['Message']}"
) from e
data = json.loads(response["Body"].read())
if not isinstance(data, list):
raise ValueError(
f"{file_path}: Expected a JSON array, got {type(data).__name__}"
)
return json.dumps({"types": data}, indent=2), len(data)
def _write_v2_consumer_and_producer_files(
s3, bucket: str, file_path: str, body: str, entry_count: int
) -> None:
for actor_type in CONSUMER_OR_PRODUCER:
dest_filepath = f"{actor_type}/{file_path}"
try:
s3.put_object(Bucket=bucket, Key=dest_filepath, Body=body)
except ClientError as e:
raise RuntimeError(
f"Failed to write s3://{bucket}/{dest_filepath}: {e.response['Error']['Message']}"
) from e
print(f" Written {entry_count} entries → s3://{bucket}/{dest_filepath}")
def migrate_v1_perms_by_app(env: str, app_id_folder: str) -> None:
bucket = _get_bucket_name(env)
s3 = _get_s3_client(env)
print(f"Source bucket : {bucket}")
print(f"Source folder : {app_id_folder}/")
json_file_paths = _list_json_files(s3, bucket, app_id_folder)
if not json_file_paths:
print(f"No JSON files found under s3://{bucket}/{app_id_folder}/")
return
print(f"Found {len(json_file_paths)} JSON files in s3://{bucket}/{app_id_folder}/:")
for file_path in json_file_paths:
body, entry_count = _read_and_transform(s3, bucket, file_path)
print(f" Transforming {file_path} → {entry_count} entries")
_write_v2_consumer_and_producer_files(s3, bucket, file_path, body, entry_count)
if __name__ == "__main__":
if len(sys.argv) != 3:
print(f"Usage: {sys.argv[0]} <env> <folder>")
sys.exit(1)
migrate_v1_perms_by_app(sys.argv[1], sys.argv[2])