gen3-dataops-toolkit 2.0.0__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.
Files changed (53) hide show
  1. g3dt/__init__.py +0 -0
  2. g3dt/cli/__init__.py +5 -0
  3. g3dt/cli/_internal/__init__.py +1 -0
  4. g3dt/cli/_internal/dispatch.py +428 -0
  5. g3dt/cli/_internal/registry.py +65 -0
  6. g3dt/cli/_internal/resolve.py +22 -0
  7. g3dt/cli/_internal/runner.py +76 -0
  8. g3dt/cli/_internal/safety.py +110 -0
  9. g3dt/cli/config_cmds.py +202 -0
  10. g3dt/cli/delete_cmds.py +101 -0
  11. g3dt/cli/dict_cmds.py +102 -0
  12. g3dt/cli/ec2_cmds.py +114 -0
  13. g3dt/cli/indexd_cmds.py +57 -0
  14. g3dt/cli/jobs.py +83 -0
  15. g3dt/cli/k8s.py +54 -0
  16. g3dt/cli/main.py +110 -0
  17. g3dt/cli/metadata.py +76 -0
  18. g3dt/cli/synth.py +206 -0
  19. g3dt/config.py +393 -0
  20. g3dt/indexd/__init__.py +0 -0
  21. g3dt/indexd/indexd_registrar.py +244 -0
  22. g3dt/ingest/ingest.py +629 -0
  23. g3dt/resolver.py +163 -0
  24. g3dt/services/delete/delete_all_metadata_for_project.py +170 -0
  25. g3dt/services/delete/delete_metadata.sh +153 -0
  26. g3dt/services/delete/delete_metadata_by_guid.py +338 -0
  27. g3dt/services/dictionary/deploy_dd.sh +65 -0
  28. g3dt/services/dictionary/pull_dict.sh +59 -0
  29. g3dt/services/dictionary/upload_dictionary.py +109 -0
  30. g3dt/services/indexd/register_indexd.py +240 -0
  31. g3dt/services/k8s_ops/argocd_restart_etl.sh +140 -0
  32. g3dt/services/k8s_ops/argocd_restart_ms.sh +102 -0
  33. g3dt/services/k8s_ops/argocd_restart_schema.sh +106 -0
  34. g3dt/services/k8s_ops/login_to_pod.sh +110 -0
  35. g3dt/services/k8s_ops/restart_etl_and_ms.sh +56 -0
  36. g3dt/services/synthetic_data/delete_synth_metadata_sheepdog.py +183 -0
  37. g3dt/services/synthetic_data/full_deploy_dd_and_synth.sh +124 -0
  38. g3dt/services/synthetic_data/generate_synth_metadata.sh +133 -0
  39. g3dt/services/synthetic_data/upload_synth_metadata_sheepdog.py +165 -0
  40. g3dt/services/upload/metadata/upload_all_studies.sh +108 -0
  41. g3dt/services/upload/metadata/upload_metadata.py +152 -0
  42. g3dt/upload/__init__.py +1 -0
  43. g3dt/upload/metadata_deleter.py +265 -0
  44. g3dt/upload/metadata_submitter.py +1093 -0
  45. g3dt/upload/upload_synthdata_s3.py +164 -0
  46. g3dt/utils/athena_utils.py +834 -0
  47. g3dt/utils/dbt_utils.py +66 -0
  48. g3dt/utils/release_writer.py +188 -0
  49. g3dt/validate/validate.py +609 -0
  50. gen3_dataops_toolkit-2.0.0.dist-info/METADATA +125 -0
  51. gen3_dataops_toolkit-2.0.0.dist-info/RECORD +53 -0
  52. gen3_dataops_toolkit-2.0.0.dist-info/WHEEL +4 -0
  53. gen3_dataops_toolkit-2.0.0.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,164 @@
