aplos-nca-saas-sdk 0.0.10__py3-none-any.whl → 0.0.12__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.
- aplos_nca_saas_sdk/aws_resources/aws_cognito.py +11 -5
- aplos_nca_saas_sdk/integration_testing/configs/{app_settings.py → app_settings_config.py} +8 -8
- aplos_nca_saas_sdk/integration_testing/configs/config_sample.json +27 -14
- aplos_nca_saas_sdk/integration_testing/configs/file_upload_config.py +94 -0
- aplos_nca_saas_sdk/integration_testing/configs/{login.py → login_config.py} +23 -11
- aplos_nca_saas_sdk/integration_testing/configs/nca_execution_config.py +186 -0
- aplos_nca_saas_sdk/integration_testing/files/executions/config1.json +46 -0
- aplos_nca_saas_sdk/integration_testing/integration_test_base.py +8 -1
- aplos_nca_saas_sdk/integration_testing/integration_test_configurations.py +10 -6
- aplos_nca_saas_sdk/integration_testing/main.py +1 -2
- aplos_nca_saas_sdk/integration_testing/tests/app_login_test.py +1 -1
- aplos_nca_saas_sdk/integration_testing/tests/file_upload_test.py +14 -11
- aplos_nca_saas_sdk/integration_testing/tests/nca_analysis_test.py +89 -0
- aplos_nca_saas_sdk/nca_resources/{nca_executions.py → nca_analysis.py} +148 -87
- aplos_nca_saas_sdk/nca_resources/nca_file_upload.py +5 -5
- aplos_nca_saas_sdk/nca_resources/nca_login.py +4 -4
- aplos_nca_saas_sdk/utilities/commandline_args.py +6 -28
- aplos_nca_saas_sdk/utilities/environment_vars.py +7 -0
- aplos_nca_saas_sdk/utilities/file_utility.py +33 -0
- aplos_nca_saas_sdk/utilities/http_utility.py +22 -6
- aplos_nca_saas_sdk/version.py +1 -1
- {aplos_nca_saas_sdk-0.0.10.dist-info → aplos_nca_saas_sdk-0.0.12.dist-info}/METADATA +1 -1
- {aplos_nca_saas_sdk-0.0.10.dist-info → aplos_nca_saas_sdk-0.0.12.dist-info}/RECORD +26 -23
- aplos_nca_saas_sdk/integration_testing/configs/file_upload.py +0 -104
- aplos_nca_saas_sdk/integration_testing/tests/app_validation_test.py +0 -5
- /aplos_nca_saas_sdk/integration_testing/tests/{app_execution_test.py → validation_test.py} +0 -0
- {aplos_nca_saas_sdk-0.0.10.dist-info → aplos_nca_saas_sdk-0.0.12.dist-info}/WHEEL +0 -0
- {aplos_nca_saas_sdk-0.0.10.dist-info → aplos_nca_saas_sdk-0.0.12.dist-info}/licenses/LICENSE +0 -0
@@ -36,13 +36,12 @@ def main():
|
|
36
36
|
)
|
37
37
|
# load it so we can see what it looks like
|
38
38
|
config.load(file_path=config_file)
|
39
|
-
|
39
|
+
|
40
40
|
# override the configuration
|
41
41
|
# override_config(config)
|
42
42
|
|
43
43
|
its.test(test_config=config)
|
44
44
|
|
45
|
-
|
46
45
|
def override_config(config: TestConfiguration):
|
47
46
|
"""Override the configuration for the tests"""
|
48
47
|
username = os.getenv("TEST_USERNAME")
|
@@ -6,11 +6,11 @@ Property of Aplos Analytics, Utah, USA
|
|
6
6
|
|
7
7
|
import time
|
8
8
|
from datetime import datetime, timedelta
|
9
|
-
from typing import Any, Dict
|
9
|
+
from typing import Any, Dict, List
|
10
10
|
|
11
11
|
import requests
|
12
12
|
from aws_lambda_powertools import Logger
|
13
|
-
from aplos_nca_saas_sdk.integration_testing.configs.
|
13
|
+
from aplos_nca_saas_sdk.integration_testing.configs.login_config import LoginConfig
|
14
14
|
from aplos_nca_saas_sdk.integration_testing.integration_test_base import (
|
15
15
|
IntegrationTestBase,
|
16
16
|
)
|
@@ -21,7 +21,7 @@ from aplos_nca_saas_sdk.nca_resources.nca_file_upload import NCAFileUpload
|
|
21
21
|
from aplos_nca_saas_sdk.nca_resources.nca_login import NCALogin
|
22
22
|
from aplos_nca_saas_sdk.utilities.http_utility import HttpUtilities
|
23
23
|
|
24
|
-
logger = Logger(
|
24
|
+
logger = Logger()
|
25
25
|
|
26
26
|
|
27
27
|
class FileUploadTest(IntegrationTestBase):
|
@@ -35,28 +35,31 @@ class FileUploadTest(IntegrationTestBase):
|
|
35
35
|
|
36
36
|
self.results.clear()
|
37
37
|
|
38
|
-
for
|
38
|
+
for file_upload in self.config.file_uploads.list:
|
39
39
|
test_response: IntegrationTestResponse = IntegrationTestResponse()
|
40
40
|
test_response.name = self.name
|
41
41
|
try:
|
42
42
|
# Confirm Login
|
43
|
-
nca_login = self.__login(
|
43
|
+
nca_login = self.__login(file_upload.login)
|
44
44
|
if not nca_login.jwt:
|
45
45
|
test_response.error = "Failed to authenticate"
|
46
46
|
else:
|
47
47
|
# Confirm Upload
|
48
48
|
upload_response: Dict[str, Any] = self.__upload(
|
49
|
-
nca_login,
|
49
|
+
nca_login, file_upload.file_path
|
50
50
|
)
|
51
51
|
if upload_response is None:
|
52
52
|
test_response.error = "Failed to upload"
|
53
53
|
else:
|
54
54
|
# Confirm conversion and download
|
55
55
|
# Allow time buffer so file data is available
|
56
|
+
file_id: str = upload_response.get("file_id", "")
|
57
|
+
if not file_id:
|
58
|
+
raise RuntimeError(
|
59
|
+
"Failed to get a file_id from the upload"
|
60
|
+
)
|
56
61
|
time.sleep(3)
|
57
|
-
self.__download(
|
58
|
-
nca_login, upload_response.get("file_id"), test_response
|
59
|
-
)
|
62
|
+
self.__download(nca_login, file_id, test_response)
|
60
63
|
|
61
64
|
except Exception as e: # pylint: disable=w0718
|
62
65
|
test_response.error = str(e)
|
@@ -65,7 +68,7 @@ class FileUploadTest(IntegrationTestBase):
|
|
65
68
|
|
66
69
|
return self.success()
|
67
70
|
|
68
|
-
def __login(self, login:
|
71
|
+
def __login(self, login: LoginConfig) -> NCALogin:
|
69
72
|
nca_login = NCALogin(aplos_saas_domain=login.domain)
|
70
73
|
nca_login.authenticate(username=login.username, password=login.password)
|
71
74
|
return nca_login
|
@@ -108,7 +111,7 @@ class FileUploadTest(IntegrationTestBase):
|
|
108
111
|
while not complete:
|
109
112
|
response = requests.get(file_info_endpoint, headers=headers, timeout=60)
|
110
113
|
json_response: dict = response.json()
|
111
|
-
errors = []
|
114
|
+
errors: List[Dict[str, Any]] = []
|
112
115
|
errors.extend(json_response.get("errors") or [])
|
113
116
|
status = json_response.get("workable_state")
|
114
117
|
complete = status == "ready"
|
@@ -0,0 +1,89 @@
|
|
1
|
+
"""
|
2
|
+
Copyright 2024 Aplos Analytics
|
3
|
+
All Rights Reserved. www.aplosanalytics.com LICENSED MATERIALS
|
4
|
+
Property of Aplos Analytics, Utah, USA
|
5
|
+
"""
|
6
|
+
|
7
|
+
from pathlib import Path
|
8
|
+
|
9
|
+
from aws_lambda_powertools import Logger
|
10
|
+
|
11
|
+
from aplos_nca_saas_sdk.integration_testing.integration_test_base import (
|
12
|
+
IntegrationTestBase,
|
13
|
+
)
|
14
|
+
from aplos_nca_saas_sdk.integration_testing.integration_test_response import (
|
15
|
+
IntegrationTestResponse,
|
16
|
+
)
|
17
|
+
from aplos_nca_saas_sdk.nca_resources.nca_analysis import NCAAnalysis
|
18
|
+
from aplos_nca_saas_sdk.utilities.file_utility import FileUtility
|
19
|
+
|
20
|
+
logger = Logger(service="NCAAnalysisTest")
|
21
|
+
|
22
|
+
|
23
|
+
class NCAAnalysisTest(IntegrationTestBase):
|
24
|
+
"""NCA Execution Test Container"""
|
25
|
+
|
26
|
+
def __init__(self):
|
27
|
+
super().__init__("nca-execution")
|
28
|
+
|
29
|
+
def test(self) -> bool:
|
30
|
+
"""Test Engine Execution"""
|
31
|
+
|
32
|
+
self.results.clear()
|
33
|
+
|
34
|
+
for nca_execution_config in self.config.nca_executions.list:
|
35
|
+
test_response: IntegrationTestResponse = IntegrationTestResponse()
|
36
|
+
test_response.name = self.name
|
37
|
+
|
38
|
+
input_file_path = (
|
39
|
+
FileUtility.load_filepath(nca_execution_config.input_file_path),
|
40
|
+
)
|
41
|
+
logger.info(
|
42
|
+
{
|
43
|
+
"message": "Creating NCA Analysis Execution for input file.",
|
44
|
+
"path": input_file_path,
|
45
|
+
"path2": nca_execution_config.input_file_path,
|
46
|
+
}
|
47
|
+
)
|
48
|
+
try:
|
49
|
+
# Create new NCA Execution
|
50
|
+
nca_execution: NCAAnalysis = NCAAnalysis(
|
51
|
+
nca_execution_config.login.domain
|
52
|
+
)
|
53
|
+
|
54
|
+
# Initialize Configuration Data
|
55
|
+
|
56
|
+
# Execute, the execution should raise errors that will fail the test
|
57
|
+
logger.info({"message": "Invoking Execution"})
|
58
|
+
execution_response = nca_execution.execute(
|
59
|
+
username=nca_execution_config.login.username,
|
60
|
+
password=nca_execution_config.login.password,
|
61
|
+
input_file_path=FileUtility.load_filepath(
|
62
|
+
nca_execution_config.input_file_path
|
63
|
+
),
|
64
|
+
config_data=nca_execution_config.config_data,
|
65
|
+
meta_data=nca_execution_config.meta_data,
|
66
|
+
wait_for_results=True,
|
67
|
+
output_directory=nca_execution_config.output_dir,
|
68
|
+
unzip_after_download=False,
|
69
|
+
)
|
70
|
+
|
71
|
+
# Verify Download
|
72
|
+
logger.info(
|
73
|
+
{"message": "Execution complete. Verifying results download."}
|
74
|
+
)
|
75
|
+
|
76
|
+
expected_output_file = execution_response.get("results", {}).get("file")
|
77
|
+
if expected_output_file is None:
|
78
|
+
raise RuntimeError(
|
79
|
+
"Expected populated output_file from NCAExecution was None."
|
80
|
+
)
|
81
|
+
elif not Path(expected_output_file).is_file():
|
82
|
+
raise RuntimeError("Expected downloaded file does not exist.")
|
83
|
+
|
84
|
+
except Exception as e: # pylint: disable=w0718
|
85
|
+
test_response.error = str(e)
|
86
|
+
|
87
|
+
self.results.append(test_response)
|
88
|
+
|
89
|
+
return self.success()
|
@@ -11,52 +11,61 @@ import zipfile
|
|
11
11
|
from datetime import datetime, timedelta
|
12
12
|
from pathlib import Path
|
13
13
|
from typing import Any, Dict
|
14
|
-
|
14
|
+
from aws_lambda_powertools import Logger
|
15
15
|
import requests
|
16
16
|
|
17
|
-
from aplos_nca_saas_sdk.aws_resources.aws_cognito import
|
17
|
+
from aplos_nca_saas_sdk.aws_resources.aws_cognito import CognitoAuthentication
|
18
18
|
from aplos_nca_saas_sdk.aws_resources.aws_s3_presigned_upload import (
|
19
19
|
S3PresignedUpload,
|
20
20
|
)
|
21
21
|
from aplos_nca_saas_sdk.utilities.commandline_args import CommandlineArgs
|
22
22
|
from aplos_nca_saas_sdk.utilities.http_utility import HttpUtilities, Routes
|
23
|
+
from aplos_nca_saas_sdk.utilities.environment_vars import EnvironmentVars
|
24
|
+
|
25
|
+
logger = Logger()
|
26
|
+
|
27
|
+
|
28
|
+
class NCAAnalysis:
|
29
|
+
"""NCA Analysis API Access"""
|
23
30
|
|
31
|
+
def __init__(self, api_domain: str) -> None:
|
32
|
+
self.__jwt: str
|
24
33
|
|
25
|
-
|
26
|
-
|
34
|
+
if not api_domain:
|
35
|
+
raise ValueError("Missing Aplos Api Domain")
|
27
36
|
|
28
|
-
|
29
|
-
self, api_domain: str | None, cognito_client_id: str | None, region: str | None
|
30
|
-
) -> None:
|
31
|
-
self.jwt: str
|
32
|
-
self.access_token: str | None = None
|
33
|
-
self.refresh_token: str | None = None
|
34
|
-
self.__api_domain: str | None = api_domain
|
37
|
+
self.__api_domain: str = api_domain
|
35
38
|
self.verbose: bool = False
|
39
|
+
self.__cognito: CognitoAuthentication | None = None
|
36
40
|
|
37
|
-
|
38
|
-
|
39
|
-
|
41
|
+
@property
|
42
|
+
def cognito(self) -> CognitoAuthentication:
|
43
|
+
"""Gets the cognito authentication object"""
|
40
44
|
|
41
45
|
if not self.__api_domain:
|
42
46
|
raise RuntimeError(
|
43
|
-
"Missing Aplos Api Domain. "
|
44
|
-
"
|
47
|
+
"Missing Aplos Api Domain. Set the internal property of __api_domain first."
|
48
|
+
"This is required to make an authentication connection"
|
45
49
|
)
|
46
50
|
|
51
|
+
if self.__cognito is None:
|
52
|
+
self.__cognito = CognitoAuthentication(
|
53
|
+
client_id=None, region=None, aplos_domain=self.__api_domain
|
54
|
+
)
|
55
|
+
|
56
|
+
return self.__cognito
|
57
|
+
|
47
58
|
@property
|
48
59
|
def api_root(self) -> str:
|
49
60
|
"""Gets the base url"""
|
50
61
|
if self.__api_domain is None:
|
51
62
|
raise RuntimeError("Missing Aplos Api Domain")
|
52
63
|
|
53
|
-
url = HttpUtilities.build_url(
|
54
|
-
|
55
|
-
|
56
|
-
f"{url}/tenants/{self.cognito.tenant_id}/users/{self.cognito.user_id}"
|
57
|
-
)
|
64
|
+
url = HttpUtilities.build_url(
|
65
|
+
self.__api_domain, self.cognito.tenant_id, self.cognito.user_id
|
66
|
+
)
|
58
67
|
|
59
|
-
|
68
|
+
return url
|
60
69
|
|
61
70
|
def execute(
|
62
71
|
self,
|
@@ -67,59 +76,101 @@ class NCAEngine:
|
|
67
76
|
*,
|
68
77
|
meta_data: str | dict | None = None,
|
69
78
|
wait_for_results: bool = True,
|
79
|
+
max_wait_in_seconds: int = 900,
|
70
80
|
output_directory: str | None = None,
|
71
81
|
unzip_after_download: bool = False,
|
72
|
-
) ->
|
73
|
-
"""
|
82
|
+
) -> Dict[str, Any]:
|
83
|
+
"""
|
84
|
+
Executes an analsysis.
|
85
|
+
- Uploads an analysis file.
|
86
|
+
- Adds the execution to the queue.
|
74
87
|
|
75
88
|
Args:
|
76
89
|
username (str): the username
|
77
90
|
password (str): the users password
|
78
|
-
input_file_path (str): the path to the input (
|
79
|
-
config_data (dict): analysis configuration
|
91
|
+
input_file_path (str): the path to the input (analysis) file
|
92
|
+
config_data (dict): analysis configuration information
|
80
93
|
meta_data (str | dict | None, optional): meta data attached to the execution. Defaults to None.
|
81
94
|
wait_for_results (bool, optional): should the program wait for results. Defaults to True.
|
82
|
-
|
95
|
+
max_wait_in_seconds (int optional): the max time to wait for a download
|
96
|
+
output_directory (str, optional): the output directory. Defaults to None (the local directory is used)
|
83
97
|
unzip_after_download (bool): Results are downloaded as a zip file, this option will unzip them automatically. Defaults to False
|
98
|
+
|
99
|
+
Returns:
|
100
|
+
Dict[str, Any]: The execution response. If you wait for the completion
|
84
101
|
"""
|
85
|
-
if self.verbose:
|
86
|
-
print("\tLogging in.")
|
87
|
-
self.jwt = self.cognito.login(username=username, password=password)
|
88
102
|
|
89
|
-
|
90
|
-
|
91
|
-
|
103
|
+
self.log(f"\tLogging into {self.__api_domain}.")
|
104
|
+
|
105
|
+
if not username:
|
106
|
+
raise ValueError("Missing username. Please provide a valid username.")
|
107
|
+
if not password:
|
108
|
+
raise ValueError("Missing password. Please provide a valid password.")
|
109
|
+
|
110
|
+
self.__jwt = self.cognito.login(username=username, password=password)
|
111
|
+
|
112
|
+
self.log("\tUploading the analysis file.")
|
113
|
+
uploader: S3PresignedUpload = S3PresignedUpload(self.__jwt, str(self.api_root))
|
92
114
|
upload_response: Dict[str, Any] = uploader.upload_file(input_file_path)
|
93
115
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
116
|
+
file_id: str = upload_response.get("file_id", "")
|
117
|
+
if not file_id:
|
118
|
+
raise RuntimeError(
|
119
|
+
"Unexpected empty file_id when attempting to upload file."
|
120
|
+
)
|
121
|
+
|
122
|
+
self.log("\tAdding analyis to the queue.")
|
123
|
+
execution_response: Dict[str, Any] = self.__add_to_queue(
|
124
|
+
file_id=file_id,
|
98
125
|
config_data=config_data,
|
99
126
|
meta_data=meta_data,
|
100
127
|
)
|
101
128
|
|
102
|
-
|
129
|
+
execution_id: str = execution_response.get("execution_id", "")
|
130
|
+
|
131
|
+
response = {
|
132
|
+
"execution": execution_response,
|
133
|
+
"upload": upload_response,
|
134
|
+
"results": {"file": None},
|
135
|
+
}
|
136
|
+
|
137
|
+
if not execution_id:
|
138
|
+
raise RuntimeError(
|
139
|
+
"Unexpected empty execution_id when attempting to execute analysis."
|
140
|
+
)
|
141
|
+
|
142
|
+
if wait_for_results:
|
103
143
|
# wait for it
|
104
|
-
download_url = self.wait_for_results(
|
144
|
+
download_url = self.wait_for_results(
|
145
|
+
execution_id=execution_id, max_wait_in_seconds=max_wait_in_seconds
|
146
|
+
)
|
105
147
|
# download the files
|
106
|
-
if download_url:
|
107
|
-
|
108
|
-
|
109
|
-
|
148
|
+
if download_url is None:
|
149
|
+
raise RuntimeError(
|
150
|
+
"Unexpected empty download_url when attempting to download results."
|
151
|
+
)
|
152
|
+
else:
|
153
|
+
self.log("\tDownloading the results.")
|
154
|
+
file_path = self.download_file(
|
110
155
|
download_url,
|
111
156
|
output_directory=output_directory,
|
112
157
|
do_unzip=unzip_after_download,
|
113
158
|
)
|
114
159
|
|
115
|
-
|
160
|
+
response["results"]["file"] = file_path
|
161
|
+
else:
|
162
|
+
self.log("Bypassed results download.")
|
163
|
+
|
164
|
+
return response
|
165
|
+
|
166
|
+
def __add_to_queue(
|
116
167
|
self,
|
117
168
|
file_id: str,
|
118
169
|
config_data: dict,
|
119
170
|
meta_data: str | dict | None = None,
|
120
|
-
) -> str:
|
171
|
+
) -> Dict[str, Any]:
|
121
172
|
"""
|
122
|
-
|
173
|
+
Adds the analysis to the execution queue.
|
123
174
|
|
124
175
|
Args:
|
125
176
|
bucket_name (str): s3 bucket name for your organization. this is returned to you
|
@@ -127,7 +178,7 @@ class NCAEngine:
|
|
127
178
|
config_data (dict): the config_data for the analysis file
|
128
179
|
meta_data (str | dict): Optional. Any meta data you'd like attached to this execution
|
129
180
|
Returns:
|
130
|
-
str: the
|
181
|
+
Dict[str, Any]: the api response
|
131
182
|
"""
|
132
183
|
|
133
184
|
if not file_id:
|
@@ -137,7 +188,7 @@ class NCAEngine:
|
|
137
188
|
raise ValueError(
|
138
189
|
"Missing config_data. Please provide a valid config_data."
|
139
190
|
)
|
140
|
-
headers = HttpUtilities.get_headers(self.
|
191
|
+
headers = HttpUtilities.get_headers(self.__jwt)
|
141
192
|
# to start a new execution we need the location of the file (s3 bucket and object key)
|
142
193
|
# you basic configuration
|
143
194
|
# optional meta data
|
@@ -166,13 +217,13 @@ class NCAEngine:
|
|
166
217
|
)
|
167
218
|
|
168
219
|
execution_id = str(json_response.get("execution_id"))
|
169
|
-
if self.verbose:
|
170
|
-
print(f"\tExecution {execution_id} started.")
|
171
220
|
|
172
|
-
|
221
|
+
self.log(f"\tExecution {execution_id} started.")
|
222
|
+
|
223
|
+
return json_response
|
173
224
|
|
174
225
|
def wait_for_results(
|
175
|
-
self, execution_id: str,
|
226
|
+
self, execution_id: str, max_wait_in_seconds: float = 900
|
176
227
|
) -> str | None:
|
177
228
|
"""
|
178
229
|
Wait for results
|
@@ -185,10 +236,10 @@ class NCAEngine:
|
|
185
236
|
|
186
237
|
url = f"{self.api_root}/{Routes.NCA_EXECUTIONS}/{execution_id}"
|
187
238
|
|
188
|
-
headers = HttpUtilities.get_headers(self.
|
239
|
+
headers = HttpUtilities.get_headers(self.__jwt)
|
189
240
|
current_time = datetime.now()
|
190
241
|
# Create a timedelta object representing 15 minutes
|
191
|
-
time_delta = timedelta(
|
242
|
+
time_delta = timedelta(seconds=max_wait_in_seconds)
|
192
243
|
|
193
244
|
# Add the timedelta to the current time
|
194
245
|
max_time = current_time + time_delta
|
@@ -205,8 +256,7 @@ class NCAEngine:
|
|
205
256
|
if status == "failed" or complete:
|
206
257
|
break
|
207
258
|
if not complete:
|
208
|
-
|
209
|
-
print(f"\t\twaiting for results.... {status}: {elapsed}")
|
259
|
+
self.log(f"\t\twaiting for results.... {status}: {elapsed}")
|
210
260
|
time.sleep(5)
|
211
261
|
if datetime.now() > max_time:
|
212
262
|
status = "timeout"
|
@@ -217,16 +267,13 @@ class NCAEngine:
|
|
217
267
|
break
|
218
268
|
|
219
269
|
if status == "complete":
|
220
|
-
|
221
|
-
|
222
|
-
print(f"\tExecution duration = {elapsed}.")
|
270
|
+
self.log("\tExecution complete.")
|
271
|
+
self.log(f"\tExecution duration = {elapsed}.")
|
223
272
|
return json_response["presigned"]["url"]
|
224
273
|
else:
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
)
|
229
|
-
return None
|
274
|
+
raise RuntimeError(
|
275
|
+
f"\tExecution failed. Execution ID = {execution_id}. reason: {json_response.get('errors')}"
|
276
|
+
)
|
230
277
|
|
231
278
|
def download_file(
|
232
279
|
self,
|
@@ -249,31 +296,47 @@ class NCAEngine:
|
|
249
296
|
output_directory = str(Path(__file__).parent.parent)
|
250
297
|
output_directory = os.path.join(output_directory, ".aplos-nca-output")
|
251
298
|
|
252
|
-
if
|
253
|
-
|
299
|
+
if EnvironmentVars.is_running_in_aws_lambda():
|
300
|
+
# /tmp is the only directory we can write to unless we mount an external drive
|
301
|
+
# TODO: allow for external mapped drives, perhaps test if we can write to it
|
254
302
|
|
255
|
-
|
256
|
-
os.makedirs(output_directory, exist_ok=True)
|
303
|
+
output_directory = os.path.join("/tmp", ".aplos-nca-output")
|
257
304
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
f.write(response.content)
|
305
|
+
self.log(
|
306
|
+
f"\t\tRunning in AWS Lambda. Setting output directory to {output_directory}"
|
307
|
+
)
|
262
308
|
|
263
|
-
|
264
|
-
if do_unzip:
|
265
|
-
with zipfile.ZipFile(output_file, "r") as zip_ref:
|
266
|
-
zip_ref.extractall(output_file.replace(".zip", ""))
|
309
|
+
output_file = f"results-{time.strftime('%Y-%m-%d-%Hh%Mm%Ss')}.zip"
|
267
310
|
|
268
|
-
|
311
|
+
output_file = os.path.join(output_directory, output_file)
|
312
|
+
os.makedirs(output_directory, exist_ok=True)
|
269
313
|
|
270
|
-
|
271
|
-
|
272
|
-
|
314
|
+
response = requests.get(presigned_download_url, timeout=60)
|
315
|
+
# write the zip to a file
|
316
|
+
with open(output_file, "wb") as f:
|
317
|
+
f.write(response.content)
|
273
318
|
|
274
|
-
|
275
|
-
|
276
|
-
|
319
|
+
# optionally, extract all the files from the zip
|
320
|
+
if do_unzip:
|
321
|
+
with zipfile.ZipFile(output_file, "r") as zip_ref:
|
322
|
+
zip_ref.extractall(output_file.replace(".zip", ""))
|
323
|
+
|
324
|
+
unzipped_state = "and unzipped" if do_unzip else "in zip format"
|
325
|
+
|
326
|
+
self.log(f"\tResults file downloaded {unzipped_state}.")
|
327
|
+
self.log(f"\t\tResults are available in: {output_directory}")
|
328
|
+
|
329
|
+
return output_file
|
330
|
+
|
331
|
+
def log(self, message: str | Dict[str, Any]):
|
332
|
+
"""Log the message"""
|
333
|
+
logger.debug(message)
|
334
|
+
|
335
|
+
if isinstance(message, dict):
|
336
|
+
message = json.dumps(message, indent=2)
|
337
|
+
|
338
|
+
if self.verbose:
|
339
|
+
print(message)
|
277
340
|
|
278
341
|
|
279
342
|
def main():
|
@@ -292,10 +355,8 @@ def main():
|
|
292
355
|
print("Missing some arguments.")
|
293
356
|
exit()
|
294
357
|
|
295
|
-
engine =
|
296
|
-
api_domain=args.api_domain,
|
297
|
-
cognito_client_id=args.cognito_client_id,
|
298
|
-
region=args.aws_region,
|
358
|
+
engine = NCAAnalysis(
|
359
|
+
api_domain=str(args.api_domain),
|
299
360
|
)
|
300
361
|
|
301
362
|
print("\tLoading analysis configurations")
|
@@ -17,7 +17,7 @@ class NCAFileUpload:
|
|
17
17
|
if nca_login is None or nca_login.jwt is None or not nca_login.jwt:
|
18
18
|
raise ValueError("Authenticated nca_login is required.")
|
19
19
|
|
20
|
-
self.__api_domain: str = nca_login.domain
|
20
|
+
self.__api_domain: str = nca_login.domain or ""
|
21
21
|
self.__tenant_id: str = nca_login.cognito.tenant_id
|
22
22
|
self.__user_id: str = nca_login.cognito.user_id
|
23
23
|
self.__jwt: str = nca_login.jwt
|
@@ -29,11 +29,11 @@ class NCAFileUpload:
|
|
29
29
|
if self.__api_domain is None:
|
30
30
|
raise RuntimeError("Missing Aplos Api Domain")
|
31
31
|
|
32
|
-
url = HttpUtilities.build_url(
|
33
|
-
|
34
|
-
|
32
|
+
url = HttpUtilities.build_url(
|
33
|
+
self.__api_domain, self.__tenant_id, self.__user_id
|
34
|
+
)
|
35
35
|
|
36
|
-
|
36
|
+
return url
|
37
37
|
|
38
38
|
def upload(self, input_file_path: str) -> Dict[str, Any]:
|
39
39
|
"""
|
@@ -5,7 +5,7 @@ Property of Aplos Analytics, Utah, USA
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
from typing import Optional
|
8
|
-
from aplos_nca_saas_sdk.aws_resources.aws_cognito import
|
8
|
+
from aplos_nca_saas_sdk.aws_resources.aws_cognito import CognitoAuthentication
|
9
9
|
from aplos_nca_saas_sdk.nca_resources.nca_app_configuration import (
|
10
10
|
NCAAppConfiguration,
|
11
11
|
)
|
@@ -39,18 +39,18 @@ class NCALogin:
|
|
39
39
|
self.__cognito_client_id = cognito_client_id
|
40
40
|
self.__region = cognito_region
|
41
41
|
self.__domain: Optional[str] = aplos_saas_domain
|
42
|
-
self.__cognito: Optional[
|
42
|
+
self.__cognito: Optional[CognitoAuthentication] = None
|
43
43
|
self.__config: Optional[NCAAppConfiguration] = None
|
44
44
|
|
45
45
|
@property
|
46
|
-
def cognito(self) ->
|
46
|
+
def cognito(self) -> CognitoAuthentication:
|
47
47
|
"""
|
48
48
|
Cognito Authentication
|
49
49
|
Returns:
|
50
50
|
CognitoAuthenication: object to handle cognito authentication
|
51
51
|
"""
|
52
52
|
if self.__cognito is None:
|
53
|
-
self.__cognito =
|
53
|
+
self.__cognito = CognitoAuthentication(
|
54
54
|
client_id=self.__cognito_client_id,
|
55
55
|
region=self.__region,
|
56
56
|
aplos_domain=self.__domain,
|