From 1836d7a4ca65fac87c375d7228dc33ca1f9a104d Mon Sep 17 00:00:00 2001 From: Matt Dean Date: Fri, 7 Mar 2025 10:24:01 +0000 Subject: [PATCH 1/3] [NRL-1311] Add script to set pointer supersede info. Add script to put points from JSON files --- scripts/put_pointers_from_files.py | 43 +++++++++++++ scripts/set_pointer_supersede.py | 96 ++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 scripts/put_pointers_from_files.py create mode 100644 scripts/set_pointer_supersede.py diff --git a/scripts/put_pointers_from_files.py b/scripts/put_pointers_from_files.py new file mode 100644 index 000000000..b3ac39958 --- /dev/null +++ b/scripts/put_pointers_from_files.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# Put pointers from the provided files into the pointers table +# This will overwrite the pointer if it already exists in the table +import json + +import fire +from aws_session_assume import get_boto_session + +from nrlf.core.dynamodb.model import DocumentPointer +from nrlf.core.logger import logger +from nrlf.producer.fhir.r4.model import DocumentReference + +logger.setLevel("ERROR") + + +def _put_pointers_from_files( + *filenames, env: str = "dev", table_name: str | None = None +): + docrefs: list[DocumentReference] = [] + print("Reading docrefs from files...") + for filename in filenames: + with open(filename) as f: + docref_json = json.load(f) + docref = DocumentReference.model_validate(docref_json) + docrefs.append(docref) + + session = get_boto_session(env) + dynamodb = session.resource("dynamodb") + if not table_name: + table_name = f"nhsd-nrlf--{env}-pointers-table" + table = dynamodb.Table(table_name) + + for docref in docrefs: + try: + print(f"Putting {docref.id}....") + pointer = DocumentPointer.from_document_reference(docref) + table.put_item(Item=pointer.model_dump()) + except Exception as e: + print(f"Unable to put pointer for {docref.id}. Error: {e}") + + +if __name__ == "__main__": + fire.Fire(_put_pointers_from_files) diff --git a/scripts/set_pointer_supersede.py b/scripts/set_pointer_supersede.py new file mode 100644 index 000000000..fab20feba --- /dev/null +++ b/scripts/set_pointer_supersede.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# Set supersede info on a pointer +import json + +import aws_session_assume +import fire + +from nrlf.core.dynamodb.model import DocumentPointer +from nrlf.core.logger import logger +from nrlf.producer.fhir.r4.model import ( + DocumentReference, + DocumentReferenceRelatesTo, + Identifier, + Reference, +) + +logger.setLevel("ERROR") + + +def _set_pointer_supersede_info( + pointer_id: str, + supersede_pointer_id: str, + delete_superceded: bool = False, + env: str = "dev", + table_name: str | None = None, +): + session = aws_session_assume.get_boto_session(env) + dynamodb = session.resource("dynamodb") + + if not table_name: + table_name = f"nhsd-nrlf--{env}-pointers-table" + table = dynamodb.Table(table_name) + + print( + f"Setting pointer {pointer_id} in {table_name} to supersede {supersede_pointer_id}...." + ) + + try: + doc_key = f"D#{pointer_id}" + print(f"Getting {pointer_id}...") + result = table.get_item( + Key={"pk": doc_key, "sk": doc_key}, + ) + except Exception as e: + print(f"Unable to get pointer. Error: {e}") + return + + if "Item" not in result: + print(f"Unable to set superseded info. Pointer {pointer_id} not found.") + return + + item = result["Item"] + + try: + pointer = DocumentPointer.model_validate({"_from_dynamo": True, **item}) + except Exception as e: + print(f"Could not validate pointer from table. Error: {e}") + return + + doc_ref = DocumentReference.model_validate_json(pointer.document) + + if not doc_ref.relatesTo: + doc_ref.relatesTo = [] + else: + for relatesTo in doc_ref.relatesTo: + if relatesTo.code == "replaces": + print( + f"Unable to add supersede info as pointer is already superseding a pointer: {relatesTo}" + ) + return + + doc_ref.relatesTo.append( + DocumentReferenceRelatesTo( + code="replaces", + target=Reference( + type="DocumentReference", + identifier=Identifier(value=supersede_pointer_id), + ), + ) + ) + + print(f"Adding superseded info to {pointer_id}...") + updated_pointer = DocumentPointer.from_document_reference(doc_ref) + table.put_item( + Item=updated_pointer.dict(exclude_none=True, exclude={"_from_dynamo"}) + ) + + if delete_superceded: + print(f"Deleting superseded {supersede_pointer_id}...") + table.delete_item( + Key={"pk": f"D#{supersede_pointer_id}", "sk": f"D#{supersede_pointer_id}"} + ) + + +if __name__ == "__main__": + fire.Fire(_set_pointer_supersede_info) From 18aab26b5f29d64344a0efc1fcf6ba5e5c180b83 Mon Sep 17 00:00:00 2001 From: Matt Dean Date: Tue, 11 Mar 2025 08:49:17 +0000 Subject: [PATCH 2/3] [NRL-1311] Add prod env warn to new scripts. Fix supersede typo --- scripts/put_pointers_from_files.py | 10 +++++++++ scripts/set_pointer_supersede.py | 35 ++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/scripts/put_pointers_from_files.py b/scripts/put_pointers_from_files.py index b3ac39958..d8fca9684 100644 --- a/scripts/put_pointers_from_files.py +++ b/scripts/put_pointers_from_files.py @@ -2,6 +2,7 @@ # Put pointers from the provided files into the pointers table # This will overwrite the pointer if it already exists in the table import json +import os import fire from aws_session_assume import get_boto_session @@ -12,10 +13,19 @@ logger.setLevel("ERROR") +SKIP_PROD_WARNING = os.getenv("SKIP_PROD_WARNING", "false") + def _put_pointers_from_files( *filenames, env: str = "dev", table_name: str | None = None ): + if env == "dev" and SKIP_PROD_WARNING != "true": + confirmation = input( + "\nWARNING - This command will modify the PROD environment. Continue? [y/n] " + ) + if confirmation != "y": + return "Exiting at user request" + docrefs: list[DocumentReference] = [] print("Reading docrefs from files...") for filename in filenames: diff --git a/scripts/set_pointer_supersede.py b/scripts/set_pointer_supersede.py index fab20feba..ab6ff56f5 100644 --- a/scripts/set_pointer_supersede.py +++ b/scripts/set_pointer_supersede.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # Set supersede info on a pointer import json +import os import aws_session_assume import fire @@ -16,14 +17,23 @@ logger.setLevel("ERROR") +SKIP_PROD_WARNING = os.getenv("SKIP_PROD_WARNING", "false") + def _set_pointer_supersede_info( pointer_id: str, supersede_pointer_id: str, - delete_superceded: bool = False, + delete_superseded: bool = False, env: str = "dev", table_name: str | None = None, ): + if env == "prod" and SKIP_PROD_WARNING != "true": + confirmation = input( + "\nWARNING - This command will modify the PROD environment. Continue? [y/n] " + ) + if confirmation != "y": + return "Exiting at user request" + session = aws_session_assume.get_boto_session(env) dynamodb = session.resource("dynamodb") @@ -53,21 +63,22 @@ def _set_pointer_supersede_info( try: pointer = DocumentPointer.model_validate({"_from_dynamo": True, **item}) + doc_ref = DocumentReference.model_validate_json(pointer.document) except Exception as e: print(f"Could not validate pointer from table. Error: {e}") return - doc_ref = DocumentReference.model_validate_json(pointer.document) - if not doc_ref.relatesTo: doc_ref.relatesTo = [] - else: - for relatesTo in doc_ref.relatesTo: - if relatesTo.code == "replaces": - print( - f"Unable to add supersede info as pointer is already superseding a pointer: {relatesTo}" - ) - return + + existing_supersedes = [ + relates_to for relates_to in doc_ref.relatesTo if relates_to.code == "replaces" + ] + if existing_supersedes: + print( + f"Unable to add supersede info as pointer is already superseding a pointer: {existing_supersedes}" + ) + return doc_ref.relatesTo.append( DocumentReferenceRelatesTo( @@ -79,13 +90,13 @@ def _set_pointer_supersede_info( ) ) - print(f"Adding superseded info to {pointer_id}...") + print(f"Adding supersede info to {pointer_id}...") updated_pointer = DocumentPointer.from_document_reference(doc_ref) table.put_item( Item=updated_pointer.dict(exclude_none=True, exclude={"_from_dynamo"}) ) - if delete_superceded: + if delete_superseded: print(f"Deleting superseded {supersede_pointer_id}...") table.delete_item( Key={"pk": f"D#{supersede_pointer_id}", "sk": f"D#{supersede_pointer_id}"} From ca426b5caf49549770f5f34cb5df9768e84ab708 Mon Sep 17 00:00:00 2001 From: Matt Dean Date: Tue, 11 Mar 2025 17:42:20 +0000 Subject: [PATCH 3/3] [NRL-1311] Fix typo dev->prod --- scripts/put_pointers_from_files.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/put_pointers_from_files.py b/scripts/put_pointers_from_files.py index d8fca9684..12a901b14 100644 --- a/scripts/put_pointers_from_files.py +++ b/scripts/put_pointers_from_files.py @@ -19,7 +19,7 @@ def _put_pointers_from_files( *filenames, env: str = "dev", table_name: str | None = None ): - if env == "dev" and SKIP_PROD_WARNING != "true": + if env == "prod" and SKIP_PROD_WARNING != "true": confirmation = input( "\nWARNING - This command will modify the PROD environment. Continue? [y/n] " )