1
+ import boto3
2
+ from urllib import parse
3
+ import os
4
+ import logging
5
+
6
+ logger = logging.getLogger(__name__)
7
+ logger.setLevel(logging.INFO)
8
+ if not logger.hasHandlers():
9
+ handler = logging.StreamHandler()
10
+ formatter = logging.Formatter('%(asctime)s %(levelname)s %(name)s: %(message)s')
11
+ handler.setFormatter(formatter)
12
+ logger.addHandler(handler)
13
+
14
+
15
+ def upload_file_with_tags(
16
+ local_file_path: str,
17
+ bucket_name: str,
18
+ s3_object_key: str,
19
+ tags: dict,
20
+ s3_client=None,
21
+ ):
22
+ """
23
+ Upload a file to S3 with tags.
24
+
25
+ Args:
26
+ local_file_path (str): Path to the local file.
27
+ bucket_name (str): Name of the S3 bucket.
28
+ s3_object_key (str): S3 object key (destination path in bucket).
29
+ tags (dict): Dictionary of tags to apply.
30
+ s3_client: Optional boto3 S3 client. If None, a new client is created.
31
+ """
32
+ if s3_client is None:
33
+ s3_client = boto3.client("s3")
34
+ tag_string = parse.urlencode(tags)
35
+ try:
36
+ s3_client.upload_file(
37
+ Filename=local_file_path,
38
+ Bucket=bucket_name,
39
+ Key=s3_object_key,
40
+ ExtraArgs={"Tagging": tag_string},
41
+ )
42
+ logger.info(f"Upload Successful: {local_file_path}")
43
+ except FileNotFoundError:
44
+ logger.error(f"The file was not found: {local_file_path}")
45
+ except Exception as e:
46
+ logger.exception(
47
+ f"An error occurred during upload of {local_file_path}: {e}"
48
+ )
49
+
50
+
51
+ def get_synth_files(synth_folder: str) -> list:
52
+ """
53
+ Recursively collects all files in the given synth_folder.
54
+
55
+ Args:
56
+ synth_folder (str): Path to the folder containing synth files.
57
+
58
+ Returns:
59
+ list: List of file paths (relative to synth_folder) for all files found.
60
+ """
61
+ synth_files = []
62
+ try:
63
+ for root, dirs, files in os.walk(synth_folder):
64
+ rel_root = root.replace(synth_folder, "")
65
+ for f in files:
66
+ synth_files.append(os.path.join(rel_root, f))
67
+ except Exception as e:
68
+ logger.exception(
69
+ f"An error occurred while collecting synth files: {e}"
70
+ )
71
+ return synth_files
72
+
73
+
74
+ def get_node_name(path):
75
+ """
76
+ Extracts the node name from a given file or folder path.
77
+
78
+ Args:
79
+ path (str): The file or folder path.
80
+
81
+ Returns:
82
+ str: The node name, which is the last component of the path without its extension.
83
+ """
84
+ try:
85
+ return path.split("/")[-1].split(".")[0]
86
+ except Exception as e:
87
+ logger.exception(
88
+ f"An error occurred while extracting node name from {path}: {e}"
89
+ )
90
+ return ""
91
+
92
+ def get_study_id(path):
93
+ """
94
+ Extracts the study ID from a given file or folder path.
95
+
96
+ Args:
97
+ path (str): The file or folder path.
98
+
99
+ Returns:
100
+ str: The study ID, which is the second component of the path.
101
+ """
102
+ try:
103
+ return path.split("/")[0]
104
+ except Exception as e:
105
+ logger.exception(
106
+ f"An error occurred while extracting study ID from {path}: {e}"
107
+ )
108
+ return ""
109
+
110
+ def upload_synth_folder_to_s3(
111
+ local_folder_path: str,
112
+ bucket_name: str,
113
+ study_id: str,
114
+ submission_date: str,
115
+ ingest_tag: str = 'true',
116
+ data_release_version: str = None
117
+ ):
118
+ """
119
+ Uploads all JSON files from a local synth folder to an S3 bucket, tagging each file.
120
+
121
+ Args:
122
+ local_folder_path (str): Path to the local synth folder.
123
+ bucket_name (str): Name of the S3 bucket.
124
+ study_id (str): Study identifier to tag and organize files.
125
+ submission_date (str): Submission date to tag and organize files.
126
+ ingest_tag (str, optional): Value for the 'ingest' tag. Defaults to 'true'.
127
+ data_release_version (str, optional): Data release version to tag and organize files.
128
+ """
129
+ try:
130
+ synth_files = get_synth_files(local_folder_path)
131
+ submission_date = submission_date.replace("_", "-")
132
+ for f in synth_files:
133
+ if not f.endswith(".json"):
134
+ logger.warning(f"Skipping non-JSON file: {f}")
135
+ continue
136
+
137
+ node_name = get_node_name(f)
138
+ study_id = get_study_id(f)
139
+
140
+ tags = {
141
+ "ingest": ingest_tag,
142
+ "submission_date": submission_date,
143
+ "study_id": study_id,
144
+ "node": node_name,
145
+ "data_release_version": data_release_version
146
+ }
147
+
148
+ try:
149
+ upload_file_with_tags(
150
+ local_file_path=os.path.join(local_folder_path, f),
151
+ bucket_name=bucket_name,
152
+ s3_object_key=f"{submission_date}_synthetic_metadata/{f}",
153
+ tags=tags,
154
+ )
155
+ logger.info(
156
+ f"SUCCESS: Uploaded {os.path.join(local_folder_path, f)} "
157
+ f"with tags: {tags} to {bucket_name}/{f}"
158
+ )
159
+ except Exception as e:
160
+ logger.exception(f"Failed to upload {f}: {e}")
161
+ except Exception as e:
162
+ logger.exception(
163
+ f"An error occurred in upload_synth_folder_to_s3: {e}"
164
+ )