From b7498afd43522ef21b30b822afd2abd27c7b9131 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Wed, 29 Nov 2023 19:38:04 -0800 Subject: [PATCH 01/10] Add a check_operation_status script Signed-off-by: steve lasker --- scitt/check_operation_status.py | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100755 scitt/check_operation_status.py diff --git a/scitt/check_operation_status.py b/scitt/check_operation_status.py new file mode 100755 index 0000000..eead126 --- /dev/null +++ b/scitt/check_operation_status.py @@ -0,0 +1,44 @@ +""" Module for checking when a statement has been anchored in the append-only ledger """ + +import json +import subprocess +import argparse +import time + +def check_operation_id( + operation_id: str +)-> str: + return subprocess.check_output("curl -s -H @$HOME/.datatrails/bearer-token.txt https://app.datatrails.ai/archivist/v1/publicscitt/operations/"+operation_id, shell=True).decode() + + +def main(): + """Creates a signed statement""" + + parser = argparse.ArgumentParser(description="Create a signed statement.") + + # signing key file + parser.add_argument( + "--operation-id", + type=str, + help="the operation-id from a registered statement", + ) + + args = parser.parse_args() + + # Check the operation status until the status=succeeded + while True: + retval=check_operation_id(args.operation_id) + if retval=="Jwt is expired": + print(retval) + return + + response = json.loads(check_operation_id(args.operation_id)) + if "status" in response and response["status"] == "succeeded": + print(response["entryID"]) + break + else: + time.sleep(1) + + +if __name__ == "__main__": + main() From 7db27d0eb19f3e54c6d4aad992372636bd9c8c38 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Wed, 29 Nov 2023 19:53:50 -0800 Subject: [PATCH 02/10] python linting fixes Signed-off-by: steve lasker --- scitt/check_operation_status.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/scitt/check_operation_status.py b/scitt/check_operation_status.py index eead126..edd1aba 100755 --- a/scitt/check_operation_status.py +++ b/scitt/check_operation_status.py @@ -5,10 +5,11 @@ import argparse import time + def check_operation_id( - operation_id: str + operation_id: str )-> str: - return subprocess.check_output("curl -s -H @$HOME/.datatrails/bearer-token.txt https://app.datatrails.ai/archivist/v1/publicscitt/operations/"+operation_id, shell=True).decode() + return subprocess.check_output("curl -s -H @$HOME/.datatrails/bearer-token.txt https://app.datatrails.ai/archivist/v1/publicscitt/operations/"+operation_id, shell=True).decode() def main(): @@ -27,17 +28,17 @@ def main(): # Check the operation status until the status=succeeded while True: - retval=check_operation_id(args.operation_id) - if retval=="Jwt is expired": - print(retval) - return - - response = json.loads(check_operation_id(args.operation_id)) - if "status" in response and response["status"] == "succeeded": - print(response["entryID"]) - break - else: - time.sleep(1) + retval=check_operation_id(args.operation_id) + if retval=="Jwt is expired": + print(retval) + return + + response = json.loads(check_operation_id(args.operation_id)) + if "status" in response and response["status"] == "succeeded": + print(response["entryID"]) + break + else: + time.sleep(1) if __name__ == "__main__": From 924e2e0d4b991b3fd6cd3003e1c0236d80cab156 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Wed, 29 Nov 2023 20:31:06 -0800 Subject: [PATCH 03/10] python linting fixes Signed-off-by: steve lasker --- scitt/check_operation_status.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scitt/check_operation_status.py b/scitt/check_operation_status.py index edd1aba..05c81f9 100755 --- a/scitt/check_operation_status.py +++ b/scitt/check_operation_status.py @@ -9,6 +9,7 @@ def check_operation_id( operation_id: str )-> str: + return subprocess.check_output("curl -s -H @$HOME/.datatrails/bearer-token.txt https://app.datatrails.ai/archivist/v1/publicscitt/operations/"+operation_id, shell=True).decode() From f74e0ae61b1c6de98c0832c0391023352b442309 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Wed, 29 Nov 2023 20:50:20 -0800 Subject: [PATCH 04/10] python linting fixes Signed-off-by: steve lasker --- scitt/check_operation_status.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scitt/check_operation_status.py b/scitt/check_operation_status.py index 05c81f9..06a6ca0 100755 --- a/scitt/check_operation_status.py +++ b/scitt/check_operation_status.py @@ -10,7 +10,7 @@ def check_operation_id( operation_id: str )-> str: - return subprocess.check_output("curl -s -H @$HOME/.datatrails/bearer-token.txt https://app.datatrails.ai/archivist/v1/publicscitt/operations/"+operation_id, shell=True).decode() + return subprocess.check_output("curl -s -H @$HOME/.datatrails/bearer-token.txt https://app.datatrails.ai/archivist/v1/publicscitt/operations/"+operation_id, shell = True).decode() def main(): From 5bf57d2b6f9f249d032e92efcd7cc5444718b6a4 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Fri, 1 Dec 2023 08:27:22 -0800 Subject: [PATCH 05/10] Address PR Feedback Signed-off-by: steve lasker --- .vscode/settings.json | 5 +++++ scitt/check_operation_status.py | 15 ++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0f92541 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.words": [ + "datatrails" + ] +} \ No newline at end of file diff --git a/scitt/check_operation_status.py b/scitt/check_operation_status.py index 06a6ca0..8495799 100755 --- a/scitt/check_operation_status.py +++ b/scitt/check_operation_status.py @@ -1,10 +1,9 @@ """ Module for checking when a statement has been anchored in the append-only ledger """ -import json import subprocess import argparse -import time - +from json import loads as json_loads +from time import sleep as time_sleep def check_operation_id( operation_id: str @@ -28,19 +27,21 @@ def main(): args = parser.parse_args() # Check the operation status until the status=succeeded - while True: + # Wait a max of 120 seconds + i = 0 + while i < 120 : retval=check_operation_id(args.operation_id) if retval=="Jwt is expired": print(retval) return - response = json.loads(check_operation_id(args.operation_id)) + response = json_loads(check_operation_id(args.operation_id)) if "status" in response and response["status"] == "succeeded": print(response["entryID"]) break - else: - time.sleep(1) + time_sleep(1) + i+=1 if __name__ == "__main__": main() From c5eaab3c43cdc628541a0d6b3761da0b8f62954f Mon Sep 17 00:00:00 2001 From: Steve Lasker Date: Fri, 1 Dec 2023 11:52:28 -0800 Subject: [PATCH 06/10] Update scitt/check_operation_status.py Co-authored-by: Joe Gough <36932486+honourfish@users.noreply.github.com> Signed-off-by: Steve Lasker --- scitt/check_operation_status.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scitt/check_operation_status.py b/scitt/check_operation_status.py index 06a6ca0..2bfed7a 100755 --- a/scitt/check_operation_status.py +++ b/scitt/check_operation_status.py @@ -18,7 +18,7 @@ def main(): parser = argparse.ArgumentParser(description="Create a signed statement.") - # signing key file + # operation id parser.add_argument( "--operation-id", type=str, From 5c545c13dec1b6c9b3298b1a0d54e875c1500fa7 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Mon, 4 Dec 2023 07:08:06 -0800 Subject: [PATCH 07/10] linting fixes Signed-off-by: steve lasker --- scitt/check_operation_status.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scitt/check_operation_status.py b/scitt/check_operation_status.py index 8099c3f..b1e85e4 100755 --- a/scitt/check_operation_status.py +++ b/scitt/check_operation_status.py @@ -5,11 +5,12 @@ from json import loads as json_loads from time import sleep as time_sleep + def check_operation_id( operation_id: str )-> str: - return subprocess.check_output("curl -s -H @$HOME/.datatrails/bearer-token.txt https://app.datatrails.ai/archivist/v1/publicscitt/operations/"+operation_id, shell = True).decode() + return subprocess.check_output("curl -s -H @$HOME/.datatrails/bearer-token.txt https://app.datatrails.ai/archivist/v1/publicscitt/operations/" + operation_id, shell=True).decode() def main(): @@ -43,5 +44,6 @@ def main(): time_sleep(1) i+=1 + if __name__ == "__main__": main() From 0811fbe530a4dca41356b2783778b4ff4098e408 Mon Sep 17 00:00:00 2001 From: jgough Date: Thu, 7 Dec 2023 14:17:53 +0000 Subject: [PATCH 08/10] fixup - linting and code reshuffle --- scitt/check_operation_status.py | 67 ++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/scitt/check_operation_status.py b/scitt/check_operation_status.py index b1e85e4..59f92ce 100755 --- a/scitt/check_operation_status.py +++ b/scitt/check_operation_status.py @@ -6,17 +6,54 @@ from time import sleep as time_sleep -def check_operation_id( - operation_id: str -)-> str: +# all timeouts and durations are in seconds +REQUEST_TIMEOUT = 30 +POLL_TIMEOUT = 360 +POLL_INTERVAL = 10 - return subprocess.check_output("curl -s -H @$HOME/.datatrails/bearer-token.txt https://app.datatrails.ai/archivist/v1/publicscitt/operations/" + operation_id, shell=True).decode() + +def get_operation_status(operation_id: str) -> str: + """ + gets the operation status from the datatrails API for retrieving operation status + """ + + # pylint: disable=fixme + # TODO: use requests.get, with the request timeout. + return subprocess.check_output( + # pylint: disable=line-too-long + "curl -s -H @$HOME/.datatrails/bearer-token.txt https://app.datatrails.ai/archivist/v1/publicscitt/operations/" + + operation_id, + shell=True, + ).decode() + + +def poll_operation_status(operation_id: str) -> str: + """ + polls for the operation status to be 'succeeded'. + """ + + poll_attempts: int = int(POLL_TIMEOUT / POLL_INTERVAL) + + for _ in range(poll_attempts): + operation_status = get_operation_status(operation_id) + + # pylint: disable=fixme + # TODO: ensure get_operation_status handles error cases from the rest request + response = json_loads(operation_status) + if "status" in response and response["status"] == "succeeded": + return response["entryID"] + + time_sleep(POLL_INTERVAL) + + raise TimeoutError("signed statement not registered within polling duration.") def main(): - """Creates a signed statement""" + """Polls for the signed statement to be registered""" - parser = argparse.ArgumentParser(description="Create a signed statement.") + parser = argparse.ArgumentParser( + description="Polls for the signed statement to be registered" + ) # operation id parser.add_argument( @@ -27,22 +64,8 @@ def main(): args = parser.parse_args() - # Check the operation status until the status=succeeded - # Wait a max of 120 seconds - i = 0 - while i < 120 : - retval=check_operation_id(args.operation_id) - if retval=="Jwt is expired": - print(retval) - return - - response = json_loads(check_operation_id(args.operation_id)) - if "status" in response and response["status"] == "succeeded": - print(response["entryID"]) - break - - time_sleep(1) - i+=1 + entry_id = poll_operation_status(args.operation_id) + print(entry_id) if __name__ == "__main__": From 6c4c6a1da14019d087c261944da11900f4f436a0 Mon Sep 17 00:00:00 2001 From: jgough Date: Fri, 8 Dec 2023 08:55:38 +0000 Subject: [PATCH 09/10] fixup - use requests library --- scitt/check_operation_status.py | 67 ++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/scitt/check_operation_status.py b/scitt/check_operation_status.py index 59f92ce..8732d9e 100755 --- a/scitt/check_operation_status.py +++ b/scitt/check_operation_status.py @@ -1,10 +1,12 @@ """ Module for checking when a statement has been anchored in the append-only ledger """ -import subprocess +import os import argparse -from json import loads as json_loads + from time import sleep as time_sleep +import requests + # all timeouts and durations are in seconds REQUEST_TIMEOUT = 30 @@ -12,22 +14,36 @@ POLL_INTERVAL = 10 -def get_operation_status(operation_id: str) -> str: +def get_token_from_file(token_file_name: str) -> dict: + """ + gets the token from a file, + assume the contents of the file is the + whole authorization header: `Authorization: Bearer {token}` + """ + with open(token_file_name, mode="r", encoding="utf-8") as token_file: + auth_header = token_file.read().strip() + header, value = auth_header.split(": ") + print(f"header:{header}") + print(f"value:{value}") + return {header: value} + + +def get_operation_status(operation_id: str, headers: dict) -> dict: """ gets the operation status from the datatrails API for retrieving operation status """ - # pylint: disable=fixme - # TODO: use requests.get, with the request timeout. - return subprocess.check_output( - # pylint: disable=line-too-long - "curl -s -H @$HOME/.datatrails/bearer-token.txt https://app.datatrails.ai/archivist/v1/publicscitt/operations/" - + operation_id, - shell=True, - ).decode() + url = ( + f"https://app.datatrails.ai/archivist/v1/publicscitt/operations/{operation_id}" + ) + + response = requests.get(url, timeout=30, headers=headers) + response.raise_for_status() + return response.json() -def poll_operation_status(operation_id: str) -> str: + +def poll_operation_status(operation_id: str, headers: dict) -> str: """ polls for the operation status to be 'succeeded'. """ @@ -35,13 +51,12 @@ def poll_operation_status(operation_id: str) -> str: poll_attempts: int = int(POLL_TIMEOUT / POLL_INTERVAL) for _ in range(poll_attempts): - operation_status = get_operation_status(operation_id) + operation_status = get_operation_status(operation_id, headers) # pylint: disable=fixme # TODO: ensure get_operation_status handles error cases from the rest request - response = json_loads(operation_status) - if "status" in response and response["status"] == "succeeded": - return response["entryID"] + if "status" in operation_status and operation_status["status"] == "succeeded": + return operation_status["entryID"] time_sleep(POLL_INTERVAL) @@ -62,9 +77,27 @@ def main(): help="the operation-id from a registered statement", ) + # get default token file name + home = os.environ.get("HOME") + if home is None: + default_token_file_name: str = ".datatrails/bearer-token.txt" + else: + default_token_file_name: str = home + "/.datatrails/bearer-token.txt" + + # token file name + parser.add_argument( + "--token-file-name", + type=str, + help="filename containing the token in the format" + "of an auth header: `Authorization: Bearer {token}", + default=default_token_file_name, + ) + args = parser.parse_args() - entry_id = poll_operation_status(args.operation_id) + headers = get_token_from_file(args.token_file_name) + + entry_id = poll_operation_status(args.operation_id, headers) print(entry_id) From 33abbff3d82c09ba87164117b2b3a5d3569ca983 Mon Sep 17 00:00:00 2001 From: jgough Date: Fri, 8 Dec 2023 08:56:10 +0000 Subject: [PATCH 10/10] fixup - remove print --- scitt/check_operation_status.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/scitt/check_operation_status.py b/scitt/check_operation_status.py index 8732d9e..267cc38 100755 --- a/scitt/check_operation_status.py +++ b/scitt/check_operation_status.py @@ -23,8 +23,6 @@ def get_token_from_file(token_file_name: str) -> dict: with open(token_file_name, mode="r", encoding="utf-8") as token_file: auth_header = token_file.read().strip() header, value = auth_header.split(": ") - print(f"header:{header}") - print(f"value:{value}") return {header: value}